@@ -1409,6 +1409,210 @@ impl<T> MaybeUninit<T> {
1409
1409
unsafe { slice:: from_raw_parts_mut ( this. as_mut_ptr ( ) as * mut MaybeUninit < u8 > , bytes) }
1410
1410
}
1411
1411
}
1412
+ impl < T > [ MaybeUninit < T > ] {
1413
+ /// Copies the elements from `src` to `self`,
1414
+ /// returning a mutable reference to the now initialized contents of `self`.
1415
+ ///
1416
+ /// If `T` does not implement `Copy`, use [`write_clone_of_slice`] instead.
1417
+ ///
1418
+ /// This is similar to [`slice::copy_from_slice`].
1419
+ ///
1420
+ /// # Panics
1421
+ ///
1422
+ /// This function will panic if the two slices have different lengths.
1423
+ ///
1424
+ /// # Examples
1425
+ ///
1426
+ /// ```
1427
+ /// #![feature(maybe_uninit_write_slice)]
1428
+ /// use std::mem::MaybeUninit;
1429
+ ///
1430
+ /// let mut dst = [MaybeUninit::uninit(); 32];
1431
+ /// let src = [0; 32];
1432
+ ///
1433
+ /// let init = dst.write_copy_of_slice(&src);
1434
+ ///
1435
+ /// assert_eq!(init, src);
1436
+ /// ```
1437
+ ///
1438
+ /// ```
1439
+ /// #![feature(maybe_uninit_write_slice)]
1440
+ /// use std::mem::MaybeUninit;
1441
+ ///
1442
+ /// let mut vec = Vec::with_capacity(32);
1443
+ /// let src = [0; 16];
1444
+ ///
1445
+ /// vec.spare_capacity_mut()[..src.len()].write_copy_of_slice(&src);
1446
+ ///
1447
+ /// // SAFETY: we have just copied all the elements of len into the spare capacity
1448
+ /// // the first src.len() elements of the vec are valid now.
1449
+ /// unsafe {
1450
+ /// vec.set_len(src.len());
1451
+ /// }
1452
+ ///
1453
+ /// assert_eq!(vec, src);
1454
+ /// ```
1455
+ ///
1456
+ /// [`write_clone_of_slice`]: MaybeUninit::write_clone_of_slice
1457
+ #[ unstable( feature = "maybe_uninit_write_slice" , issue = "79995" ) ]
1458
+ pub fn write_copy_of_slice ( & mut self , src : & [ T ] ) -> & mut [ T ]
1459
+ where
1460
+ T : Copy ,
1461
+ {
1462
+ // SAFETY: &[T] and &[MaybeUninit<T>] have the same layout
1463
+ let uninit_src: & [ MaybeUninit < T > ] = unsafe { super :: transmute ( src) } ;
1464
+
1465
+ self . copy_from_slice ( uninit_src) ;
1466
+
1467
+ // SAFETY: Valid elements have just been copied into `self` so it is initialized
1468
+ unsafe { self . assume_init_mut ( ) }
1469
+ }
1470
+
1471
+ /// Clones the elements from `src` to `self`,
1472
+ /// returning a mutable reference to the now initialized contents of `self`.
1473
+ /// Any already initialized elements will not be dropped.
1474
+ ///
1475
+ /// If `T` implements `Copy`, use [`write_copy_of_slice`] instead.
1476
+ ///
1477
+ /// This is similar to [`slice::clone_from_slice`] but does not drop existing elements.
1478
+ ///
1479
+ /// # Panics
1480
+ ///
1481
+ /// This function will panic if the two slices have different lengths, or if the implementation of `Clone` panics.
1482
+ ///
1483
+ /// If there is a panic, the already cloned elements will be dropped.
1484
+ ///
1485
+ /// # Examples
1486
+ ///
1487
+ /// ```
1488
+ /// #![feature(maybe_uninit_write_slice)]
1489
+ /// use std::mem::MaybeUninit;
1490
+ ///
1491
+ /// let mut dst = [MaybeUninit::uninit(); 5];
1492
+ /// let src = ["wibbly", "wobbly", "timey", "wimey", "stuff"].map(|s| s.to_string());
1493
+ ///
1494
+ /// let init = dst.write_clone_of_slice(&src);
1495
+ ///
1496
+ /// assert_eq!(init, src);
1497
+ ///
1498
+ /// # // Prevent leaks for Miri
1499
+ /// # unsafe { std::ptr::drop_in_place(init); }
1500
+ /// ```
1501
+ ///
1502
+ /// ```
1503
+ /// #![feature(maybe_uninit_write_slice)]
1504
+ /// use std::mem::MaybeUninit;
1505
+ ///
1506
+ /// let mut vec = Vec::with_capacity(32);
1507
+ /// let src = ["rust", "is", "a", "pretty", "cool", "language"].map(|s| s.to_string());
1508
+ ///
1509
+ /// vec.spare_capacity_mut()[..src.len()].write_clone_of_slice(&src);
1510
+ ///
1511
+ /// // SAFETY: we have just cloned all the elements of len into the spare capacity
1512
+ /// // the first src.len() elements of the vec are valid now.
1513
+ /// unsafe {
1514
+ /// vec.set_len(src.len());
1515
+ /// }
1516
+ ///
1517
+ /// assert_eq!(vec, src);
1518
+ /// ```
1519
+ ///
1520
+ /// [`write_copy_of_slice`]: MaybeUninit::write_copy_of_slice
1521
+ #[ unstable( feature = "maybe_uninit_write_slice" , issue = "79995" ) ]
1522
+ pub fn write_clone_of_slice ( & mut self , src : & [ T ] ) -> & mut [ T ]
1523
+ where
1524
+ T : Clone ,
1525
+ {
1526
+ // unlike copy_from_slice this does not call clone_from_slice on the slice
1527
+ // this is because `MaybeUninit<T: Clone>` does not implement Clone.
1528
+
1529
+ assert_eq ! ( self . len( ) , src. len( ) , "destination and source slices have different lengths" ) ;
1530
+
1531
+ // NOTE: We need to explicitly slice them to the same length
1532
+ // for bounds checking to be elided, and the optimizer will
1533
+ // generate memcpy for simple cases (for example T = u8).
1534
+ let len = self . len ( ) ;
1535
+ let src = & src[ ..len] ;
1536
+
1537
+ // guard is needed b/c panic might happen during a clone
1538
+ let mut guard = Guard { slice : self , initialized : 0 } ;
1539
+
1540
+ for i in 0 ..len {
1541
+ guard. slice [ i] . write ( src[ i] . clone ( ) ) ;
1542
+ guard. initialized += 1 ;
1543
+ }
1544
+
1545
+ super :: forget ( guard) ;
1546
+
1547
+ // SAFETY: Valid elements have just been written into `self` so it is initialized
1548
+ unsafe { self . assume_init_mut ( ) }
1549
+ }
1550
+
1551
+ /// Drops the contained values in place.
1552
+ ///
1553
+ /// # Safety
1554
+ ///
1555
+ /// It is up to the caller to guarantee that every `MaybeUninit<T>` in the slice
1556
+ /// really is in an initialized state. Calling this when the content is not yet
1557
+ /// fully initialized causes undefined behavior.
1558
+ ///
1559
+ /// On top of that, all additional invariants of the type `T` must be
1560
+ /// satisfied, as the `Drop` implementation of `T` (or its members) may
1561
+ /// rely on this. For example, setting a [`Vec<T>`] to an invalid but
1562
+ /// non-null address makes it initialized (under the current implementation;
1563
+ /// this does not constitute a stable guarantee), because the only
1564
+ /// requirement the compiler knows about it is that the data pointer must be
1565
+ /// non-null. Dropping such a `Vec<T>` however will cause undefined
1566
+ /// behaviour.
1567
+ ///
1568
+ /// [`Vec<T>`]: ../../std/vec/struct.Vec.html
1569
+ #[ unstable( feature = "maybe_uninit_slice" , issue = "63569" ) ]
1570
+ pub unsafe fn assume_init_drop ( & mut self ) {
1571
+ // SAFETY: the caller must guarantee that every element of `self`
1572
+ // is initialized and satisfies all invariants of `T`.
1573
+ // Dropping the value in place is safe if that is the case.
1574
+ unsafe { ptr:: drop_in_place ( self as * mut [ MaybeUninit < T > ] as * mut [ T ] ) }
1575
+ }
1576
+
1577
+ /// Gets a shared reference to the contained value.
1578
+ ///
1579
+ /// # Safety
1580
+ ///
1581
+ /// Calling this when the content is not yet fully initialized causes undefined
1582
+ /// behavior: it is up to the caller to guarantee that every `MaybeUninit<T>` in
1583
+ /// the slice really is in an initialized state.
1584
+ #[ unstable( feature = "maybe_uninit_slice" , issue = "63569" ) ]
1585
+ #[ rustc_const_unstable( feature = "maybe_uninit_slice" , issue = "63569" ) ]
1586
+ #[ inline( always) ]
1587
+ pub const unsafe fn assume_init_ref ( & self ) -> & [ T ] {
1588
+ // SAFETY: the caller must guarantee that `self` is initialized.
1589
+ // This also means that `self` must be a `value` variant.
1590
+ unsafe {
1591
+ intrinsics:: assert_inhabited :: < T > ( ) ;
1592
+ slice:: from_raw_parts ( self . as_ptr ( ) . cast :: < T > ( ) , self . len ( ) )
1593
+ }
1594
+ }
1595
+
1596
+ /// Gets a mutable (unique) reference to the contained value.
1597
+ ///
1598
+ /// # Safety
1599
+ ///
1600
+ /// Calling this when the content is not yet fully initialized causes undefined
1601
+ /// behavior: it is up to the caller to guarantee that every `MaybeUninit<T>` in the
1602
+ /// slice really is in an initialized state. For instance, `.assume_init_mut()` cannot
1603
+ /// be used to initialize a `MaybeUninit` slice.
1604
+ #[ unstable( feature = "maybe_uninit_slice" , issue = "63569" ) ]
1605
+ #[ rustc_const_unstable( feature = "maybe_uninit_slice" , issue = "63569" ) ]
1606
+ #[ inline( always) ]
1607
+ pub const unsafe fn assume_init_mut ( & mut self ) -> & mut [ T ] {
1608
+ // SAFETY: the caller must guarantee that `self` is initialized.
1609
+ // This also means that `self` must be a `value` variant.
1610
+ unsafe {
1611
+ intrinsics:: assert_inhabited :: < T > ( ) ;
1612
+ slice:: from_raw_parts_mut ( self . as_mut_ptr ( ) . cast :: < T > ( ) , self . len ( ) )
1613
+ }
1614
+ }
1615
+ }
1412
1616
1413
1617
impl < T , const N : usize > MaybeUninit < [ T ; N ] > {
1414
1618
/// Transposes a `MaybeUninit<[T; N]>` into a `[MaybeUninit<T>; N]`.
@@ -1459,7 +1663,7 @@ impl<'a, T> Drop for Guard<'a, T> {
1459
1663
let initialized_part = & mut self . slice [ ..self . initialized ] ;
1460
1664
// SAFETY: this raw sub-slice will contain only initialized objects.
1461
1665
unsafe {
1462
- crate :: ptr :: drop_in_place ( MaybeUninit :: slice_assume_init_mut ( initialized_part) ) ;
1666
+ initialized_part. assume_init_drop ( ) ;
1463
1667
}
1464
1668
}
1465
1669
}
0 commit comments