@@ -3511,8 +3511,8 @@ safety_comment! {
3511
3511
///
3512
3512
/// In other words, the layout of a `[T]` or `[T; N]` is a sequence of `T`s
3513
3513
/// laid out back-to-back with no bytes in between. Therefore, `[T]` or `[T;
3514
- /// N]` are `FromZeroes`, `FromBytes`, and `AsBytes` if `T` is
3515
- /// (respectively). Furthermore, since an array/slice has "the same
3514
+ /// N]` are `TryFromBytes`, ` FromZeroes`, `FromBytes`, and `AsBytes` if `T`
3515
+ /// is (respectively). Furthermore, since an array/slice has "the same
3516
3516
/// alignment of `T`", `[T]` and `[T; N]` are `Unaligned` if `T` is.
3517
3517
///
3518
3518
/// Note that we don't `assert_unaligned!` for slice types because
@@ -3524,6 +3524,42 @@ safety_comment! {
3524
3524
unsafe_impl!( const N : usize , T : AsBytes => AsBytes for [ T ; N ] ) ;
3525
3525
unsafe_impl!( const N : usize , T : Unaligned => Unaligned for [ T ; N ] ) ;
3526
3526
assert_unaligned!( [ ( ) ; 0 ] , [ ( ) ; 1 ] , [ u8 ; 0 ] , [ u8 ; 1 ] ) ;
3527
+ unsafe_impl!( T : TryFromBytes => TryFromBytes for [ T ] ; |c: Ptr <[ T ] >| {
3528
+ // SAFETY: Assuming the preconditions of `is_bit_valid` are satisfied,
3529
+ // so too will the postcondition: that, if `is_bit_valid(candidate)`
3530
+ // returns true, `*candidate` contains a valid `Self`. Per the reference
3531
+ // [1]:
3532
+ //
3533
+ // An array of `[T; N]` has a size of `size_of::<T>() * N` and the
3534
+ // same alignment of `T`. Arrays are laid out so that the zero-based
3535
+ // `nth` element of the array is offset from the start of the array by
3536
+ // `n * size_of::<T>()` bytes.
3537
+ //
3538
+ // ...
3539
+ //
3540
+ // Slices have the same layout as the section of the array they slice.
3541
+ //
3542
+ // In other words, the layout of a `[T] is a sequence of `T`s laid out
3543
+ // back-to-back with no bytes in between. If all elements in `candidate`
3544
+ // are `is_bit_valid`, so too is `candidate`.
3545
+ //
3546
+ // Note that any of the below calls may panic, but it would still be
3547
+ // sound even if it did. `is_bit_valid` does not promise that it will
3548
+ // not panic (in fact, it explicitly warns that it's a possibility), and
3549
+ // we have not violated any safety invariants that we must fix before
3550
+ // returning.
3551
+ c. iter( ) . all( |elem|
3552
+ // SAFETY: We uphold the safety contract of `is_bit_valid(elem)`, by
3553
+ // precondition on the surrounding call to `is_bit_valid`. The
3554
+ // memory referenced by `elem` is contained entirely within `c`, and
3555
+ // satisfies the preconditions satisfied by `c`. By axiom, we assume
3556
+ // that `Iterator:all` does not invalidate these preconditions
3557
+ // (e.g., by writing to `elem`.) Since `elem` is derived from `c`,
3558
+ // it is only possible for uninitialized bytes to occur in `elem` at
3559
+ // the same bytes they occur within `c`.
3560
+ unsafe { <T as TryFromBytes >:: is_bit_valid( elem) }
3561
+ )
3562
+ } ) ;
3527
3563
unsafe_impl!( T : FromZeroes => FromZeroes for [ T ] ) ;
3528
3564
unsafe_impl!( T : FromBytes => FromBytes for [ T ] ) ;
3529
3565
unsafe_impl!( T : AsBytes => AsBytes for [ T ] ) ;
@@ -7666,6 +7702,7 @@ mod tests {
7666
7702
@failure 0xD800u32 , 0xDFFFu32 , 0x110000u32 ;
7667
7703
str => @success "" , "hello" , "❤️🧡💛💚💙💜" ,
7668
7704
@failure [ 0 , 159 , 146 , 150 ] ;
7705
+ [ u8 ] => @success [ ] , [ 0 , 1 , 2 ] ;
7669
7706
NonZeroU8 , NonZeroI8 , NonZeroU16 , NonZeroI16 , NonZeroU32 ,
7670
7707
NonZeroI32 , NonZeroU64 , NonZeroI64 , NonZeroU128 , NonZeroI128 ,
7671
7708
NonZeroUsize , NonZeroIsize
@@ -7675,6 +7712,9 @@ mod tests {
7675
7712
// `0` may be any integer type with a different size or
7676
7713
// alignment than some `NonZeroXxx` types).
7677
7714
@failure Option :: <Self >:: None ;
7715
+ [ bool ]
7716
+ => @success [ true , false ] , [ false , true ] ,
7717
+ @failure [ 2u8 ] , [ 3u8 ] , [ 0xFFu8 ] , [ 0u8 , 1u8 , 2u8 ] ;
7678
7718
) ;
7679
7719
7680
7720
// Asserts that `$ty` implements any `$trait` and doesn't implement any
@@ -7840,7 +7880,8 @@ mod tests {
7840
7880
assert_impls ! ( Unalign <u8 >: KnownLayout , FromZeroes , FromBytes , AsBytes , Unaligned , !TryFromBytes ) ;
7841
7881
assert_impls ! ( Unalign <NotZerocopy >: Unaligned , !KnownLayout , !TryFromBytes , !FromZeroes , !FromBytes , !AsBytes ) ;
7842
7882
7843
- assert_impls ! ( [ u8 ] : KnownLayout , FromZeroes , FromBytes , AsBytes , Unaligned , !TryFromBytes ) ;
7883
+ assert_impls ! ( [ u8 ] : KnownLayout , TryFromBytes , FromZeroes , FromBytes , AsBytes , Unaligned ) ;
7884
+ assert_impls ! ( [ bool ] : KnownLayout , TryFromBytes , FromZeroes , AsBytes , Unaligned , !FromBytes ) ;
7844
7885
assert_impls ! ( [ NotZerocopy ] : !KnownLayout , !TryFromBytes , !FromZeroes , !FromBytes , !AsBytes , !Unaligned ) ;
7845
7886
assert_impls ! ( [ u8 ; 0 ] : KnownLayout , FromZeroes , FromBytes , AsBytes , Unaligned , !TryFromBytes ) ;
7846
7887
assert_impls ! ( [ NotZerocopy ; 0 ] : KnownLayout , !TryFromBytes , !FromZeroes , !FromBytes , !AsBytes , !Unaligned ) ;
0 commit comments