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