@@ -736,46 +736,15 @@ impl<T> Option<T> {
736
736
}
737
737
738
738
/// This is a guess at how many bytes into the option the payload can be found.
739
- ///
740
- /// For niche-optimized types it's correct because it's pigeon-holed to only
741
- /// one possible place. For other types, it's usually correct today, but
742
- /// tweaks to the layout algorithm (particularly expansions of
743
- /// `-Z randomize-layout`) might make it incorrect at any point.
744
- ///
745
- /// It's guaranteed to be a multiple of alignment (so will always give a
746
- /// correctly-aligned location) and to be within the allocated object, so
747
- /// is valid to use with `offset` and to use for a zero-sized read.
748
- ///
749
- /// FIXME: This is a horrible hack, but allows a nice optimization. It should
750
- /// be replaced with `offset_of!` once that works on enum variants.
751
- const SOME_BYTE_OFFSET_GUESS : isize = {
752
- let some_uninit = Some ( mem:: MaybeUninit :: < T > :: uninit ( ) ) ;
753
- let payload_ref = some_uninit. as_ref ( ) . unwrap ( ) ;
754
- // SAFETY: `as_ref` gives an address inside the existing `Option`,
755
- // so both pointers are derived from the same thing and the result
756
- // cannot overflow an `isize`.
757
- let offset = unsafe { <* const _ >:: byte_offset_from ( payload_ref, & some_uninit) } ;
758
-
759
- // The offset is into the object, so it's guaranteed to be non-negative.
760
- assert ! ( offset >= 0 ) ;
761
-
762
- // The payload and the overall option are aligned,
763
- // so the offset will be a multiple of the alignment too.
764
- assert ! ( ( offset as usize ) % mem:: align_of:: <T >( ) == 0 ) ;
765
-
766
- let max_offset = mem:: size_of :: < Self > ( ) - mem:: size_of :: < T > ( ) ;
767
- if offset as usize <= max_offset {
768
- // There's enough space after this offset for a `T` to exist without
769
- // overflowing the bounds of the object, so let's try it.
770
- offset
771
- } else {
772
- // The offset guess is definitely wrong, so use the address
773
- // of the original option since we have it already.
774
- // This also correctly handles the case of layout-optimized enums
775
- // where `max_offset == 0` and thus this is the only possibility.
776
- 0
777
- }
778
- } ;
739
+ /// As this version will only be ever used to compile rustc and the performance
740
+ /// penalty is negligible, use a minimal implementation here.
741
+ #[ cfg( bootstrap) ]
742
+ const SOME_BYTE_OFFSET_GUESS : usize = 0 ;
743
+
744
+ // FIXME: replace this with whatever stable method to get the offset of an enum
745
+ // field may appear first.
746
+ #[ cfg( not( bootstrap) ) ]
747
+ const SOME_BYTE_OFFSET_GUESS : usize = crate :: intrinsics:: option_some_offset :: < Option < T > > ( ) ;
779
748
780
749
/// Returns a slice of the contained value, if any. If this is `None`, an
781
750
/// empty slice is returned. This can be useful to have a single type of
@@ -820,7 +789,7 @@ impl<T> Option<T> {
820
789
let self_ptr: * const Self = self ;
821
790
// SAFETY: `SOME_BYTE_OFFSET_GUESS` guarantees that its value is
822
791
// such that this will be in-bounds of the object.
823
- unsafe { self_ptr. byte_offset ( Self :: SOME_BYTE_OFFSET_GUESS ) . cast ( ) }
792
+ unsafe { self_ptr. byte_add ( Self :: SOME_BYTE_OFFSET_GUESS ) . cast ( ) }
824
793
} ;
825
794
let len = usize:: from ( self . is_some ( ) ) ;
826
795
@@ -886,7 +855,7 @@ impl<T> Option<T> {
886
855
let self_ptr: * mut Self = self ;
887
856
// SAFETY: `SOME_BYTE_OFFSET_GUESS` guarantees that its value is
888
857
// such that this will be in-bounds of the object.
889
- unsafe { self_ptr. byte_offset ( Self :: SOME_BYTE_OFFSET_GUESS ) . cast ( ) }
858
+ unsafe { self_ptr. byte_add ( Self :: SOME_BYTE_OFFSET_GUESS ) . cast ( ) }
890
859
} ;
891
860
let len = usize:: from ( self . is_some ( ) ) ;
892
861
0 commit comments