@@ -33,11 +33,33 @@ enum AllocInit {
3333 Zeroed ,
3434}
3535
36+ pub trait CapacityHolder : Copy {
37+ fn as_usize < T > ( self ) -> usize {
38+ if T :: IS_ZST {
39+ usize:: MAX
40+ } else {
41+ Self :: as_usize_raw ( self )
42+ }
43+ }
44+ fn as_usize_raw ( c : Self ) -> usize ;
45+ }
46+
47+ #[ derive( Copy , Clone ) ]
48+ pub struct FixedCapacity < const N : usize > ;
49+ impl < const N : usize > CapacityHolder for FixedCapacity < N > {
50+ fn as_usize_raw ( _: Self ) -> usize { N }
51+ }
52+
3653#[ repr( transparent) ]
54+ #[ derive( Copy , Clone ) ]
3755#[ cfg_attr( target_pointer_width = "16" , rustc_layout_scalar_valid_range_end( 0x7fff ) ) ]
3856#[ cfg_attr( target_pointer_width = "32" , rustc_layout_scalar_valid_range_end( 0x7fff_ffff ) ) ]
3957#[ cfg_attr( target_pointer_width = "64" , rustc_layout_scalar_valid_range_end( 0x7fff_ffff_ffff_ffff ) ) ]
40- struct Cap ( usize ) ;
58+ pub ( crate ) struct Cap ( usize ) ;
59+
60+ impl CapacityHolder for Cap {
61+ fn as_usize_raw ( c : Self ) -> usize { c. 0 }
62+ }
4163
4264impl Cap {
4365 const ZERO : Cap = unsafe { Cap ( 0 ) } ;
@@ -66,14 +88,9 @@ impl Cap {
6688/// `usize::MAX`. This means that you need to be careful when round-tripping this type with a
6789/// `Box<[T]>`, since `capacity()` won't yield the length.
6890#[ allow( missing_debug_implementations) ]
69- pub ( crate ) struct RawVec < T , A : Allocator = Global > {
91+ pub ( crate ) struct RawVec < T , A : Allocator = Global , C : CapacityHolder = Cap > {
7092 ptr : Unique < T > ,
71- /// Never used for ZSTs; it's `capacity()`'s responsibility to return usize::MAX in that case.
72- ///
73- /// # Safety
74- ///
75- /// `cap` must be in the `0..=isize::MAX` range.
76- cap : Cap ,
93+ cap : C ,
7794 alloc : A ,
7895}
7996
@@ -129,6 +146,27 @@ impl<T> RawVec<T, Global> {
129146 }
130147}
131148
149+ impl < T , A : Allocator , C : CapacityHolder > RawVec < T , A , C > {
150+ fn current_memory ( & self ) -> Option < ( NonNull < u8 > , Layout ) > {
151+ let cap = self . cap . as_usize :: < T > ( ) ;
152+ if T :: IS_ZST || cap == 0 {
153+ None
154+ } else {
155+ // We could use Layout::array here which ensures the absence of isize and usize overflows
156+ // and could hypothetically handle differences between stride and size, but this memory
157+ // has already been allocated so we know it can't overflow and currently Rust does not
158+ // support such types. So we can do better by skipping some checks and avoid an unwrap.
159+ const { assert ! ( mem:: size_of:: <T >( ) % mem:: align_of:: <T >( ) == 0 ) } ;
160+ unsafe {
161+ let align = mem:: align_of :: < T > ( ) ;
162+ let size = mem:: size_of :: < T > ( ) . unchecked_mul ( cap) ;
163+ let layout = Layout :: from_size_align_unchecked ( size, align) ;
164+ Some ( ( self . ptr . cast ( ) . into ( ) , layout) )
165+ }
166+ }
167+ }
168+ }
169+
132170impl < T , A : Allocator > RawVec < T , A > {
133171 // Tiny Vecs are dumb. Skip to:
134172 // - 8 if the element size is 1, because any heap allocators is likely
@@ -296,24 +334,6 @@ impl<T, A: Allocator> RawVec<T, A> {
296334 & self . alloc
297335 }
298336
299- fn current_memory ( & self ) -> Option < ( NonNull < u8 > , Layout ) > {
300- if T :: IS_ZST || self . cap . 0 == 0 {
301- None
302- } else {
303- // We could use Layout::array here which ensures the absence of isize and usize overflows
304- // and could hypothetically handle differences between stride and size, but this memory
305- // has already been allocated so we know it can't overflow and currently Rust does not
306- // support such types. So we can do better by skipping some checks and avoid an unwrap.
307- const { assert ! ( mem:: size_of:: <T >( ) % mem:: align_of:: <T >( ) == 0 ) } ;
308- unsafe {
309- let align = mem:: align_of :: < T > ( ) ;
310- let size = mem:: size_of :: < T > ( ) . unchecked_mul ( self . cap . 0 ) ;
311- let layout = Layout :: from_size_align_unchecked ( size, align) ;
312- Some ( ( self . ptr . cast ( ) . into ( ) , layout) )
313- }
314- }
315- }
316-
317337 /// Ensures that the buffer contains at least enough space to hold `len +
318338 /// additional` elements. If it doesn't already have enough capacity, will
319339 /// reallocate enough space plus comfortable slack space to get amortized
@@ -576,7 +596,7 @@ where
576596 memory. map_err ( |_| AllocError { layout : new_layout, non_exhaustive : ( ) } . into ( ) )
577597}
578598
579- unsafe impl < #[ may_dangle] T , A : Allocator > Drop for RawVec < T , A > {
599+ unsafe impl < #[ may_dangle] T , A : Allocator , C : CapacityHolder > Drop for RawVec < T , A , C > {
580600 /// Frees the memory owned by the `RawVec` *without* trying to drop its contents.
581601 fn drop ( & mut self ) {
582602 if let Some ( ( ptr, layout) ) = self . current_memory ( ) {
0 commit comments