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