@@ -860,4 +860,154 @@ impl<T> MaybeUninit<T> {
860860 pub const fn slice_as_mut_ptr ( this : & mut [ MaybeUninit < T > ] ) -> * mut T {
861861 this. as_mut_ptr ( ) as * mut T
862862 }
863+
864+ /// Copies the elements from `src` to `this`, returning a mutable reference to the now initalized contents of `this`.
865+ ///
866+ /// If `T` does not implement `Copy`, use [`write_slice_cloned`]
867+ ///
868+ /// This is similar to [`slice::copy_from_slice`].
869+ ///
870+ /// # Panics
871+ ///
872+ /// This function will panic if the two slices have different lengths.
873+ ///
874+ /// # Examples
875+ ///
876+ /// ```
877+ /// #![feature(maybe_uninit_write_slice)]
878+ /// use std::mem::MaybeUninit;
879+ ///
880+ /// let mut dst = [MaybeUninit::uninit(); 32];
881+ /// let src = [0; 32];
882+ ///
883+ /// let init = MaybeUninit::write_slice(&mut dst, &src);
884+ ///
885+ /// assert_eq!(init, src);
886+ /// ```
887+ ///
888+ /// ```
889+ /// #![feature(maybe_uninit_write_slice, vec_spare_capacity)]
890+ /// use std::mem::MaybeUninit;
891+ ///
892+ /// let mut vec = Vec::with_capacity(32);
893+ /// let src = [0; 16];
894+ ///
895+ /// MaybeUninit::write_slice(&mut vec.spare_capacity_mut()[..src.len()], &src);
896+ ///
897+ /// // SAFETY: we have just copied all the elements of len into the spare capacity
898+ /// // the first src.len() elements of the vec are valid now.
899+ /// unsafe {
900+ /// vec.set_len(src.len());
901+ /// }
902+ ///
903+ /// assert_eq!(vec, src);
904+ /// ```
905+ ///
906+ /// [`write_slice_cloned`]: MaybeUninit::write_slice_cloned
907+ /// [`slice::copy_from_slice`]: ../../std/primitive.slice.html#method.copy_from_slice
908+ #[ unstable( feature = "maybe_uninit_write_slice" , issue = "79995" ) ]
909+ pub fn write_slice < ' a > ( this : & ' a mut [ MaybeUninit < T > ] , src : & [ T ] ) -> & ' a mut [ T ]
910+ where
911+ T : Copy ,
912+ {
913+ // SAFETY: &[T] and &[MaybeUninit<T>] have the same layout
914+ let uninit_src: & [ MaybeUninit < T > ] = unsafe { super :: transmute ( src) } ;
915+
916+ this. copy_from_slice ( uninit_src) ;
917+
918+ // SAFETY: Valid elements have just been copied into `this` so it is initalized
919+ unsafe { MaybeUninit :: slice_assume_init_mut ( this) }
920+ }
921+
922+ /// Clones the elements from `src` to `this`, returning a mutable reference to the now initalized contents of `this`.
923+ /// Any already initalized elements will not be dropped.
924+ ///
925+ /// If `T` implements `Copy`, use [`write_slice`]
926+ ///
927+ /// This is similar to [`slice::clone_from_slice`] but does not drop existing elements.
928+ ///
929+ /// # Panics
930+ ///
931+ /// This function will panic if the two slices have different lengths, or if the implementation of `Clone` panics.
932+ ///
933+ /// If there is a panic, the already cloned elements will be dropped.
934+ ///
935+ /// # Examples
936+ ///
937+ /// ```
938+ /// #![feature(maybe_uninit_write_slice)]
939+ /// use std::mem::MaybeUninit;
940+ ///
941+ /// let mut dst = [MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit()];
942+ /// let src = ["wibbly".to_string(), "wobbly".to_string(), "timey".to_string(), "wimey".to_string(), "stuff".to_string()];
943+ ///
944+ /// let init = MaybeUninit::write_slice_cloned(&mut dst, &src);
945+ ///
946+ /// assert_eq!(init, src);
947+ /// ```
948+ ///
949+ /// ```
950+ /// #![feature(maybe_uninit_write_slice, vec_spare_capacity)]
951+ /// use std::mem::MaybeUninit;
952+ ///
953+ /// let mut vec = Vec::with_capacity(32);
954+ /// let src = ["rust", "is", "a", "pretty", "cool", "language"];
955+ ///
956+ /// MaybeUninit::write_slice_cloned(&mut vec.spare_capacity_mut()[..src.len()], &src);
957+ ///
958+ /// // SAFETY: we have just cloned all the elements of len into the spare capacity
959+ /// // the first src.len() elements of the vec are valid now.
960+ /// unsafe {
961+ /// vec.set_len(src.len());
962+ /// }
963+ ///
964+ /// assert_eq!(vec, src);
965+ /// ```
966+ ///
967+ /// [`write_slice`]: MaybeUninit::write_slice
968+ /// [`slice::clone_from_slice`]: ../../std/primitive.slice.html#method.clone_from_slice
969+ #[ unstable( feature = "maybe_uninit_write_slice" , issue = "79995" ) ]
970+ pub fn write_slice_cloned < ' a > ( this : & ' a mut [ MaybeUninit < T > ] , src : & [ T ] ) -> & ' a mut [ T ]
971+ where
972+ T : Clone ,
973+ {
974+ // unlike copy_from_slice this does not call clone_from_slice on the slice
975+ // this is because `MaybeUninit<T: Clone>` does not implement Clone.
976+
977+ struct Guard < ' a , T > {
978+ slice : & ' a mut [ MaybeUninit < T > ] ,
979+ initialized : usize ,
980+ }
981+
982+ impl < ' a , T > Drop for Guard < ' a , T > {
983+ fn drop ( & mut self ) {
984+ let initialized_part = & mut self . slice [ ..self . initialized ] ;
985+ // SAFETY: this raw slice will contain only initialized objects
986+ // that's why, it is allowed to drop it.
987+ unsafe {
988+ crate :: ptr:: drop_in_place ( MaybeUninit :: slice_assume_init_mut ( initialized_part) ) ;
989+ }
990+ }
991+ }
992+
993+ assert_eq ! ( this. len( ) , src. len( ) , "destination and source slices have different lengths" ) ;
994+ // NOTE: We need to explicitly slice them to the same length
995+ // for bounds checking to be elided, and the optimizer will
996+ // generate memcpy for simple cases (for example T = u8).
997+ let len = this. len ( ) ;
998+ let src = & src[ ..len] ;
999+
1000+ // guard is needed b/c panic might happen during a clone
1001+ let mut guard = Guard { slice : this, initialized : 0 } ;
1002+
1003+ for i in 0 ..len {
1004+ guard. slice [ i] . write ( src[ i] . clone ( ) ) ;
1005+ guard. initialized += 1 ;
1006+ }
1007+
1008+ super :: forget ( guard) ;
1009+
1010+ // SAFETY: Valid elements have just been written into `this` so it is initalized
1011+ unsafe { MaybeUninit :: slice_assume_init_mut ( this) }
1012+ }
8631013}
0 commit comments