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 {}