| 
 | 1 | +// Copyright 2024 The Fuchsia Authors  | 
 | 2 | +//  | 
 | 3 | +// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0  | 
 | 4 | +// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT  | 
 | 5 | +// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.  | 
 | 6 | +// This file may not be copied, modified, or distributed except according to  | 
 | 7 | +// those terms.  | 
 | 8 | + | 
 | 9 | +use core::{  | 
 | 10 | +    cell::UnsafeCell,  | 
 | 11 | +    mem::{ManuallyDrop, MaybeUninit},  | 
 | 12 | +    num::Wrapping,  | 
 | 13 | +};  | 
 | 14 | + | 
 | 15 | +use crate::{  | 
 | 16 | +    pointer::invariant::{self, Invariants},  | 
 | 17 | +    Unalign,  | 
 | 18 | +};  | 
 | 19 | + | 
 | 20 | +/// A type which has the same layout as the type it wraps.  | 
 | 21 | +///  | 
 | 22 | +/// # Safety  | 
 | 23 | +///  | 
 | 24 | +/// `T: TransparentWrapper` implies that `T` has the same size as [`T::Inner`].  | 
 | 25 | +/// Further, `T: TransparentWrapper<I>` implies that:  | 
 | 26 | +/// - If `T::UnsafeCellVariance = Covariant`, then `T` has `UnsafeCell`s  | 
 | 27 | +///   covering the same byte ranges as `T::Inner`.  | 
 | 28 | +/// - If a `T` pointer satisfies the alignment invariant `I::Alignment`, then  | 
 | 29 | +///   that same pointer, cast to `T::Inner`, satisfies the alignment invariant  | 
 | 30 | +///   `<T::AlignmentVariance as AlignmentVariance<I::Alignment>>::Applied`.  | 
 | 31 | +/// - If a `T` pointer satisfies the validity invariant `I::Validity`, then that  | 
 | 32 | +///   same pointer, cast to `T::Inner`, satisfies the validity invariant  | 
 | 33 | +///   `<T::ValidityVariance as ValidityVariance<I::Validity>>::Applied`.  | 
 | 34 | +///  | 
 | 35 | +/// [`T::Inner`]: TransparentWrapper::Inner  | 
 | 36 | +/// [`UnsafeCell`]: core::cell::UnsafeCell  | 
 | 37 | +/// [`T::AlignmentVariance`]: TransparentWrapper::AlignmentVariance  | 
 | 38 | +/// [`T::ValidityVariance`]: TransparentWrapper::ValidityVariance  | 
 | 39 | +#[doc(hidden)]  | 
 | 40 | +pub unsafe trait TransparentWrapper<I: Invariants> {  | 
 | 41 | +    type Inner: ?Sized;  | 
 | 42 | + | 
 | 43 | +    type UnsafeCellVariance;  | 
 | 44 | +    type AlignmentVariance: AlignmentVariance<I::Alignment>;  | 
 | 45 | +    type ValidityVariance: ValidityVariance<I::Validity>;  | 
 | 46 | + | 
 | 47 | +    /// Casts a wrapper pointer to an inner pointer.  | 
 | 48 | +    ///  | 
 | 49 | +    /// # Safety  | 
 | 50 | +    ///  | 
 | 51 | +    /// The resulting pointer has the same address and provenance as `ptr`, and  | 
 | 52 | +    /// addresses the same number of bytes.  | 
 | 53 | +    fn cast_into_inner(ptr: *mut Self) -> *mut Self::Inner;  | 
 | 54 | + | 
 | 55 | +    /// Casts an inner pointer to a wrapper pointer.  | 
 | 56 | +    ///  | 
 | 57 | +    /// # Safety  | 
 | 58 | +    ///  | 
 | 59 | +    /// The resulting pointer has the same address and provenance as `ptr`, and  | 
 | 60 | +    /// addresses the same number of bytes.  | 
 | 61 | +    fn cast_from_inner(ptr: *mut Self::Inner) -> *mut Self;  | 
 | 62 | +}  | 
 | 63 | + | 
 | 64 | +#[allow(unreachable_pub)]  | 
 | 65 | +#[doc(hidden)]  | 
 | 66 | +pub trait AlignmentVariance<I: invariant::Alignment> {  | 
 | 67 | +    type Applied: invariant::Alignment;  | 
 | 68 | +}  | 
 | 69 | + | 
 | 70 | +#[allow(unreachable_pub)]  | 
 | 71 | +#[doc(hidden)]  | 
 | 72 | +pub trait ValidityVariance<I: invariant::Validity> {  | 
 | 73 | +    type Applied: invariant::Validity;  | 
 | 74 | +}  | 
 | 75 | + | 
 | 76 | +#[doc(hidden)]  | 
 | 77 | +#[allow(missing_copy_implementations, missing_debug_implementations)]  | 
 | 78 | +pub enum Covariant {}  | 
 | 79 | + | 
 | 80 | +impl<I: invariant::Alignment> AlignmentVariance<I> for Covariant {  | 
 | 81 | +    type Applied = I;  | 
 | 82 | +}  | 
 | 83 | + | 
 | 84 | +impl<I: invariant::Validity> ValidityVariance<I> for Covariant {  | 
 | 85 | +    type Applied = I;  | 
 | 86 | +}  | 
 | 87 | + | 
 | 88 | +#[doc(hidden)]  | 
 | 89 | +#[allow(missing_copy_implementations, missing_debug_implementations)]  | 
 | 90 | +pub enum Invariant {}  | 
 | 91 | + | 
 | 92 | +impl<I: invariant::Alignment> AlignmentVariance<I> for Invariant {  | 
 | 93 | +    type Applied = invariant::Unknown;  | 
 | 94 | +}  | 
 | 95 | + | 
 | 96 | +impl<I: invariant::Validity> ValidityVariance<I> for Invariant {  | 
 | 97 | +    type Applied = invariant::Unknown;  | 
 | 98 | +}  | 
 | 99 | + | 
 | 100 | +// SAFETY:  | 
 | 101 | +// - Per [1], `MaybeUninit<T>` has the same size as `T`.  | 
 | 102 | +// - See inline comments for other safety justifications.  | 
 | 103 | +//  | 
 | 104 | +// [1] Per https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#layout-1:  | 
 | 105 | +//  | 
 | 106 | +//   `MaybeUninit<T>` is guaranteed to have the same size, alignment, and ABI as  | 
 | 107 | +//   `T`  | 
 | 108 | +unsafe impl<T, I: Invariants> TransparentWrapper<I> for MaybeUninit<T> {  | 
 | 109 | +    type Inner = T;  | 
 | 110 | + | 
 | 111 | +    // SAFETY: `MaybeUninit<T>` has `UnsafeCell`s covering the same byte ranges  | 
 | 112 | +    // as `Inner = T`. This is not explicitly documented, but it can be  | 
 | 113 | +    // inferred. Per [1] in the preceding safety comment, `MaybeUninit<T>` has  | 
 | 114 | +    // the same size as `T`. Further, note the signature of  | 
 | 115 | +    // `MaybeUninit::assume_init_ref` [2]:  | 
 | 116 | +    //  | 
 | 117 | +    //   pub unsafe fn assume_init_ref(&self) -> &T  | 
 | 118 | +    //  | 
 | 119 | +    // If the argument `&MaybeUninit<T>` and the returned `&T` had `UnsafeCell`s  | 
 | 120 | +    // at different offsets, this would be unsound. Its existence is proof that  | 
 | 121 | +    // this is not the case.  | 
 | 122 | +    //  | 
 | 123 | +    // [2] https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#method.assume_init_ref  | 
 | 124 | +    type UnsafeCellVariance = Covariant;  | 
 | 125 | +    // SAFETY: Per [1], `MaybeUninit<T>` has the same layout as `T`, and thus  | 
 | 126 | +    // has the same alignment as `T`.  | 
 | 127 | +    //  | 
 | 128 | +    // [1] Per https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#layout-1:  | 
 | 129 | +    //  | 
 | 130 | +    //   `MaybeUninit<T>` is guaranteed to have the same size, alignment, and  | 
 | 131 | +    //   ABI as `T`.  | 
 | 132 | +    type AlignmentVariance = Covariant;  | 
 | 133 | +    // SAFETY: `MaybeUninit` has no validity invariants. Thus, a valid  | 
 | 134 | +    // `MaybeUninit<T>` is not necessarily a valid `T`.  | 
 | 135 | +    type ValidityVariance = Invariant;  | 
 | 136 | + | 
 | 137 | +    #[inline(always)]  | 
 | 138 | +    fn cast_into_inner(ptr: *mut MaybeUninit<T>) -> *mut T {  | 
 | 139 | +        // SAFETY: Per [1] (from comment above), `MaybeUninit<T>` has the same  | 
 | 140 | +        // layout as `T`. Thus, this cast preserves size.  | 
 | 141 | +        //  | 
 | 142 | +        // This cast trivially preserves provenance.  | 
 | 143 | +        ptr.cast::<T>()  | 
 | 144 | +    }  | 
 | 145 | + | 
 | 146 | +    #[inline(always)]  | 
 | 147 | +    fn cast_from_inner(ptr: *mut T) -> *mut MaybeUninit<T> {  | 
 | 148 | +        // SAFETY: Per [1] (from comment above), `MaybeUninit<T>` has the same  | 
 | 149 | +        // layout as `T`. Thus, this cast preserves size.  | 
 | 150 | +        //  | 
 | 151 | +        // This cast trivially preserves provenance.  | 
 | 152 | +        ptr.cast::<MaybeUninit<T>>()  | 
 | 153 | +    }  | 
 | 154 | +}  | 
 | 155 | + | 
 | 156 | +// SAFETY:  | 
 | 157 | +// - Per [1], `ManuallyDrop<T>` has the same size as `T`.  | 
 | 158 | +// - See inline comments for other safety justifications.  | 
 | 159 | +//  | 
 | 160 | +// [1] Per https://doc.rust-lang.org/1.81.0/std/mem/struct.ManuallyDrop.html:  | 
 | 161 | +//  | 
 | 162 | +//   `ManuallyDrop<T>` is guaranteed to have the same layout and bit validity as  | 
 | 163 | +//   `T`  | 
 | 164 | +unsafe impl<T: ?Sized, I: Invariants> TransparentWrapper<I> for ManuallyDrop<T> {  | 
 | 165 | +    type Inner = T;  | 
 | 166 | + | 
 | 167 | +    // SAFETY: Per [1], `ManuallyDrop<T>` has `UnsafeCell`s covering the same  | 
 | 168 | +    // byte ranges as `Inner = T`.  | 
 | 169 | +    //  | 
 | 170 | +    // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/struct.ManuallyDrop.html:  | 
 | 171 | +    //  | 
 | 172 | +    //   `ManuallyDrop<T>` is guaranteed to have the same layout and bit  | 
 | 173 | +    //   validity as `T`, and is subject to the same layout optimizations as  | 
 | 174 | +    //   `T`. As a consequence, it has no effect on the assumptions that the  | 
 | 175 | +    //   compiler makes about its contents.  | 
 | 176 | +    type UnsafeCellVariance = Covariant;  | 
 | 177 | +    // SAFETY: Per [1], `ManuallyDrop<T>` has the same layout as `T`, and thus  | 
 | 178 | +    // has the same alignment as `T`.  | 
 | 179 | +    //  | 
 | 180 | +    // [1] Per https://doc.rust-lang.org/nightly/core/mem/struct.ManuallyDrop.html:  | 
 | 181 | +    //  | 
 | 182 | +    //   `ManuallyDrop<T>` is guaranteed to have the same layout and bit  | 
 | 183 | +    //   validity as `T`  | 
 | 184 | +    type AlignmentVariance = Covariant;  | 
 | 185 | + | 
 | 186 | +    // SAFETY: Per [1] (from comment above), `ManuallyDrop<T>` has the same bit  | 
 | 187 | +    // validity as `T`.  | 
 | 188 | +    type ValidityVariance = Covariant;  | 
 | 189 | + | 
 | 190 | +    #[inline(always)]  | 
 | 191 | +    fn cast_into_inner(ptr: *mut ManuallyDrop<T>) -> *mut T {  | 
 | 192 | +        // SAFETY: Per [1] (from comment above), `ManuallyDrop<T>` has the same  | 
 | 193 | +        // layout as `T`. Thus, this cast preserves size even if `T` is unsized.  | 
 | 194 | +        //  | 
 | 195 | +        // This cast trivially preserves provenance.  | 
 | 196 | +        #[allow(clippy::as_conversions)]  | 
 | 197 | +        return ptr as *mut T;  | 
 | 198 | +    }  | 
 | 199 | + | 
 | 200 | +    #[inline(always)]  | 
 | 201 | +    fn cast_from_inner(ptr: *mut T) -> *mut ManuallyDrop<T> {  | 
 | 202 | +        // SAFETY: Per [1] (from comment above), `ManuallyDrop<T>` has the same  | 
 | 203 | +        // layout as `T`. Thus, this cast preserves size even if `T` is unsized.  | 
 | 204 | +        //  | 
 | 205 | +        // This cast trivially preserves provenance.  | 
 | 206 | +        #[allow(clippy::as_conversions)]  | 
 | 207 | +        return ptr as *mut ManuallyDrop<T>;  | 
 | 208 | +    }  | 
 | 209 | +}  | 
 | 210 | + | 
 | 211 | +// SAFETY:  | 
 | 212 | +// - Per [1], `Wrapping<T>` has the same size as `T`.  | 
 | 213 | +// - See inline comments for other safety justifications.  | 
 | 214 | +//  | 
 | 215 | +// [1] Per https://doc.rust-lang.org/1.81.0/std/num/struct.Wrapping.html#layout-1:  | 
 | 216 | +//  | 
 | 217 | +//   `Wrapping<T>` is guaranteed to have the same layout and ABI as `T`.  | 
 | 218 | +unsafe impl<T, I: Invariants> TransparentWrapper<I> for Wrapping<T> {  | 
 | 219 | +    type Inner = T;  | 
 | 220 | + | 
 | 221 | +    // SAFETY: Per [1], `Wrapping<T>` has the same layout as `T`. Since its  | 
 | 222 | +    // single field (of type `T`) is public, it would be a breaking change to  | 
 | 223 | +    // add or remove fields. Thus, we know that `Wrapping<T>` contains a `T` (as  | 
 | 224 | +    // opposed to just having the same size and alignment as `T`) with no pre-  | 
 | 225 | +    // or post-padding. Thus, `Wrapping<T>` must have `UnsafeCell`s covering the  | 
 | 226 | +    // same byte ranges as `Inner = T`.  | 
 | 227 | +    //  | 
 | 228 | +    // [1] Per https://doc.rust-lang.org/1.81.0/std/num/struct.Wrapping.html#layout-1:  | 
 | 229 | +    //  | 
 | 230 | +    //   `Wrapping<T>` is guaranteed to have the same layout and ABI as `T`.  | 
 | 231 | +    type UnsafeCellVariance = Covariant;  | 
 | 232 | +    // SAFETY: Per [1], `Wrapping<T>` has the same layout as `T`, and thus has  | 
 | 233 | +    // the same alignment as `T`.  | 
 | 234 | +    //  | 
 | 235 | +    // [1] Per https://doc.rust-lang.org/core/num/struct.Wrapping.html#layout-1:  | 
 | 236 | +    //  | 
 | 237 | +    //   `Wrapping<T>` is guaranteed to have the same layout and ABI as `T`.  | 
 | 238 | +    type AlignmentVariance = Covariant;  | 
 | 239 | + | 
 | 240 | +    // SAFETY: `Wrapping<T>` has only one field, which is `pub` [2]. We are also  | 
 | 241 | +    // guaranteed per [1] (from the comment above) that `Wrapping<T>` has the  | 
 | 242 | +    // same layout as `T`. The only way for both of these to be true  | 
 | 243 | +    // simultaneously is for `Wrapping<T>` to have the same bit validity as `T`.  | 
 | 244 | +    // In particular, in order to change the bit validity, one of the following  | 
 | 245 | +    // would need to happen:  | 
 | 246 | +    // - `Wrapping` could change its `repr`, but this would violate the layout  | 
 | 247 | +    //   guarantee.  | 
 | 248 | +    // - `Wrapping` could add or change its fields, but this would be a  | 
 | 249 | +    //   stability-breaking change.  | 
 | 250 | +    //  | 
 | 251 | +    // [2] https://doc.rust-lang.org/core/num/struct.Wrapping.html  | 
 | 252 | +    type ValidityVariance = Covariant;  | 
 | 253 | + | 
 | 254 | +    #[inline(always)]  | 
 | 255 | +    fn cast_into_inner(ptr: *mut Wrapping<T>) -> *mut T {  | 
 | 256 | +        // SAFETY: Per [1] (from comment above), `Wrapping<T>` has the same  | 
 | 257 | +        // layout as `T`. Thus, this cast preserves size.  | 
 | 258 | +        //  | 
 | 259 | +        // This cast trivially preserves provenance.  | 
 | 260 | +        ptr.cast::<T>()  | 
 | 261 | +    }  | 
 | 262 | + | 
 | 263 | +    #[inline(always)]  | 
 | 264 | +    fn cast_from_inner(ptr: *mut T) -> *mut Wrapping<T> {  | 
 | 265 | +        // SAFETY: Per [1] (from comment above), `Wrapping<T>` has the same  | 
 | 266 | +        // layout as `T`. Thus, this cast preserves size.  | 
 | 267 | +        //  | 
 | 268 | +        // This cast trivially preserves provenance.  | 
 | 269 | +        ptr.cast::<Wrapping<T>>()  | 
 | 270 | +    }  | 
 | 271 | +}  | 
 | 272 | + | 
 | 273 | +// SAFETY:  | 
 | 274 | +// - Per [1], `UnsafeCell<T>` has the same size as `T`.  | 
 | 275 | +// - See inline comments for other safety justifications.  | 
 | 276 | +//  | 
 | 277 | +// [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout:  | 
 | 278 | +//  | 
 | 279 | +//   `UnsafeCell<T>` has the same in-memory representation as its inner type  | 
 | 280 | +//   `T`.  | 
 | 281 | +unsafe impl<T: ?Sized, I: Invariants> TransparentWrapper<I> for UnsafeCell<T> {  | 
 | 282 | +    type Inner = T;  | 
 | 283 | + | 
 | 284 | +    // SAFETY: Since we set this to `Invariant`, we make no safety claims.  | 
 | 285 | +    type UnsafeCellVariance = Invariant;  | 
 | 286 | + | 
 | 287 | +    // SAFETY: Per [1] (from comment on impl), `Unalign<T>` has the same  | 
 | 288 | +    // representation as `T`, and thus has the same alignment as `T`.  | 
 | 289 | +    type AlignmentVariance = Covariant;  | 
 | 290 | + | 
 | 291 | +    // SAFETY: Per [1], `Unalign<T>` has the same bit validity as `T`.  | 
 | 292 | +    // Technically the term "representation" doesn't guarantee this, but the  | 
 | 293 | +    // subsequent sentence in the documentation makes it clear that this is the  | 
 | 294 | +    // intention.  | 
 | 295 | +    //  | 
 | 296 | +    // [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout:  | 
 | 297 | +    //  | 
 | 298 | +    //   `UnsafeCell<T>` has the same in-memory representation as its inner type  | 
 | 299 | +    //   `T`. A consequence of this guarantee is that it is possible to convert  | 
 | 300 | +    //   between `T` and `UnsafeCell<T>`.  | 
 | 301 | +    type ValidityVariance = Covariant;  | 
 | 302 | + | 
 | 303 | +    #[inline(always)]  | 
 | 304 | +    fn cast_into_inner(ptr: *mut UnsafeCell<T>) -> *mut T {  | 
 | 305 | +        // SAFETY: Per [1] (from comment above), `UnsafeCell<T>` has the same  | 
 | 306 | +        // representation as `T`. Thus, this cast preserves size.  | 
 | 307 | +        //  | 
 | 308 | +        // This cast trivially preserves provenance.  | 
 | 309 | +        #[allow(clippy::as_conversions)]  | 
 | 310 | +        return ptr as *mut T;  | 
 | 311 | +    }  | 
 | 312 | + | 
 | 313 | +    #[inline(always)]  | 
 | 314 | +    fn cast_from_inner(ptr: *mut T) -> *mut UnsafeCell<T> {  | 
 | 315 | +        // SAFETY: Per [1] (from comment above), `UnsafeCell<T>` has the same  | 
 | 316 | +        // representation as `T`. Thus, this cast preserves size.  | 
 | 317 | +        //  | 
 | 318 | +        // This cast trivially preserves provenance.  | 
 | 319 | +        #[allow(clippy::as_conversions)]  | 
 | 320 | +        return ptr as *mut UnsafeCell<T>;  | 
 | 321 | +    }  | 
 | 322 | +}  | 
 | 323 | + | 
 | 324 | +// SAFETY: `Unalign<T>` promises to have the same size as `T`.  | 
 | 325 | +//  | 
 | 326 | +// See inline comments for other safety justifications.  | 
 | 327 | +unsafe impl<T, I: Invariants> TransparentWrapper<I> for Unalign<T> {  | 
 | 328 | +    type Inner = T;  | 
 | 329 | + | 
 | 330 | +    // SAFETY: `Unalign<T>` promises to have `UnsafeCell`s covering the same  | 
 | 331 | +    // byte ranges as `Inner = T`.  | 
 | 332 | +    type UnsafeCellVariance = Covariant;  | 
 | 333 | + | 
 | 334 | +    // SAFETY: Since `Unalign<T>` promises to have alignment 1 regardless of  | 
 | 335 | +    // `T`'s alignment. Thus, an aligned pointer to `Unalign<T>` is not  | 
 | 336 | +    // necessarily an aligned pointer to `T`.  | 
 | 337 | +    type AlignmentVariance = Invariant;  | 
 | 338 | + | 
 | 339 | +    // SAFETY: `Unalign<T>` promises to have the same validity as `T`.  | 
 | 340 | +    type ValidityVariance = Covariant;  | 
 | 341 | + | 
 | 342 | +    #[inline(always)]  | 
 | 343 | +    fn cast_into_inner(ptr: *mut Unalign<T>) -> *mut T {  | 
 | 344 | +        // SAFETY: Per the safety comment on the impl block, `Unalign<T>` has  | 
 | 345 | +        // the size as `T`. Thus, this cast preserves size.  | 
 | 346 | +        //  | 
 | 347 | +        // This cast trivially preserves provenance.  | 
 | 348 | +        ptr.cast::<T>()  | 
 | 349 | +    }  | 
 | 350 | + | 
 | 351 | +    #[inline(always)]  | 
 | 352 | +    fn cast_from_inner(ptr: *mut T) -> *mut Unalign<T> {  | 
 | 353 | +        // SAFETY: Per the safety comment on the impl block, `Unalign<T>` has  | 
 | 354 | +        // the size as `T`. Thus, this cast preserves size.  | 
 | 355 | +        //  | 
 | 356 | +        // This cast trivially preserves provenance.  | 
 | 357 | +        ptr.cast::<Unalign<T>>()  | 
 | 358 | +    }  | 
 | 359 | +}  | 
0 commit comments