@@ -1014,154 +1014,6 @@ impl<T> MaybeUninit<T> {
10141014 this. as_mut_ptr ( ) as * mut T
10151015 }
10161016
1017- /// Copies the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`.
1018- ///
1019- /// If `T` does not implement `Copy`, use [`write_slice_cloned`]
1020- ///
1021- /// This is similar to [`slice::copy_from_slice`].
1022- ///
1023- /// # Panics
1024- ///
1025- /// This function will panic if the two slices have different lengths.
1026- ///
1027- /// # Examples
1028- ///
1029- /// ```
1030- /// #![feature(maybe_uninit_write_slice)]
1031- /// use std::mem::MaybeUninit;
1032- ///
1033- /// let mut dst = [MaybeUninit::uninit(); 32];
1034- /// let src = [0; 32];
1035- ///
1036- /// let init = MaybeUninit::write_slice(&mut dst, &src);
1037- ///
1038- /// assert_eq!(init, src);
1039- /// ```
1040- ///
1041- /// ```
1042- /// #![feature(maybe_uninit_write_slice)]
1043- /// use std::mem::MaybeUninit;
1044- ///
1045- /// let mut vec = Vec::with_capacity(32);
1046- /// let src = [0; 16];
1047- ///
1048- /// MaybeUninit::write_slice(&mut vec.spare_capacity_mut()[..src.len()], &src);
1049- ///
1050- /// // SAFETY: we have just copied all the elements of len into the spare capacity
1051- /// // the first src.len() elements of the vec are valid now.
1052- /// unsafe {
1053- /// vec.set_len(src.len());
1054- /// }
1055- ///
1056- /// assert_eq!(vec, src);
1057- /// ```
1058- ///
1059- /// [`write_slice_cloned`]: MaybeUninit::write_slice_cloned
1060- #[ unstable( feature = "maybe_uninit_write_slice" , issue = "79995" ) ]
1061- pub fn write_slice < ' a > ( this : & ' a mut [ MaybeUninit < T > ] , src : & [ T ] ) -> & ' a mut [ T ]
1062- where
1063- T : Copy ,
1064- {
1065- // SAFETY: &[T] and &[MaybeUninit<T>] have the same layout
1066- let uninit_src: & [ MaybeUninit < T > ] = unsafe { super :: transmute ( src) } ;
1067-
1068- this. copy_from_slice ( uninit_src) ;
1069-
1070- // SAFETY: Valid elements have just been copied into `this` so it is initialized
1071- unsafe { MaybeUninit :: slice_assume_init_mut ( this) }
1072- }
1073-
1074- /// Clones the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`.
1075- /// Any already initialized elements will not be dropped.
1076- ///
1077- /// If `T` implements `Copy`, use [`write_slice`]
1078- ///
1079- /// This is similar to [`slice::clone_from_slice`] but does not drop existing elements.
1080- ///
1081- /// # Panics
1082- ///
1083- /// This function will panic if the two slices have different lengths, or if the implementation of `Clone` panics.
1084- ///
1085- /// If there is a panic, the already cloned elements will be dropped.
1086- ///
1087- /// # Examples
1088- ///
1089- /// ```
1090- /// #![feature(maybe_uninit_write_slice)]
1091- /// use std::mem::MaybeUninit;
1092- ///
1093- /// let mut dst = [MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit()];
1094- /// let src = ["wibbly".to_string(), "wobbly".to_string(), "timey".to_string(), "wimey".to_string(), "stuff".to_string()];
1095- ///
1096- /// let init = MaybeUninit::write_slice_cloned(&mut dst, &src);
1097- ///
1098- /// assert_eq!(init, src);
1099- /// ```
1100- ///
1101- /// ```
1102- /// #![feature(maybe_uninit_write_slice)]
1103- /// use std::mem::MaybeUninit;
1104- ///
1105- /// let mut vec = Vec::with_capacity(32);
1106- /// let src = ["rust", "is", "a", "pretty", "cool", "language"];
1107- ///
1108- /// MaybeUninit::write_slice_cloned(&mut vec.spare_capacity_mut()[..src.len()], &src);
1109- ///
1110- /// // SAFETY: we have just cloned all the elements of len into the spare capacity
1111- /// // the first src.len() elements of the vec are valid now.
1112- /// unsafe {
1113- /// vec.set_len(src.len());
1114- /// }
1115- ///
1116- /// assert_eq!(vec, src);
1117- /// ```
1118- ///
1119- /// [`write_slice`]: MaybeUninit::write_slice
1120- #[ unstable( feature = "maybe_uninit_write_slice" , issue = "79995" ) ]
1121- pub fn write_slice_cloned < ' a > ( this : & ' a mut [ MaybeUninit < T > ] , src : & [ T ] ) -> & ' a mut [ T ]
1122- where
1123- T : Clone ,
1124- {
1125- // unlike copy_from_slice this does not call clone_from_slice on the slice
1126- // this is because `MaybeUninit<T: Clone>` does not implement Clone.
1127-
1128- struct Guard < ' a , T > {
1129- slice : & ' a mut [ MaybeUninit < T > ] ,
1130- initialized : usize ,
1131- }
1132-
1133- impl < ' a , T > Drop for Guard < ' a , T > {
1134- fn drop ( & mut self ) {
1135- let initialized_part = & mut self . slice [ ..self . initialized ] ;
1136- // SAFETY: this raw slice will contain only initialized objects
1137- // that's why, it is allowed to drop it.
1138- unsafe {
1139- crate :: ptr:: drop_in_place ( MaybeUninit :: slice_assume_init_mut ( initialized_part) ) ;
1140- }
1141- }
1142- }
1143-
1144- assert_eq ! ( this. len( ) , src. len( ) , "destination and source slices have different lengths" ) ;
1145- // NOTE: We need to explicitly slice them to the same length
1146- // for bounds checking to be elided, and the optimizer will
1147- // generate memcpy for simple cases (for example T = u8).
1148- let len = this. len ( ) ;
1149- let src = & src[ ..len] ;
1150-
1151- // guard is needed b/c panic might happen during a clone
1152- let mut guard = Guard { slice : this, initialized : 0 } ;
1153-
1154- for i in 0 ..len {
1155- guard. slice [ i] . write ( src[ i] . clone ( ) ) ;
1156- guard. initialized += 1 ;
1157- }
1158-
1159- super :: forget ( guard) ;
1160-
1161- // SAFETY: Valid elements have just been written into `this` so it is initialized
1162- unsafe { MaybeUninit :: slice_assume_init_mut ( this) }
1163- }
1164-
11651017 /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes.
11661018 ///
11671019 /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
@@ -1265,7 +1117,7 @@ impl<T> MaybeUninit<T> {
12651117 ///
12661118 /// let mut uninit = [MaybeUninit::<u16>::uninit(), MaybeUninit::<u16>::uninit()];
12671119 /// let uninit_bytes = MaybeUninit::slice_as_bytes_mut(&mut uninit);
1268- /// MaybeUninit:: write_slice(uninit_bytes, &[0x12, 0x34, 0x56, 0x78]);
1120+ /// uninit_bytes. write_slice(&[0x12, 0x34, 0x56, 0x78]);
12691121 /// let vals = unsafe { MaybeUninit::slice_assume_init_ref(&uninit) };
12701122 /// if cfg!(target_endian = "little") {
12711123 /// assert_eq!(vals, &[0x3412u16, 0x7856u16]);
@@ -1321,3 +1173,145 @@ impl<T, const N: usize> [MaybeUninit<T>; N] {
13211173 unsafe { super :: transmute_copy ( & ManuallyDrop :: new ( self ) ) }
13221174 }
13231175}
1176+
1177+ impl < T > [ MaybeUninit < T > ] {
1178+ /// Copies the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`.
1179+ ///
1180+ /// If `T` does not implement `Copy`, use [`write_slice_cloned`](slice::write_slice_cloned)
1181+ ///
1182+ /// This is similar to [`slice::copy_from_slice`].
1183+ ///
1184+ /// # Panics
1185+ ///
1186+ /// This function will panic if the two slices have different lengths.
1187+ ///
1188+ /// # Examples
1189+ ///
1190+ /// ```
1191+ /// #![feature(maybe_uninit_write_slice)]
1192+ /// use std::mem::MaybeUninit;
1193+ ///
1194+ /// let mut dst = [MaybeUninit::uninit(); 32];
1195+ /// let src = [0; 32];
1196+ ///
1197+ /// let init = dst.write_slice(&src);
1198+ ///
1199+ /// assert_eq!(init, src);
1200+ /// ```
1201+ ///
1202+ /// ```
1203+ /// #![feature(maybe_uninit_write_slice)]
1204+ /// let mut vec = Vec::with_capacity(32);
1205+ /// let src = [0; 16];
1206+ ///
1207+ /// vec.spare_capacity_mut()[..src.len()].write_slice(&src);
1208+ ///
1209+ /// // SAFETY: we have just copied all the elements of len into the spare capacity
1210+ /// // the first src.len() elements of the vec are valid now.
1211+ /// unsafe {
1212+ /// vec.set_len(src.len());
1213+ /// }
1214+ ///
1215+ /// assert_eq!(vec, src);
1216+ /// ```
1217+ #[ unstable( feature = "maybe_uninit_write_slice" , issue = "79995" ) ]
1218+ pub fn write_slice ( & mut self , src : & [ T ] ) -> & mut [ T ]
1219+ where
1220+ T : Copy ,
1221+ {
1222+ // SAFETY: &[T] and &[MaybeUninit<T>] have the same layout
1223+ let uninit_src: & [ MaybeUninit < T > ] = unsafe { super :: transmute ( src) } ;
1224+
1225+ self . copy_from_slice ( uninit_src) ;
1226+
1227+ // SAFETY: Valid elements have just been copied into `this` so it is initialized
1228+ unsafe { MaybeUninit :: slice_assume_init_mut ( self ) }
1229+ }
1230+
1231+ /// Clones the elements from `src` to `this`, returning a mutable reference to the now initialized contents of `this`.
1232+ /// Any already initialized elements will not be dropped.
1233+ ///
1234+ /// If `T` implements `Copy`, use [`write_slice`](slice::write_slice)
1235+ ///
1236+ /// This is similar to [`slice::clone_from_slice`] but does not drop existing elements.
1237+ ///
1238+ /// # Panics
1239+ ///
1240+ /// This function will panic if the two slices have different lengths, or if the implementation of `Clone` panics.
1241+ ///
1242+ /// If there is a panic, the already cloned elements will be dropped.
1243+ ///
1244+ /// # Examples
1245+ ///
1246+ /// ```
1247+ /// #![feature(maybe_uninit_write_slice)]
1248+ /// use std::mem::MaybeUninit;
1249+ ///
1250+ /// let mut dst = [MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit()];
1251+ /// let src = ["wibbly".to_string(), "wobbly".to_string(), "timey".to_string(), "wimey".to_string(), "stuff".to_string()];
1252+ ///
1253+ /// let init = dst.write_slice_cloned(&src);
1254+ ///
1255+ /// assert_eq!(init, src);
1256+ /// ```
1257+ ///
1258+ /// ```
1259+ /// #![feature(maybe_uninit_write_slice)]
1260+ /// let mut vec = Vec::with_capacity(32);
1261+ /// let src = ["rust", "is", "a", "pretty", "cool", "language"];
1262+ ///
1263+ /// vec.spare_capacity_mut()[..src.len()].write_slice_cloned(&src);
1264+ ///
1265+ /// // SAFETY: we have just cloned all the elements of len into the spare capacity
1266+ /// // the first src.len() elements of the vec are valid now.
1267+ /// unsafe {
1268+ /// vec.set_len(src.len());
1269+ /// }
1270+ ///
1271+ /// assert_eq!(vec, src);
1272+ /// ```
1273+ #[ unstable( feature = "maybe_uninit_write_slice" , issue = "79995" ) ]
1274+ pub fn write_slice_cloned ( & mut self , src : & [ T ] ) -> & mut [ T ]
1275+ where
1276+ T : Clone ,
1277+ {
1278+ // unlike copy_from_slice this does not call clone_from_slice on the slice
1279+ // this is because `MaybeUninit<T: Clone>` does not implement Clone.
1280+
1281+ struct Guard < ' a , T > {
1282+ slice : & ' a mut [ MaybeUninit < T > ] ,
1283+ initialized : usize ,
1284+ }
1285+
1286+ impl < ' a , T > Drop for Guard < ' a , T > {
1287+ fn drop ( & mut self ) {
1288+ let initialized_part = & mut self . slice [ ..self . initialized ] ;
1289+ // SAFETY: this raw slice will contain only initialized objects
1290+ // that's why, it is allowed to drop it.
1291+ unsafe {
1292+ ptr:: drop_in_place ( MaybeUninit :: slice_assume_init_mut ( initialized_part) ) ;
1293+ }
1294+ }
1295+ }
1296+
1297+ assert_eq ! ( self . len( ) , src. len( ) , "destination and source slices have different lengths" ) ;
1298+ // NOTE: We need to explicitly slice them to the same length
1299+ // for bounds checking to be elided, and the optimizer will
1300+ // generate memcpy for simple cases (for example T = u8).
1301+ let len = self . len ( ) ;
1302+ let src = & src[ ..len] ;
1303+
1304+ // guard is needed b/c panic might happen during a clone
1305+ let mut guard = Guard { slice : self , initialized : 0 } ;
1306+
1307+ for i in 0 ..len {
1308+ guard. slice [ i] . write ( src[ i] . clone ( ) ) ;
1309+ guard. initialized += 1 ;
1310+ }
1311+
1312+ super :: forget ( guard) ;
1313+
1314+ // SAFETY: Valid elements have just been written into `self` so it is initialized
1315+ unsafe { MaybeUninit :: slice_assume_init_mut ( self ) }
1316+ }
1317+ }
0 commit comments