@@ -33,21 +33,15 @@ enum AllocInit {
3333 Zeroed,
3434}
3535
36- #[repr(transparent)]
37- #[cfg_attr(target_pointer_width = "16", rustc_layout_scalar_valid_range_end(0x7fff))]
38- #[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0x7fff_ffff))]
39- #[cfg_attr(target_pointer_width = "64", rustc_layout_scalar_valid_range_end(0x7fff_ffff_ffff_ffff))]
40- struct Cap(usize);
36+ type Cap = core::num::niche_types::UsizeNoHighBit;
4137
42- impl Cap {
43- const ZERO: Cap = unsafe { Cap(0) };
38+ const ZERO_CAP: Cap = unsafe { Cap::new_unchecked(0) };
4439
45- /// `Cap(cap)`, except if `T` is a ZST then `Cap::ZERO`.
46- ///
47- /// # Safety: cap must be <= `isize::MAX`.
48- unsafe fn new<T>(cap: usize) -> Self {
49- if T::IS_ZST { Cap::ZERO } else { unsafe { Self(cap) } }
50- }
40+ /// `Cap(cap)`, except if `T` is a ZST then `Cap::ZERO`.
41+ ///
42+ /// # Safety: cap must be <= `isize::MAX`.
43+ unsafe fn new_cap<T>(cap: usize) -> Cap {
44+ if T::IS_ZST { ZERO_CAP } else { unsafe { Cap::new_unchecked(cap) } }
5145}
5246
5347/// A low-level utility for more ergonomically allocating, reallocating, and deallocating
@@ -257,7 +251,7 @@ impl<T, A: Allocator> RawVec<T, A> {
257251 // SAFETY: Precondition passed to the caller
258252 unsafe {
259253 let ptr = ptr.cast();
260- let capacity = Cap::new ::<T>(capacity);
254+ let capacity = new_cap ::<T>(capacity);
261255 Self {
262256 inner: RawVecInner::from_raw_parts_in(ptr, capacity, alloc),
263257 _marker: PhantomData,
@@ -275,7 +269,7 @@ impl<T, A: Allocator> RawVec<T, A> {
275269 // SAFETY: Precondition passed to the caller
276270 unsafe {
277271 let ptr = ptr.cast();
278- let capacity = Cap::new ::<T>(capacity);
272+ let capacity = new_cap ::<T>(capacity);
279273 Self { inner: RawVecInner::from_nonnull_in(ptr, capacity, alloc), _marker: PhantomData }
280274 }
281275 }
@@ -410,7 +404,7 @@ impl<A: Allocator> RawVecInner<A> {
410404 const fn new_in(alloc: A, align: usize) -> Self {
411405 let ptr = unsafe { core::mem::transmute(align) };
412406 // `cap: 0` means "unallocated". zero-sized types are ignored.
413- Self { ptr, cap: Cap::ZERO , alloc }
407+ Self { ptr, cap: ZERO_CAP , alloc }
414408 }
415409
416410 #[cfg(not(no_global_oom_handling))]
@@ -483,7 +477,11 @@ impl<A: Allocator> RawVecInner<A> {
483477 // Allocators currently return a `NonNull<[u8]>` whose length
484478 // matches the size requested. If that ever changes, the capacity
485479 // here should change to `ptr.len() / mem::size_of::<T>()`.
486- Ok(Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc })
480+ Ok(Self {
481+ ptr: Unique::from(ptr.cast()),
482+ cap: unsafe { Cap::new_unchecked(capacity) },
483+ alloc,
484+ })
487485 }
488486
489487 #[inline]
@@ -508,7 +506,7 @@ impl<A: Allocator> RawVecInner<A> {
508506
509507 #[inline]
510508 const fn capacity(&self, elem_size: usize) -> usize {
511- if elem_size == 0 { usize::MAX } else { self.cap.0 }
509+ if elem_size == 0 { usize::MAX } else { self.cap.as_inner() }
512510 }
513511
514512 #[inline]
@@ -518,15 +516,15 @@ impl<A: Allocator> RawVecInner<A> {
518516
519517 #[inline]
520518 fn current_memory(&self, elem_layout: Layout) -> Option<(NonNull<u8>, Layout)> {
521- if elem_layout.size() == 0 || self.cap.0 == 0 {
519+ if elem_layout.size() == 0 || self.cap.as_inner() == 0 {
522520 None
523521 } else {
524522 // We could use Layout::array here which ensures the absence of isize and usize overflows
525523 // and could hypothetically handle differences between stride and size, but this memory
526524 // has already been allocated so we know it can't overflow and currently Rust does not
527525 // support such types. So we can do better by skipping some checks and avoid an unwrap.
528526 unsafe {
529- let alloc_size = elem_layout.size().unchecked_mul(self.cap.0 );
527+ let alloc_size = elem_layout.size().unchecked_mul(self.cap.as_inner() );
530528 let layout = Layout::from_size_align_unchecked(alloc_size, elem_layout.align());
531529 Some((self.ptr.into(), layout))
532530 }
@@ -562,7 +560,7 @@ impl<A: Allocator> RawVecInner<A> {
562560 #[inline]
563561 #[track_caller]
564562 fn grow_one(&mut self, elem_layout: Layout) {
565- if let Err(err) = self.grow_amortized(self.cap.0 , 1, elem_layout) {
563+ if let Err(err) = self.grow_amortized(self.cap.as_inner() , 1, elem_layout) {
566564 handle_error(err);
567565 }
568566 }
@@ -627,7 +625,7 @@ impl<A: Allocator> RawVecInner<A> {
627625 // the size requested. If that ever changes, the capacity here should
628626 // change to `ptr.len() / mem::size_of::<T>()`.
629627 self.ptr = Unique::from(ptr.cast());
630- self.cap = unsafe { Cap(cap) };
628+ self.cap = unsafe { Cap::new_unchecked (cap) };
631629 }
632630
633631 fn grow_amortized(
@@ -650,7 +648,7 @@ impl<A: Allocator> RawVecInner<A> {
650648
651649 // This guarantees exponential growth. The doubling cannot overflow
652650 // because `cap <= isize::MAX` and the type of `cap` is `usize`.
653- let cap = cmp::max(self.cap.0 * 2, required_cap);
651+ let cap = cmp::max(self.cap.as_inner() * 2, required_cap);
654652 let cap = cmp::max(min_non_zero_cap(elem_layout.size()), cap);
655653
656654 let new_layout = layout_array(cap, elem_layout)?;
@@ -719,7 +717,7 @@ impl<A: Allocator> RawVecInner<A> {
719717 unsafe { self.alloc.deallocate(ptr, layout) };
720718 self.ptr =
721719 unsafe { Unique::new_unchecked(ptr::without_provenance_mut(elem_layout.align())) };
722- self.cap = Cap::ZERO ;
720+ self.cap = ZERO_CAP ;
723721 } else {
724722 let ptr = unsafe {
725723 // Layout cannot overflow here because it would have
0 commit comments