@@ -1334,6 +1334,96 @@ pub fn uninit<T, E>() -> impl Init<MaybeUninit<T>, E> {
13341334 unsafe { init_from_closure ( |_| Ok ( ( ) ) ) }
13351335}
13361336
1337+ /// Initializes an array by initializing each element via the provided initializer.
1338+ ///
1339+ /// # Examples
1340+ ///
1341+ /// ```rust
1342+ /// let array: Box<[usize; 1000_000_000]>= Box::init(init_array_from_fn(|i| i)).unwrap();
1343+ /// println!("{array:?}");
1344+ /// ```
1345+ pub fn init_array_from_fn < I , const N : usize , T , E > (
1346+ mut make_init : impl FnMut ( usize ) -> I ,
1347+ ) -> impl Init < [ T ; N ] , E >
1348+ where
1349+ I : Init < T , E > ,
1350+ {
1351+ let init = move |slot : * mut [ T ; N ] | {
1352+ let slot = slot. cast :: < T > ( ) ;
1353+ for i in 0 ..N {
1354+ let init = make_init ( i) ;
1355+ // SAFETY: since 0 <= `i` < N, it is still in bounds of `[T; N]`.
1356+ let ptr = unsafe { slot. add ( i) } ;
1357+ // SAFETY: The pointer is derived from `slot` and thus satisfies the `__init`
1358+ // requirements.
1359+ match unsafe { init. __init ( ptr) } {
1360+ Ok ( ( ) ) => { }
1361+ Err ( e) => {
1362+ // We now free every element that has been initialized before:
1363+ for j in 0 ..i {
1364+ let ptr = unsafe { slot. add ( j) } ;
1365+ // SAFETY: The value was initialized in a previous iteration of the loop
1366+ // and since we return `Err` below, the caller will consider the memory at
1367+ // `slot` as uninitialized.
1368+ unsafe { ptr:: drop_in_place ( ptr) } ;
1369+ }
1370+ return Err ( e) ;
1371+ }
1372+ }
1373+ }
1374+ Ok ( ( ) )
1375+ } ;
1376+ // SAFETY: The initializer above initializes every element of the array. On failure it drops
1377+ // any initialized elements and returns `Err`.
1378+ unsafe { init_from_closure ( init) }
1379+ }
1380+
1381+ /// Initializes an array by initializing each element via the provided initializer.
1382+ ///
1383+ /// # Examples
1384+ ///
1385+ /// ```rust
1386+ /// let array: Arc<[Mutex<usize>; 1000_000_000]>=
1387+ /// Arc::pin_init(init_array_from_fn(|i| new_mutex!(i))).unwrap();
1388+ /// println!("{array:?}");
1389+ /// ```
1390+ pub fn pin_init_array_from_fn < I , const N : usize , T , E > (
1391+ mut make_init : impl FnMut ( usize ) -> I ,
1392+ ) -> impl PinInit < [ T ; N ] , E >
1393+ where
1394+ I : PinInit < T , E > ,
1395+ {
1396+ let init = move |slot : * mut [ T ; N ] | {
1397+ let slot = slot. cast :: < T > ( ) ;
1398+ for i in 0 ..N {
1399+ let init = make_init ( i) ;
1400+ // SAFETY: since 0 <= `i` < N, it is still in bounds of `[T; N]`.
1401+ let ptr = unsafe { slot. add ( i) } ;
1402+ // SAFETY: The pointer is derived from `slot` and thus satisfies the `__pinned_init`
1403+ // requirements.
1404+ match unsafe { init. __pinned_init ( ptr) } {
1405+ Ok ( ( ) ) => { }
1406+ Err ( e) => {
1407+ // We now have to free every element that has been initialized before, since we
1408+ // have to abide by the drop guarantee.
1409+ for j in 0 ..i {
1410+ let ptr = unsafe { slot. add ( j) } ;
1411+ // SAFETY: The value was initialized in a previous iteration of the loop
1412+ // and since we return `Err` below, the caller will consider the memory at
1413+ // `slot` as uninitialized.
1414+ unsafe { ptr:: drop_in_place ( ptr) } ;
1415+ }
1416+ return Err ( e) ;
1417+ }
1418+ }
1419+ }
1420+ Ok ( ( ) )
1421+ } ;
1422+ // SAFETY: The initializer above initializes every element of the array. On failure it drops
1423+ // any initialized elements and returns `Err`.
1424+ unsafe { pin_init_from_closure ( init) }
1425+ }
1426+
13371427// SAFETY: Every type can be initialized by-value.
13381428unsafe impl < T , E > Init < T , E > for T {
13391429 unsafe fn __init ( self , slot : * mut T ) -> Result < ( ) , E > {
0 commit comments