From 1724501193e9611f2ac05941d2557d43f59be900 Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Fri, 14 Aug 2026 23:15:12 +0200 Subject: [PATCH 1/6] allocator: wording & grammar nitpicks ref mut const unstable matching ref vec, vecdeque: rename alloc to allocator staticallocator on ref mut as well wording will be the death of me words order words random word words random good eeeeeeeeeeeee oh yeah these need the bound --- .../alloc/src/collections/vec_deque/mod.rs | 2 +- library/alloc/src/rc.rs | 6 +- library/alloc/src/sync.rs | 4 +- library/alloc/src/vec/mod.rs | 16 ++-- library/core/src/alloc/mod.rs | 79 +++++++++++-------- tests/ui/allocator/157089-box-pin-in.stderr | 3 + .../ui/allocator/159445-unsize-pin-box.stderr | 3 + 7 files changed, 67 insertions(+), 46 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 940fce7377938..5f1fd39bbbc3b 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -3991,7 +3991,7 @@ impl From> for VecDeque { /// any additional memory. #[inline] fn from(other: Vec) -> Self { - let (ptr, len, cap, alloc) = other.into_raw_parts_with_alloc(); + let (ptr, len, cap, alloc) = other.into_raw_parts_with_allocator(); Self { head: WrappedIndex::zero(), len, diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index e639a32370703..689f015d586b0 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2983,7 +2983,7 @@ impl From for Rc { #[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] -impl From> for Rc { +impl From> for Rc { /// Move a boxed object to a new, reference counted, allocation. /// /// # Example @@ -3002,7 +3002,7 @@ impl From> for Rc { #[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] -impl From> for Rc<[T], A> { +impl From> for Rc<[T], A> { /// Allocates a reference-counted slice and moves `v`'s items into it. /// /// # Example @@ -3016,7 +3016,7 @@ impl From> for Rc<[T], A> { #[inline] fn from(v: Vec) -> Rc<[T], A> { unsafe { - let (vec_ptr, len, cap, alloc) = v.into_raw_parts_with_alloc(); + let (vec_ptr, len, cap, alloc) = v.into_raw_parts_with_allocator(); let rc_ptr = Self::allocate_for_slice_in(len, &alloc); ptr::copy_nonoverlapping(vec_ptr, (&raw mut (*rc_ptr).value) as *mut T, len); diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 5ea0fd3a394d4..fd4a630422011 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -4050,7 +4050,7 @@ impl From for Arc { #[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] -impl From> for Arc { +impl From> for Arc { /// Move a boxed object to a new, reference-counted allocation. /// /// # Example @@ -4083,7 +4083,7 @@ impl From> for Arc<[T], A> { #[inline] fn from(v: Vec) -> Arc<[T], A> { unsafe { - let (vec_ptr, len, cap, alloc) = v.into_raw_parts_with_alloc(); + let (vec_ptr, len, cap, alloc) = v.into_raw_parts_with_allocator(); let rc_ptr = Self::allocate_for_slice_in(len, &alloc); ptr::copy_nonoverlapping(vec_ptr, (&raw mut (*rc_ptr).data) as *mut T, len); diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index a619aa6e5427b..698379b96a696 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1140,7 +1140,7 @@ impl Vec { /// v.push(3); /// /// // Deconstruct the vector into parts. - /// let (p, len, cap, alloc) = v.into_raw_parts_with_alloc(); + /// let (p, len, cap, alloc) = v.into_raw_parts_with_allocator(); /// /// unsafe { /// // Overwrite memory with 4, 5, 6 @@ -1337,7 +1337,7 @@ impl Vec { /// v.push(0); /// v.push(1); /// - /// let (ptr, len, cap, alloc) = v.into_raw_parts_with_alloc(); + /// let (ptr, len, cap, alloc) = v.into_raw_parts_with_allocator(); /// /// let rebuilt = unsafe { /// // We can now make changes to the components, such as @@ -1351,7 +1351,7 @@ impl Vec { #[must_use = "losing the pointer will leak memory"] #[unstable(feature = "allocator_api", issue = "32838")] #[rustc_const_unstable(feature = "allocator_api", issue = "32838")] - pub const fn into_raw_parts_with_alloc(self) -> (*mut T, usize, usize, A) { + pub const fn into_raw_parts_with_allocator(self) -> (*mut T, usize, usize, A) { let mut me = ManuallyDrop::new(self); let len = me.len(); let capacity = me.capacity(); @@ -1402,7 +1402,7 @@ impl Vec { #[unstable(feature = "allocator_api", issue = "32838")] #[rustc_const_unstable(feature = "allocator_api", issue = "32838")] pub const fn into_parts_with_alloc(self) -> (NonNull, usize, usize, A) { - let (ptr, len, capacity, alloc) = self.into_raw_parts_with_alloc(); + let (ptr, len, capacity, alloc) = self.into_raw_parts_with_allocator(); // SAFETY: A `Vec` always has a non-null pointer. (unsafe { NonNull::new_unchecked(ptr) }, len, capacity, alloc) } @@ -3439,10 +3439,10 @@ impl Vec { self.buf.shrink_to_fit(cap - cap_remainder); } - let (ptr, _, _, alloc) = self.into_raw_parts_with_alloc(); + let (ptr, _, _, alloc) = self.into_raw_parts_with_allocator(); // SAFETY: - // - `ptr` and `alloc` were just returned from `self.into_raw_parts_with_alloc()` + // - `ptr` and `alloc` were just returned from `self.into_raw_parts_with_allocator()` // - `[T; N]` has the same alignment as `T` // - `size_of::<[T; N]>() * cap / N == size_of::() * cap` // - `len / N <= cap / N` because `len <= cap` @@ -3515,7 +3515,7 @@ impl Vec { let (ptr, length, capacity, alloc) = self.into_parts_with_alloc(); debug_assert_eq!(length, 0); // SAFETY: - // - `ptr` and `alloc` were just returned from `self.into_raw_parts_with_alloc()` + // - `ptr` and `alloc` were just returned from `self.into_raw_parts_with_allocator()` // - `T` & `U` have the same layout, so `capacity` does not need to be changed and we can safely use `alloc.dealloc` later // - the original vector was cleared, so there is no problem with "transmuting" the stored values unsafe { Vec::from_parts_in(ptr.cast::(), length, capacity, alloc) } @@ -3686,7 +3686,7 @@ impl Vec<[T; N], A> { /// ``` #[stable(feature = "slice_flatten", since = "1.80.0")] pub fn into_flattened(self) -> Vec { - let (ptr, len, cap, alloc) = self.into_raw_parts_with_alloc(); + let (ptr, len, cap, alloc) = self.into_raw_parts_with_allocator(); let (new_len, new_cap) = if T::IS_ZST { (len.checked_mul(N).expect("vec len overflow"), usize::MAX) } else { diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 7816709ac4663..5fed1fae2a2d2 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -49,21 +49,27 @@ impl fmt::Display for AllocError { /// An implementation of `Allocator` can allocate, grow, shrink, and deallocate arbitrary blocks of /// data described via [`Layout`][]. /// -/// `Allocator` is designed to be implemented on ZSTs, references, or smart pointers. -/// An allocator for `MyAlloc([u8; N])` cannot be moved, without updating the pointers to the -/// allocated memory. +/// `Allocator` is mostly designed to be implemented on ZSTs, references, or smart pointers, +/// but can also be implemented directly on the underlying memory-owning type so long as it +/// upholds the necessary guarantees. In general, an allocator for `MyAlloc([u8; N])` cannot be +/// moved, without updating the pointers to the allocated memory. /// /// In contrast to [`GlobalAlloc`][], `Allocator` allows zero-sized allocations. If an underlying /// allocator does not support this (like jemalloc) or responds by returning a null pointer /// (such as `libc::malloc`), this must be caught by the implementation. /// +/// In order to be usable in a flexible manner while still being sound, implementors of the trait +/// must uphold very detailed semantics as explained below; the following terms are thus provided +/// as vocabulary for allocator safety and implementation requirements: +/// /// ### Equivalent allocators /// /// Multiple allocator values can sometimes be interchangeable with each other. /// When this is the case, we refer to those allocators as being *equivalent* to /// each other. /// -/// The following conditions are sufficient conditions for allocators to be equivalent. +/// Users of allocators may assume the following are true of equivalent allocators, +/// and implementors must ensure these rules are upheld: /// * An allocator is equivalent to itself. (Equivalence is reflexive.) /// * If an allocator is equivalent to a second allocator, then /// the second allocator is also equivalent to the first. (Equivalence is symmetric.) @@ -73,9 +79,8 @@ impl fmt::Display for AllocError { /// (Equivalence is transitive.) /// * Moving, subtyping, unsize-coercing, or trait-upcasting an allocator does not change /// what the allocator is equivalent to. -/// * Copying or cloning allocator results in an allocator that's -/// equivalent to the initial allocator, should the [`AllocatorClone`] trait -/// be implemented. +/// * Copying or cloning an allocator creates an equivalent one, should the +/// [`AllocatorClone`] trait be implemented. /// /// Additionally, implementors of `Allocator` may specify additional equivalences /// between allocators. It is the responsibility of such implementors to make sure @@ -104,14 +109,14 @@ impl fmt::Display for AllocError { /// * The memory block is deallocated. This occurs when the memory block /// is passed as an argument to a [`deallocate`] call, or when it is passed /// as an argument to a [`grow`], [`grow_zeroed`] or [`shrink`] call that returns `Ok`. -/// * All (equivalent) allocators that this memory block is allocated with, -/// each has one of the following happen to them: +/// * For all (equivalent) allocators that this memory block is currently allocated by, at +/// least one of the following has occurred: /// * The allocator's destructor runs. -/// * The allocator is mutated through public API taking `&mut` access. +/// * The allocator is mutated through a public or otherwise untrusted API taking `&mut` access. /// * One of the borrow-checker lifetimes in the allocator's type expires. /// /// Note that these conditions imply that a collection may ensure that -/// any specific currently allocated memory block won't be invalidated, by: +/// any specific currently allocated memory block won't be invalidated by: /// * not deallocating that memory block, /// * owning an allocator that memory block is allocated with, and /// * not publicly exposing `&mut` access to that allocator. @@ -120,11 +125,11 @@ impl fmt::Display for AllocError { /// allowed to invalidate its memory blocks. Furthermore, unsafe public API /// of an allocator with `&` access must document that they invalidate /// memory blocks (e.g., by calling `deallocate`) if they do. Therefore, -/// collections may safely expose `&` access to its allocator. +/// a collection may safely expose `&` access to its allocator. /// -/// Also note that, even in cases where are other "alive" allocators known to be -/// equivalent to a given collection's allocator, most collections still should -/// not publicly expose `&mut` access to its allocator. The fact that there are +/// Also note that, even in cases where there are other "alive" allocators known +/// to be equivalent to a given collection's allocator, most collections still should +/// not publicly expose `&mut` access to their allocators. The fact that there are /// other "alive" allocators would prevent this `&mut` access from invalidating /// the collection's memory block, but public `&mut` access is still likely to /// be unsound, since a user could replace the collection's allocator with @@ -140,8 +145,8 @@ impl fmt::Display for AllocError { /// /// ### Memory fitting /// -/// Some of the methods require that a `layout` *fit* a memory block or vice versa. This means that the -/// following conditions must hold: +/// Some of the methods require that a `layout` *fits* a memory block or vice versa. This means +/// that the following conditions must hold: /// * the memory block must be *currently allocated* with alignment of [`layout.align()`], and /// * [`layout.size()`] must fall in the range `min ..= max`, where: /// - `min` is the size of the layout used to allocate the block, and @@ -154,28 +159,33 @@ impl fmt::Display for AllocError { /// # Safety /// /// Implementors of `Allocator` must ensure that a memory block that -/// is [*currently allocated*] by the allocator points to valid memory, +/// is [*currently allocated*] by the allocator points to valid memory /// until that memory block is [*invalidated*]. The implementor must also /// not violate this invariant of `Allocator` via allocator equivalences -/// that are in the implementor's control (e.g., via an incorrect `unsafe -/// impl AllocatorClone for MyAllocator`). +/// that are in the implementor's control, and generally ensure that equivalence +/// is respected. /// /// Additionally, any memory block returned by the allocator must /// satisfy the allocation invariants described in `core::ptr`. /// In particular, if a block has base address `p` and size `n`, -/// then `p as usize + n <= usize::MAX` must hold. +/// then `p as usize + n <= usize::MAX` must hold. These blocks must also +/// be wholly disjoint. /// /// This ensures that pointer arithmetic within the allocation -/// (for example, `ptr.add(len)`) cannot overflow the address space. +/// (for example, `ptr.add(len)`) cannot overflow the address space, and +/// that it is possible to perform nonoverlapping copies between allocations. /// /// None of the allocating or deallocating methods may unwind. This restriction /// may be lifted in the future by ensuring unwinding out of an allocating function always /// aborts. If an implementor of `Allocator` also has drop glue or directly implements `Drop`, /// dropping the allocator must not result in an unwind. /// -/// Lastly, the methods on this trait must be *correct*; i.e. the layout requested +/// It is undefined behavior for the allocator to read, write, or deallocate any memory that +/// is currently allocated. This memory is owned by the user; the allocator must not touch it. +/// +/// Lastly, the methods on this trait must be *correct*; in particular, the layout requested /// must be respected, calls must zero out memory if the documentation so requires, -/// and returning an `AllocError` from a reallocating method must indeed ensure that +/// returning an `AllocError` from a reallocating method must indeed ensure that /// the old pointer was not invalidated, and de/reallocating calls must accept layouts /// in the ranges defined by their documentation. /// @@ -203,7 +213,7 @@ pub const unsafe trait Allocator { /// Note that the returned block of memory is considered [*currently allocated*] /// with this allocator (and equivalent allocators). /// Therefore, it is the responsibility of implementors of `Allocator` to make sure that - /// this block of memory points to valid memory until the block is [*invalidated*] + /// this block of memory remains valid until it is [*invalidated*]. /// /// [*currently allocated*]: #currently-allocated-memory /// [*invalidated*]: #invalidating-memory-blocks @@ -539,14 +549,15 @@ pub unsafe trait AllocatorClone: Allocator + Clone {} /// /// # Safety /// -/// Implementors must ensure that memory cannot be freed except via a call to -/// `Allocator::deallocate`, and that subtype coercion preserves this invariant. +/// Implementors must ensure that memory blocks are *only, ever* invalidated by a +/// call to a de/reallocating method on `Allocator`, and that this holds true for all +/// possible instances of all subtypes of the implementor as well. /// /// These requirements trivially apply to allocators that always maintain global state, such as /// `System` or `Global`. However, due to subtype coercion, it is *not* sound to implement -/// for an arbitrary `Allocator + 'static` due to [edge-case interactions][unsound] with -/// `Pin::clone`. Namely, an impl of `StaticAllocator for MyAllocator + 'long` guarantees that an -/// impl of `StaticAllocator for MyAllocator + 'short` would be sound to write. +/// for an arbitrary `Allocator + 'static` due to [edge-case interactions][unsound] with e.g. +/// `Pin::clone`. Namely, an impl of `StaticAllocator for MyAllocator + 'long` guarantees that any +/// value of `MyAllocator + 'short` also fulfills the requirements of `StaticAllocator`. /// /// The following must thus be guaranteed: /// - the `Drop` impl of the allocator does not invalidate any allocations; @@ -617,9 +628,10 @@ where } #[unstable(feature = "allocator_api", issue = "32838")] -unsafe impl Allocator for &mut A +#[rustc_const_unstable(feature = "const_heap", issue = "79597")] +const unsafe impl Allocator for &mut A where - A: Allocator + ?Sized, + A: [const] Allocator + ?Sized, { #[inline] fn allocate(&self, layout: Layout) -> Result, AllocError> { @@ -678,3 +690,6 @@ unsafe impl AllocatorClone for &A {} // its semantics, and references are equivalent to the allocator they reference. #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl StaticAllocator for &A {} + +#[unstable(feature = "allocator_api", issue = "32838")] +unsafe impl StaticAllocator for &mut A {} diff --git a/tests/ui/allocator/157089-box-pin-in.stderr b/tests/ui/allocator/157089-box-pin-in.stderr index f25736d819a1f..e919eb8e3286e 100644 --- a/tests/ui/allocator/157089-box-pin-in.stderr +++ b/tests/ui/allocator/157089-box-pin-in.stderr @@ -15,6 +15,9 @@ help: the following other types implement trait `StaticAllocator` --> $SRC_DIR/core/src/alloc/mod.rs:LL:COL | = note: `&A` + ::: $SRC_DIR/core/src/alloc/mod.rs:LL:COL + | + = note: `&mut A` --> $SRC_DIR/std/src/alloc.rs:LL:COL | = note: `System` diff --git a/tests/ui/allocator/159445-unsize-pin-box.stderr b/tests/ui/allocator/159445-unsize-pin-box.stderr index 0fb3d0f176eb2..c17019be03799 100644 --- a/tests/ui/allocator/159445-unsize-pin-box.stderr +++ b/tests/ui/allocator/159445-unsize-pin-box.stderr @@ -13,6 +13,9 @@ help: the following other types implement trait `StaticAllocator` --> $SRC_DIR/core/src/alloc/mod.rs:LL:COL | = note: `&A` + ::: $SRC_DIR/core/src/alloc/mod.rs:LL:COL + | + = note: `&mut A` --> $SRC_DIR/std/src/alloc.rs:LL:COL | = note: `System` From c132f36b30a03f11adcd3f6ef61d2f6515ec14ab Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Tue, 18 Aug 2026 20:49:13 +0200 Subject: [PATCH 2/6] okay max sure --- library/core/src/alloc/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 5fed1fae2a2d2..430da3e7142d6 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -162,8 +162,7 @@ impl fmt::Display for AllocError { /// is [*currently allocated*] by the allocator points to valid memory /// until that memory block is [*invalidated*]. The implementor must also /// not violate this invariant of `Allocator` via allocator equivalences -/// that are in the implementor's control, and generally ensure that equivalence -/// is respected. +/// that are in the implementor's control. /// /// Additionally, any memory block returned by the allocator must /// satisfy the allocation invariants described in `core::ptr`. From 2ee54ff4e93d3ff4eaed85d2386ab70fc79b3701 Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Tue, 18 Aug 2026 21:05:35 +0200 Subject: [PATCH 3/6] undo rc and arc thing --- library/alloc/src/rc.rs | 2 +- library/alloc/src/sync.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 689f015d586b0..12ab0b6fe5437 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2983,7 +2983,7 @@ impl From for Rc { #[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] -impl From> for Rc { +impl From> for Rc { /// Move a boxed object to a new, reference counted, allocation. /// /// # Example diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index fd4a630422011..bb98788ca7b3a 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -4050,7 +4050,7 @@ impl From for Arc { #[cfg(not(no_global_oom_handling))] #[stable(feature = "shared_from_slice", since = "1.21.0")] -impl From> for Arc { +impl From> for Arc { /// Move a boxed object to a new, reference-counted allocation. /// /// # Example From 4f2bbfd897e31a139ed020862df9d721b68cf835 Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Tue, 18 Aug 2026 21:16:43 +0200 Subject: [PATCH 4/6] tighten send so bad rc can't be used --- library/alloc/src/sync.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index bb98788ca7b3a..0ae099cccbbe7 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -281,7 +281,7 @@ pub struct Arc< } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Send for Arc {} +unsafe impl Send for Arc {} #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Sync for Arc {} @@ -364,7 +364,7 @@ pub struct Weak< } #[stable(feature = "arc_weak", since = "1.4.0")] -unsafe impl Send for Weak {} +unsafe impl Send for Weak {} #[stable(feature = "arc_weak", since = "1.4.0")] unsafe impl Sync for Weak {} @@ -4423,7 +4423,7 @@ pub struct UniqueArc< } #[unstable(feature = "unique_rc_arc", issue = "112566")] -unsafe impl Send for UniqueArc {} +unsafe impl Send for UniqueArc {} #[unstable(feature = "unique_rc_arc", issue = "112566")] unsafe impl Sync for UniqueArc {} From 31d172e735acb8d768360b481d8ea6fb1a664419 Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Tue, 18 Aug 2026 21:19:36 +0200 Subject: [PATCH 5/6] this too --- library/alloc/src/rc.rs | 7 +++++-- library/alloc/src/sync.rs | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 12ab0b6fe5437..30e4e1aa504bf 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -342,9 +342,12 @@ impl !Send for Rc {} impl !Sync for Rc {} #[stable(feature = "catch_unwind", since = "1.9.0")] -impl UnwindSafe for Rc {} +impl UnwindSafe for Rc {} #[stable(feature = "rc_ref_unwind_safe", since = "1.58.0")] -impl RefUnwindSafe for Rc {} +impl RefUnwindSafe + for Rc +{ +} #[unstable(feature = "coerce_unsized", issue = "18598")] impl, U: ?Sized, A: Allocator> CoerceUnsized> for Rc {} diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 0ae099cccbbe7..706eba3aab8e5 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -286,7 +286,10 @@ unsafe impl Send for Arc Sync for Arc {} #[stable(feature = "catch_unwind", since = "1.9.0")] -impl UnwindSafe for Arc {} +impl UnwindSafe + for Arc +{ +} #[unstable(feature = "coerce_unsized", issue = "18598")] impl, U: ?Sized, A: Allocator> CoerceUnsized> for Arc {} From 7d40fdb67d7aec852f7a5aa60f53eff192f9b94a Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Tue, 18 Aug 2026 21:46:37 +0200 Subject: [PATCH 6/6] there u go --- library/core/src/alloc/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 430da3e7142d6..6069c468f96e4 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -51,8 +51,9 @@ impl fmt::Display for AllocError { /// /// `Allocator` is mostly designed to be implemented on ZSTs, references, or smart pointers, /// but can also be implemented directly on the underlying memory-owning type so long as it -/// upholds the necessary guarantees. In general, an allocator for `MyAlloc([u8; N])` cannot be -/// moved, without updating the pointers to the allocated memory. +/// upholds the necessary guarantees. In general, an allocator of the type `MyAlloc([u8; N])` +/// cannot be soundly created without being pinned or otherwise immovable in order to be +/// correct. /// /// In contrast to [`GlobalAlloc`][], `Allocator` allows zero-sized allocations. If an underlying /// allocator does not support this (like jemalloc) or responds by returning a null pointer