From b36cb1c3b9a77c27ce8c920218a053b00759b318 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Sat, 12 Oct 2024 17:42:41 -0700 Subject: [PATCH] [pointer][transmute] Migrate from util This prepares us to rename `TransparentWrapper` to `TransmuteFrom`, which we'll do in a follow-up commit to preserve nice git diffs. Makes progress on #1122 gherrit-pr-id: Ifc49755af0d90eeefe7822d755d508403c266bda --- src/pointer/mod.rs | 1 + src/pointer/ptr.rs | 4 +- src/pointer/transmute.rs | 359 ++++++++++++++++++++++++++++++ src/util/macros.rs | 105 ++++++++- src/util/mod.rs | 458 +-------------------------------------- 5 files changed, 469 insertions(+), 458 deletions(-) create mode 100644 src/pointer/transmute.rs diff --git a/src/pointer/mod.rs b/src/pointer/mod.rs index 1b9bd44234..944a959da7 100644 --- a/src/pointer/mod.rs +++ b/src/pointer/mod.rs @@ -12,6 +12,7 @@ mod inner; #[doc(hidden)] pub mod invariant; mod ptr; +pub(crate) mod transmute; #[doc(hidden)] pub use invariant::{BecauseExclusive, BecauseImmutable, Read}; diff --git a/src/pointer/ptr.rs b/src/pointer/ptr.rs index b476d1428f..74219b7faa 100644 --- a/src/pointer/ptr.rs +++ b/src/pointer/ptr.rs @@ -172,7 +172,9 @@ mod _external { /// Methods for converting to and from `Ptr` and Rust's safe reference types. mod _conversions { use super::*; - use crate::util::{AlignmentVariance, Covariant, TransparentWrapper, ValidityVariance}; + use crate::pointer::transmute::{ + AlignmentVariance, Covariant, TransparentWrapper, ValidityVariance, + }; /// `&'a T` → `Ptr<'a, T>` impl<'a, T> Ptr<'a, T, (Shared, Aligned, Valid)> diff --git a/src/pointer/transmute.rs b/src/pointer/transmute.rs new file mode 100644 index 0000000000..113eb60ec3 --- /dev/null +++ b/src/pointer/transmute.rs @@ -0,0 +1,359 @@ +// Copyright 2024 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use core::{ + cell::UnsafeCell, + mem::{ManuallyDrop, MaybeUninit}, + num::Wrapping, +}; + +use crate::{ + pointer::invariant::{self, Invariants}, + Unalign, +}; + +/// A type which has the same layout as the type it wraps. +/// +/// # Safety +/// +/// `T: TransparentWrapper` implies that `T` has the same size as [`T::Inner`]. +/// Further, `T: TransparentWrapper` implies that: +/// - If `T::UnsafeCellVariance = Covariant`, then `T` has `UnsafeCell`s +/// covering the same byte ranges as `T::Inner`. +/// - If a `T` pointer satisfies the alignment invariant `I::Alignment`, then +/// that same pointer, cast to `T::Inner`, satisfies the alignment invariant +/// `>::Applied`. +/// - If a `T` pointer satisfies the validity invariant `I::Validity`, then that +/// same pointer, cast to `T::Inner`, satisfies the validity invariant +/// `>::Applied`. +/// +/// [`T::Inner`]: TransparentWrapper::Inner +/// [`UnsafeCell`]: core::cell::UnsafeCell +/// [`T::AlignmentVariance`]: TransparentWrapper::AlignmentVariance +/// [`T::ValidityVariance`]: TransparentWrapper::ValidityVariance +#[doc(hidden)] +pub unsafe trait TransparentWrapper { + type Inner: ?Sized; + + type UnsafeCellVariance; + type AlignmentVariance: AlignmentVariance; + type ValidityVariance: ValidityVariance; + + /// Casts a wrapper pointer to an inner pointer. + /// + /// # Safety + /// + /// The resulting pointer has the same address and provenance as `ptr`, and + /// addresses the same number of bytes. + fn cast_into_inner(ptr: *mut Self) -> *mut Self::Inner; + + /// Casts an inner pointer to a wrapper pointer. + /// + /// # Safety + /// + /// The resulting pointer has the same address and provenance as `ptr`, and + /// addresses the same number of bytes. + fn cast_from_inner(ptr: *mut Self::Inner) -> *mut Self; +} + +#[allow(unreachable_pub)] +#[doc(hidden)] +pub trait AlignmentVariance { + type Applied: invariant::Alignment; +} + +#[allow(unreachable_pub)] +#[doc(hidden)] +pub trait ValidityVariance { + type Applied: invariant::Validity; +} + +#[doc(hidden)] +#[allow(missing_copy_implementations, missing_debug_implementations)] +pub enum Covariant {} + +impl AlignmentVariance for Covariant { + type Applied = I; +} + +impl ValidityVariance for Covariant { + type Applied = I; +} + +#[doc(hidden)] +#[allow(missing_copy_implementations, missing_debug_implementations)] +pub enum Invariant {} + +impl AlignmentVariance for Invariant { + type Applied = invariant::Unknown; +} + +impl ValidityVariance for Invariant { + type Applied = invariant::Unknown; +} + +// SAFETY: +// - Per [1], `MaybeUninit` has the same size as `T`. +// - See inline comments for other safety justifications. +// +// [1] Per https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#layout-1: +// +// `MaybeUninit` is guaranteed to have the same size, alignment, and ABI as +// `T` +unsafe impl TransparentWrapper for MaybeUninit { + type Inner = T; + + // SAFETY: `MaybeUninit` has `UnsafeCell`s covering the same byte ranges + // as `Inner = T`. This is not explicitly documented, but it can be + // inferred. Per [1] in the preceding safety comment, `MaybeUninit` has + // the same size as `T`. Further, note the signature of + // `MaybeUninit::assume_init_ref` [2]: + // + // pub unsafe fn assume_init_ref(&self) -> &T + // + // If the argument `&MaybeUninit` and the returned `&T` had `UnsafeCell`s + // at different offsets, this would be unsound. Its existence is proof that + // this is not the case. + // + // [2] https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#method.assume_init_ref + type UnsafeCellVariance = Covariant; + // SAFETY: Per [1], `MaybeUninit` has the same layout as `T`, and thus + // has the same alignment as `T`. + // + // [1] Per https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#layout-1: + // + // `MaybeUninit` is guaranteed to have the same size, alignment, and + // ABI as `T`. + type AlignmentVariance = Covariant; + // SAFETY: `MaybeUninit` has no validity invariants. Thus, a valid + // `MaybeUninit` is not necessarily a valid `T`. + type ValidityVariance = Invariant; + + #[inline(always)] + fn cast_into_inner(ptr: *mut MaybeUninit) -> *mut T { + // SAFETY: Per [1] (from comment above), `MaybeUninit` has the same + // layout as `T`. Thus, this cast preserves size. + // + // This cast trivially preserves provenance. + ptr.cast::() + } + + #[inline(always)] + fn cast_from_inner(ptr: *mut T) -> *mut MaybeUninit { + // SAFETY: Per [1] (from comment above), `MaybeUninit` has the same + // layout as `T`. Thus, this cast preserves size. + // + // This cast trivially preserves provenance. + ptr.cast::>() + } +} + +// SAFETY: +// - Per [1], `ManuallyDrop` has the same size as `T`. +// - See inline comments for other safety justifications. +// +// [1] Per https://doc.rust-lang.org/1.81.0/std/mem/struct.ManuallyDrop.html: +// +// `ManuallyDrop` is guaranteed to have the same layout and bit validity as +// `T` +unsafe impl TransparentWrapper for ManuallyDrop { + type Inner = T; + + // SAFETY: Per [1], `ManuallyDrop` has `UnsafeCell`s covering the same + // byte ranges as `Inner = T`. + // + // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/struct.ManuallyDrop.html: + // + // `ManuallyDrop` is guaranteed to have the same layout and bit + // validity as `T`, and is subject to the same layout optimizations as + // `T`. As a consequence, it has no effect on the assumptions that the + // compiler makes about its contents. + type UnsafeCellVariance = Covariant; + // SAFETY: Per [1], `ManuallyDrop` has the same layout as `T`, and thus + // has the same alignment as `T`. + // + // [1] Per https://doc.rust-lang.org/nightly/core/mem/struct.ManuallyDrop.html: + // + // `ManuallyDrop` is guaranteed to have the same layout and bit + // validity as `T` + type AlignmentVariance = Covariant; + + // SAFETY: Per [1] (from comment above), `ManuallyDrop` has the same bit + // validity as `T`. + type ValidityVariance = Covariant; + + #[inline(always)] + fn cast_into_inner(ptr: *mut ManuallyDrop) -> *mut T { + // SAFETY: Per [1] (from comment above), `ManuallyDrop` has the same + // layout as `T`. Thus, this cast preserves size even if `T` is unsized. + // + // This cast trivially preserves provenance. + #[allow(clippy::as_conversions)] + return ptr as *mut T; + } + + #[inline(always)] + fn cast_from_inner(ptr: *mut T) -> *mut ManuallyDrop { + // SAFETY: Per [1] (from comment above), `ManuallyDrop` has the same + // layout as `T`. Thus, this cast preserves size even if `T` is unsized. + // + // This cast trivially preserves provenance. + #[allow(clippy::as_conversions)] + return ptr as *mut ManuallyDrop; + } +} + +// SAFETY: +// - Per [1], `Wrapping` has the same size as `T`. +// - See inline comments for other safety justifications. +// +// [1] Per https://doc.rust-lang.org/1.81.0/std/num/struct.Wrapping.html#layout-1: +// +// `Wrapping` is guaranteed to have the same layout and ABI as `T`. +unsafe impl TransparentWrapper for Wrapping { + type Inner = T; + + // SAFETY: Per [1], `Wrapping` has the same layout as `T`. Since its + // single field (of type `T`) is public, it would be a breaking change to + // add or remove fields. Thus, we know that `Wrapping` contains a `T` (as + // opposed to just having the same size and alignment as `T`) with no pre- + // or post-padding. Thus, `Wrapping` must have `UnsafeCell`s covering the + // same byte ranges as `Inner = T`. + // + // [1] Per https://doc.rust-lang.org/1.81.0/std/num/struct.Wrapping.html#layout-1: + // + // `Wrapping` is guaranteed to have the same layout and ABI as `T`. + type UnsafeCellVariance = Covariant; + // SAFETY: Per [1], `Wrapping` has the same layout as `T`, and thus has + // the same alignment as `T`. + // + // [1] Per https://doc.rust-lang.org/core/num/struct.Wrapping.html#layout-1: + // + // `Wrapping` is guaranteed to have the same layout and ABI as `T`. + type AlignmentVariance = Covariant; + + // SAFETY: `Wrapping` has only one field, which is `pub` [2]. We are also + // guaranteed per [1] (from the comment above) that `Wrapping` has the + // same layout as `T`. The only way for both of these to be true + // simultaneously is for `Wrapping` to have the same bit validity as `T`. + // In particular, in order to change the bit validity, one of the following + // would need to happen: + // - `Wrapping` could change its `repr`, but this would violate the layout + // guarantee. + // - `Wrapping` could add or change its fields, but this would be a + // stability-breaking change. + // + // [2] https://doc.rust-lang.org/core/num/struct.Wrapping.html + type ValidityVariance = Covariant; + + #[inline(always)] + fn cast_into_inner(ptr: *mut Wrapping) -> *mut T { + // SAFETY: Per [1] (from comment above), `Wrapping` has the same + // layout as `T`. Thus, this cast preserves size. + // + // This cast trivially preserves provenance. + ptr.cast::() + } + + #[inline(always)] + fn cast_from_inner(ptr: *mut T) -> *mut Wrapping { + // SAFETY: Per [1] (from comment above), `Wrapping` has the same + // layout as `T`. Thus, this cast preserves size. + // + // This cast trivially preserves provenance. + ptr.cast::>() + } +} + +// SAFETY: +// - Per [1], `UnsafeCell` has the same size as `T`. +// - See inline comments for other safety justifications. +// +// [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout: +// +// `UnsafeCell` has the same in-memory representation as its inner type +// `T`. +unsafe impl TransparentWrapper for UnsafeCell { + type Inner = T; + + // SAFETY: Since we set this to `Invariant`, we make no safety claims. + type UnsafeCellVariance = Invariant; + + // SAFETY: Per [1] (from comment on impl), `Unalign` has the same + // representation as `T`, and thus has the same alignment as `T`. + type AlignmentVariance = Covariant; + + // SAFETY: Per [1], `Unalign` has the same bit validity as `T`. + // Technically the term "representation" doesn't guarantee this, but the + // subsequent sentence in the documentation makes it clear that this is the + // intention. + // + // [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout: + // + // `UnsafeCell` has the same in-memory representation as its inner type + // `T`. A consequence of this guarantee is that it is possible to convert + // between `T` and `UnsafeCell`. + type ValidityVariance = Covariant; + + #[inline(always)] + fn cast_into_inner(ptr: *mut UnsafeCell) -> *mut T { + // SAFETY: Per [1] (from comment above), `UnsafeCell` has the same + // representation as `T`. Thus, this cast preserves size. + // + // This cast trivially preserves provenance. + #[allow(clippy::as_conversions)] + return ptr as *mut T; + } + + #[inline(always)] + fn cast_from_inner(ptr: *mut T) -> *mut UnsafeCell { + // SAFETY: Per [1] (from comment above), `UnsafeCell` has the same + // representation as `T`. Thus, this cast preserves size. + // + // This cast trivially preserves provenance. + #[allow(clippy::as_conversions)] + return ptr as *mut UnsafeCell; + } +} + +// SAFETY: `Unalign` promises to have the same size as `T`. +// +// See inline comments for other safety justifications. +unsafe impl TransparentWrapper for Unalign { + type Inner = T; + + // SAFETY: `Unalign` promises to have `UnsafeCell`s covering the same + // byte ranges as `Inner = T`. + type UnsafeCellVariance = Covariant; + + // SAFETY: Since `Unalign` promises to have alignment 1 regardless of + // `T`'s alignment. Thus, an aligned pointer to `Unalign` is not + // necessarily an aligned pointer to `T`. + type AlignmentVariance = Invariant; + + // SAFETY: `Unalign` promises to have the same validity as `T`. + type ValidityVariance = Covariant; + + #[inline(always)] + fn cast_into_inner(ptr: *mut Unalign) -> *mut T { + // SAFETY: Per the safety comment on the impl block, `Unalign` has + // the size as `T`. Thus, this cast preserves size. + // + // This cast trivially preserves provenance. + ptr.cast::() + } + + #[inline(always)] + fn cast_from_inner(ptr: *mut T) -> *mut Unalign { + // SAFETY: Per the safety comment on the impl block, `Unalign` has + // the size as `T`. Thus, this cast preserves size. + // + // This cast trivially preserves provenance. + ptr.cast::>() + } +} diff --git a/src/util/macros.rs b/src/util/macros.rs index 263fde6ac7..725e75c58d 100644 --- a/src/util/macros.rs +++ b/src/util/macros.rs @@ -239,7 +239,7 @@ macro_rules! impl_for_transparent_wrapper { #[allow(dead_code, clippy::missing_inline_in_public_items)] #[cfg_attr(coverage_nightly, coverage(off))] fn only_derive_is_allowed_to_implement_this_trait() { - use crate::{pointer::invariant::Invariants, util::*}; + use crate::pointer::{invariant::Invariants, transmute::*}; impl_for_transparent_wrapper!(@define_is_transparent_wrapper $trait); @@ -343,6 +343,109 @@ macro_rules! impl_for_transparent_wrapper { }; } +/// Implements `TransparentWrapper` for an atomic type. +/// +/// # Safety +/// +/// The caller promises that `$atomic` is an atomic type whose natie equivalent +/// is `$native`. +#[cfg(any( + target_has_atomic = "8", + target_has_atomic = "16", + target_has_atomic = "32", + target_has_atomic = "64", + target_has_atomic = "ptr" +))] +macro_rules! unsafe_impl_transparent_wrapper_for_atomic { + ($(#[$attr:meta])* $(,)?) => {}; + ($(#[$attr:meta])* $atomic:ty [$native:ty], $($atomics:ty [$natives:ty]),* $(,)?) => { + $(#[$attr])* + // SAFETY: See safety comment in next match arm. + unsafe impl crate::pointer::transmute::TransparentWrapper for $atomic { + unsafe_impl_transparent_wrapper_for_atomic!(@inner $atomic [$native]); + } + unsafe_impl_transparent_wrapper_for_atomic!($(#[$attr])* $($atomics [$natives],)*); + }; + ($(#[$attr:meta])* $tyvar:ident => $atomic:ty [$native:ty]) => { + // We implement for `$atomic` and set `Inner = $native`. The caller has + // promised that `$atomic` and `$native` are an atomic type and its + // native counterpart, respectively. Per [1], `$atomic` and `$native` + // have the same size. + // + // [1] Per (for example) https://doc.rust-lang.org/1.81.0/std/sync/atomic/struct.AtomicU64.html: + // + // This type has the same size and bit validity as the underlying + // integer type + $(#[$attr])* + unsafe impl<$tyvar, I: crate::invariant::Invariants> crate::pointer::transmute::TransparentWrapper for $atomic { + unsafe_impl_transparent_wrapper_for_atomic!(@inner $atomic [$native]); + } + }; + (@inner $atomic:ty [$native:ty]) => { + type Inner = UnsafeCell<$native>; + + // SAFETY: It is "obvious" that each atomic type contains a single + // `UnsafeCell` that covers all bytes of the type, but we can also prove + // it: + // - Since `$atomic` provides an API which permits loading and storing + // values of type `$native` via a `&self` (shared) reference, *some* + // interior mutation must be happening, and interior mutation can only + // happen via `UnsafeCell`. Further, there must be enough bytes in + // `$atomic` covered by an `UnsafeCell` to hold every possible value + // of `$native`. + // - Per [1], `$atomic` has the same size as `$native`. This on its own + // isn't enough: it would still be possible for `$atomic` to store + // `$native` using a compact representation (for `$native` types for + // which some bit patterns are illegal). However, this is ruled out by + // the fact that `$atomic` has the same bit validity as `$native` [1]. + // Thus, we can conclude that every byte of `$atomic` must be covered + // by an `UnsafeCell`. + // + // Thus, every byte of `$atomic` is covered by an `UnsafeCell`, and we + // set `type Inner = UnsafeCell<$native>`. Thus, `Self` and + // `Self::Inner` have `UnsafeCell`s covering the same byte ranges. + // + // [1] Per (for example) https://doc.rust-lang.org/1.81.0/std/sync/atomic/struct.AtomicU64.html: + // + // This type has the same size and bit validity as the underlying + // integer type + type UnsafeCellVariance = crate::pointer::transmute::Covariant; + + // SAFETY: No safety justification is required for an invariant + // variance. + type AlignmentVariance = crate::pointer::transmute::Invariant; + + // SAFETY: Per [1], all atomic types have the same bit validity as their + // native counterparts. The caller has promised that `$atomic` and + // `$native` are an atomic type and its native counterpart, + // respectively. + // + // [1] Per (for example) https://doc.rust-lang.org/1.81.0/std/sync/atomic/struct.AtomicU64.html: + // + // This type has the same size and bit validity as the underlying + // integer type + type ValidityVariance = crate::pointer::transmute::Covariant; + + #[inline(always)] + fn cast_into_inner(ptr: *mut $atomic) -> *mut UnsafeCell<$native> { + // SAFETY: Per [1] (from comment on impl block), `$atomic` has the + // same size as `$native`. Thus, this cast preserves size. + // + // This cast trivially preserves provenance. + ptr.cast::>() + } + + #[inline(always)] + fn cast_from_inner(ptr: *mut UnsafeCell<$native>) -> *mut $atomic { + // SAFETY: Per [1] (from comment on impl block), `$atomic` has the + // same size as `$native`. Thus, this cast preserves size. + // + // This cast trivially preserves provenance. + ptr.cast::<$atomic>() + } + }; +} + /// Implements a trait for a type, bounding on each memeber of the power set of /// a set of type variables. This is useful for implementing traits for tuples /// or `fn` types. diff --git a/src/util/mod.rs b/src/util/mod.rs index dd2e5bdd61..3822873dfe 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -12,463 +12,9 @@ mod macros; #[doc(hidden)] pub mod macro_util; -use core::{ - cell::UnsafeCell, - marker::PhantomData, - mem::{self, ManuallyDrop, MaybeUninit}, - num::{NonZeroUsize, Wrapping}, - ptr::NonNull, -}; - -use crate::{ - error::AlignmentError, - pointer::invariant::{self, Invariants}, - Unalign, -}; - -/// A type which has the same layout as the type it wraps. -/// -/// # Safety -/// -/// `T: TransparentWrapper` implies that `T` has the same size as [`T::Inner`]. -/// Further, `T: TransparentWrapper` implies that: -/// - If `T::UnsafeCellVariance = Covariant`, then `T` has `UnsafeCell`s -/// covering the same byte ranges as `T::Inner`. -/// - If a `T` pointer satisfies the alignment invariant `I::Alignment`, then -/// that same pointer, cast to `T::Inner`, satisfies the alignment invariant -/// `>::Applied`. -/// - If a `T` pointer satisfies the validity invariant `I::Validity`, then that -/// same pointer, cast to `T::Inner`, satisfies the validity invariant -/// `>::Applied`. -/// -/// [`T::Inner`]: TransparentWrapper::Inner -/// [`UnsafeCell`]: core::cell::UnsafeCell -/// [`T::AlignmentVariance`]: TransparentWrapper::AlignmentVariance -/// [`T::ValidityVariance`]: TransparentWrapper::ValidityVariance -#[doc(hidden)] -pub unsafe trait TransparentWrapper { - type Inner: ?Sized; - - type UnsafeCellVariance; - type AlignmentVariance: AlignmentVariance; - type ValidityVariance: ValidityVariance; - - /// Casts a wrapper pointer to an inner pointer. - /// - /// # Safety - /// - /// The resulting pointer has the same address and provenance as `ptr`, and - /// addresses the same number of bytes. - fn cast_into_inner(ptr: *mut Self) -> *mut Self::Inner; +use core::{marker::PhantomData, mem, num::NonZeroUsize, ptr::NonNull}; - /// Casts an inner pointer to a wrapper pointer. - /// - /// # Safety - /// - /// The resulting pointer has the same address and provenance as `ptr`, and - /// addresses the same number of bytes. - fn cast_from_inner(ptr: *mut Self::Inner) -> *mut Self; -} - -#[allow(unreachable_pub)] -#[doc(hidden)] -pub trait AlignmentVariance { - type Applied: invariant::Alignment; -} - -#[allow(unreachable_pub)] -#[doc(hidden)] -pub trait ValidityVariance { - type Applied: invariant::Validity; -} - -#[doc(hidden)] -#[allow(missing_copy_implementations, missing_debug_implementations)] -pub enum Covariant {} - -impl AlignmentVariance for Covariant { - type Applied = I; -} - -impl ValidityVariance for Covariant { - type Applied = I; -} - -#[doc(hidden)] -#[allow(missing_copy_implementations, missing_debug_implementations)] -pub enum Invariant {} - -impl AlignmentVariance for Invariant { - type Applied = invariant::Unknown; -} - -impl ValidityVariance for Invariant { - type Applied = invariant::Unknown; -} - -// SAFETY: -// - Per [1], `MaybeUninit` has the same size as `T`. -// - See inline comments for other safety justifications. -// -// [1] Per https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#layout-1: -// -// `MaybeUninit` is guaranteed to have the same size, alignment, and ABI as -// `T` -unsafe impl TransparentWrapper for MaybeUninit { - type Inner = T; - - // SAFETY: `MaybeUninit` has `UnsafeCell`s covering the same byte ranges - // as `Inner = T`. This is not explicitly documented, but it can be - // inferred. Per [1] in the preceding safety comment, `MaybeUninit` has - // the same size as `T`. Further, note the signature of - // `MaybeUninit::assume_init_ref` [2]: - // - // pub unsafe fn assume_init_ref(&self) -> &T - // - // If the argument `&MaybeUninit` and the returned `&T` had `UnsafeCell`s - // at different offsets, this would be unsound. Its existence is proof that - // this is not the case. - // - // [2] https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#method.assume_init_ref - type UnsafeCellVariance = Covariant; - // SAFETY: Per [1], `MaybeUninit` has the same layout as `T`, and thus - // has the same alignment as `T`. - // - // [1] Per https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#layout-1: - // - // `MaybeUninit` is guaranteed to have the same size, alignment, and - // ABI as `T`. - type AlignmentVariance = Covariant; - // SAFETY: `MaybeUninit` has no validity invariants. Thus, a valid - // `MaybeUninit` is not necessarily a valid `T`. - type ValidityVariance = Invariant; - - #[inline(always)] - fn cast_into_inner(ptr: *mut MaybeUninit) -> *mut T { - // SAFETY: Per [1] (from comment above), `MaybeUninit` has the same - // layout as `T`. Thus, this cast preserves size. - // - // This cast trivially preserves provenance. - ptr.cast::() - } - - #[inline(always)] - fn cast_from_inner(ptr: *mut T) -> *mut MaybeUninit { - // SAFETY: Per [1] (from comment above), `MaybeUninit` has the same - // layout as `T`. Thus, this cast preserves size. - // - // This cast trivially preserves provenance. - ptr.cast::>() - } -} - -// SAFETY: -// - Per [1], `ManuallyDrop` has the same size as `T`. -// - See inline comments for other safety justifications. -// -// [1] Per https://doc.rust-lang.org/1.81.0/std/mem/struct.ManuallyDrop.html: -// -// `ManuallyDrop` is guaranteed to have the same layout and bit validity as -// `T` -unsafe impl TransparentWrapper for ManuallyDrop { - type Inner = T; - - // SAFETY: Per [1], `ManuallyDrop` has `UnsafeCell`s covering the same - // byte ranges as `Inner = T`. - // - // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/struct.ManuallyDrop.html: - // - // `ManuallyDrop` is guaranteed to have the same layout and bit - // validity as `T`, and is subject to the same layout optimizations as - // `T`. As a consequence, it has no effect on the assumptions that the - // compiler makes about its contents. - type UnsafeCellVariance = Covariant; - // SAFETY: Per [1], `ManuallyDrop` has the same layout as `T`, and thus - // has the same alignment as `T`. - // - // [1] Per https://doc.rust-lang.org/nightly/core/mem/struct.ManuallyDrop.html: - // - // `ManuallyDrop` is guaranteed to have the same layout and bit - // validity as `T` - type AlignmentVariance = Covariant; - - // SAFETY: Per [1] (from comment above), `ManuallyDrop` has the same bit - // validity as `T`. - type ValidityVariance = Covariant; - - #[inline(always)] - fn cast_into_inner(ptr: *mut ManuallyDrop) -> *mut T { - // SAFETY: Per [1] (from comment above), `ManuallyDrop` has the same - // layout as `T`. Thus, this cast preserves size even if `T` is unsized. - // - // This cast trivially preserves provenance. - #[allow(clippy::as_conversions)] - return ptr as *mut T; - } - - #[inline(always)] - fn cast_from_inner(ptr: *mut T) -> *mut ManuallyDrop { - // SAFETY: Per [1] (from comment above), `ManuallyDrop` has the same - // layout as `T`. Thus, this cast preserves size even if `T` is unsized. - // - // This cast trivially preserves provenance. - #[allow(clippy::as_conversions)] - return ptr as *mut ManuallyDrop; - } -} - -// SAFETY: -// - Per [1], `Wrapping` has the same size as `T`. -// - See inline comments for other safety justifications. -// -// [1] Per https://doc.rust-lang.org/1.81.0/std/num/struct.Wrapping.html#layout-1: -// -// `Wrapping` is guaranteed to have the same layout and ABI as `T`. -unsafe impl TransparentWrapper for Wrapping { - type Inner = T; - - // SAFETY: Per [1], `Wrapping` has the same layout as `T`. Since its - // single field (of type `T`) is public, it would be a breaking change to - // add or remove fields. Thus, we know that `Wrapping` contains a `T` (as - // opposed to just having the same size and alignment as `T`) with no pre- - // or post-padding. Thus, `Wrapping` must have `UnsafeCell`s covering the - // same byte ranges as `Inner = T`. - // - // [1] Per https://doc.rust-lang.org/1.81.0/std/num/struct.Wrapping.html#layout-1: - // - // `Wrapping` is guaranteed to have the same layout and ABI as `T`. - type UnsafeCellVariance = Covariant; - // SAFETY: Per [1], `Wrapping` has the same layout as `T`, and thus has - // the same alignment as `T`. - // - // [1] Per https://doc.rust-lang.org/core/num/struct.Wrapping.html#layout-1: - // - // `Wrapping` is guaranteed to have the same layout and ABI as `T`. - type AlignmentVariance = Covariant; - - // SAFETY: `Wrapping` has only one field, which is `pub` [2]. We are also - // guaranteed per [1] (from the comment above) that `Wrapping` has the - // same layout as `T`. The only way for both of these to be true - // simultaneously is for `Wrapping` to have the same bit validity as `T`. - // In particular, in order to change the bit validity, one of the following - // would need to happen: - // - `Wrapping` could change its `repr`, but this would violate the layout - // guarantee. - // - `Wrapping` could add or change its fields, but this would be a - // stability-breaking change. - // - // [2] https://doc.rust-lang.org/core/num/struct.Wrapping.html - type ValidityVariance = Covariant; - - #[inline(always)] - fn cast_into_inner(ptr: *mut Wrapping) -> *mut T { - // SAFETY: Per [1] (from comment above), `Wrapping` has the same - // layout as `T`. Thus, this cast preserves size. - // - // This cast trivially preserves provenance. - ptr.cast::() - } - - #[inline(always)] - fn cast_from_inner(ptr: *mut T) -> *mut Wrapping { - // SAFETY: Per [1] (from comment above), `Wrapping` has the same - // layout as `T`. Thus, this cast preserves size. - // - // This cast trivially preserves provenance. - ptr.cast::>() - } -} - -// SAFETY: -// - Per [1], `UnsafeCell` has the same size as `T`. -// - See inline comments for other safety justifications. -// -// [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout: -// -// `UnsafeCell` has the same in-memory representation as its inner type -// `T`. -unsafe impl TransparentWrapper for UnsafeCell { - type Inner = T; - - // SAFETY: Since we set this to `Invariant`, we make no safety claims. - type UnsafeCellVariance = Invariant; - - // SAFETY: Per [1] (from comment on impl), `Unalign` has the same - // representation as `T`, and thus has the same alignment as `T`. - type AlignmentVariance = Covariant; - - // SAFETY: Per [1], `Unalign` has the same bit validity as `T`. - // Technically the term "representation" doesn't guarantee this, but the - // subsequent sentence in the documentation makes it clear that this is the - // intention. - // - // [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout: - // - // `UnsafeCell` has the same in-memory representation as its inner type - // `T`. A consequence of this guarantee is that it is possible to convert - // between `T` and `UnsafeCell`. - type ValidityVariance = Covariant; - - #[inline(always)] - fn cast_into_inner(ptr: *mut UnsafeCell) -> *mut T { - // SAFETY: Per [1] (from comment above), `UnsafeCell` has the same - // representation as `T`. Thus, this cast preserves size. - // - // This cast trivially preserves provenance. - #[allow(clippy::as_conversions)] - return ptr as *mut T; - } - - #[inline(always)] - fn cast_from_inner(ptr: *mut T) -> *mut UnsafeCell { - // SAFETY: Per [1] (from comment above), `UnsafeCell` has the same - // representation as `T`. Thus, this cast preserves size. - // - // This cast trivially preserves provenance. - #[allow(clippy::as_conversions)] - return ptr as *mut UnsafeCell; - } -} - -// SAFETY: `Unalign` promises to have the same size as `T`. -// -// See inline comments for other safety justifications. -unsafe impl TransparentWrapper for Unalign { - type Inner = T; - - // SAFETY: `Unalign` promises to have `UnsafeCell`s covering the same - // byte ranges as `Inner = T`. - type UnsafeCellVariance = Covariant; - - // SAFETY: Since `Unalign` promises to have alignment 1 regardless of - // `T`'s alignment. Thus, an aligned pointer to `Unalign` is not - // necessarily an aligned pointer to `T`. - type AlignmentVariance = Invariant; - - // SAFETY: `Unalign` promises to have the same validity as `T`. - type ValidityVariance = Covariant; - - #[inline(always)] - fn cast_into_inner(ptr: *mut Unalign) -> *mut T { - // SAFETY: Per the safety comment on the impl block, `Unalign` has - // the size as `T`. Thus, this cast preserves size. - // - // This cast trivially preserves provenance. - ptr.cast::() - } - - #[inline(always)] - fn cast_from_inner(ptr: *mut T) -> *mut Unalign { - // SAFETY: Per the safety comment on the impl block, `Unalign` has - // the size as `T`. Thus, this cast preserves size. - // - // This cast trivially preserves provenance. - ptr.cast::>() - } -} - -/// Implements `TransparentWrapper` for an atomic type. -/// -/// # Safety -/// -/// The caller promises that `$atomic` is an atomic type whose natie equivalent -/// is `$native`. -#[cfg(any( - target_has_atomic = "8", - target_has_atomic = "16", - target_has_atomic = "32", - target_has_atomic = "64", - target_has_atomic = "ptr" -))] -macro_rules! unsafe_impl_transparent_wrapper_for_atomic { - ($(#[$attr:meta])* $(,)?) => {}; - ($(#[$attr:meta])* $atomic:ty [$native:ty], $($atomics:ty [$natives:ty]),* $(,)?) => { - $(#[$attr])* - // SAFETY: See safety comment in next match arm. - unsafe impl crate::util::TransparentWrapper for $atomic { - unsafe_impl_transparent_wrapper_for_atomic!(@inner $atomic [$native]); - } - unsafe_impl_transparent_wrapper_for_atomic!($(#[$attr])* $($atomics [$natives],)*); - }; - ($(#[$attr:meta])* $tyvar:ident => $atomic:ty [$native:ty]) => { - // We implement for `$atomic` and set `Inner = $native`. The caller has - // promised that `$atomic` and `$native` are an atomic type and its - // native counterpart, respectively. Per [1], `$atomic` and `$native` - // have the same size. - // - // [1] Per (for example) https://doc.rust-lang.org/1.81.0/std/sync/atomic/struct.AtomicU64.html: - // - // This type has the same size and bit validity as the underlying - // integer type - $(#[$attr])* - unsafe impl<$tyvar, I: crate::invariant::Invariants> crate::util::TransparentWrapper for $atomic { - unsafe_impl_transparent_wrapper_for_atomic!(@inner $atomic [$native]); - } - }; - (@inner $atomic:ty [$native:ty]) => { - type Inner = UnsafeCell<$native>; - - // SAFETY: It is "obvious" that each atomic type contains a single - // `UnsafeCell` that covers all bytes of the type, but we can also prove - // it: - // - Since `$atomic` provides an API which permits loading and storing - // values of type `$native` via a `&self` (shared) reference, *some* - // interior mutation must be happening, and interior mutation can only - // happen via `UnsafeCell`. Further, there must be enough bytes in - // `$atomic` covered by an `UnsafeCell` to hold every possible value - // of `$native`. - // - Per [1], `$atomic` has the same size as `$native`. This on its own - // isn't enough: it would still be possible for `$atomic` to store - // `$native` using a compact representation (for `$native` types for - // which some bit patterns are illegal). However, this is ruled out by - // the fact that `$atomic` has the same bit validity as `$native` [1]. - // Thus, we can conclude that every byte of `$atomic` must be covered - // by an `UnsafeCell`. - // - // Thus, every byte of `$atomic` is covered by an `UnsafeCell`, and we - // set `type Inner = UnsafeCell<$native>`. Thus, `Self` and - // `Self::Inner` have `UnsafeCell`s covering the same byte ranges. - // - // [1] Per (for example) https://doc.rust-lang.org/1.81.0/std/sync/atomic/struct.AtomicU64.html: - // - // This type has the same size and bit validity as the underlying - // integer type - type UnsafeCellVariance = crate::util::Covariant; - - // SAFETY: No safety justification is required for an invariant - // variance. - type AlignmentVariance = crate::util::Invariant; - - // SAFETY: Per [1], all atomic types have the same bit validity as their - // native counterparts. The caller has promised that `$atomic` and - // `$native` are an atomic type and its native counterpart, - // respectively. - // - // [1] Per (for example) https://doc.rust-lang.org/1.81.0/std/sync/atomic/struct.AtomicU64.html: - // - // This type has the same size and bit validity as the underlying - // integer type - type ValidityVariance = crate::util::Covariant; - - #[inline(always)] - fn cast_into_inner(ptr: *mut $atomic) -> *mut UnsafeCell<$native> { - // SAFETY: Per [1] (from comment on impl block), `$atomic` has the - // same size as `$native`. Thus, this cast preserves size. - // - // This cast trivially preserves provenance. - ptr.cast::>() - } - - #[inline(always)] - fn cast_from_inner(ptr: *mut UnsafeCell<$native>) -> *mut $atomic { - // SAFETY: Per [1] (from comment on impl block), `$atomic` has the - // same size as `$native`. Thus, this cast preserves size. - // - // This cast trivially preserves provenance. - ptr.cast::<$atomic>() - } - }; -} +use crate::error::AlignmentError; /// Like [`PhantomData`], but [`Send`] and [`Sync`] regardless of whether the /// wrapped `T` is.