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