diff --git a/src/impls.rs b/src/impls.rs index 0ee2719a87..471a8831ab 100644 --- a/src/impls.rs +++ b/src/impls.rs @@ -7,7 +7,11 @@ // This file may not be copied, modified, or distributed except according to // those terms. -use core::{cell::UnsafeCell, mem::MaybeUninit as CoreMaybeUninit, ptr::NonNull}; +use core::{ + cell::{Cell, UnsafeCell}, + mem::MaybeUninit as CoreMaybeUninit, + ptr::NonNull, +}; use super::*; @@ -862,6 +866,21 @@ safety_comment! { } assert_unaligned!(ManuallyDrop<()>, ManuallyDrop); +impl_for_transmute_from!(T: ?Sized + TryFromBytes => TryFromBytes for Cell[UnsafeCell]); +impl_for_transmute_from!(T: ?Sized + FromZeros => FromZeros for Cell[UnsafeCell]); +impl_for_transmute_from!(T: ?Sized + FromBytes => FromBytes for Cell[UnsafeCell]); +impl_for_transmute_from!(T: ?Sized + IntoBytes => IntoBytes for Cell[UnsafeCell]); +safety_comment! { + /// SAFETY: + /// `Cell` has the same in-memory representation as `T` [1], and thus has + /// the same alignment as `T`. + /// + /// [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.Cell.html#memory-layout: + /// + /// `Cell` has the same in-memory representation as its inner type `T`. + unsafe_impl!(T: ?Sized + Unaligned => Unaligned for Cell); +} + impl_for_transmute_from!(T: ?Sized + FromZeros => FromZeros for UnsafeCell[]); impl_for_transmute_from!(T: ?Sized + FromBytes => FromBytes for UnsafeCell[]); impl_for_transmute_from!(T: ?Sized + IntoBytes => IntoBytes for UnsafeCell[]); diff --git a/src/lib.rs b/src/lib.rs index d507a21267..7458b72038 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -357,7 +357,7 @@ pub use crate::r#ref::*; pub use crate::wrappers::*; use core::{ - cell::UnsafeCell, + cell::{Cell, UnsafeCell}, cmp::Ordering, fmt::{self, Debug, Display, Formatter}, hash::Hasher, @@ -983,29 +983,27 @@ impl_known_layout!(const N: usize, T => [T; N]); safety_comment! { /// SAFETY: - /// `str`, `ManuallyDrop<[T]>` [1], and `UnsafeCell` [2] have the same - /// representations as `[u8]`, `[T]`, and `T` repsectively. `str` has - /// different bit validity than `[u8]`, but that doesn't affect the - /// soundness of this impl. + /// `str` has the same representation as `[u8]`. `ManuallyDrop` [1], + /// `UnsafeCell` [2], and `Cell` [3] have the same representation as + /// `T`. /// - /// [1] Per https://doc.rust-lang.org/nightly/core/mem/struct.ManuallyDrop.html: + /// [1] Per https://doc.rust-lang.org/1.85.0/std/mem/struct.ManuallyDrop.html: /// /// `ManuallyDrop` is guaranteed to have the same layout and bit /// validity as `T` /// - /// [2] Per https://doc.rust-lang.org/core/cell/struct.UnsafeCell.html#memory-layout: + /// [2] Per https://doc.rust-lang.org/1.85.0/core/cell/struct.UnsafeCell.html#memory-layout: /// /// `UnsafeCell` has the same in-memory representation as its inner /// type `T`. /// - /// TODO(#429): - /// - Add quotes from docs. - /// - Once [1] (added in - /// https://github.com/rust-lang/rust/pull/115522) is available on stable, - /// quote the stable docs instead of the nightly docs. + /// [3] Per https://doc.rust-lang.org/1.85.0/core/cell/struct.Cell.html#memory-layout: + /// + /// `Cell` has the same in-memory representation as `T`. unsafe_impl_known_layout!(#[repr([u8])] str); unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T)] ManuallyDrop); unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T)] UnsafeCell); + unsafe_impl_known_layout!(T: ?Sized + KnownLayout => #[repr(T)] Cell); } safety_comment! { diff --git a/src/pointer/transmute.rs b/src/pointer/transmute.rs index d98e7a795a..a774cd8d31 100644 --- a/src/pointer/transmute.rs +++ b/src/pointer/transmute.rs @@ -7,7 +7,7 @@ // those terms. use core::{ - cell::UnsafeCell, + cell::{Cell, UnsafeCell}, mem::{ManuallyDrop, MaybeUninit}, num::Wrapping, ptr::NonNull, @@ -405,20 +405,44 @@ safety_comment! { unsafe_impl_invariants_eq!(T => T, Wrapping); /// SAFETY: - /// - `Unalign` has the same size as `T` [1]. - /// - Per [1], `Unalign` has the same bit validity as `T`. Technically + /// - `UnsafeCell` has the same size as `T` [1]. + /// - Per [1], `UnsafeCell` 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`. + /// `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`. unsafe_impl_for_transparent_wrapper!(T: ?Sized => UnsafeCell); + + /// SAFETY: + /// - `Cell` has the same size as `T` [1]. + /// - Per [1], `Cell` has the same bit validity as `T`. Technically the + /// term "representation" doesn't guarantee this, but it does promise to + /// have the "same memory layout and caveats as `UnsafeCell`." The + /// `UnsafeCell` docs [2] make it clear that bit validity is the intention + /// even if that phrase isn't used. + /// + /// [1] Per https://doc.rust-lang.org/1.85.0/std/cell/struct.Cell.html#memory-layout: + /// + /// `Cell` has the same memory layout and caveats as `UnsafeCell`. + /// In particular, this means that `Cell` has the same in-memory + /// representation as its inner type `T`. + /// + /// [2] 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`. + unsafe_impl_for_transparent_wrapper!(T: ?Sized => Cell); } +impl_transitive_transmute_from!(T: ?Sized => Cell => T => UnsafeCell); +impl_transitive_transmute_from!(T: ?Sized => UnsafeCell => T => Cell); + // SAFETY: `MaybeUninit` has no validity requirements. Currently this is not // explicitly guaranteed, but it's obvious from `MaybeUninit`'s documentation // that this is the intention: diff --git a/tests/ui-nightly/diagnostic-not-implemented-unaligned.stderr b/tests/ui-nightly/diagnostic-not-implemented-unaligned.stderr index 4ee17e1b9a..9ff575a23c 100644 --- a/tests/ui-nightly/diagnostic-not-implemented-unaligned.stderr +++ b/tests/ui-nightly/diagnostic-not-implemented-unaligned.stderr @@ -10,10 +10,10 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::Unaligned` is not satisfie AtomicBool AtomicI8 AtomicU8 + Cell F32 F64 I128 - I16 and $N others note: required by a bound in `takes_unaligned` --> tests/ui-nightly/diagnostic-not-implemented-unaligned.rs:21:23 diff --git a/tests/ui-stable/diagnostic-not-implemented-unaligned.stderr b/tests/ui-stable/diagnostic-not-implemented-unaligned.stderr index 27b3769ed2..d9463715de 100644 --- a/tests/ui-stable/diagnostic-not-implemented-unaligned.stderr +++ b/tests/ui-stable/diagnostic-not-implemented-unaligned.stderr @@ -10,10 +10,10 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::Unaligned` is not satisfie AtomicBool AtomicI8 AtomicU8 + Cell F32 F64 I128 - I16 and $N others note: required by a bound in `takes_unaligned` --> tests/ui-stable/diagnostic-not-implemented-unaligned.rs:21:23 diff --git a/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr b/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr index ffad1b5041..c287a19c26 100644 --- a/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr +++ b/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr @@ -126,10 +126,10 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::Unaligned` is not satisfie AtomicBool AtomicI8 AtomicU8 + Cell F32 F64 I128 - I16 and $N others note: required for `TransparentStruct` to implement `zerocopy::Unaligned` --> tests/ui-nightly/derive_transparent.rs:24:32 diff --git a/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr b/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr index 5ced90a5e9..41d63e096d 100644 --- a/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr +++ b/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr @@ -186,10 +186,10 @@ error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied AtomicBool AtomicI8 AtomicU8 + Cell F32 F64 I128 - I16 and $N others = help: see issue #48214 = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -210,10 +210,10 @@ error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied AtomicBool AtomicI8 AtomicU8 + Cell F32 F64 I128 - I16 and $N others = help: see issue #48214 = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -234,10 +234,10 @@ error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied AtomicBool AtomicI8 AtomicU8 + Cell F32 F64 I128 - I16 and $N others = help: see issue #48214 = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/zerocopy-derive/tests/ui-nightly/struct.stderr b/zerocopy-derive/tests/ui-nightly/struct.stderr index 010e8d6d38..43e643bf06 100644 --- a/zerocopy-derive/tests/ui-nightly/struct.stderr +++ b/zerocopy-derive/tests/ui-nightly/struct.stderr @@ -284,10 +284,10 @@ error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied AtomicBool AtomicI8 AtomicU8 + Cell F32 F64 I128 - I16 and $N others = help: see issue #48214 = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -386,10 +386,10 @@ error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied AtomicBool AtomicI8 AtomicU8 + Cell F32 F64 I128 - I16 and $N others note: required for `IntoBytes11` to implement `zerocopy::IntoBytes` --> tests/ui-nightly/struct.rs:150:10 diff --git a/zerocopy-derive/tests/ui-stable/derive_transparent.stderr b/zerocopy-derive/tests/ui-stable/derive_transparent.stderr index b122ce48f9..762c65fde7 100644 --- a/zerocopy-derive/tests/ui-stable/derive_transparent.stderr +++ b/zerocopy-derive/tests/ui-stable/derive_transparent.stderr @@ -126,10 +126,10 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::Unaligned` is not satisfie AtomicBool AtomicI8 AtomicU8 + Cell F32 F64 I128 - I16 and $N others note: required for `TransparentStruct` to implement `zerocopy::Unaligned` --> tests/ui-stable/derive_transparent.rs:24:32 diff --git a/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr b/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr index 4fed0f6a42..8552a73ea6 100644 --- a/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr +++ b/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr @@ -158,10 +158,10 @@ error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied AtomicBool AtomicI8 AtomicU8 + Cell F32 F64 I128 - I16 and $N others = help: see issue #48214 = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -178,10 +178,10 @@ error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied AtomicBool AtomicI8 AtomicU8 + Cell F32 F64 I128 - I16 and $N others = help: see issue #48214 = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -198,10 +198,10 @@ error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied AtomicBool AtomicI8 AtomicU8 + Cell F32 F64 I128 - I16 and $N others = help: see issue #48214 = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/zerocopy-derive/tests/ui-stable/struct.stderr b/zerocopy-derive/tests/ui-stable/struct.stderr index ea0e40aa15..5c5a680945 100644 --- a/zerocopy-derive/tests/ui-stable/struct.stderr +++ b/zerocopy-derive/tests/ui-stable/struct.stderr @@ -257,10 +257,10 @@ error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied AtomicBool AtomicI8 AtomicU8 + Cell F32 F64 I128 - I16 and $N others = help: see issue #48214 = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -347,10 +347,10 @@ error[E0277]: the trait bound `AU16: zerocopy::Unaligned` is not satisfied AtomicBool AtomicI8 AtomicU8 + Cell F32 F64 I128 - I16 and $N others note: required for `IntoBytes11` to implement `zerocopy::IntoBytes` --> tests/ui-stable/struct.rs:150:10