bevy/crates/bevy_ptr/src/lib.rs
Zachary Harrold 5241e09671
Upgrade to Rust Edition 2024 (#17967)
# Objective

- Fixes #17960

## Solution

- Followed the [edition upgrade
guide](https://doc.rust-lang.org/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html)

## Testing

- CI

---

## Summary of Changes

### Documentation Indentation

When using lists in documentation, proper indentation is now linted for.
This means subsequent lines within the same list item must start at the
same indentation level as the item.

```rust
/* Valid */
/// - Item 1
///   Run-on sentence.
/// - Item 2
struct Foo;

/* Invalid */
/// - Item 1
///     Run-on sentence.
/// - Item 2
struct Foo;
```

### Implicit `!` to `()` Conversion

`!` (the never return type, returned by `panic!`, etc.) no longer
implicitly converts to `()`. This is particularly painful for systems
with `todo!` or `panic!` statements, as they will no longer be functions
returning `()` (or `Result<()>`), making them invalid systems for
functions like `add_systems`. The ideal fix would be to accept functions
returning `!` (or rather, _not_ returning), but this is blocked on the
[stabilisation of the `!` type
itself](https://doc.rust-lang.org/std/primitive.never.html), which is
not done.

The "simple" fix would be to add an explicit `-> ()` to system
signatures (e.g., `|| { todo!() }` becomes `|| -> () { todo!() }`).
However, this is _also_ banned, as there is an existing lint which (IMO,
incorrectly) marks this as an unnecessary annotation.

So, the "fix" (read: workaround) is to put these kinds of `|| -> ! { ...
}` closuers into variables and give the variable an explicit type (e.g.,
`fn()`).

```rust
// Valid
let system: fn() = || todo!("Not implemented yet!");
app.add_systems(..., system);

// Invalid
app.add_systems(..., || todo!("Not implemented yet!"));
```

### Temporary Variable Lifetimes

The order in which temporary variables are dropped has changed. The
simple fix here is _usually_ to just assign temporaries to a named
variable before use.

### `gen` is a keyword

We can no longer use the name `gen` as it is reserved for a future
generator syntax. This involved replacing uses of the name `gen` with
`r#gen` (the raw-identifier syntax).

### Formatting has changed

Use statements have had the order of imports changed, causing a
substantial +/-3,000 diff when applied. For now, I have opted-out of
this change by amending `rustfmt.toml`

```toml
style_edition = "2021"
```

This preserves the original formatting for now, reducing the size of
this PR. It would be a simple followup to update this to 2024 and run
`cargo fmt`.

### New `use<>` Opt-Out Syntax

Lifetimes are now implicitly included in RPIT types. There was a handful
of instances where it needed to be added to satisfy the borrow checker,
but there may be more cases where it _should_ be added to avoid
breakages in user code.

### `MyUnitStruct { .. }` is an invalid pattern

Previously, you could match against unit structs (and unit enum
variants) with a `{ .. }` destructuring. This is no longer valid.

### Pretty much every use of `ref` and `mut` are gone

Pattern binding has changed to the point where these terms are largely
unused now. They still serve a purpose, but it is far more niche now.

### `iter::repeat(...).take(...)` is bad

New lint recommends using the more explicit `iter::repeat_n(..., ...)`
instead.

## Migration Guide

The lifetimes of functions using return-position impl-trait (RPIT) are
likely _more_ conservative than they had been previously. If you
encounter lifetime issues with such a function, please create an issue
to investigate the addition of `+ use<...>`.

## Notes

- Check the individual commits for a clearer breakdown for what
_actually_ changed.

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2025-02-24 03:54:47 +00:00

642 lines
24 KiB
Rust

#![doc = include_str!("../README.md")]
#![no_std]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![expect(unsafe_code, reason = "Raw pointers are inherently unsafe.")]
#![doc(
html_logo_url = "https://bevyengine.org/assets/icon.png",
html_favicon_url = "https://bevyengine.org/assets/icon.png"
)]
use core::{
cell::UnsafeCell,
fmt::{self, Formatter, Pointer},
marker::PhantomData,
mem::ManuallyDrop,
num::NonZeroUsize,
ptr::{self, NonNull},
};
/// Used as a type argument to [`Ptr`], [`PtrMut`] and [`OwningPtr`] to specify that the pointer is aligned.
#[derive(Copy, Clone)]
pub struct Aligned;
/// Used as a type argument to [`Ptr`], [`PtrMut`] and [`OwningPtr`] to specify that the pointer is not aligned.
#[derive(Copy, Clone)]
pub struct Unaligned;
/// Trait that is only implemented for [`Aligned`] and [`Unaligned`] to work around the lack of ability
/// to have const generics of an enum.
pub trait IsAligned: sealed::Sealed {}
impl IsAligned for Aligned {}
impl IsAligned for Unaligned {}
mod sealed {
pub trait Sealed {}
impl Sealed for super::Aligned {}
impl Sealed for super::Unaligned {}
}
/// A newtype around [`NonNull`] that only allows conversion to read-only borrows or pointers.
///
/// This type can be thought of as the `*const T` to [`NonNull<T>`]'s `*mut T`.
#[repr(transparent)]
pub struct ConstNonNull<T: ?Sized>(NonNull<T>);
impl<T: ?Sized> ConstNonNull<T> {
/// Creates a new `ConstNonNull` if `ptr` is non-null.
///
/// # Examples
///
/// ```
/// use bevy_ptr::ConstNonNull;
///
/// let x = 0u32;
/// let ptr = ConstNonNull::<u32>::new(&x as *const _).expect("ptr is null!");
///
/// if let Some(ptr) = ConstNonNull::<u32>::new(core::ptr::null()) {
/// unreachable!();
/// }
/// ```
pub fn new(ptr: *const T) -> Option<Self> {
NonNull::new(ptr.cast_mut()).map(Self)
}
/// Creates a new `ConstNonNull`.
///
/// # Safety
///
/// `ptr` must be non-null.
///
/// # Examples
///
/// ```
/// use bevy_ptr::ConstNonNull;
///
/// let x = 0u32;
/// let ptr = unsafe { ConstNonNull::new_unchecked(&x as *const _) };
/// ```
///
/// *Incorrect* usage of this function:
///
/// ```rust,no_run
/// use bevy_ptr::ConstNonNull;
///
/// // NEVER DO THAT!!! This is undefined behavior. ⚠️
/// let ptr = unsafe { ConstNonNull::<u32>::new_unchecked(core::ptr::null()) };
/// ```
pub const unsafe fn new_unchecked(ptr: *const T) -> Self {
// SAFETY: This function's safety invariants are identical to `NonNull::new_unchecked`
// The caller must satisfy all of them.
unsafe { Self(NonNull::new_unchecked(ptr.cast_mut())) }
}
/// Returns a shared reference to the value.
///
/// # Safety
///
/// When calling this method, you have to ensure that all of the following is true:
///
/// * The pointer must be properly aligned.
///
/// * It must be "dereferenceable" in the sense defined in [the module documentation].
///
/// * The pointer must point to an initialized instance of `T`.
///
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
/// In particular, while this reference exists, the memory the pointer points to must
/// not get mutated (except inside `UnsafeCell`).
///
/// This applies even if the result of this method is unused!
/// (The part about being initialized is not yet fully decided, but until
/// it is, the only safe approach is to ensure that they are indeed initialized.)
///
/// # Examples
///
/// ```
/// use bevy_ptr::ConstNonNull;
///
/// let mut x = 0u32;
/// let ptr = ConstNonNull::new(&mut x as *mut _).expect("ptr is null!");
///
/// let ref_x = unsafe { ptr.as_ref() };
/// println!("{ref_x}");
/// ```
///
/// [the module documentation]: core::ptr#safety
#[inline]
pub unsafe fn as_ref<'a>(&self) -> &'a T {
// SAFETY: This function's safety invariants are identical to `NonNull::as_ref`
// The caller must satisfy all of them.
unsafe { self.0.as_ref() }
}
}
impl<T: ?Sized> From<NonNull<T>> for ConstNonNull<T> {
fn from(value: NonNull<T>) -> ConstNonNull<T> {
ConstNonNull(value)
}
}
impl<'a, T: ?Sized> From<&'a T> for ConstNonNull<T> {
fn from(value: &'a T) -> ConstNonNull<T> {
ConstNonNull(NonNull::from(value))
}
}
impl<'a, T: ?Sized> From<&'a mut T> for ConstNonNull<T> {
fn from(value: &'a mut T) -> ConstNonNull<T> {
ConstNonNull(NonNull::from(value))
}
}
/// Type-erased borrow of some unknown type chosen when constructing this type.
///
/// This type tries to act "borrow-like" which means that:
/// - It should be considered immutable: its target must not be changed while this pointer is alive.
/// - It must always points to a valid value of whatever the pointee type is.
/// - The lifetime `'a` accurately represents how long the pointer is valid for.
/// - Must be sufficiently aligned for the unknown pointee type.
///
/// It may be helpful to think of this type as similar to `&'a dyn Any` but without
/// the metadata and able to point to data that does not correspond to a Rust type.
#[derive(Copy, Clone, Debug)]
#[repr(transparent)]
pub struct Ptr<'a, A: IsAligned = Aligned>(NonNull<u8>, PhantomData<(&'a u8, A)>);
/// Type-erased mutable borrow of some unknown type chosen when constructing this type.
///
/// This type tries to act "borrow-like" which means that:
/// - Pointer is considered exclusive and mutable. It cannot be cloned as this would lead to
/// aliased mutability.
/// - It must always points to a valid value of whatever the pointee type is.
/// - The lifetime `'a` accurately represents how long the pointer is valid for.
/// - Must be sufficiently aligned for the unknown pointee type.
///
/// It may be helpful to think of this type as similar to `&'a mut dyn Any` but without
/// the metadata and able to point to data that does not correspond to a Rust type.
#[derive(Debug)]
#[repr(transparent)]
pub struct PtrMut<'a, A: IsAligned = Aligned>(NonNull<u8>, PhantomData<(&'a mut u8, A)>);
/// Type-erased Box-like pointer to some unknown type chosen when constructing this type.
///
/// Conceptually represents ownership of whatever data is being pointed to and so is
/// responsible for calling its `Drop` impl. This pointer is _not_ responsible for freeing
/// the memory pointed to by this pointer as it may be pointing to an element in a `Vec` or
/// to a local in a function etc.
///
/// This type tries to act "borrow-like" like which means that:
/// - Pointer should be considered exclusive and mutable. It cannot be cloned as this would lead
/// to aliased mutability and potentially use after free bugs.
/// - It must always points to a valid value of whatever the pointee type is.
/// - The lifetime `'a` accurately represents how long the pointer is valid for.
/// - Must be sufficiently aligned for the unknown pointee type.
///
/// It may be helpful to think of this type as similar to `&'a mut ManuallyDrop<dyn Any>` but
/// without the metadata and able to point to data that does not correspond to a Rust type.
#[derive(Debug)]
#[repr(transparent)]
pub struct OwningPtr<'a, A: IsAligned = Aligned>(NonNull<u8>, PhantomData<(&'a mut u8, A)>);
macro_rules! impl_ptr {
($ptr:ident) => {
impl<'a> $ptr<'a, Aligned> {
/// Removes the alignment requirement of this pointer
pub fn to_unaligned(self) -> $ptr<'a, Unaligned> {
$ptr(self.0, PhantomData)
}
}
impl<'a, A: IsAligned> From<$ptr<'a, A>> for NonNull<u8> {
fn from(ptr: $ptr<'a, A>) -> Self {
ptr.0
}
}
impl<A: IsAligned> $ptr<'_, A> {
/// Calculates the offset from a pointer.
/// As the pointer is type-erased, there is no size information available. The provided
/// `count` parameter is in raw bytes.
///
/// *See also: [`ptr::offset`][ptr_offset]*
///
/// # Safety
/// - The offset cannot make the existing ptr null, or take it out of bounds for its allocation.
/// - If the `A` type parameter is [`Aligned`] then the offset must not make the resulting pointer
/// be unaligned for the pointee type.
/// - The value pointed by the resulting pointer must outlive the lifetime of this pointer.
///
/// [ptr_offset]: https://doc.rust-lang.org/std/primitive.pointer.html#method.offset
#[inline]
pub unsafe fn byte_offset(self, count: isize) -> Self {
Self(
// SAFETY: The caller upholds safety for `offset` and ensures the result is not null.
unsafe { NonNull::new_unchecked(self.as_ptr().offset(count)) },
PhantomData,
)
}
/// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
/// As the pointer is type-erased, there is no size information available. The provided
/// `count` parameter is in raw bytes.
///
/// *See also: [`ptr::add`][ptr_add]*
///
/// # Safety
/// - The offset cannot make the existing ptr null, or take it out of bounds for its allocation.
/// - If the `A` type parameter is [`Aligned`] then the offset must not make the resulting pointer
/// be unaligned for the pointee type.
/// - The value pointed by the resulting pointer must outlive the lifetime of this pointer.
///
/// [ptr_add]: https://doc.rust-lang.org/std/primitive.pointer.html#method.add
#[inline]
pub unsafe fn byte_add(self, count: usize) -> Self {
Self(
// SAFETY: The caller upholds safety for `add` and ensures the result is not null.
unsafe { NonNull::new_unchecked(self.as_ptr().add(count)) },
PhantomData,
)
}
}
impl<A: IsAligned> Pointer for $ptr<'_, A> {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Pointer::fmt(&self.0, f)
}
}
};
}
impl_ptr!(Ptr);
impl_ptr!(PtrMut);
impl_ptr!(OwningPtr);
impl<'a, A: IsAligned> Ptr<'a, A> {
/// Creates a new instance from a raw pointer.
///
/// # Safety
/// - `inner` must point to valid value of whatever the pointee type is.
/// - If the `A` type parameter is [`Aligned`] then `inner` must be sufficiently aligned for the pointee type.
/// - `inner` must have correct provenance to allow reads of the pointee type.
/// - The lifetime `'a` must be constrained such that this [`Ptr`] will stay valid and nothing
/// can mutate the pointee while this [`Ptr`] is live except through an [`UnsafeCell`].
#[inline]
pub unsafe fn new(inner: NonNull<u8>) -> Self {
Self(inner, PhantomData)
}
/// Transforms this [`Ptr`] into an [`PtrMut`]
///
/// # Safety
/// * The data pointed to by this `Ptr` must be valid for writes.
/// * There must be no active references (mutable or otherwise) to the data underlying this `Ptr`.
/// * Another [`PtrMut`] for the same [`Ptr`] must not be created until the first is dropped.
#[inline]
pub unsafe fn assert_unique(self) -> PtrMut<'a, A> {
PtrMut(self.0, PhantomData)
}
/// Transforms this [`Ptr<T>`] into a `&T` with the same lifetime
///
/// # Safety
/// - `T` must be the erased pointee type for this [`Ptr`].
/// - If the type parameter `A` is [`Unaligned`] then this pointer must be sufficiently aligned
/// for the pointee type `T`.
#[inline]
pub unsafe fn deref<T>(self) -> &'a T {
let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();
// SAFETY: The caller ensures the pointee is of type `T` and the pointer can be dereferenced.
unsafe { &*ptr }
}
/// Gets the underlying pointer, erasing the associated lifetime.
///
/// If possible, it is strongly encouraged to use [`deref`](Self::deref) over this function,
/// as it retains the lifetime.
#[inline]
pub fn as_ptr(self) -> *mut u8 {
self.0.as_ptr()
}
}
impl<'a, T: ?Sized> From<&'a T> for Ptr<'a> {
#[inline]
fn from(val: &'a T) -> Self {
// SAFETY: The returned pointer has the same lifetime as the passed reference.
// Access is immutable.
unsafe { Self::new(NonNull::from(val).cast()) }
}
}
impl<'a, A: IsAligned> PtrMut<'a, A> {
/// Creates a new instance from a raw pointer.
///
/// # Safety
/// - `inner` must point to valid value of whatever the pointee type is.
/// - If the `A` type parameter is [`Aligned`] then `inner` must be sufficiently aligned for the pointee type.
/// - `inner` must have correct provenance to allow read and writes of the pointee type.
/// - The lifetime `'a` must be constrained such that this [`PtrMut`] will stay valid and nothing
/// else can read or mutate the pointee while this [`PtrMut`] is live.
#[inline]
pub unsafe fn new(inner: NonNull<u8>) -> Self {
Self(inner, PhantomData)
}
/// Transforms this [`PtrMut`] into an [`OwningPtr`]
///
/// # Safety
/// Must have right to drop or move out of [`PtrMut`].
#[inline]
pub unsafe fn promote(self) -> OwningPtr<'a, A> {
OwningPtr(self.0, PhantomData)
}
/// Transforms this [`PtrMut<T>`] into a `&mut T` with the same lifetime
///
/// # Safety
/// - `T` must be the erased pointee type for this [`PtrMut`].
/// - If the type parameter `A` is [`Unaligned`] then this pointer must be sufficiently aligned
/// for the pointee type `T`.
#[inline]
pub unsafe fn deref_mut<T>(self) -> &'a mut T {
let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();
// SAFETY: The caller ensures the pointee is of type `T` and the pointer can be dereferenced.
unsafe { &mut *ptr }
}
/// Gets the underlying pointer, erasing the associated lifetime.
///
/// If possible, it is strongly encouraged to use [`deref_mut`](Self::deref_mut) over
/// this function, as it retains the lifetime.
#[inline]
pub fn as_ptr(&self) -> *mut u8 {
self.0.as_ptr()
}
/// Gets a [`PtrMut`] from this with a smaller lifetime.
#[inline]
pub fn reborrow(&mut self) -> PtrMut<'_, A> {
// SAFETY: the ptrmut we're borrowing from is assumed to be valid
unsafe { PtrMut::new(self.0) }
}
/// Gets an immutable reference from this mutable reference
#[inline]
pub fn as_ref(&self) -> Ptr<'_, A> {
// SAFETY: The `PtrMut` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees
unsafe { Ptr::new(self.0) }
}
}
impl<'a, T: ?Sized> From<&'a mut T> for PtrMut<'a> {
#[inline]
fn from(val: &'a mut T) -> Self {
// SAFETY: The returned pointer has the same lifetime as the passed reference.
// The reference is mutable, and thus will not alias.
unsafe { Self::new(NonNull::from(val).cast()) }
}
}
impl<'a> OwningPtr<'a> {
/// This exists mostly to reduce compile times;
/// code is only duplicated per type, rather than per function called.
///
/// # Safety
///
/// Safety constraints of [`PtrMut::promote`] must be upheld.
unsafe fn make_internal<T>(temp: &mut ManuallyDrop<T>) -> OwningPtr<'_> {
// SAFETY: The constraints of `promote` are upheld by caller.
unsafe { PtrMut::from(&mut *temp).promote() }
}
/// Consumes a value and creates an [`OwningPtr`] to it while ensuring a double drop does not happen.
#[inline]
pub fn make<T, F: FnOnce(OwningPtr<'_>) -> R, R>(val: T, f: F) -> R {
let mut val = ManuallyDrop::new(val);
// SAFETY: The value behind the pointer will not get dropped or observed later,
// so it's safe to promote it to an owning pointer.
f(unsafe { Self::make_internal(&mut val) })
}
}
impl<'a, A: IsAligned> OwningPtr<'a, A> {
/// Creates a new instance from a raw pointer.
///
/// # Safety
/// - `inner` must point to valid value of whatever the pointee type is.
/// - If the `A` type parameter is [`Aligned`] then `inner` must be sufficiently aligned for the pointee type.
/// - `inner` must have correct provenance to allow read and writes of the pointee type.
/// - The lifetime `'a` must be constrained such that this [`OwningPtr`] will stay valid and nothing
/// else can read or mutate the pointee while this [`OwningPtr`] is live.
#[inline]
pub unsafe fn new(inner: NonNull<u8>) -> Self {
Self(inner, PhantomData)
}
/// Consumes the [`OwningPtr`] to obtain ownership of the underlying data of type `T`.
///
/// # Safety
/// - `T` must be the erased pointee type for this [`OwningPtr`].
/// - If the type parameter `A` is [`Unaligned`] then this pointer must be sufficiently aligned
/// for the pointee type `T`.
#[inline]
pub unsafe fn read<T>(self) -> T {
let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();
// SAFETY: The caller ensure the pointee is of type `T` and uphold safety for `read`.
unsafe { ptr.read() }
}
/// Consumes the [`OwningPtr`] to drop the underlying data of type `T`.
///
/// # Safety
/// - `T` must be the erased pointee type for this [`OwningPtr`].
/// - If the type parameter `A` is [`Unaligned`] then this pointer must be sufficiently aligned
/// for the pointee type `T`.
#[inline]
pub unsafe fn drop_as<T>(self) {
let ptr = self.as_ptr().cast::<T>().debug_ensure_aligned();
// SAFETY: The caller ensure the pointee is of type `T` and uphold safety for `drop_in_place`.
unsafe {
ptr.drop_in_place();
}
}
/// Gets the underlying pointer, erasing the associated lifetime.
///
/// If possible, it is strongly encouraged to use the other more type-safe functions
/// over this function.
#[inline]
pub fn as_ptr(&self) -> *mut u8 {
self.0.as_ptr()
}
/// Gets an immutable pointer from this owned pointer.
#[inline]
pub fn as_ref(&self) -> Ptr<'_, A> {
// SAFETY: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees
unsafe { Ptr::new(self.0) }
}
/// Gets a mutable pointer from this owned pointer.
#[inline]
pub fn as_mut(&mut self) -> PtrMut<'_, A> {
// SAFETY: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees
unsafe { PtrMut::new(self.0) }
}
}
impl<'a> OwningPtr<'a, Unaligned> {
/// Consumes the [`OwningPtr`] to obtain ownership of the underlying data of type `T`.
///
/// # Safety
/// - `T` must be the erased pointee type for this [`OwningPtr`].
pub unsafe fn read_unaligned<T>(self) -> T {
let ptr = self.as_ptr().cast::<T>();
// SAFETY: The caller ensure the pointee is of type `T` and uphold safety for `read_unaligned`.
unsafe { ptr.read_unaligned() }
}
}
/// Conceptually equivalent to `&'a [T]` but with length information cut out for performance reasons
pub struct ThinSlicePtr<'a, T> {
ptr: NonNull<T>,
#[cfg(debug_assertions)]
len: usize,
_marker: PhantomData<&'a [T]>,
}
impl<'a, T> ThinSlicePtr<'a, T> {
#[inline]
/// Indexes the slice without doing bounds checks
///
/// # Safety
/// `index` must be in-bounds.
pub unsafe fn get(self, index: usize) -> &'a T {
#[cfg(debug_assertions)]
debug_assert!(index < self.len);
let ptr = self.ptr.as_ptr();
// SAFETY: `index` is in-bounds so the resulting pointer is valid to dereference.
unsafe { &*ptr.add(index) }
}
}
impl<'a, T> Clone for ThinSlicePtr<'a, T> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, T> Copy for ThinSlicePtr<'a, T> {}
impl<'a, T> From<&'a [T]> for ThinSlicePtr<'a, T> {
#[inline]
fn from(slice: &'a [T]) -> Self {
let ptr = slice.as_ptr().cast_mut();
Self {
// SAFETY: a reference can never be null
ptr: unsafe { NonNull::new_unchecked(ptr.debug_ensure_aligned()) },
#[cfg(debug_assertions)]
len: slice.len(),
_marker: PhantomData,
}
}
}
/// Creates a dangling pointer with specified alignment.
/// See [`NonNull::dangling`].
pub const fn dangling_with_align(align: NonZeroUsize) -> NonNull<u8> {
debug_assert!(align.is_power_of_two(), "Alignment must be power of two.");
// SAFETY: The pointer will not be null, since it was created
// from the address of a `NonZero<usize>`.
// TODO: use https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.with_addr once stabilized
unsafe { NonNull::new_unchecked(ptr::null_mut::<u8>().wrapping_add(align.get())) }
}
mod private {
use core::cell::UnsafeCell;
pub trait SealedUnsafeCell {}
impl<'a, T> SealedUnsafeCell for &'a UnsafeCell<T> {}
}
/// Extension trait for helper methods on [`UnsafeCell`]
pub trait UnsafeCellDeref<'a, T>: private::SealedUnsafeCell {
/// # Safety
/// - The returned value must be unique and not alias any mutable or immutable references to the contents of the [`UnsafeCell`].
/// - At all times, you must avoid data races. If multiple threads have access to the same [`UnsafeCell`], then any writes must have a proper happens-before relation to all other accesses or use atomics ([`UnsafeCell`] docs for reference).
unsafe fn deref_mut(self) -> &'a mut T;
/// # Safety
/// - For the lifetime `'a` of the returned value you must not construct a mutable reference to the contents of the [`UnsafeCell`].
/// - At all times, you must avoid data races. If multiple threads have access to the same [`UnsafeCell`], then any writes must have a proper happens-before relation to all other accesses or use atomics ([`UnsafeCell`] docs for reference).
unsafe fn deref(self) -> &'a T;
/// Returns a copy of the contained value.
///
/// # Safety
/// - The [`UnsafeCell`] must not currently have a mutable reference to its content.
/// - At all times, you must avoid data races. If multiple threads have access to the same [`UnsafeCell`], then any writes must have a proper happens-before relation to all other accesses or use atomics ([`UnsafeCell`] docs for reference).
unsafe fn read(self) -> T
where
T: Copy;
}
impl<'a, T> UnsafeCellDeref<'a, T> for &'a UnsafeCell<T> {
#[inline]
unsafe fn deref_mut(self) -> &'a mut T {
// SAFETY: The caller upholds the alias rules.
unsafe { &mut *self.get() }
}
#[inline]
unsafe fn deref(self) -> &'a T {
// SAFETY: The caller upholds the alias rules.
unsafe { &*self.get() }
}
#[inline]
unsafe fn read(self) -> T
where
T: Copy,
{
// SAFETY: The caller upholds the alias rules.
unsafe { self.get().read() }
}
}
trait DebugEnsureAligned {
fn debug_ensure_aligned(self) -> Self;
}
// Disable this for miri runs as it already checks if pointer to reference
// casts are properly aligned.
#[cfg(all(debug_assertions, not(miri)))]
impl<T: Sized> DebugEnsureAligned for *mut T {
#[track_caller]
fn debug_ensure_aligned(self) -> Self {
let align = align_of::<T>();
// Implementation shamelessly borrowed from the currently unstable
// ptr.is_aligned_to.
//
// Replace once https://github.com/rust-lang/rust/issues/96284 is stable.
assert_eq!(
self as usize & (align - 1),
0,
"pointer is not aligned. Address {:p} does not have alignment {} for type {}",
self,
align,
core::any::type_name::<T>()
);
self
}
}
#[cfg(any(not(debug_assertions), miri))]
impl<T: Sized> DebugEnsureAligned for *mut T {
#[inline(always)]
fn debug_ensure_aligned(self) -> Self {
self
}
}