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