@@ -349,7 +349,7 @@ use core::{
349
349
fmt:: { self , Debug , Display , Formatter } ,
350
350
hash:: Hasher ,
351
351
marker:: PhantomData ,
352
- mem:: { self , ManuallyDrop , MaybeUninit } ,
352
+ mem:: { self , ManuallyDrop , MaybeUninit as CoreMaybeUninit } ,
353
353
num:: {
354
354
NonZeroI128 , NonZeroI16 , NonZeroI32 , NonZeroI64 , NonZeroI8 , NonZeroIsize , NonZeroU128 ,
355
355
NonZeroU16 , NonZeroU32 , NonZeroU64 , NonZeroU8 , NonZeroUsize , Wrapping ,
@@ -724,6 +724,22 @@ pub unsafe trait KnownLayout {
724
724
/// This is `()` for sized types and `usize` for slice DSTs.
725
725
type PointerMetadata : PointerMetadata ;
726
726
727
+ /// A maybe-uninitialized analog of `Self`
728
+ ///
729
+ /// # Safety
730
+ ///
731
+ /// Users may assume that:
732
+ /// - `Self` and `Self::MaybeUninit` have the same:
733
+ /// - Fixed prefix size
734
+ /// - Alignment
735
+ /// - (For DSTs) trailing slice element size
736
+ /// - It is valid to perform an `as` cast from `*mut Self` and `*mut
737
+ /// Self::MaybeUninit`, and this operation preserves referent size (ie,
738
+ /// `size_of_val_raw`).
739
+ #[ cfg( zerocopy_unstable) ]
740
+ #[ doc( hidden) ]
741
+ type MaybeUninit : ?Sized + KnownLayout < PointerMetadata = Self :: PointerMetadata > ;
742
+
727
743
/// The layout of `Self`.
728
744
///
729
745
/// # Safety
@@ -856,6 +872,17 @@ unsafe impl<T> KnownLayout for [T] {
856
872
857
873
type PointerMetadata = usize ;
858
874
875
+ // SAFETY: `CoreMaybeUninit<T>` has the same size and alignment as `T`.
876
+ // Consequently, `[CoreMaybeUninit<T>]` has the same size and alignment as
877
+ // `[T]`, becuase `CoreMaybeUninit<T>` has the same size and alignment as
878
+ // `T` [1].
879
+ //
880
+ // [1] Per https://doc.rust-lang.org/1.81.0/std/mem/union.MaybeUninit.html#layout-1:
881
+ //
882
+ // `MaybeUninit<T>` is guaranteed to have the same size, alignment, and ABI as
883
+ // `T`
884
+ type MaybeUninit = [ CoreMaybeUninit < T > ] ;
885
+
859
886
const LAYOUT : DstLayout = DstLayout :: for_slice :: < T > ( ) ;
860
887
861
888
// SAFETY: `.cast` preserves address and provenance. The returned pointer
@@ -908,7 +935,7 @@ impl_known_layout!(
908
935
T => Option <T >,
909
936
T : ?Sized => PhantomData <T >,
910
937
T => Wrapping <T >,
911
- T => MaybeUninit <T >,
938
+ T => CoreMaybeUninit <T >,
912
939
T : ?Sized => * const T ,
913
940
T : ?Sized => * mut T
914
941
) ;
@@ -941,6 +968,19 @@ safety_comment! {
941
968
unsafe_impl_known_layout!( T : ?Sized + KnownLayout => #[ repr( T ) ] UnsafeCell <T >) ;
942
969
}
943
970
971
+ safety_comment ! {
972
+ /// SAFETY:
973
+ /// - By invariant on `KnownLayout::MaybeUninit`, `T` and `T::MaybeUninit`
974
+ /// have the same:
975
+ /// - Fixed prefix size
976
+ /// - Alignment
977
+ /// - (For DSTs) trailing slice element size
978
+ /// - By invariant on `KnownLayout`, it is valid to perform an `as` cast
979
+ /// from `*mut T` and `*mut T::MaybeUninit`, and this operation preserves
980
+ /// referent size (ie, `size_of_val_raw`).
981
+ unsafe_impl_known_layout!( T : ?Sized + KnownLayout => #[ repr( T :: MaybeUninit ) ] MaybeUninit <T >) ;
982
+ }
983
+
944
984
/// Analyzes whether a type is [`FromZeros`].
945
985
///
946
986
/// This derive analyzes, at compile time, whether the annotated type satisfies
@@ -2539,7 +2579,7 @@ pub unsafe trait TryFromBytes {
2539
2579
where
2540
2580
Self : Sized ,
2541
2581
{
2542
- let candidate = match MaybeUninit :: < Self > :: read_from_bytes ( source) {
2582
+ let candidate = match CoreMaybeUninit :: < Self > :: read_from_bytes ( source) {
2543
2583
Ok ( candidate) => candidate,
2544
2584
Err ( e) => {
2545
2585
return Err ( TryReadError :: Size ( e. with_dst ( ) ) ) ;
@@ -2600,7 +2640,7 @@ pub unsafe trait TryFromBytes {
2600
2640
where
2601
2641
Self : Sized ,
2602
2642
{
2603
- let ( candidate, suffix) = match MaybeUninit :: < Self > :: read_from_prefix ( source) {
2643
+ let ( candidate, suffix) = match CoreMaybeUninit :: < Self > :: read_from_prefix ( source) {
2604
2644
Ok ( candidate) => candidate,
2605
2645
Err ( e) => {
2606
2646
return Err ( TryReadError :: Size ( e. with_dst ( ) ) ) ;
@@ -2662,7 +2702,7 @@ pub unsafe trait TryFromBytes {
2662
2702
where
2663
2703
Self : Sized ,
2664
2704
{
2665
- let ( prefix, candidate) = match MaybeUninit :: < Self > :: read_from_suffix ( source) {
2705
+ let ( prefix, candidate) = match CoreMaybeUninit :: < Self > :: read_from_suffix ( source) {
2666
2706
Ok ( candidate) => candidate,
2667
2707
Err ( e) => {
2668
2708
return Err ( TryReadError :: Size ( e. with_dst ( ) ) ) ;
@@ -2735,7 +2775,7 @@ fn swap<T, U>((t, u): (T, U)) -> (U, T) {
2735
2775
#[ inline( always) ]
2736
2776
unsafe fn try_read_from < S , T : TryFromBytes > (
2737
2777
source : S ,
2738
- mut candidate : MaybeUninit < T > ,
2778
+ mut candidate : CoreMaybeUninit < T > ,
2739
2779
) -> Result < T , TryReadError < S , T > > {
2740
2780
// We use `from_mut` despite not mutating via `c_ptr` so that we don't need
2741
2781
// to add a `T: Immutable` bound.
0 commit comments