stable_alloc_shim/lib.rs
1#![no_std]
2#![allow(unused_unsafe)]
3
4//! A simple crate that provides stable copies of the unstable allocator APIs
5//! found in `alloc`, for the purpose of implementing collections targetting
6//! stable Rust.
7//!
8//! ```toml
9//! [dependencies]
10//! stable-alloc-shim = "0.57"
11//! ```
12//!
13//! The minimum required Rust version for this crate is Rust 1.50.
14//!
15//! This crate does not do its own versioning and instead follows the standard
16//! library. As an example, v0.57.x of this crate will have the definitions and
17//! implementations of the allocator API as they were in Rust version 1.57. The
18//! x will be reserved for fixing errors, and applying the
19//! [semver trick](https://github.com/dtolnay/semver-trick) for future
20//! compatibility.
21//!
22//! When nightly features get changed in future releases, this crate will update
23//! their definitions in a new version. If a feature gets stabilized, it is
24//! similarly changed to a re-export from the standard library, if a
25//! sufficiently high rustc version is detected (as to not unnecessarily bump
26//! the minimum required Rust version). Either way the semver trick is used for
27//! unchanged definitions in the older version to keep versions as compatible as
28//! possible.
29
30extern crate alloc as std_alloc;
31
32mod alloc_alloc; // alloc/alloc.rs
33mod core_alloc; // core/alloc/mod.rs
34
35pub mod alloc {
36 pub use crate::alloc_alloc::Global;
37 pub use crate::core_alloc::{AllocError, Allocator};
38}
39
40pub mod collections;
41
42use core::hint::unreachable_unchecked;
43use core::mem::MaybeUninit;
44use core::ptr::NonNull;
45
46use std_alloc::alloc::Layout;
47
48// Private stable shims.
49fn nonnull_as_mut_ptr<T>(ptr: NonNull<[T]>) -> *mut T {
50 ptr.as_ptr() as *mut T
51}
52
53unsafe fn nonnull_len<T>(ptr: NonNull<[T]>) -> usize {
54 let uninit_ptr = core::mem::transmute::<NonNull<[T]>, NonNull<[MaybeUninit<T>]>>(ptr);
55 (*uninit_ptr.as_ptr()).len()
56}
57
58fn nonnull_slice_from_raw_parts<T>(data: NonNull<T>, len: usize) -> NonNull<[T]> {
59 // SAFETY: `data` is a `NonNull` pointer which is necessarily non-null
60 unsafe { NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(data.as_ptr(), len)) }
61}
62
63fn invalid_mut<T>(addr: usize) -> *mut T {
64 unsafe { core::mem::transmute(addr) }
65}
66
67fn layout_dangling(slf: &Layout) -> NonNull<u8> {
68 unsafe { NonNull::new_unchecked(invalid_mut(slf.align())) }
69}
70
71unsafe fn assume(b: bool) {
72 if !b {
73 unreachable_unchecked()
74 }
75}