|
253 | 253 | use crate::cmp::Ordering;
|
254 | 254 | use crate::fmt::{self, Debug, Display};
|
255 | 255 | use crate::marker::{PhantomData, Unsize};
|
256 |
| -use crate::mem; |
257 |
| -use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn}; |
| 256 | +use crate::mem::{self, ManuallyDrop}; |
| 257 | +use crate::ops::{self, CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn}; |
258 | 258 | use crate::panic::const_panic;
|
259 | 259 | use crate::pin::PinCoerceUnsized;
|
260 | 260 | use crate::ptr::{self, NonNull};
|
| 261 | +use crate::range; |
261 | 262 |
|
262 | 263 | mod lazy;
|
263 | 264 | mod once;
|
@@ -713,6 +714,93 @@ impl<T, const N: usize> Cell<[T; N]> {
|
713 | 714 | }
|
714 | 715 | }
|
715 | 716 |
|
| 717 | +/// Types for which cloning `Cell<Self>` is sound. |
| 718 | +/// |
| 719 | +/// # Safety |
| 720 | +/// |
| 721 | +/// Implementing this trait for a type is sound if and only if the following code is sound for T = |
| 722 | +/// that type. |
| 723 | +/// |
| 724 | +/// ``` |
| 725 | +/// #![feature(cell_get_cloned)] |
| 726 | +/// # use std::cell::{CloneFromCell, Cell}; |
| 727 | +/// fn clone_from_cell<T: CloneFromCell>(cell: &Cell<T>) -> T { |
| 728 | +/// unsafe { T::clone(&*cell.as_ptr()) } |
| 729 | +/// } |
| 730 | +/// ``` |
| 731 | +/// |
| 732 | +/// Importantly, you can't just implement `CloneFromCell` for any arbitrary `Copy` type, e.g. the |
| 733 | +/// following is unsound: |
| 734 | +/// |
| 735 | +/// ```rust |
| 736 | +/// #![feature(cell_get_cloned)] |
| 737 | +/// # use std::cell::Cell; |
| 738 | +/// |
| 739 | +/// #[derive(Copy, Debug)] |
| 740 | +/// pub struct Bad<'a>(Option<&'a Cell<Bad<'a>>>, u8); |
| 741 | +/// |
| 742 | +/// impl Clone for Bad<'_> { |
| 743 | +/// fn clone(&self) -> Self { |
| 744 | +/// let a: &u8 = &self.1; |
| 745 | +/// // when self.0 points to self, we write to self.1 while we have a live `&u8` pointing to |
| 746 | +/// // it -- this is UB |
| 747 | +/// self.0.unwrap().set(Self(None, 1)); |
| 748 | +/// dbg!((a, self)); |
| 749 | +/// Self(None, 0) |
| 750 | +/// } |
| 751 | +/// } |
| 752 | +/// |
| 753 | +/// // this is not sound |
| 754 | +/// // unsafe impl CloneFromCell for Bad<'_> {} |
| 755 | +/// ``` |
| 756 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 757 | +// Allow potential overlapping implementations in user code |
| 758 | +#[marker] |
| 759 | +pub unsafe trait CloneFromCell: Clone {} |
| 760 | + |
| 761 | +// `CloneFromCell` can be implemented for types that don't have indirection and which don't access |
| 762 | +// `Cell`s in their `Clone` implementation. A commonly-used subset is covered here. |
| 763 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 764 | +unsafe impl<T: CloneFromCell, const N: usize> CloneFromCell for [T; N] {} |
| 765 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 766 | +unsafe impl<T: CloneFromCell> CloneFromCell for Option<T> {} |
| 767 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 768 | +unsafe impl<T: CloneFromCell, E: CloneFromCell> CloneFromCell for Result<T, E> {} |
| 769 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 770 | +unsafe impl<T: ?Sized> CloneFromCell for PhantomData<T> {} |
| 771 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 772 | +unsafe impl<T: CloneFromCell> CloneFromCell for ManuallyDrop<T> {} |
| 773 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 774 | +unsafe impl<T: CloneFromCell> CloneFromCell for ops::Range<T> {} |
| 775 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 776 | +unsafe impl<T: CloneFromCell> CloneFromCell for range::Range<T> {} |
| 777 | + |
| 778 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 779 | +impl<T: CloneFromCell> Cell<T> { |
| 780 | + /// Get a clone of the `Cell` that contains a copy of the original value. |
| 781 | + /// |
| 782 | + /// This allows a cheaply `Clone`-able type like an `Rc` to be stored in a `Cell`, exposing the |
| 783 | + /// cheaper `clone()` method. |
| 784 | + /// |
| 785 | + /// # Examples |
| 786 | + /// |
| 787 | + /// ``` |
| 788 | + /// #![feature(cell_get_cloned)] |
| 789 | + /// |
| 790 | + /// use core::cell::Cell; |
| 791 | + /// use std::rc::Rc; |
| 792 | + /// |
| 793 | + /// let rc = Rc::new(1usize); |
| 794 | + /// let c1 = Cell::new(rc); |
| 795 | + /// let c2 = c1.get_cloned(); |
| 796 | + /// assert_eq!(*c2.into_inner(), 1); |
| 797 | + /// ``` |
| 798 | + pub fn get_cloned(&self) -> Self { |
| 799 | + // SAFETY: T is CloneFromCell, which guarantees that this is sound. |
| 800 | + Cell::new(T::clone(unsafe { &*self.as_ptr() })) |
| 801 | + } |
| 802 | +} |
| 803 | + |
716 | 804 | /// A mutable memory location with dynamically checked borrow rules
|
717 | 805 | ///
|
718 | 806 | /// See the [module-level documentation](self) for more.
|
|
0 commit comments