@@ -955,7 +955,7 @@ pub unsafe trait KnownLayout {
955955}
956956
957957// SAFETY: Delegates safety to `DstLayout::for_slice`.
958- unsafe impl < T : KnownLayout > KnownLayout for [ T ] {
958+ unsafe impl < T > KnownLayout for [ T ] {
959959 #[ allow( clippy:: missing_inline_in_public_items) ]
960960 fn only_derive_is_allowed_to_implement_this_trait ( )
961961 where
@@ -4989,84 +4989,94 @@ where
49894989
49904990impl < ' a , B , T > Ref < B , T >
49914991where
4992- B : ' a + ByteSlice ,
4992+ B : ' a + IntoByteSlice < ' a > ,
49934993 T : FromBytes + NoCell ,
49944994{
49954995 /// Converts this `Ref` into a reference.
49964996 ///
49974997 /// `into_ref` consumes the `Ref`, and returns a reference to `T`.
49984998 #[ inline( always) ]
49994999 pub fn into_ref ( self ) -> & ' a T {
5000- assert ! ( B :: INTO_REF_INTO_MUT_ARE_SOUND ) ;
5001-
5002- // SAFETY: According to the safety preconditions on
5003- // `ByteSlice::INTO_REF_INTO_MUT_ARE_SOUND`, the preceding assert
5004- // ensures that, given `B: 'a`, it is sound to drop `self` and still
5005- // access the underlying memory using reads for `'a`.
5006- unsafe { self . deref_helper ( ) }
5000+ let ptr = Ptr :: from_ref ( self . 0 . into ( ) ) ;
5001+ // SAFETY: By invariant on `Ref`, `self.0`'s size is equal to
5002+ // `size_of::<T>()`.
5003+ let ptr = unsafe { ptr. cast :: < T > ( ) } ;
5004+ // SAFETY: By invariant on `Ref`, `self.0` is aligned to `T`'s
5005+ // alignment.
5006+ let ptr = unsafe { ptr. assume_aligned ( ) } ;
5007+ // SAFETY: `ptr` is derived from `self.0.into()`, which is of type
5008+ // `[u8]`, whose bit validity requires that all of its bytes are
5009+ // initialized.
5010+ let ptr = unsafe { ptr. assume_initialized ( ) } ;
5011+ let ptr = ptr. bikeshed_recall_valid ( ) ;
5012+ ptr. as_ref ( )
50075013 }
50085014}
50095015
50105016impl < ' a , B , T > Ref < B , T >
50115017where
5012- B : ' a + ByteSliceMut ,
5018+ B : ' a + IntoByteSliceMut < ' a > ,
50135019 T : FromBytes + IntoBytes + NoCell ,
50145020{
50155021 /// Converts this `Ref` into a mutable reference.
50165022 ///
50175023 /// `into_mut` consumes the `Ref`, and returns a mutable reference to `T`.
50185024 #[ inline( always) ]
5019- pub fn into_mut ( mut self ) -> & ' a mut T {
5020- assert ! ( B :: INTO_REF_INTO_MUT_ARE_SOUND ) ;
5021-
5022- // SAFETY: According to the safety preconditions on
5023- // `ByteSlice::INTO_REF_INTO_MUT_ARE_SOUND`, the preceding assert
5024- // ensures that, given `B: 'a + ByteSliceMut`, it is sound to drop
5025- // `self` and still access the underlying memory using both reads and
5026- // writes for `'a`.
5027- unsafe { self . deref_mut_helper ( ) }
5025+ pub fn into_mut ( self ) -> & ' a mut T {
5026+ let ptr = Ptr :: from_mut ( self . 0 . into ( ) ) ;
5027+ // SAFETY: By invariant on `Ref`, `self.0`'s size is equal to
5028+ // `size_of::<T>()`.
5029+ let ptr = unsafe { ptr. cast :: < T > ( ) } ;
5030+ // SAFETY: By invariant on `Ref`, `self.0` is aligned to `T`'s
5031+ // alignment.
5032+ let ptr = unsafe { ptr. assume_aligned ( ) } ;
5033+ // SAFETY: `ptr` is derived from `self.0.into()`, which is of type
5034+ // `[u8]`, whose bit validity requires that all of its bytes are
5035+ // initialized.
5036+ let ptr = unsafe { ptr. assume_initialized ( ) } ;
5037+ let ptr = ptr. bikeshed_recall_valid ( ) ;
5038+ ptr. as_mut ( )
50285039 }
50295040}
50305041
50315042impl < ' a , B , T > Ref < B , [ T ] >
50325043where
5033- B : ' a + ByteSlice ,
5044+ B : ' a + IntoByteSlice < ' a > ,
50345045 T : FromBytes + NoCell ,
50355046{
50365047 /// Converts this `Ref` into a slice reference.
50375048 ///
50385049 /// `into_slice` consumes the `Ref`, and returns a reference to `[T]`.
50395050 #[ inline( always) ]
50405051 pub fn into_slice ( self ) -> & ' a [ T ] {
5041- assert ! ( B :: INTO_REF_INTO_MUT_ARE_SOUND ) ;
5042-
5043- // SAFETY: According to the safety preconditions on
5044- // `ByteSlice::INTO_REF_INTO_MUT_ARE_SOUND`, the preceding assert
5045- // ensures that, given `B: 'a`, it is sound to drop `self` and still
5046- // access the underlying memory using reads for `'a`.
5047- unsafe { self . deref_slice_helper ( ) }
5052+ // PANICS: By invariant on `Ref`, `self.0`'s size and alignment are
5053+ // valid for `[T]`, and so this `unwrap` will not panic.
5054+ let ptr = Ptr :: from_ref ( self . 0 . into ( ) )
5055+ . try_cast_into_no_leftover :: < [ T ] > ( )
5056+ . expect ( "zerocopy internal error: into_slice should be infallible" ) ;
5057+ let ptr = ptr . bikeshed_recall_valid ( ) ;
5058+ ptr . as_ref ( )
50485059 }
50495060}
50505061
50515062impl < ' a , B , T > Ref < B , [ T ] >
50525063where
5053- B : ' a + ByteSliceMut ,
5064+ B : ' a + IntoByteSliceMut < ' a > ,
50545065 T : FromBytes + IntoBytes + NoCell ,
50555066{
50565067 /// Converts this `Ref` into a mutable slice reference.
50575068 ///
50585069 /// `into_mut_slice` consumes the `Ref`, and returns a mutable reference to
50595070 /// `[T]`.
50605071 #[ inline( always) ]
5061- pub fn into_mut_slice ( mut self ) -> & ' a mut [ T ] {
5062- assert ! ( B :: INTO_REF_INTO_MUT_ARE_SOUND ) ;
5063-
5064- // SAFETY: According to the safety preconditions on
5065- // `ByteSlice::INTO_REF_INTO_MUT_ARE_SOUND`, the preceding assert
5066- // ensures that, given `B: 'a + ByteSliceMut`, it is sound to drop
5067- // `self` and still access the underlying memory using both reads and
5068- // writes for `'a`.
5069- unsafe { self . deref_mut_slice_helper ( ) }
5072+ pub fn into_mut_slice ( self ) -> & ' a mut [ T ] {
5073+ // PANICS: By invariant on `Ref`, `self.0`'s size and alignment are
5074+ // valid for `[T]`, and so this `unwrap` will not panic.
5075+ let ptr = Ptr :: from_mut ( self . 0 . into ( ) )
5076+ . try_cast_into_no_leftover :: < [ T ] > ( )
5077+ . expect ( "zerocopy internal error: into_mut_slice should be infallible" ) ;
5078+ let ptr = ptr. bikeshed_recall_valid ( ) ;
5079+ ptr. as_mut ( )
50705080 }
50715081}
50725082
@@ -5481,29 +5491,6 @@ mod sealed {
54815491pub unsafe trait ByteSlice :
54825492 Deref < Target = [ u8 ] > + Sized + self :: sealed:: ByteSliceSealed
54835493{
5484- /// Are the [`Ref::into_ref`] and [`Ref::into_mut`] methods sound when used
5485- /// with `Self`? If not, evaluating this constant must panic at compile
5486- /// time.
5487- ///
5488- /// This exists to work around #716 on versions of zerocopy prior to 0.8.
5489- ///
5490- /// # Safety
5491- ///
5492- /// This may only be set to true if the following holds: Given the
5493- /// following:
5494- /// - `Self: 'a`
5495- /// - `bytes: Self`
5496- /// - `let ptr = bytes.as_ptr()`
5497- ///
5498- /// ...then:
5499- /// - Using `ptr` to read the memory previously addressed by `bytes` is
5500- /// sound for `'a` even after `bytes` has been dropped.
5501- /// - If `Self: ByteSliceMut`, using `ptr` to write the memory previously
5502- /// addressed by `bytes` is sound for `'a` even after `bytes` has been
5503- /// dropped.
5504- #[ doc( hidden) ]
5505- const INTO_REF_INTO_MUT_ARE_SOUND : bool ;
5506-
55075494 /// Gets a raw pointer to the first byte in the slice.
55085495 #[ inline]
55095496 fn as_ptr ( & self ) -> * const u8 {
@@ -5534,48 +5521,58 @@ pub unsafe trait ByteSliceMut: ByteSlice + DerefMut {
55345521 }
55355522}
55365523
5524+ /// A [`ByteSlice`] that conveys no ownership, and so can be converted into a
5525+ /// byte slice.
5526+ ///
5527+ /// Some `ByteSlice` types (notably, the standard library's [`Ref`] type) convey
5528+ /// ownership, and so they cannot soundly be moved by-value into a byte slice
5529+ /// type (`&[u8]`). Some methods in this crate's API (such as [`Ref::into_ref`])
5530+ /// are only compatible with `ByteSlice` types without these ownership
5531+ /// semantics.
5532+ ///
5533+ /// [`Ref`]: core::cell::Ref
5534+ pub trait IntoByteSlice < ' a > : ByteSlice + Into < & ' a [ u8 ] > { }
5535+
5536+ /// A [`ByteSliceMut`] that conveys no ownership, and so can be converted into a
5537+ /// mutable byte slice.
5538+ ///
5539+ /// Some `ByteSliceMut` types (notably, the standard library's [`RefMut`] type)
5540+ /// convey ownership, and so they cannot soundly be moved by-value into a byte
5541+ /// slice type (`&mut [u8]`). Some methods in this crate's API (such as
5542+ /// [`Ref::into_mut`]) are only compatible with `ByteSliceMut` types without
5543+ /// these ownership semantics.
5544+ ///
5545+ /// [`RefMut`]: core::cell::RefMut
5546+ pub trait IntoByteSliceMut < ' a > : ByteSliceMut + Into < & ' a mut [ u8 ] > { }
5547+
55375548impl < ' a > sealed:: ByteSliceSealed for & ' a [ u8 ] { }
55385549// TODO(#429): Add a "SAFETY" comment and remove this `allow`.
55395550#[ allow( clippy:: undocumented_unsafe_blocks) ]
55405551unsafe impl < ' a > ByteSlice for & ' a [ u8 ] {
5541- // SAFETY: If `&'b [u8]: 'a`, then the underlying memory is treated as
5542- // borrowed immutably for `'a` even if the slice itself is dropped.
5543- const INTO_REF_INTO_MUT_ARE_SOUND : bool = true ;
5544-
55455552 #[ inline]
55465553 fn split_at ( self , mid : usize ) -> ( Self , Self ) {
55475554 <[ u8 ] >:: split_at ( self , mid)
55485555 }
55495556}
55505557
5558+ impl < ' a > IntoByteSlice < ' a > for & ' a [ u8 ] { }
5559+
55515560impl < ' a > sealed:: ByteSliceSealed for & ' a mut [ u8 ] { }
55525561// TODO(#429): Add a "SAFETY" comment and remove this `allow`.
55535562#[ allow( clippy:: undocumented_unsafe_blocks) ]
55545563unsafe impl < ' a > ByteSlice for & ' a mut [ u8 ] {
5555- // SAFETY: If `&'b mut [u8]: 'a`, then the underlying memory is treated as
5556- // borrowed mutably for `'a` even if the slice itself is dropped.
5557- const INTO_REF_INTO_MUT_ARE_SOUND : bool = true ;
5558-
55595564 #[ inline]
55605565 fn split_at ( self , mid : usize ) -> ( Self , Self ) {
55615566 <[ u8 ] >:: split_at_mut ( self , mid)
55625567 }
55635568}
55645569
5570+ impl < ' a > IntoByteSliceMut < ' a > for & ' a mut [ u8 ] { }
5571+
55655572impl < ' a > sealed:: ByteSliceSealed for cell:: Ref < ' a , [ u8 ] > { }
55665573// TODO(#429): Add a "SAFETY" comment and remove this `allow`.
55675574#[ allow( clippy:: undocumented_unsafe_blocks) ]
55685575unsafe impl < ' a > ByteSlice for cell:: Ref < ' a , [ u8 ] > {
5569- const INTO_REF_INTO_MUT_ARE_SOUND : bool = if !cfg ! ( doc) {
5570- const_panic ! ( "Ref::into_ref and Ref::into_mut are unsound when used with core::cell::Ref; see https://github.com/google/zerocopy/issues/716" )
5571- } else {
5572- // When compiling documentation, allow the evaluation of this constant
5573- // to succeed. This doesn't represent a soundness hole - it just delays
5574- // any error to runtime. The reason we need this is that, otherwise,
5575- // `rustdoc` will fail when trying to document this item.
5576- false
5577- } ;
5578-
55795576 #[ inline]
55805577 fn split_at ( self , mid : usize ) -> ( Self , Self ) {
55815578 cell:: Ref :: map_split ( self , |slice| <[ u8 ] >:: split_at ( slice, mid) )
@@ -5586,16 +5583,6 @@ impl<'a> sealed::ByteSliceSealed for RefMut<'a, [u8]> {}
55865583// TODO(#429): Add a "SAFETY" comment and remove this `allow`.
55875584#[ allow( clippy:: undocumented_unsafe_blocks) ]
55885585unsafe impl < ' a > ByteSlice for RefMut < ' a , [ u8 ] > {
5589- const INTO_REF_INTO_MUT_ARE_SOUND : bool = if !cfg ! ( doc) {
5590- const_panic ! ( "Ref::into_ref and Ref::into_mut are unsound when used with core::cell::RefMut; see https://github.com/google/zerocopy/issues/716" )
5591- } else {
5592- // When compiling documentation, allow the evaluation of this constant
5593- // to succeed. This doesn't represent a soundness hole - it just delays
5594- // any error to runtime. The reason we need this is that, otherwise,
5595- // `rustdoc` will fail when trying to document this item.
5596- false
5597- } ;
5598-
55995586 #[ inline]
56005587 fn split_at ( self , mid : usize ) -> ( Self , Self ) {
56015588 RefMut :: map_split ( self , |slice| <[ u8 ] >:: split_at_mut ( slice, mid) )
@@ -8911,7 +8898,7 @@ mod tests {
89118898 // implementation of `<ManuallyDrop<T> as TryFromBytes>::is_bit_valid`.
89128899 assert_impls ! ( ManuallyDrop <[ bool ] >: KnownLayout , NoCell , TryFromBytes , FromZeros , IntoBytes , Unaligned , !FromBytes ) ;
89138900 assert_impls ! ( ManuallyDrop <NotZerocopy >: !NoCell , !TryFromBytes , !KnownLayout , !FromZeros , !FromBytes , !IntoBytes , !Unaligned ) ;
8914- assert_impls ! ( ManuallyDrop <[ NotZerocopy ] >: ! NoCell , !TryFromBytes , !KnownLayout , !FromZeros , !FromBytes , !IntoBytes , !Unaligned ) ;
8901+ assert_impls ! ( ManuallyDrop <[ NotZerocopy ] >: KnownLayout , !NoCell , !TryFromBytes , !FromZeros , !FromBytes , !IntoBytes , !Unaligned ) ;
89158902 assert_impls ! ( ManuallyDrop <UnsafeCell <( ) >>: KnownLayout , TryFromBytes , FromZeros , FromBytes , IntoBytes , Unaligned , !NoCell ) ;
89168903 assert_impls ! ( ManuallyDrop <[ UnsafeCell <u8 >] >: KnownLayout , TryFromBytes , FromZeros , FromBytes , IntoBytes , Unaligned , !NoCell ) ;
89178904 assert_impls ! ( ManuallyDrop <[ UnsafeCell <bool >] >: KnownLayout , TryFromBytes , FromZeros , IntoBytes , Unaligned , !NoCell , !FromBytes ) ;
@@ -8951,7 +8938,7 @@ mod tests {
89518938 Unaligned ,
89528939 !FromBytes
89538940 ) ;
8954- assert_impls ! ( [ NotZerocopy ] : ! KnownLayout , !NoCell , !TryFromBytes , !FromZeros , !FromBytes , !IntoBytes , !Unaligned ) ;
8941+ assert_impls ! ( [ NotZerocopy ] : KnownLayout , !NoCell , !TryFromBytes , !FromZeros , !FromBytes , !IntoBytes , !Unaligned ) ;
89558942 assert_impls ! (
89568943 [ u8 ; 0 ] : KnownLayout ,
89578944 NoCell ,
0 commit comments