Skip to main content

core/alloc/
mod.rs

1//! Memory allocation APIs
2
3#![stable(feature = "alloc_module", since = "1.28.0")]
4
5mod global;
6mod layout;
7
8#[stable(feature = "global_alloc", since = "1.28.0")]
9pub use self::global::GlobalAlloc;
10#[stable(feature = "alloc_layout", since = "1.28.0")]
11pub use self::layout::Layout;
12#[stable(feature = "alloc_layout", since = "1.28.0")]
13#[deprecated(
14    since = "1.52.0",
15    note = "Name does not follow std convention, use LayoutError",
16    suggestion = "LayoutError"
17)]
18#[allow(deprecated, deprecated_in_future)]
19pub use self::layout::LayoutErr;
20#[stable(feature = "alloc_layout_error", since = "1.50.0")]
21pub use self::layout::LayoutError;
22use crate::error::Error;
23use crate::fmt;
24use crate::ptr::{self, NonNull};
25
26/// The `AllocError` error indicates an allocation failure
27/// that may be due to resource exhaustion or to
28/// something wrong when combining the given input arguments with this
29/// allocator.
30#[unstable(feature = "allocator_api", issue = "32838")]
31#[derive(Copy, Clone, PartialEq, Eq, Debug)]
32pub struct AllocError;
33
34#[unstable(
35    feature = "allocator_api",
36    reason = "the precise API and guarantees it provides may be tweaked.",
37    issue = "32838"
38)]
39impl Error for AllocError {}
40
41// (we need this for downstream impl of trait Error)
42#[unstable(feature = "allocator_api", issue = "32838")]
43impl fmt::Display for AllocError {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        f.write_str("memory allocation failed")
46    }
47}
48
49/// An implementation of `Allocator` can allocate, grow, shrink, and deallocate arbitrary blocks of
50/// data described via [`Layout`][].
51///
52/// `Allocator` is designed to be implemented on ZSTs, references, or smart pointers.
53/// An allocator for `MyAlloc([u8; N])` cannot be moved, without updating the pointers to the
54/// allocated memory.
55///
56/// In contrast to [`GlobalAlloc`][], `Allocator` allows zero-sized allocations. If an underlying
57/// allocator does not support this (like jemalloc) or responds by returning a null pointer
58/// (such as `libc::malloc`), this must be caught by the implementation.
59///
60/// ### Equivalent allocators
61///
62/// Multiple allocator values can sometimes be interchangeable with each other.
63/// When this is the case, we refer to those allocators as being *equivalent* to
64/// each other.
65///
66/// The following conditions are sufficient conditions for allocators to be equivalent.
67/// * An allocator is equivalent to itself. (Equivalence is reflexive.)
68/// * If an allocator is equivalent to a second allocator, then
69///   the second allocator is also equivalent to the first. (Equivalence is symmetric.)
70/// * If an allocator is equivalent to a second allocator, and
71///   the second allocator is equivalent to a third allocator, then
72///   the first allocator is also equivalent to the third allocator.
73///   (Equivalence is transitive.)
74/// * Moving, subtyping, unsize-coercing, or trait-upcasting an allocator does not change
75///   what the allocator is equivalent to.
76/// * Copying or cloning allocator results in an allocator that's
77///   equivalent to the initial allocator, should the [`AllocatorClone`] trait
78///   be implemented.
79///
80/// Additionally, implementors of `Allocator` may specify additional equivalences
81/// between allocators. It is the responsibility of such implementors to make sure
82/// that equivalent allocators have "compatible" `Allocator` implementations.
83/// In particular, the standard library specifies the following equivalences:
84/// * A reference to an allocator (either `&` or `&mut`) is equivalent to
85///   the allocator being referenced.
86/// * A `Box`, `Rc`, or `Arc` containing an allocator is equivalent to
87///   the allocator inside.
88/// * All `Global` allocator instances are equivalent with each other.
89/// * All `System` allocator instances are equivalent with each other.
90///
91/// ### Currently allocated memory
92///
93/// Some of the methods require that a memory block is *currently allocated* by some specific allocator.
94/// This means that:
95/// * the starting address for that memory block was previously returned by
96///   the [`allocate`], [`allocate_zeroed`], [`grow`], [`grow_zeroed`], or [`shrink`] methods,
97///   called on an allocator that's equivalent to this specific allocator; and
98/// * the memory block has not subsequently been [*invalidated*].
99///
100/// ### Invalidating memory blocks
101///
102/// A memory block that is currently allocated becomes *invalidated* when one
103/// of the following happens:
104/// * The memory block is deallocated. This occurs when the memory block
105///   is passed as an argument to a [`deallocate`] call, or when it is passed
106///   as an argument to a [`grow`], [`grow_zeroed`] or [`shrink`] call that returns `Ok`.
107/// * All (equivalent) allocators that this memory block is allocated with,
108///   each has one of the following happen to them:
109///   * The allocator's destructor runs.
110///   * The allocator is mutated through public API taking `&mut` access.
111///   * One of the borrow-checker lifetimes in the allocator's type expires.
112///
113/// Note that these conditions imply that a collection may ensure that
114/// any specific currently allocated memory block won't be invalidated, by:
115/// * not deallocating that memory block,
116/// * owning an allocator that memory block is allocated with, and
117/// * not publicly exposing `&mut` access to that allocator.
118///
119/// Also note that safe public API of an allocator with `&` access is not
120/// allowed to invalidate its memory blocks. Furthermore, unsafe public API
121/// of an allocator with `&` access must document that they invalidate
122/// memory blocks (e.g., by calling `deallocate`) if they do. Therefore,
123/// collections may safely expose `&` access to its allocator.
124///
125/// Also note that, even in cases where are other "alive" allocators known to be
126/// equivalent to a given collection's allocator, most collections still should
127/// not publicly expose `&mut` access to its allocator. The fact that there are
128/// other "alive" allocators would prevent this `&mut` access from invalidating
129/// the collection's memory block, but public `&mut` access is still likely to
130/// be unsound, since a user could replace the collection's allocator with
131/// a non-equivalent allocator, causing the collection to deallocate its memory
132/// with the wrong allocator.
133///
134/// [`allocate`]: Allocator::allocate
135/// [`allocate_zeroed`]: Allocator::allocate_zeroed
136/// [`grow`]: Allocator::grow
137/// [`grow_zeroed`]: Allocator::grow_zeroed
138/// [`shrink`]: Allocator::shrink
139/// [`deallocate`]: Allocator::deallocate
140///
141/// ### Memory fitting
142///
143/// Some of the methods require that a `layout` *fit* a memory block or vice versa. This means that the
144/// following conditions must hold:
145///  * the memory block must be *currently allocated* with alignment of [`layout.align()`], and
146///  * [`layout.size()`] must fall in the range `min ..= max`, where:
147///    - `min` is the size of the layout used to allocate the block, and
148///    - `max` is the actual size returned from [`allocate`], [`allocate_zeroed`],
149///      [`grow`], [`grow_zeroed`], or [`shrink`].
150///
151/// [`layout.align()`]: Layout::align
152/// [`layout.size()`]: Layout::size
153///
154/// # Safety
155///
156/// Implementors of `Allocator` must ensure that a memory block that
157/// is [*currently allocated*] by the allocator points to valid memory,
158/// until that memory block is [*invalidated*]. The implementor must also
159/// not violate this invariant of `Allocator` via allocator equivalences
160/// that are in the implementor's control (e.g., via an incorrect `unsafe
161/// impl AllocatorClone for MyAllocator`).
162///
163/// Additionally, any memory block returned by the allocator must
164/// satisfy the allocation invariants described in `core::ptr`.
165/// In particular, if a block has base address `p` and size `n`,
166/// then `p as usize + n <= usize::MAX` must hold.
167///
168/// This ensures that pointer arithmetic within the allocation
169/// (for example, `ptr.add(len)`) cannot overflow the address space.
170///
171/// None of the allocating or deallocating methods may unwind. This restriction
172/// may be lifted in the future by ensuring unwinding out of an allocating function always
173/// aborts. If an implementor of `Allocator` also has drop glue or directly implements `Drop`,
174/// dropping the allocator must not result in an unwind.
175///
176/// Lastly, the methods on this trait must be *correct*; i.e. the layout requested
177/// must be respected, calls must zero out memory if the documentation so requires,
178/// and returning an `AllocError` from a reallocating method must indeed ensure that
179/// the old pointer was not invalidated, and de/reallocating calls must accept layouts
180/// in the ranges defined by their documentation.
181///
182/// [*currently allocated*]: #currently-allocated-memory
183/// [*invalidated*]: #invalidating-memory-blocks
184// NOTE: the above bound on allocating methods not unwinding, alongside the similar
185// bound on `AllocatorClone`, are currently load-bearing in std! see the below issues
186// and make sure they cannot be triggered before relaxing this:
187// https://rust.tf/156490
188// https://rust.tf/159982
189#[unstable(feature = "allocator_api", issue = "32838")]
190#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
191pub const unsafe trait Allocator {
192    /// Attempts to allocate a block of memory.
193    ///
194    /// On success, returns a [`NonNull<[u8]>`][NonNull] meeting the size and alignment
195    /// guarantees of `layout`. The returned block may have a larger size than specified
196    /// by `layout.size()`, and may or may not have its contents initialized.
197    ///
198    /// It is recommended that overallocating as per the above is only performed if doing so
199    /// is cheap; there is no guarantee that the caller is able to take advantage of the
200    /// returned excess. Implementors are free to e.g. provide an alternate method to query
201    /// available excess if doing so is expensive and should be left to the caller.
202    ///
203    /// Note that the returned block of memory is considered [*currently allocated*]
204    /// with this allocator (and equivalent allocators).
205    /// Therefore, it is the responsibility of implementors of `Allocator` to make sure that
206    /// this block of memory points to valid memory until the block is [*invalidated*]
207    ///
208    /// [*currently allocated*]: #currently-allocated-memory
209    /// [*invalidated*]: #invalidating-memory-blocks
210    ///
211    /// # Errors
212    ///
213    /// Returning `Err` indicates that either memory is exhausted or `layout` does not meet
214    /// allocator's size or alignment constraints.
215    ///
216    /// Implementations are encouraged to return `Err` on memory exhaustion rather than
217    /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
218    /// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
219    ///
220    /// Clients wishing to abort computation in response to an allocation error are encouraged to
221    /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
222    ///
223    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
224    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>;
225
226    /// Behaves like `allocate`, but also ensures that the returned memory is zero-initialized.
227    ///
228    /// # Errors
229    ///
230    /// Returning `Err` indicates that either memory is exhausted or `layout` does not meet
231    /// allocator's size or alignment constraints.
232    ///
233    /// Implementations are encouraged to return `Err` on memory exhaustion rather than
234    /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
235    /// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
236    ///
237    /// Clients wishing to abort computation in response to an allocation error are encouraged to
238    /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
239    ///
240    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
241    fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
242        let ptr = self.allocate(layout)?;
243        // SAFETY: `alloc` returns a valid memory block
244        unsafe { ptr.as_non_null_ptr().as_ptr().write_bytes(0, ptr.len()) }
245        Ok(ptr)
246    }
247
248    /// Deallocates the memory referenced by `ptr`.
249    ///
250    /// # Safety
251    ///
252    /// * `ptr` must denote a block of memory [*currently allocated*] via this allocator, and
253    /// * `layout` must [*fit*] that block of memory.
254    ///
255    /// Note that it is *immediate* language UB for a deallocation or reallocation to
256    /// invalidate any outstanding references, smart pointers, etc.; thus, notably, an
257    /// allocator that has been moved into its own [*currently allocated*] memory may
258    /// not have its backing memory be freed, even if the allocator is never used again
259    /// afterwards. This is due to the fact that such a deallocation would invalidate the
260    /// `&self` reference passed to this method.
261    ///
262    /// [*currently allocated*]: #currently-allocated-memory
263    /// [*fit*]: #memory-fitting
264    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout);
265
266    /// Attempts to extend the memory block.
267    ///
268    /// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated
269    /// memory. The pointer is suitable for holding data described by `new_layout`. To accomplish
270    /// this, the allocator may extend the allocation referenced by `ptr` to fit the new layout.
271    ///
272    /// If this returns `Ok`, then the memory block referenced by `ptr` has been [*invalidated*].
273    /// The old `ptr` must not be used to access the memory, even if the allocation was grown in-place.
274    /// The newly returned pointer is the only valid pointer for accessing this memory now.
275    /// All bytes past `old_layout.size()` should be assumed to be uninitialised.
276    ///
277    /// If this method returns `Err`, then the memory block has not been *invalidated*,
278    /// and the contents of the memory block are unaltered.
279    ///
280    /// # Safety
281    ///
282    /// * `ptr` must denote a block of memory [*currently allocated*] via this allocator.
283    /// * `old_layout` must [*fit*] that block of memory (The `new_layout` argument need not fit it.).
284    /// * `new_layout.size()` must be greater than or equal to `old_layout.size()`.
285    ///
286    /// Note that `new_layout.align()` need not be the same as `old_layout.align()`.
287    ///
288    /// [*currently allocated*]: #currently-allocated-memory
289    /// [*fit*]: #memory-fitting
290    /// [*invalidated*]: #invalidating-memory-blocks
291    ///
292    /// # Errors
293    ///
294    /// Returns `Err` if the new layout does not meet the allocator's size and alignment
295    /// constraints of the allocator, or if growing otherwise fails.
296    ///
297    /// Implementations are encouraged to return `Err` on memory exhaustion rather than
298    /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
299    /// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
300    ///
301    /// Clients wishing to abort computation in response to an allocation error are encouraged to
302    /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
303    ///
304    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
305    unsafe fn grow(
306        &self,
307        ptr: NonNull<u8>,
308        old_layout: Layout,
309        new_layout: Layout,
310    ) -> Result<NonNull<[u8]>, AllocError> {
311        debug_assert!(
312            new_layout.size() >= old_layout.size(),
313            "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
314        );
315
316        let new_ptr = self.allocate(new_layout)?;
317
318        // SAFETY: because `new_layout.size()` must be greater than or equal to
319        // `old_layout.size()`, both the old and new memory allocation are valid for reads and
320        // writes for `old_layout.size()` bytes. Also, because the old allocation wasn't yet
321        // deallocated, it cannot overlap `new_ptr`. Thus, the call to `copy_nonoverlapping` is
322        // safe. The safety contract for `dealloc` must be upheld by the caller.
323        unsafe {
324            ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), old_layout.size());
325            self.deallocate(ptr, old_layout);
326        }
327
328        Ok(new_ptr)
329    }
330
331    /// Behaves like `grow`, but also ensures that the new contents are set to zero before being
332    /// returned.
333    ///
334    /// The memory block will contain the following contents after a successful call to
335    /// `grow_zeroed`:
336    ///   * Bytes `0..old_layout.size()` are preserved from the original allocation.
337    ///   * Bytes `old_layout.size()..new_size` are zeroed. `new_size` refers to the size
338    ///     of the memory block returned by the `grow_zeroed` call, which may be larger than
339    ///     `new_layout.size()`.
340    ///
341    /// # Safety
342    ///
343    /// * `ptr` must denote a block of memory [*currently allocated*] via this allocator.
344    /// * `old_layout` must [*fit*] that block of memory (The `new_layout` argument need not fit it.).
345    /// * `new_layout.size()` must be greater than or equal to `old_layout.size()`.
346    ///
347    /// Note that `new_layout.align()` need not be the same as `old_layout.align()`.
348    ///
349    /// [*currently allocated*]: #currently-allocated-memory
350    /// [*fit*]: #memory-fitting
351    ///
352    /// # Errors
353    ///
354    /// Returns `Err` if the new layout does not meet the allocator's size and alignment
355    /// constraints of the allocator, or if growing otherwise fails.
356    ///
357    /// Implementations are encouraged to return `Err` on memory exhaustion rather than
358    /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
359    /// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
360    ///
361    /// Clients wishing to abort computation in response to an allocation error are encouraged to
362    /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
363    ///
364    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
365    unsafe fn grow_zeroed(
366        &self,
367        ptr: NonNull<u8>,
368        old_layout: Layout,
369        new_layout: Layout,
370    ) -> Result<NonNull<[u8]>, AllocError> {
371        debug_assert!(
372            new_layout.size() >= old_layout.size(),
373            "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
374        );
375
376        let new_ptr = self.allocate_zeroed(new_layout)?;
377
378        // SAFETY: because `new_layout.size()` must be greater than or equal to
379        // `old_layout.size()`, both the old and new memory allocation are valid for reads and
380        // writes for `old_layout.size()` bytes. Also, because the old allocation wasn't yet
381        // deallocated, it cannot overlap `new_ptr`. Thus, the call to `copy_nonoverlapping` is
382        // safe. The safety contract for `dealloc` must be upheld by the caller.
383        unsafe {
384            ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), old_layout.size());
385            self.deallocate(ptr, old_layout);
386        }
387
388        Ok(new_ptr)
389    }
390
391    /// Attempts to shrink the memory block.
392    ///
393    /// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated
394    /// memory. The pointer is suitable for holding data described by `new_layout`. To accomplish
395    /// this, the allocator may shrink the allocation referenced by `ptr` to fit the new layout.
396    ///
397    ///
398    /// If this returns `Ok`, then the memory block referenced by `ptr` has been [*invalidated*].
399    /// The old `ptr` must not be used to access the memory, even if the allocation was shrunk in-place.
400    /// The newly returned pointer is the only valid pointer for accessing this memory now.
401    /// All bytes past `new_layout.size()` should be assumed to be uninitialised.
402    ///
403    /// If this method returns `Err`, then the memory block has not been *invalidated*,
404    /// and the contents of the memory block are unaltered.
405    ///
406    /// # Safety
407    ///
408    /// * `ptr` must denote a block of memory [*currently allocated*] via this allocator.
409    /// * `old_layout` must [*fit*] that block of memory (The `new_layout` argument need not fit it.).
410    /// * `new_layout.size()` must be smaller than or equal to `old_layout.size()`.
411    ///
412    /// Note that `new_layout.align()` need not be the same as `old_layout.align()`.
413    ///
414    /// [*currently allocated*]: #currently-allocated-memory
415    /// [*fit*]: #memory-fitting
416    /// [*invalidated*]: #invalidating-memory-blocks
417    ///
418    /// # Errors
419    ///
420    /// Returns `Err` if the new layout does not meet the allocator's size and alignment
421    /// constraints of the allocator, or if shrinking otherwise fails.
422    ///
423    /// Implementations are encouraged to return `Err` on memory exhaustion rather than
424    /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
425    /// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
426    ///
427    /// Clients wishing to abort computation in response to an allocation error are encouraged to
428    /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
429    ///
430    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
431    unsafe fn shrink(
432        &self,
433        ptr: NonNull<u8>,
434        old_layout: Layout,
435        new_layout: Layout,
436    ) -> Result<NonNull<[u8]>, AllocError> {
437        debug_assert!(
438            new_layout.size() <= old_layout.size(),
439            "`new_layout.size()` must be smaller than or equal to `old_layout.size()`"
440        );
441
442        let new_ptr = self.allocate(new_layout)?;
443
444        // SAFETY: because `new_layout.size()` must be lower than or equal to
445        // `old_layout.size()`, both the old and new memory allocation are valid for reads and
446        // writes for `new_layout.size()` bytes. Also, because the old allocation wasn't yet
447        // deallocated, it cannot overlap `new_ptr`. Thus, the call to `copy_nonoverlapping` is
448        // safe. The safety contract for `dealloc` must be upheld by the caller.
449        unsafe {
450            ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), new_layout.size());
451            self.deallocate(ptr, old_layout);
452        }
453
454        Ok(new_ptr)
455    }
456}
457
458/// An [`Allocator`] that can be registered as the standard library’s default
459/// through the `#[global_allocator]` attribute.
460///
461/// Types implementing this trait can be used as the default allocator for
462/// memory allocations through `Box`, `Vec` and the collection types. For
463/// instance, the `System` allocator implements this trait, and thus can be
464/// explicitly set as the default like so:
465/// ```
466/// use std::alloc::System;
467///
468/// #[global_allocator]
469/// static ALLOCATOR: System = System;
470/// ```
471///
472/// The `Global` allocator forwards all memory allocation requests to the
473/// `static` annotated with `#[global_allocator]`. Hence, `Global` does not
474/// implement `GlobalAllocator` itself, as that would lead to infinite recursion.
475///
476/// # Note to implementors
477///
478/// This trait is used to prevent the infinite recursion that would occur if the
479/// default allocator were to attempt to allocate memory through `Global` (and
480/// thus from itself).
481///
482/// When to implement this trait:
483/// * for custom global allocators that only use system memory allocation
484///   services.
485/// * for allocators that wrap another allocator that implements `GlobalAllocator`.
486///
487/// When **not** to implement this trait:
488/// * for wrappers of arbitrary allocators (which might end up being `Global`,
489///   leading to infinite recursion).
490///
491/// # Safety
492///
493/// When implementing a global allocator, one has to be careful not to create an infinitely
494/// recursive implementation by accident, as many constructs in the Rust standard library may
495/// allocate in their implementation. For example, on some platforms, [`std::sync::Mutex`] may
496/// allocate, so using it is highly problematic in a global allocator.
497///
498/// For this reason, one should generally stick to library features available through
499/// [`core`], and avoid using [`std`] in a global allocator. A few features from [`std`] are
500/// guaranteed to not use `#[global_allocator]` to allocate:
501///
502///  - [`std::thread_local`],
503///  - [`std::thread::current`],
504///  - [`std::thread::park`] and [`std::thread::Thread`]'s [`unpark`] method and
505/// [`Clone`] implementation.
506///
507/// [`std`]: ../../std/index.html
508/// [`std::sync::Mutex`]: ../../std/sync/struct.Mutex.html
509/// [`std::thread_local`]: ../../std/macro.thread_local.html
510/// [`std::thread::current`]: ../../std/thread/fn.current.html
511/// [`std::thread::park`]: ../../std/thread/fn.park.html
512/// [`std::thread::Thread`]: ../../std/thread/struct.Thread.html
513/// [`unpark`]: ../../std/thread/struct.Thread.html#method.unpark
514#[unstable(feature = "allocator_api", issue = "32838")]
515#[expect(multiple_supertrait_upcastable)]
516pub unsafe trait GlobalAllocator: StaticAllocator + Sync + 'static {}
517
518/// Marks a type's [`Clone`] implementation as sound with regard to [`Allocator`] equivalence.
519/// Implementors must ensure that, upon cloning, the two allocators are equivalent
520/// (i.e. it is possible to free memory with one that was allocated with the other).
521/// Further, mutable accesses such as moving or dropping the allocator must not invalidate
522/// its currently allocated blocks at least so long as clones exist.
523///
524/// Additionally, the bound that allocators do not unwind when (de)allocating also applies
525/// to guaranteeing allocators will not unwind when cloned.
526///
527/// It must also be the case that types which are `AllocatorClone` are either explicitly not
528/// copyable (such as by containing a `!Copy` field) or that copying them also respects allocator
529/// equivalence as if it had been a clone.
530#[unstable(feature = "allocator_api", issue = "32838")]
531pub unsafe trait AllocatorClone: Allocator + Clone {}
532
533/// Marks that an allocator and its supertypes will never invalidate currently allocated
534/// memory unless explicitly deallocated via a call to a deallocating method, even if
535/// dropped or if the allocator's lifetime expires.
536///
537/// This is a necessity in conjunction with [`Pin`], as only allocators that promise
538/// memory is never reused without a destructor running may be used to back a pinned pointer.
539///
540/// # Safety
541///
542/// Implementors must ensure that memory cannot be freed except via a call to
543/// `Allocator::deallocate`, and that subtype coercion preserves this invariant.
544///
545/// These requirements trivially apply to allocators that always maintain global state, such as
546/// `System` or `Global`. However, due to subtype coercion, it is *not* sound to implement
547/// for an arbitrary `Allocator + 'static` due to [edge-case interactions][unsound] with
548/// `Pin::clone`. Namely, an impl of `StaticAllocator for MyAllocator + 'long` guarantees that an
549/// impl of `StaticAllocator for MyAllocator + 'short` would be sound to write.
550///
551/// The following must thus be guaranteed:
552/// - the `Drop` impl of the allocator does not invalidate any allocations;
553/// - the allocator does not expose a safe API surface that allows invalidating
554///   its allocations;
555/// - the allocator's lifetime expiring does not invalidate any allocations;
556/// - the above also hold for all equivalent allocators (see [`Allocator`] docs).
557///
558/// [`Pin`]: ../../core/pin/struct.Pin.html
559/// [unsound]: https://github.com/rust-lang/rust/issues/157089
560#[unstable(feature = "allocator_api", issue = "32838")]
561pub unsafe trait StaticAllocator: Allocator {}
562
563#[unstable(feature = "allocator_api", issue = "32838")]
564#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
565const unsafe impl<A> Allocator for &A
566where
567    A: [const] Allocator + ?Sized,
568{
569    #[inline]
570    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
571        (**self).allocate(layout)
572    }
573
574    #[inline]
575    fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
576        (**self).allocate_zeroed(layout)
577    }
578
579    #[inline]
580    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
581        // SAFETY: the safety contract must be upheld by the caller
582        unsafe { (**self).deallocate(ptr, layout) }
583    }
584
585    #[inline]
586    unsafe fn grow(
587        &self,
588        ptr: NonNull<u8>,
589        old_layout: Layout,
590        new_layout: Layout,
591    ) -> Result<NonNull<[u8]>, AllocError> {
592        // SAFETY: the safety contract must be upheld by the caller
593        unsafe { (**self).grow(ptr, old_layout, new_layout) }
594    }
595
596    #[inline]
597    unsafe fn grow_zeroed(
598        &self,
599        ptr: NonNull<u8>,
600        old_layout: Layout,
601        new_layout: Layout,
602    ) -> Result<NonNull<[u8]>, AllocError> {
603        // SAFETY: the safety contract must be upheld by the caller
604        unsafe { (**self).grow_zeroed(ptr, old_layout, new_layout) }
605    }
606
607    #[inline]
608    unsafe fn shrink(
609        &self,
610        ptr: NonNull<u8>,
611        old_layout: Layout,
612        new_layout: Layout,
613    ) -> Result<NonNull<[u8]>, AllocError> {
614        // SAFETY: the safety contract must be upheld by the caller
615        unsafe { (**self).shrink(ptr, old_layout, new_layout) }
616    }
617}
618
619#[unstable(feature = "allocator_api", issue = "32838")]
620unsafe impl<A> Allocator for &mut A
621where
622    A: Allocator + ?Sized,
623{
624    #[inline]
625    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
626        (**self).allocate(layout)
627    }
628
629    #[inline]
630    fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
631        (**self).allocate_zeroed(layout)
632    }
633
634    #[inline]
635    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
636        // SAFETY: the safety contract must be upheld by the caller
637        unsafe { (**self).deallocate(ptr, layout) }
638    }
639
640    #[inline]
641    unsafe fn grow(
642        &self,
643        ptr: NonNull<u8>,
644        old_layout: Layout,
645        new_layout: Layout,
646    ) -> Result<NonNull<[u8]>, AllocError> {
647        // SAFETY: the safety contract must be upheld by the caller
648        unsafe { (**self).grow(ptr, old_layout, new_layout) }
649    }
650
651    #[inline]
652    unsafe fn grow_zeroed(
653        &self,
654        ptr: NonNull<u8>,
655        old_layout: Layout,
656        new_layout: Layout,
657    ) -> Result<NonNull<[u8]>, AllocError> {
658        // SAFETY: the safety contract must be upheld by the caller
659        unsafe { (**self).grow_zeroed(ptr, old_layout, new_layout) }
660    }
661
662    #[inline]
663    unsafe fn shrink(
664        &self,
665        ptr: NonNull<u8>,
666        old_layout: Layout,
667        new_layout: Layout,
668    ) -> Result<NonNull<[u8]>, AllocError> {
669        // SAFETY: the safety contract must be upheld by the caller
670        unsafe { (**self).shrink(ptr, old_layout, new_layout) }
671    }
672}
673
674#[unstable(feature = "allocator_api", issue = "32838")]
675unsafe impl<A: Allocator + ?Sized> AllocatorClone for &A {}
676
677// If an allocator is `StaticAllocator` all equivalent allocators must also uphold
678// its semantics, and references are equivalent to the allocator they reference.
679#[unstable(feature = "allocator_api", issue = "32838")]
680unsafe impl<A: StaticAllocator + ?Sized> StaticAllocator for &A {}