|
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; |
@@ -712,6 +713,61 @@ impl<T, const N: usize> Cell<[T; N]> { |
712 | 713 | } |
713 | 714 | } |
714 | 715 |
|
| 716 | +/// Types that can be cloned from a copy of the value. |
| 717 | +/// |
| 718 | +/// # Safety |
| 719 | +/// |
| 720 | +/// Implementing this trait is safe for any type that can be safely bitwise copied. |
| 721 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 722 | +// Allow potential overlapping implementations in user code |
| 723 | +#[marker] |
| 724 | +pub unsafe trait CloneFromCopy: Clone {} |
| 725 | + |
| 726 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 727 | +unsafe impl<T: Copy> CloneFromCopy for T {} |
| 728 | + |
| 729 | +// `CloneFromCopy` can be implemented for types that don't have indirection. A commonly-used subset is covered here. |
| 730 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 731 | +unsafe impl<T: CloneFromCopy, const N: usize> CloneFromCopy for [T; N] {} |
| 732 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 733 | +unsafe impl<T: CloneFromCopy> CloneFromCopy for Option<T> {} |
| 734 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 735 | +unsafe impl<T: CloneFromCopy, E: CloneFromCopy> CloneFromCopy for Result<T, E> {} |
| 736 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 737 | +unsafe impl<T: CloneFromCopy> CloneFromCopy for PhantomData<T> {} |
| 738 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 739 | +unsafe impl<T: CloneFromCopy> CloneFromCopy for ManuallyDrop<T> {} |
| 740 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 741 | +unsafe impl<T: CloneFromCopy> CloneFromCopy for ops::Range<T> {} |
| 742 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 743 | +unsafe impl<T: CloneFromCopy> CloneFromCopy for range::Range<T> {} |
| 744 | + |
| 745 | +#[unstable(feature = "cell_get_cloned", issue = "145329")] |
| 746 | +impl<T: CloneFromCopy> Cell<T> { |
| 747 | + /// Get a clone of the `Cell` that contains a copy of the original value. |
| 748 | + /// |
| 749 | + /// This allows a cheaply `Clone`-able type like an `Rc` to be stored in a `Cell`, exposing the |
| 750 | + /// cheaper `clone()` method. |
| 751 | + /// |
| 752 | + /// # Examples |
| 753 | + /// |
| 754 | + /// ``` |
| 755 | + /// #![feature(cell_get_cloned)] |
| 756 | + /// |
| 757 | + /// use core::cell::Cell; |
| 758 | + /// |
| 759 | + /// let rc = Rc::new(1usize); |
| 760 | + /// let c1 = Cell::new(rc); |
| 761 | + /// let c2 = c1.get_cloned(); |
| 762 | + /// assert_eq!(*c2.into_inner(), 1); |
| 763 | + /// ``` |
| 764 | + pub fn get_cloned(&self) -> Self { |
| 765 | + // SAFETY: T is CloneFromCopy, which guarantees that this is sound. |
| 766 | + let copy = ManuallyDrop::new(unsafe { self.as_ptr().read() }); |
| 767 | + Cell::new(T::clone(&*copy)) |
| 768 | + } |
| 769 | +} |
| 770 | + |
715 | 771 | /// A mutable memory location with dynamically checked borrow rules |
716 | 772 | /// |
717 | 773 | /// See the [module-level documentation](self) for more. |
|
0 commit comments