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