Skip to content

Commit fe78582

Browse files
committed
add CopyFromClone and Cell::get_cloned
1 parent e8a792d commit fe78582

File tree

4 files changed

+90
-3
lines changed

4 files changed

+90
-3
lines changed

library/alloc/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
#![feature(bstr)]
104104
#![feature(bstr_internals)]
105105
#![feature(cast_maybe_uninit)]
106+
#![feature(cell_get_cloned)]
106107
#![feature(char_internals)]
107108
#![feature(char_max_len)]
108109
#![feature(clone_to_uninit)]

library/alloc/src/rc.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@
242242
#![stable(feature = "rust1", since = "1.0.0")]
243243

244244
use core::any::Any;
245-
use core::cell::Cell;
245+
use core::cell::{Cell, CloneFromCopy};
246246
#[cfg(not(no_global_oom_handling))]
247247
use core::clone::CloneToUninit;
248248
use core::clone::UseCloned;
@@ -338,6 +338,9 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Rc<U, A>> for
338338
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
339339
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Rc<U>> for Rc<T> {}
340340

341+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
342+
unsafe impl<T: ?Sized> CloneFromCopy for Rc<T> {}
343+
341344
impl<T: ?Sized> Rc<T> {
342345
#[inline]
343346
unsafe fn from_inner(ptr: NonNull<RcInner<T>>) -> Self {
@@ -3032,6 +3035,9 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Weak<U, A>> f
30323035
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
30333036
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}
30343037

3038+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
3039+
unsafe impl<T: ?Sized> CloneFromCopy for Weak<T> {}
3040+
30353041
impl<T> Weak<T> {
30363042
/// Constructs a new `Weak<T>`, without allocating any memory.
30373043
/// Calling [`upgrade`] on the return value always gives [`None`].

library/alloc/src/sync.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//! `#[cfg(target_has_atomic = "ptr")]`.
1010
1111
use core::any::Any;
12+
use core::cell::CloneFromCopy;
1213
#[cfg(not(no_global_oom_handling))]
1314
use core::clone::CloneToUninit;
1415
use core::clone::UseCloned;
@@ -281,6 +282,9 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Arc<U, A>> fo
281282
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
282283
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Arc<U>> for Arc<T> {}
283284

285+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
286+
unsafe impl<T: ?Sized> CloneFromCopy for Arc<T> {}
287+
284288
impl<T: ?Sized> Arc<T> {
285289
unsafe fn from_inner(ptr: NonNull<ArcInner<T>>) -> Self {
286290
unsafe { Self::from_inner_in(ptr, Global) }
@@ -356,6 +360,9 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Weak<U, A>> f
356360
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
357361
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}
358362

363+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
364+
unsafe impl<T: ?Sized> CloneFromCopy for Weak<T> {}
365+
359366
#[stable(feature = "arc_weak", since = "1.4.0")]
360367
impl<T: ?Sized, A: Allocator> fmt::Debug for Weak<T, A> {
361368
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

library/core/src/cell.rs

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,12 @@
253253
use crate::cmp::Ordering;
254254
use crate::fmt::{self, Debug, Display};
255255
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};
258258
use crate::panic::const_panic;
259259
use crate::pin::PinCoerceUnsized;
260260
use crate::ptr::{self, NonNull};
261+
use crate::range;
261262

262263
mod lazy;
263264
mod once;
@@ -712,6 +713,78 @@ impl<T, const N: usize> Cell<[T; N]> {
712713
}
713714
}
714715

716+
/// Safety: can call `Self::clone(&*ManuallyDrop::new(ptr::read(ptr_to_self)))`
717+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
718+
#[marker]
719+
pub unsafe trait CloneFromCopy: Clone {}
720+
721+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
722+
unsafe impl<T: Copy> CloneFromCopy for T {}
723+
724+
// basically all std types that don't have indirection:
725+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
726+
unsafe impl<T: CloneFromCopy, const N: usize> CloneFromCopy for [T; N] {}
727+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
728+
unsafe impl<T: CloneFromCopy> CloneFromCopy for Option<T> {}
729+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
730+
unsafe impl<T: CloneFromCopy, E: CloneFromCopy> CloneFromCopy for Result<T, E> {}
731+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
732+
unsafe impl<T: CloneFromCopy> CloneFromCopy for PhantomData<T> {}
733+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
734+
unsafe impl<T: CloneFromCopy> CloneFromCopy for ManuallyDrop<T> {}
735+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
736+
unsafe impl<T: CloneFromCopy> CloneFromCopy for ops::Range<T> {}
737+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
738+
unsafe impl<T: CloneFromCopy> CloneFromCopy for range::Range<T> {}
739+
740+
macro_rules! impl_tuple {
741+
() => {
742+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
743+
unsafe impl CloneFromCopy for () {}
744+
};
745+
($($name:ident)+) => {
746+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
747+
unsafe impl<$($name: CloneFromCopy,)+> CloneFromCopy for ($($name,)+) {}
748+
}
749+
}
750+
751+
impl_tuple! {}
752+
impl_tuple! { T }
753+
impl_tuple! { T B }
754+
impl_tuple! { T B C }
755+
impl_tuple! { T B C D }
756+
impl_tuple! { T B C D E }
757+
impl_tuple! { T B C D E F }
758+
impl_tuple! { T B C D E F G }
759+
impl_tuple! { T B C D E F G H }
760+
impl_tuple! { T B C D E F G H I }
761+
impl_tuple! { T B C D E F G H I J }
762+
impl_tuple! { T B C D E F G H I J K }
763+
impl_tuple! { T B C D E F G H I J K L }
764+
765+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
766+
impl<T: CloneFromCopy> Cell<T> {
767+
/// Get a clone of the Cell that contains a copy of the original value.
768+
///
769+
/// # Examples
770+
///
771+
/// ```
772+
/// #![feature(cell_get_cloned)]
773+
///
774+
/// use core::cell::Cell;
775+
///
776+
/// let o = Some(1usize);
777+
/// let c1 = Cell::new(o);
778+
/// let c2 = c1.get_cloned();
779+
/// assert_eq!(c2.into_inner(), Some(1));
780+
/// ```
781+
pub fn get_cloned(&self) -> Self {
782+
// SAFETY: T is CloneFromCopy, which guarantees that this is sound.
783+
let copy = ManuallyDrop::new(unsafe { self.as_ptr().read() });
784+
Cell::new(T::clone(&*copy))
785+
}
786+
}
787+
715788
/// A mutable memory location with dynamically checked borrow rules
716789
///
717790
/// See the [module-level documentation](self) for more.

0 commit comments

Comments
 (0)