Skip to content

Commit 32b53c9

Browse files
committed
Move into const impl blocks
1 parent dfcd270 commit 32b53c9

File tree

3 files changed

+255
-269
lines changed

3 files changed

+255
-269
lines changed

library/alloc/src/raw_vec/mod.rs

Lines changed: 148 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,32 @@ const fn min_non_zero_cap(size: usize) -> usize {
165165
}
166166
}
167167

168+
const impl<T, A: [const] Allocator + [const] Destruct> RawVec<T, A> {
169+
/// Like `with_capacity`, but parameterized over the choice of
170+
/// allocator for the returned `RawVec`.
171+
#[cfg(not(no_global_oom_handling))]
172+
#[inline]
173+
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
174+
pub(crate) fn with_capacity_in(capacity: usize, alloc: A) -> Self
175+
{
176+
Self {
177+
inner: RawVecInner::with_capacity_in(capacity, alloc, T::LAYOUT),
178+
_marker: PhantomData,
179+
}
180+
}
181+
182+
/// A specialized version of `self.reserve(len, 1)` which requires the
183+
/// caller to ensure `len == self.capacity()`.
184+
#[cfg(not(no_global_oom_handling))]
185+
#[inline(never)]
186+
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
187+
pub(crate) fn grow_one(&mut self)
188+
{
189+
// SAFETY: All calls on self.inner pass T::LAYOUT as the elem_layout
190+
unsafe { self.inner.grow_one(T::LAYOUT) }
191+
}
192+
}
193+
168194
impl<T, A: Allocator> RawVec<T, A> {
169195
#[cfg(not(no_global_oom_handling))]
170196
pub(crate) const MIN_NON_ZERO_CAP: usize = min_non_zero_cap(size_of::<T>());
@@ -178,21 +204,6 @@ impl<T, A: Allocator> RawVec<T, A> {
178204
Self { inner: RawVecInner::new_in(alloc, Alignment::of::<T>()), _marker: PhantomData }
179205
}
180206

181-
/// Like `with_capacity`, but parameterized over the choice of
182-
/// allocator for the returned `RawVec`.
183-
#[cfg(not(no_global_oom_handling))]
184-
#[inline]
185-
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
186-
pub(crate) const fn with_capacity_in(capacity: usize, alloc: A) -> Self
187-
where
188-
A: [const] Allocator + [const] Destruct,
189-
{
190-
Self {
191-
inner: RawVecInner::with_capacity_in(capacity, alloc, T::LAYOUT),
192-
_marker: PhantomData,
193-
}
194-
}
195-
196207
/// Like `try_with_capacity`, but parameterized over the choice of
197208
/// allocator for the returned `RawVec`.
198209
#[inline]
@@ -331,19 +342,6 @@ impl<T, A: Allocator> RawVec<T, A> {
331342
unsafe { self.inner.reserve(len, additional, T::LAYOUT) }
332343
}
333344

334-
/// A specialized version of `self.reserve(len, 1)` which requires the
335-
/// caller to ensure `len == self.capacity()`.
336-
#[cfg(not(no_global_oom_handling))]
337-
#[inline(never)]
338-
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
339-
pub(crate) const fn grow_one(&mut self)
340-
where
341-
A: [const] Allocator,
342-
{
343-
// SAFETY: All calls on self.inner pass T::LAYOUT as the elem_layout
344-
unsafe { self.inner.grow_one(T::LAYOUT) }
345-
}
346-
347345
/// The same as `reserve`, but returns on errors instead of panicking or aborting.
348346
pub(crate) fn try_reserve(
349347
&mut self,
@@ -413,20 +411,11 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec<T, A> {
413411
}
414412
}
415413

416-
impl<A: Allocator> RawVecInner<A> {
417-
#[inline]
418-
const fn new_in(alloc: A, align: Alignment) -> Self {
419-
let ptr = Unique::from_non_null(NonNull::without_provenance(align.as_nonzero()));
420-
// `cap: 0` means "unallocated". zero-sized types are ignored.
421-
Self { ptr, cap: ZERO_CAP, alloc }
422-
}
423-
414+
const impl<A: [const] Allocator + [const] Destruct> RawVecInner<A> {
424415
#[cfg(not(no_global_oom_handling))]
425416
#[inline]
426417
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
427-
const fn with_capacity_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self
428-
where
429-
A: [const] Allocator + [const] Destruct,
418+
fn with_capacity_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self
430419
{
431420
match Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc, elem_layout) {
432421
Ok(this) => {
@@ -439,34 +428,13 @@ impl<A: Allocator> RawVecInner<A> {
439428
Err(err) => handle_error(err),
440429
}
441430
}
442-
443-
#[inline]
444-
fn try_with_capacity_in(
445-
capacity: usize,
446-
alloc: A,
447-
elem_layout: Layout,
448-
) -> Result<Self, TryReserveError> {
449-
Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc, elem_layout)
450-
}
451-
452-
#[cfg(not(no_global_oom_handling))]
453-
#[inline]
454-
fn with_capacity_zeroed_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self {
455-
match Self::try_allocate_in(capacity, AllocInit::Zeroed, alloc, elem_layout) {
456-
Ok(res) => res,
457-
Err(err) => handle_error(err),
458-
}
459-
}
460-
461431
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
462-
const fn try_allocate_in(
432+
fn try_allocate_in(
463433
capacity: usize,
464434
init: AllocInit,
465435
alloc: A,
466436
elem_layout: Layout,
467437
) -> Result<Self, TryReserveError>
468-
where
469-
A: [const] Allocator + [const] Destruct,
470438
{
471439
// We avoid `unwrap_or_else` here because it bloats the amount of
472440
// LLVM IR generated.
@@ -500,6 +468,125 @@ impl<A: Allocator> RawVecInner<A> {
500468
})
501469
}
502470

471+
/// # Safety
472+
/// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to
473+
/// initially construct `self`
474+
/// - `elem_layout`'s size must be a multiple of its alignment
475+
#[cfg(not(no_global_oom_handling))]
476+
#[inline]
477+
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
478+
unsafe fn grow_one(&mut self, elem_layout: Layout)
479+
{
480+
// SAFETY: Precondition passed to caller
481+
if let Err(err) = unsafe { self.grow_amortized(self.cap.as_inner(), 1, elem_layout) } {
482+
handle_error(err);
483+
}
484+
}
485+
486+
487+
/// # Safety
488+
/// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to
489+
/// initially construct `self`
490+
/// - `elem_layout`'s size must be a multiple of its alignment
491+
/// - The sum of `len` and `additional` must be greater than the current capacity
492+
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
493+
unsafe fn grow_amortized(
494+
&mut self,
495+
len: usize,
496+
additional: usize,
497+
elem_layout: Layout,
498+
) -> Result<(), TryReserveError>
499+
{
500+
// This is ensured by the calling contexts.
501+
debug_assert!(additional > 0);
502+
503+
if elem_layout.size() == 0 {
504+
// Since we return a capacity of `usize::MAX` when `elem_size` is
505+
// 0, getting to here necessarily means the `RawVec` is overfull.
506+
return Err(CapacityOverflow.into());
507+
}
508+
509+
// Nothing we can really do about these checks, sadly.
510+
let required_cap = len.checked_add(additional).ok_or(CapacityOverflow)?;
511+
512+
// This guarantees exponential growth. The doubling cannot overflow
513+
// because `cap <= isize::MAX` and the type of `cap` is `usize`.
514+
let cap = cmp::max(self.cap.as_inner() * 2, required_cap);
515+
let cap = cmp::max(min_non_zero_cap(elem_layout.size()), cap);
516+
517+
// SAFETY:
518+
// - cap >= len + additional
519+
// - other preconditions passed to caller
520+
let ptr = unsafe { self.finish_grow(cap, elem_layout)? };
521+
522+
// SAFETY: `finish_grow` would have failed if `cap > isize::MAX`
523+
unsafe { self.set_ptr_and_cap(ptr, cap) };
524+
Ok(())
525+
}
526+
527+
/// # Safety
528+
/// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to
529+
/// initially construct `self`
530+
/// - `elem_layout`'s size must be a multiple of its alignment
531+
/// - `cap` must be greater than the current capacity
532+
// not marked inline(never) since we want optimizers to be able to observe the specifics of this
533+
// function, see tests/codegen-llvm/vec-reserve-extend.rs.
534+
#[cold]
535+
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
536+
unsafe fn finish_grow(
537+
&self,
538+
cap: usize,
539+
elem_layout: Layout,
540+
) -> Result<NonNull<[u8]>, TryReserveError>
541+
{
542+
let new_layout = layout_array(cap, elem_layout)?;
543+
544+
let memory = if let Some((ptr, old_layout)) = unsafe { self.current_memory(elem_layout) } {
545+
// FIXME(const-hack): switch to `debug_assert_eq`
546+
debug_assert!(old_layout.align() == new_layout.align());
547+
unsafe {
548+
// The allocator checks for alignment equality
549+
hint::assert_unchecked(old_layout.align() == new_layout.align());
550+
self.alloc.grow(ptr, old_layout, new_layout)
551+
}
552+
} else {
553+
self.alloc.allocate(new_layout)
554+
};
555+
556+
// FIXME(const-hack): switch back to `map_err`
557+
match memory {
558+
Ok(memory) => Ok(memory),
559+
Err(_) => Err(AllocError { layout: new_layout, non_exhaustive: () }.into()),
560+
}
561+
}
562+
}
563+
564+
impl<A: Allocator> RawVecInner<A> {
565+
#[inline]
566+
const fn new_in(alloc: A, align: Alignment) -> Self {
567+
let ptr = Unique::from_non_null(NonNull::without_provenance(align.as_nonzero()));
568+
// `cap: 0` means "unallocated". zero-sized types are ignored.
569+
Self { ptr, cap: ZERO_CAP, alloc }
570+
}
571+
572+
#[inline]
573+
fn try_with_capacity_in(
574+
capacity: usize,
575+
alloc: A,
576+
elem_layout: Layout,
577+
) -> Result<Self, TryReserveError> {
578+
Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc, elem_layout)
579+
}
580+
581+
#[cfg(not(no_global_oom_handling))]
582+
#[inline]
583+
fn with_capacity_zeroed_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self {
584+
match Self::try_allocate_in(capacity, AllocInit::Zeroed, alloc, elem_layout) {
585+
Ok(res) => res,
586+
Err(err) => handle_error(err),
587+
}
588+
}
589+
503590
#[inline]
504591
unsafe fn from_raw_parts_in(ptr: *mut u8, cap: Cap, alloc: A) -> Self {
505592
Self { ptr: unsafe { Unique::new_unchecked(ptr) }, cap, alloc }
@@ -583,23 +670,6 @@ impl<A: Allocator> RawVecInner<A> {
583670
}
584671
}
585672

586-
/// # Safety
587-
/// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to
588-
/// initially construct `self`
589-
/// - `elem_layout`'s size must be a multiple of its alignment
590-
#[cfg(not(no_global_oom_handling))]
591-
#[inline]
592-
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
593-
const unsafe fn grow_one(&mut self, elem_layout: Layout)
594-
where
595-
A: [const] Allocator,
596-
{
597-
// SAFETY: Precondition passed to caller
598-
if let Err(err) = unsafe { self.grow_amortized(self.cap.as_inner(), 1, elem_layout) } {
599-
handle_error(err);
600-
}
601-
}
602-
603673
/// # Safety
604674
/// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to
605675
/// initially construct `self`
@@ -686,48 +756,6 @@ impl<A: Allocator> RawVecInner<A> {
686756
self.cap = unsafe { Cap::new_unchecked(cap) };
687757
}
688758

689-
/// # Safety
690-
/// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to
691-
/// initially construct `self`
692-
/// - `elem_layout`'s size must be a multiple of its alignment
693-
/// - The sum of `len` and `additional` must be greater than the current capacity
694-
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
695-
const unsafe fn grow_amortized(
696-
&mut self,
697-
len: usize,
698-
additional: usize,
699-
elem_layout: Layout,
700-
) -> Result<(), TryReserveError>
701-
where
702-
A: [const] Allocator,
703-
{
704-
// This is ensured by the calling contexts.
705-
debug_assert!(additional > 0);
706-
707-
if elem_layout.size() == 0 {
708-
// Since we return a capacity of `usize::MAX` when `elem_size` is
709-
// 0, getting to here necessarily means the `RawVec` is overfull.
710-
return Err(CapacityOverflow.into());
711-
}
712-
713-
// Nothing we can really do about these checks, sadly.
714-
let required_cap = len.checked_add(additional).ok_or(CapacityOverflow)?;
715-
716-
// This guarantees exponential growth. The doubling cannot overflow
717-
// because `cap <= isize::MAX` and the type of `cap` is `usize`.
718-
let cap = cmp::max(self.cap.as_inner() * 2, required_cap);
719-
let cap = cmp::max(min_non_zero_cap(elem_layout.size()), cap);
720-
721-
// SAFETY:
722-
// - cap >= len + additional
723-
// - other preconditions passed to caller
724-
let ptr = unsafe { self.finish_grow(cap, elem_layout)? };
725-
726-
// SAFETY: `finish_grow` would have failed if `cap > isize::MAX`
727-
unsafe { self.set_ptr_and_cap(ptr, cap) };
728-
Ok(())
729-
}
730-
731759
/// # Safety
732760
/// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to
733761
/// initially construct `self`
@@ -755,44 +783,6 @@ impl<A: Allocator> RawVecInner<A> {
755783
Ok(())
756784
}
757785

758-
/// # Safety
759-
/// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to
760-
/// initially construct `self`
761-
/// - `elem_layout`'s size must be a multiple of its alignment
762-
/// - `cap` must be greater than the current capacity
763-
// not marked inline(never) since we want optimizers to be able to observe the specifics of this
764-
// function, see tests/codegen-llvm/vec-reserve-extend.rs.
765-
#[cold]
766-
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
767-
const unsafe fn finish_grow(
768-
&self,
769-
cap: usize,
770-
elem_layout: Layout,
771-
) -> Result<NonNull<[u8]>, TryReserveError>
772-
where
773-
A: [const] Allocator,
774-
{
775-
let new_layout = layout_array(cap, elem_layout)?;
776-
777-
let memory = if let Some((ptr, old_layout)) = unsafe { self.current_memory(elem_layout) } {
778-
// FIXME(const-hack): switch to `debug_assert_eq`
779-
debug_assert!(old_layout.align() == new_layout.align());
780-
unsafe {
781-
// The allocator checks for alignment equality
782-
hint::assert_unchecked(old_layout.align() == new_layout.align());
783-
self.alloc.grow(ptr, old_layout, new_layout)
784-
}
785-
} else {
786-
self.alloc.allocate(new_layout)
787-
};
788-
789-
// FIXME(const-hack): switch back to `map_err`
790-
match memory {
791-
Ok(memory) => Ok(memory),
792-
Err(_) => Err(AllocError { layout: new_layout, non_exhaustive: () }.into()),
793-
}
794-
}
795-
796786
/// # Safety
797787
/// - `elem_layout` must be valid for `self`, i.e. it must be the same `elem_layout` used to
798788
/// initially construct `self`

0 commit comments

Comments
 (0)