@@ -83,59 +83,11 @@ struct MonoRawVec<A: Allocator = Global> {
8383}
8484
8585#[ inline]
86- const fn max_size_for_align ( align : usize ) -> usize {
87- // (power-of-two implies align != 0.)
88-
89- // Rounded up size is:
90- // size_rounded_up = (size + align - 1) & !(align - 1);
91- //
92- // We know from above that align != 0. If adding (align - 1)
93- // does not overflow, then rounding up will be fine.
94- //
95- // Conversely, &-masking with !(align - 1) will subtract off
96- // only low-order-bits. Thus if overflow occurs with the sum,
97- // the &-mask cannot subtract enough to undo that overflow.
98- //
99- // Above implies that checking for summation overflow is both
100- // necessary and sufficient.
101- isize:: MAX as usize - ( align - 1 )
102- }
103-
104- #[ inline]
105- fn layout_array ( cap : usize , size : usize , align : usize ) -> Result < Layout , TryReserveError > {
106- // We need to check two things about the size:
107- // - That the total size won't overflow a `usize`, and
108- // - That the total size still fits in an `isize`.
109- // By using division we can check them both with a single threshold.
110- // That'd usually be a bad idea, but thankfully here the element size
111- // and alignment are constants, so the compiler will fold all of it.
112- if size != 0 && cap > max_size_for_align ( align) / size {
113- return Err ( CapacityOverflow . into ( ) ) ;
114- }
115-
116- // SAFETY: We just checked that we won't overflow `usize` when we multiply.
117- // This is a useless hint inside this function, but after inlining this helps
118- // deduplicate checks for whether the overall capacity is zero (e.g., in RawVec's
119- // allocation path) before/after this multiplication.
120- let array_size = unsafe { size. unchecked_mul ( cap) } ;
121-
122- // SAFETY: We just checked above that the `array_size` will not
123- // exceed `isize::MAX` even when rounded up to the alignment.
124- // And `Alignment` guarantees it's a power of two.
125- unsafe { Ok ( Layout :: from_size_align_unchecked ( array_size, align) ) }
86+ fn layout_array ( cap : usize , elem_layout : Layout ) -> Result < Layout , TryReserveError > {
87+ elem_layout. repeat ( cap) . map ( |( layout, _pad) | layout) . map_err ( |_| CapacityOverflow . into ( ) )
12688}
12789
12890impl < A : Allocator > MonoRawVec < A > {
129- #[ inline]
130- fn ptr < T > ( & self ) -> * mut T {
131- unsafe { core:: mem:: transmute ( self . ptr ) }
132- }
133-
134- #[ inline]
135- fn non_null < T > ( & self ) -> NonNull < T > {
136- unsafe { core:: mem:: transmute ( self . ptr ) }
137- }
138-
13991 /// # Safety:
14092 ///
14193 /// `cap` must not exceed `isize::MAX`.
@@ -149,8 +101,8 @@ impl<A: Allocator> MonoRawVec<A> {
149101 }
150102
151103 #[ inline]
152- fn current_memory ( & self , size : usize , align : usize ) -> Option < ( NonNull < u8 > , Layout ) > {
153- if size == 0 || self . cap . 0 == 0 {
104+ fn current_memory ( & self , elem_layout : Layout ) -> Option < ( NonNull < u8 > , Layout ) > {
105+ if elem_layout . size ( ) == 0 || self . cap . 0 == 0 {
154106 return None ;
155107 }
156108
@@ -159,21 +111,19 @@ impl<A: Allocator> MonoRawVec<A> {
159111 // has already been allocated so we know it can't overflow and currently Rust does not
160112 // support such types. So we can do better by skipping some checks and avoid an unwrap.
161113 unsafe {
162- let size = size. unchecked_mul ( self . cap . 0 ) ;
163- let layout = Layout :: from_size_align_unchecked ( size , align) ;
114+ let alloc_size = elem_layout . size ( ) . unchecked_mul ( self . cap . 0 ) ;
115+ let layout = Layout :: from_size_align_unchecked ( alloc_size , elem_layout . align ( ) ) ;
164116 Some ( ( self . ptr . into ( ) , layout) )
165117 }
166118 }
167119
168- #[ inline]
169120 fn grow_amortized (
170121 & mut self ,
171122 len : usize ,
172123 additional : usize ,
173- size : usize ,
174- align : usize ,
124+ elem_layout : Layout ,
175125 ) -> Result < ( ) , TryReserveError > {
176- if size == 0 {
126+ if elem_layout . size ( ) == 0 {
177127 // Since we return a capacity of `usize::MAX` when `elem_size` is
178128 // 0, getting to here necessarily means the `RawVec` is overfull.
179129 return Err ( CapacityOverflow . into ( ) ) ;
@@ -185,36 +135,34 @@ impl<A: Allocator> MonoRawVec<A> {
185135 // This guarantees exponential growth. The doubling cannot overflow
186136 // because `cap <= isize::MAX` and the type of `cap` is `usize`.
187137 let cap = cmp:: max ( self . cap . 0 * 2 , required_cap) ;
188- let cap = cmp:: max ( min_non_zero_cap ( size) , cap) ;
138+ let cap = cmp:: max ( min_non_zero_cap ( elem_layout . size ( ) ) , cap) ;
189139
190- let new_layout = layout_array ( cap, size , align ) ?;
140+ let new_layout = layout_array ( cap, elem_layout ) ?;
191141
192142 // `finish_grow` is non-generic over `T`.
193- let ptr = finish_grow ( new_layout, self . current_memory ( size , align ) , & mut self . alloc ) ?;
143+ let ptr = finish_grow ( new_layout, self . current_memory ( elem_layout ) , & mut self . alloc ) ?;
194144 // SAFETY: finish_grow would have resulted in a capacity overflow if we tried to allocate more than isize::MAX items
195145 unsafe { self . set_ptr_and_cap ( ptr, cap) } ;
196146 Ok ( ( ) )
197147 }
198148
199- #[ inline]
200149 fn grow_exact (
201150 & mut self ,
202151 len : usize ,
203152 additional : usize ,
204- size : usize ,
205- align : usize ,
153+ elem_layout : Layout ,
206154 ) -> Result < ( ) , TryReserveError > {
207- if size == 0 {
155+ if elem_layout . size ( ) == 0 {
208156 // Since we return a capacity of `usize::MAX` when the type size is
209157 // 0, getting to here necessarily means the `RawVec` is overfull.
210158 return Err ( CapacityOverflow . into ( ) ) ;
211159 }
212160
213161 let cap = len. checked_add ( additional) . ok_or ( CapacityOverflow ) ?;
214- let new_layout = layout_array ( cap, size , align ) ?;
162+ let new_layout = layout_array ( cap, elem_layout ) ?;
215163
216164 // `finish_grow` is non-generic over `T`.
217- let ptr = finish_grow ( new_layout, self . current_memory ( size , align ) , & mut self . alloc ) ?;
165+ let ptr = finish_grow ( new_layout, self . current_memory ( elem_layout ) , & mut self . alloc ) ?;
218166 // SAFETY: finish_grow would have resulted in a capacity overflow if we tried to allocate more than isize::MAX items
219167 unsafe {
220168 self . set_ptr_and_cap ( ptr, cap) ;
@@ -223,27 +171,27 @@ impl<A: Allocator> MonoRawVec<A> {
223171 }
224172
225173 #[ cfg( not( no_global_oom_handling) ) ]
226- #[ inline]
227- fn shrink ( & mut self , cap : usize , size : usize , align : usize ) -> Result < ( ) , TryReserveError > {
228- if size > 0 {
174+ fn shrink ( & mut self , cap : usize , elem_layout : Layout ) -> Result < ( ) , TryReserveError > {
175+ if elem_layout. size ( ) > 0 {
229176 assert ! ( cap <= self . cap. 0 , "Tried to shrink to a larger capacity" ) ;
230177 }
231178
232179 let ( ptr, layout) =
233- if let Some ( mem) = self . current_memory ( size , align ) { mem } else { return Ok ( ( ) ) } ;
180+ if let Some ( mem) = self . current_memory ( elem_layout ) { mem } else { return Ok ( ( ) ) } ;
234181
235182 // If shrinking to 0, deallocate the buffer. We don't reach this point
236183 // for the T::IS_ZST case since current_memory() will have returned
237184 // None.
238185 if cap == 0 {
239186 unsafe { self . alloc . deallocate ( ptr, layout) } ;
240- self . ptr = unsafe { Unique :: new_unchecked ( ptr:: without_provenance_mut ( align) ) } ;
187+ self . ptr =
188+ unsafe { Unique :: new_unchecked ( ptr:: without_provenance_mut ( elem_layout. align ( ) ) ) } ;
241189 self . cap = Cap :: ZERO ;
242190 } else {
243191 let ptr = unsafe {
244192 // `Layout::array` cannot overflow here because it would have
245193 // overflowed earlier when capacity was larger.
246- let new_size = size. unchecked_mul ( cap) ;
194+ let new_size = elem_layout . size ( ) . unchecked_mul ( cap) ;
247195 let new_layout = Layout :: from_size_align_unchecked ( new_size, layout. align ( ) ) ;
248196 self . alloc
249197 . shrink ( ptr, layout, new_layout)
@@ -264,21 +212,19 @@ impl<A: Allocator> MonoRawVec<A> {
264212 Self { ptr, cap : Cap :: ZERO , alloc }
265213 }
266214
267- #[ inline]
268215 fn try_allocate_in (
269216 capacity : usize ,
270217 init : AllocInit ,
271218 alloc : A ,
272- size : usize ,
273- align : usize ,
219+ elem_layout : Layout ,
274220 ) -> Result < Self , TryReserveError > {
275221 // Don't allocate here because `Drop` will not deallocate when `capacity` is 0.
276- if size == 0 || capacity == 0 {
277- Ok ( Self :: new_in ( alloc, align) )
222+ if elem_layout . size ( ) == 0 || capacity == 0 {
223+ Ok ( Self :: new_in ( alloc, elem_layout . align ( ) ) )
278224 } else {
279225 // We avoid `unwrap_or_else` here because it bloats the amount of
280226 // LLVM IR generated.
281- let layout = match layout_array ( capacity, size , align ) {
227+ let layout = match layout_array ( capacity, elem_layout ) {
282228 Ok ( layout) => layout,
283229 Err ( _) => return Err ( CapacityOverflow . into ( ) ) ,
284230 } ;
@@ -304,10 +250,8 @@ impl<A: Allocator> MonoRawVec<A> {
304250 }
305251 }
306252
307- #[ inline]
308- #[ rustc_no_mir_inline]
309- fn drop_if_needed ( & mut self , size : usize , align : usize ) {
310- if let Some ( ( ptr, layout) ) = self . current_memory ( size, align) {
253+ fn drop_if_needed ( & mut self , elem_layout : Layout ) {
254+ if let Some ( ( ptr, layout) ) = self . current_memory ( elem_layout) {
311255 unsafe { self . alloc . deallocate ( ptr, layout) }
312256 }
313257 }
@@ -449,13 +393,7 @@ impl<T, A: Allocator> RawVec<T, A> {
449393 init : AllocInit ,
450394 alloc : A ,
451395 ) -> Result < Self , TryReserveError > {
452- match MonoRawVec :: try_allocate_in (
453- capacity,
454- init,
455- alloc,
456- mem:: size_of :: < T > ( ) ,
457- mem:: align_of :: < T > ( ) ,
458- ) {
396+ match MonoRawVec :: try_allocate_in ( capacity, init, alloc, T :: LAYOUT ) {
459397 Ok ( inner) => Ok ( Self { inner, _phantom : PhantomData } ) ,
460398 Err ( e) => Err ( e) ,
461399 }
@@ -499,23 +437,24 @@ impl<T, A: Allocator> RawVec<T, A> {
499437 /// be careful.
500438 #[ inline]
501439 pub fn ptr ( & self ) -> * mut T {
502- self . inner . ptr ( )
440+ unsafe { core :: mem :: transmute ( self . inner . ptr ) }
503441 }
504442
505443 #[ inline]
506444 pub fn non_null ( & self ) -> NonNull < T > {
507- self . inner . non_null ( )
445+ unsafe { core :: mem :: transmute ( self . inner . ptr ) }
508446 }
509447
510448 /// Gets the capacity of the allocation.
511449 ///
512450 /// This will always be `usize::MAX` if `T` is zero-sized.
513- #[ inline( always ) ]
451+ #[ inline]
514452 pub fn capacity ( & self ) -> usize {
515453 if T :: IS_ZST { usize:: MAX } else { self . inner . cap . 0 }
516454 }
517455
518456 /// Returns a shared reference to the allocator backing this `RawVec`.
457+ #[ inline]
519458 pub fn allocator ( & self ) -> & A {
520459 & self . inner . alloc
521460 }
@@ -645,6 +584,7 @@ impl<T, A: Allocator> RawVec<T, A> {
645584impl < T , A : Allocator > RawVec < T , A > {
646585 /// Returns if the buffer needs to grow to fulfill the needed extra capacity.
647586 /// Mainly used to make inlining reserve-calls possible without inlining `grow`.
587+ #[ inline]
648588 fn needs_to_grow ( & self , len : usize , additional : usize ) -> bool {
649589 additional > self . capacity ( ) . wrapping_sub ( len)
650590 }
@@ -656,27 +596,25 @@ impl<T, A: Allocator> RawVec<T, A> {
656596 // so that all of the code that depends on `T` is within it, while as much
657597 // of the code that doesn't depend on `T` as possible is in functions that
658598 // are non-generic over `T`.
599+ #[ inline]
659600 fn grow_amortized ( & mut self , len : usize , additional : usize ) -> Result < ( ) , TryReserveError > {
660- const { assert ! ( mem:: size_of:: <T >( ) % mem:: align_of:: <T >( ) == 0 ) } ;
661-
662601 // This is ensured by the calling contexts.
663602 debug_assert ! ( additional > 0 ) ;
664603
665- self . inner . grow_amortized ( len, additional, mem :: size_of :: < T > ( ) , mem :: align_of :: < T > ( ) )
604+ self . inner . grow_amortized ( len, additional, T :: LAYOUT )
666605 }
667606
668607 // The constraints on this method are much the same as those on
669608 // `grow_amortized`, but this method is usually instantiated less often so
670609 // it's less critical.
610+ #[ inline]
671611 fn grow_exact ( & mut self , len : usize , additional : usize ) -> Result < ( ) , TryReserveError > {
672- const { assert ! ( mem:: size_of:: <T >( ) % mem:: align_of:: <T >( ) == 0 ) } ;
673- self . inner . grow_exact ( len, additional, mem:: size_of :: < T > ( ) , mem:: align_of :: < T > ( ) )
612+ self . inner . grow_exact ( len, additional, T :: LAYOUT )
674613 }
675614
676615 #[ cfg( not( no_global_oom_handling) ) ]
677616 fn shrink ( & mut self , cap : usize ) -> Result < ( ) , TryReserveError > {
678- const { assert ! ( mem:: size_of:: <T >( ) % mem:: align_of:: <T >( ) == 0 ) } ;
679- self . inner . shrink ( cap, mem:: size_of :: < T > ( ) , mem:: align_of :: < T > ( ) )
617+ self . inner . shrink ( cap, T :: LAYOUT )
680618 }
681619}
682620
@@ -712,8 +650,7 @@ where
712650unsafe impl < #[ may_dangle] T , A : Allocator > Drop for RawVec < T , A > {
713651 /// Frees the memory owned by the `RawVec` *without* trying to drop its contents.
714652 fn drop ( & mut self ) {
715- const { assert ! ( mem:: size_of:: <T >( ) % mem:: align_of:: <T >( ) == 0 ) } ;
716- self . inner . drop_if_needed ( mem:: size_of :: < T > ( ) , mem:: align_of :: < T > ( ) ) ;
653+ self . inner . drop_if_needed ( T :: LAYOUT ) ;
717654 }
718655}
719656
0 commit comments