allocator_api2/
lib.rs

1//!
2//! allocator-api2 crate.
3//!
4#![cfg_attr(not(feature = "std"), no_std)]
5#![deny(unsafe_op_in_unsafe_fn)]
6#![allow(clippy::needless_doctest_main, clippy::partialeq_ne_impl)]
7
8#[cfg(feature = "alloc")]
9extern crate alloc as alloc_crate;
10
11#[cfg(feature = "alloc")]
12pub use self::slice::SliceExt;
13
14pub mod alloc;
15
16#[cfg(feature = "alloc")]
17pub mod boxed;
18
19#[cfg(feature = "alloc")]
20mod raw_vec;
21
22#[cfg(feature = "alloc")]
23pub mod vec;
24
25#[cfg(feature = "alloc")]
26#[macro_use]
27mod macros;
28
29#[cfg(feature = "alloc")]
30mod slice;
31
32#[cfg(feature = "alloc")]
33mod unique;
34
35/// Allows turning a [`Box<T: Sized, A>`][boxed::Box] into a [`Box<U: ?Sized, A>`][boxed::Box] where `T` can be unsizing-coerced into a `U`.
36///
37/// This is the only way to create an `allocator_api2::boxed::Box` of an unsized type on stable.
38///
39/// With the standard library's `alloc::boxed::Box`, this is done automatically using the unstable unsize traits, but this crate's Box
40/// can't take advantage of that machinery on stable. So, we need to use type inference and the fact that you *can*
41/// still coerce the inner pointer of a box to get the compiler to help us unsize it using this macro.
42///
43/// # Example
44///
45/// ```
46/// use allocator_api2::unsize_box;
47/// use allocator_api2::boxed::Box;
48/// use core::any::Any;
49///
50/// let sized_box: Box<u64> = Box::new(0);
51/// let unsized_box: Box<dyn Any> = unsize_box!(sized_box);
52/// ```
53#[macro_export]
54#[cfg(feature = "alloc")]
55macro_rules! unsize_box {( $boxed:expr $(,)? ) => ({
56    let (ptr, allocator) = ::allocator_api2::boxed::Box::into_raw_with_allocator($boxed);
57    // we don't want to allow casting to arbitrary type U, but we do want to allow unsize coercion to happen.
58    // that's exactly what's happening here -- this is *not* a pointer cast ptr as *mut _, but the compiler
59    // *will* allow an unsizing coercion to happen into the `ptr` place, if one is available. And we use _ so that the user can
60    // fill in what they want the unsized type to be by annotating the type of the variable this macro will
61    // assign its result to.
62    let ptr: *mut _ = ptr;
63    // SAFETY: see above for why ptr's type can only be something that can be safely coerced.
64    // also, ptr just came from a properly allocated box in the same allocator.
65    unsafe {
66        ::allocator_api2::boxed::Box::from_raw_in(ptr, allocator)
67    }
68})}
69
70#[cfg(feature = "alloc")]
71pub mod collections {
72    pub use super::raw_vec::{TryReserveError, TryReserveErrorKind};
73}
74
75#[cfg(feature = "alloc")]
76#[track_caller]
77#[inline(always)]
78#[cfg(debug_assertions)]
79unsafe fn assume(v: bool) {
80    if !v {
81        core::unreachable!()
82    }
83}
84
85#[cfg(feature = "alloc")]
86#[track_caller]
87#[inline(always)]
88#[cfg(not(debug_assertions))]
89unsafe fn assume(v: bool) {
90    if !v {
91        unsafe {
92            core::hint::unreachable_unchecked();
93        }
94    }
95}
96
97#[cfg(feature = "alloc")]
98#[inline(always)]
99fn addr<T>(x: *const T) -> usize {
100    #[allow(clippy::useless_transmute, clippy::transmutes_expressible_as_ptr_casts)]
101    unsafe {
102        core::mem::transmute(x)
103    }
104}
105
106#[cfg(feature = "alloc")]
107#[inline(always)]
108fn invalid_mut<T>(addr: usize) -> *mut T {
109    #[allow(clippy::useless_transmute, clippy::transmutes_expressible_as_ptr_casts)]
110    unsafe {
111        core::mem::transmute(addr)
112    }
113}