@@ -1123,22 +1123,6 @@ impl<T> MaybeUninit<T> {
11231123 // unlike copy_from_slice this does not call clone_from_slice on the slice
11241124 // this is because `MaybeUninit<T: Clone>` does not implement Clone.
11251125
1126- struct Guard < ' a , T > {
1127- slice : & ' a mut [ MaybeUninit < T > ] ,
1128- initialized : usize ,
1129- }
1130-
1131- impl < ' a , T > Drop for Guard < ' a , T > {
1132- fn drop ( & mut self ) {
1133- let initialized_part = & mut self . slice [ ..self . initialized ] ;
1134- // SAFETY: this raw slice will contain only initialized objects
1135- // that's why, it is allowed to drop it.
1136- unsafe {
1137- crate :: ptr:: drop_in_place ( MaybeUninit :: slice_assume_init_mut ( initialized_part) ) ;
1138- }
1139- }
1140- }
1141-
11421126 assert_eq ! ( this. len( ) , src. len( ) , "destination and source slices have different lengths" ) ;
11431127 // NOTE: We need to explicitly slice them to the same length
11441128 // for bounds checking to be elided, and the optimizer will
@@ -1147,7 +1131,7 @@ impl<T> MaybeUninit<T> {
11471131 let src = & src[ ..len] ;
11481132
11491133 // guard is needed b/c panic might happen during a clone
1150- let mut guard = Guard { slice : this, initialized : 0 } ;
1134+ let mut guard = CloneGuard { slice : this, initialized : 0 } ;
11511135
11521136 for i in 0 ..len {
11531137 guard. slice [ i] . write ( src[ i] . clone ( ) ) ;
@@ -1160,6 +1144,202 @@ impl<T> MaybeUninit<T> {
11601144 unsafe { MaybeUninit :: slice_assume_init_mut ( this) }
11611145 }
11621146
1147+ /// Fills `this` with elements by copying `value`, returning a reference to
1148+ /// the now initialized contents of `this`.
1149+ ///
1150+ /// This is similar to [`slice::fill`] but is restricted to `Copy` values.
1151+ /// Use [`MaybeUninit::fill_cloned`] to initialize from a `Clone` value.
1152+ ///
1153+ /// # Examples
1154+ ///
1155+ /// ```
1156+ /// #![feature(maybe_uninit_fill)]
1157+ /// use std::mem::MaybeUninit;
1158+ ///
1159+ /// let mut dst = [MaybeUninit::uninit(); 5];
1160+ /// let init = MaybeUninit::fill(&mut dst, 0u8);
1161+ ///
1162+ /// assert_eq!(init, &[0, 0, 0, 0, 0]);
1163+ /// ```
1164+ #[ doc( alias = "memset" ) ]
1165+ #[ unstable( feature = "maybe_uninit_fill" , issue = "none" ) ]
1166+ pub fn fill < ' a > ( this : & ' a mut [ MaybeUninit < T > ] , value : T ) -> & ' a [ T ]
1167+ where
1168+ T : Copy ,
1169+ {
1170+ this. fill ( MaybeUninit :: new ( value) ) ;
1171+ // SAFETY: Valid elements have just been copied into `this` so it is initialized
1172+ unsafe { MaybeUninit :: slice_assume_init_ref ( this) }
1173+ }
1174+
1175+ /// Fills `this` with elements by copying `value`, returning a mutable
1176+ /// reference to the now initialized contents of `this`.
1177+ ///
1178+ /// This is similar to [`slice::fill`] but is restricted to `Copy` values.
1179+ /// Use [`MaybeUninit::fill_cloned`] to initialize from a `Clone` value.
1180+ ///
1181+ /// # Examples
1182+ ///
1183+ /// ```
1184+ /// #![feature(maybe_uninit_fill)]
1185+ /// use std::mem::MaybeUninit;
1186+ ///
1187+ /// let mut dst = [MaybeUninit::uninit(); 5];
1188+ /// let init = MaybeUninit::fill_mut(&mut dst, 0u8);
1189+ /// init[4] = 123;
1190+ ///
1191+ /// assert_eq!(init, &[0, 0, 0, 0, 123]);
1192+ /// ```
1193+ #[ unstable( feature = "maybe_uninit_fill" , issue = "none" ) ]
1194+ pub fn fill_mut < ' a > ( this : & ' a mut [ MaybeUninit < T > ] , value : T ) -> & ' a mut [ T ]
1195+ where
1196+ T : Copy ,
1197+ {
1198+ this. fill ( MaybeUninit :: new ( value) ) ;
1199+ // SAFETY: Valid elements have just been copied into `this` so it is initialized
1200+ unsafe { MaybeUninit :: slice_assume_init_mut ( this) }
1201+ }
1202+
1203+ /// Fills `this` with elements by cloning `value`, returning a reference to
1204+ /// the now initialized contents of `this`. Any already initialized elements
1205+ /// will not be dropped.
1206+ ///
1207+ /// This is similar to [`slice::fill`] but does not drop existing elements.
1208+ ///
1209+ /// # Panics
1210+ ///
1211+ /// This function will panic if the implementation of `Clone` panics.
1212+ ///
1213+ /// If there is a panic, the already initialized elements will be dropped.
1214+ ///
1215+ /// # Examples
1216+ ///
1217+ /// ```
1218+ /// #![feature(maybe_uninit_fill)]
1219+ /// use std::mem::MaybeUninit;
1220+ ///
1221+ /// let mut dst = [
1222+ /// MaybeUninit::uninit(),
1223+ /// MaybeUninit::uninit(),
1224+ /// MaybeUninit::uninit(),
1225+ /// ];
1226+ /// let msg = String::from("hello");
1227+ /// let init = MaybeUninit::fill_cloned(&mut dst, &msg);
1228+ ///
1229+ /// assert_eq!(init, &["hello", "hello", "hello"]);
1230+ /// ```
1231+ #[ unstable( feature = "maybe_uninit_fill" , issue = "none" ) ]
1232+ pub fn fill_cloned < ' a > ( this : & ' a mut [ MaybeUninit < T > ] , value : & T ) -> & ' a [ T ]
1233+ where
1234+ T : Clone ,
1235+ {
1236+ let len = this. len ( ) ;
1237+
1238+ // guard is needed b/c panic might happen during a clone
1239+ let mut guard = CloneGuard { slice : this, initialized : 0 } ;
1240+
1241+ for i in 0 ..len {
1242+ guard. slice [ i] . write ( value. clone ( ) ) ;
1243+ guard. initialized += 1 ;
1244+ }
1245+
1246+ super :: forget ( guard) ;
1247+
1248+ // SAFETY: Valid elements have just been written into `this` so it is initialized
1249+ unsafe { MaybeUninit :: slice_assume_init_ref ( this) }
1250+ }
1251+
1252+ /// Fills `this` with elements returned by calling a closure repeatedly,
1253+ /// returning a reference to the now initialized contents of `this`. Any
1254+ /// already initialized elements will not be dropped.
1255+ ///
1256+ /// This is similar to [`slice::fill_with`] but does not drop existing
1257+ /// elements.
1258+ ///
1259+ /// # Panics
1260+ ///
1261+ /// This function will panic if the closure panics.
1262+ ///
1263+ /// If there is a panic, the already initialized elements will be dropped.
1264+ ///
1265+ /// # Examples
1266+ ///
1267+ /// ```
1268+ /// #![feature(maybe_uninit_fill)]
1269+ /// use std::mem::MaybeUninit;
1270+ ///
1271+ /// let mut dst = [MaybeUninit::uninit(); 5];
1272+ /// let mut next = 0;
1273+ /// let init = MaybeUninit::fill_with(&mut dst, || { next += 1; next });
1274+ ///
1275+ /// assert_eq!(init, &[1, 2, 3, 4, 5]);
1276+ /// ```
1277+ #[ unstable( feature = "maybe_uninit_fill" , issue = "none" ) ]
1278+ pub fn fill_with < ' a , F > ( this : & ' a mut [ MaybeUninit < T > ] , mut f : F ) -> & ' a [ T ]
1279+ where
1280+ F : FnMut ( ) -> T ,
1281+ {
1282+ let len = this. len ( ) ;
1283+ let mut guard = CloneGuard { slice : this, initialized : 0 } ;
1284+
1285+ for i in 0 ..len {
1286+ guard. slice [ i] . write ( f ( ) ) ;
1287+ guard. initialized += 1 ;
1288+ }
1289+
1290+ super :: forget ( guard) ;
1291+
1292+ // SAFETY: Valid elements have just been written into `this` so it is initialized
1293+ unsafe { MaybeUninit :: slice_assume_init_ref ( this) }
1294+ }
1295+
1296+ /// Fills `this` with the contents of an iterator, returning a reference to
1297+ /// the now initialized contents of `this`. Any already initialized elements
1298+ /// will not be dropped.
1299+ ///
1300+ /// # Panics
1301+ ///
1302+ /// This function will panic if the iterator panics.
1303+ ///
1304+ /// If there is a panic, the already initialized elements will be dropped.
1305+ ///
1306+ /// # Examples
1307+ ///
1308+ /// ```
1309+ /// #![feature(maybe_uninit_fill)]
1310+ /// use std::mem::MaybeUninit;
1311+ ///
1312+ /// let mut dst = [MaybeUninit::uninit(); 5];
1313+ /// let mut iter = [1, 2, 3].into_iter().cycle();
1314+ /// let init = MaybeUninit::fill_from(&mut dst, iter);
1315+ ///
1316+ /// assert_eq!(init, &[1, 2, 3, 1, 2]);
1317+ /// ```
1318+ #[ unstable( feature = "maybe_uninit_fill" , issue = "none" ) ]
1319+ pub fn fill_from < ' a , I > ( this : & ' a mut [ MaybeUninit < T > ] , mut iter : I ) -> & ' a [ T ]
1320+ where
1321+ I : Iterator < Item = T > ,
1322+ {
1323+ let len = this. len ( ) ;
1324+ let mut guard = CloneGuard { slice : this, initialized : 0 } ;
1325+
1326+ for i in 0 ..len {
1327+ match iter. next ( ) {
1328+ Some ( value) => {
1329+ guard. slice [ i] . write ( value) ;
1330+ guard. initialized += 1 ;
1331+ }
1332+ None => break ,
1333+ }
1334+ }
1335+
1336+ let init_len = guard. initialized ;
1337+ super :: forget ( guard) ;
1338+
1339+ // SAFETY: Valid elements have just been written into `this` so it is initialized
1340+ unsafe { MaybeUninit :: slice_assume_init_ref ( & mut this[ ..init_len] ) }
1341+ }
1342+
11631343 /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes.
11641344 ///
11651345 /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still
@@ -1313,3 +1493,19 @@ impl<T, const N: usize> [MaybeUninit<T>; N] {
13131493 unsafe { intrinsics:: transmute_unchecked ( self ) }
13141494 }
13151495}
1496+
1497+ struct CloneGuard < ' a , T > {
1498+ slice : & ' a mut [ MaybeUninit < T > ] ,
1499+ initialized : usize ,
1500+ }
1501+
1502+ impl < ' a , T > Drop for CloneGuard < ' a , T > {
1503+ fn drop ( & mut self ) {
1504+ let initialized_part = & mut self . slice [ ..self . initialized ] ;
1505+ // SAFETY: this raw slice will contain only initialized objects
1506+ // that's why, it is allowed to drop it.
1507+ unsafe {
1508+ crate :: ptr:: drop_in_place ( MaybeUninit :: slice_assume_init_mut ( initialized_part) ) ;
1509+ }
1510+ }
1511+ }
0 commit comments