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