@@ -553,6 +553,7 @@ use crate::pin::Pin;
553553use crate :: {
554554 cmp, convert, hint, mem,
555555 ops:: { self , ControlFlow , Deref , DerefMut } ,
556+ slice,
556557} ;
557558
558559/// The `Option` type. See [the module level documentation](self) for more.
@@ -734,6 +735,124 @@ impl<T> Option<T> {
734735 }
735736 }
736737
738+ const fn get_some_offset ( ) -> isize {
739+ if mem:: size_of :: < Option < T > > ( ) == mem:: size_of :: < T > ( ) {
740+ // niche optimization means the `T` is always stored at the same position as the Option.
741+ 0
742+ } else {
743+ assert ! ( mem:: size_of:: <Option <T >>( ) == mem:: size_of:: <Option <mem:: MaybeUninit <T >>>( ) ) ;
744+ let some_uninit = Some ( mem:: MaybeUninit :: < T > :: uninit ( ) ) ;
745+ // SAFETY: This gets the byte offset of the `Some(_)` value following the fact that
746+ // niche optimization is not active, and thus Option<T> and Option<MaybeUninit<t>> share
747+ // the same layout.
748+ unsafe {
749+ ( some_uninit. as_ref ( ) . unwrap ( ) as * const mem:: MaybeUninit < T > )
750+ . byte_offset_from ( & some_uninit as * const Option < mem:: MaybeUninit < T > > )
751+ }
752+ }
753+ }
754+
755+ /// Returns a slice of the contained value, if any. If this is `None`, an
756+ /// empty slice is returned. This can be useful to have a single type of
757+ /// iterator over an `Option` or slice.
758+ ///
759+ /// Note: Should you have an `Option<&T>` and wish to get a slice of `T`,
760+ /// you can unpack it via `opt.map_or(&[], std::slice::from_ref)`.
761+ ///
762+ /// # Examples
763+ ///
764+ /// ```rust
765+ /// #![feature(option_as_slice)]
766+ ///
767+ /// assert_eq!(
768+ /// [Some(1234).as_slice(), None.as_slice()],
769+ /// [&[1234][..], &[][..]],
770+ /// );
771+ /// ```
772+ ///
773+ /// The inverse of this function is (discounting
774+ /// borrowing) [`[_]::first`](slice::first):
775+ ///
776+ /// ```rust
777+ /// #![feature(option_as_slice)]
778+ ///
779+ /// for i in [Some(1234_u16), None] {
780+ /// assert_eq!(i.as_ref(), i.as_slice().first());
781+ /// }
782+ /// ```
783+ #[ inline]
784+ #[ must_use]
785+ #[ unstable( feature = "option_as_slice" , issue = "108545" ) ]
786+ pub fn as_slice ( & self ) -> & [ T ] {
787+ // SAFETY: This is sound as long as `get_some_offset` returns the
788+ // correct offset. Though in the `None` case, the slice may be located
789+ // at a pointer pointing into padding, the fact that the slice is
790+ // empty, and the padding is at a properly aligned position for a
791+ // value of that type makes it sound.
792+ unsafe {
793+ slice:: from_raw_parts (
794+ ( self as * const Option < T > ) . wrapping_byte_offset ( Self :: get_some_offset ( ) )
795+ as * const T ,
796+ self . is_some ( ) as usize ,
797+ )
798+ }
799+ }
800+
801+ /// Returns a mutable slice of the contained value, if any. If this is
802+ /// `None`, an empty slice is returned. This can be useful to have a
803+ /// single type of iterator over an `Option` or slice.
804+ ///
805+ /// Note: Should you have an `Option<&mut T>` instead of a
806+ /// `&mut Option<T>`, which this method takes, you can obtain a mutable
807+ /// slice via `opt.map_or(&mut [], std::slice::from_mut)`.
808+ ///
809+ /// # Examples
810+ ///
811+ /// ```rust
812+ /// #![feature(option_as_slice)]
813+ ///
814+ /// assert_eq!(
815+ /// [Some(1234).as_mut_slice(), None.as_mut_slice()],
816+ /// [&mut [1234][..], &mut [][..]],
817+ /// );
818+ /// ```
819+ ///
820+ /// The result is a mutable slice of zero or one items that points into
821+ /// our original `Option`:
822+ ///
823+ /// ```rust
824+ /// #![feature(option_as_slice)]
825+ ///
826+ /// let mut x = Some(1234);
827+ /// x.as_mut_slice()[0] += 1;
828+ /// assert_eq!(x, Some(1235));
829+ /// ```
830+ ///
831+ /// The inverse of this method (discounting borrowing)
832+ /// is [`[_]::first_mut`](slice::first_mut):
833+ ///
834+ /// ```rust
835+ /// #![feature(option_as_slice)]
836+ ///
837+ /// assert_eq!(Some(123).as_mut_slice().first_mut(), Some(&mut 123))
838+ /// ```
839+ #[ inline]
840+ #[ must_use]
841+ #[ unstable( feature = "option_as_slice" , issue = "108545" ) ]
842+ pub fn as_mut_slice ( & mut self ) -> & mut [ T ] {
843+ // SAFETY: This is sound as long as `get_some_offset` returns the
844+ // correct offset. Though in the `None` case, the slice may be located
845+ // at a pointer pointing into padding, the fact that the slice is
846+ // empty, and the padding is at a properly aligned position for a
847+ // value of that type makes it sound.
848+ unsafe {
849+ slice:: from_raw_parts_mut (
850+ ( self as * mut Option < T > ) . wrapping_byte_offset ( Self :: get_some_offset ( ) ) as * mut T ,
851+ self . is_some ( ) as usize ,
852+ )
853+ }
854+ }
855+
737856 /////////////////////////////////////////////////////////////////////////
738857 // Getting to contained values
739858 /////////////////////////////////////////////////////////////////////////
0 commit comments