Skip to content

Commit dd990a7

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

File tree

5 files changed

+91
-3
lines changed

5 files changed

+91
-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: 11 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,11 @@ 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+
// SAFETY: The bitwise copy has the same `RcInner` pointer as the original, so the clone increments
342+
// the right counts and maintains the invariants.
343+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
344+
unsafe impl<T: ?Sized> CloneFromCopy for Rc<T> {}
345+
341346
impl<T: ?Sized> Rc<T> {
342347
#[inline]
343348
unsafe fn from_inner(ptr: NonNull<RcInner<T>>) -> Self {
@@ -3032,6 +3037,11 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Weak<U, A>> f
30323037
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
30333038
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}
30343039

3040+
// SAFETY: The bitwise copy has the same `RcInner` pointer as the original, so the clone increments
3041+
// the right counts and maintains the invariants.
3042+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
3043+
unsafe impl<T: ?Sized> CloneFromCopy for Weak<T> {}
3044+
30353045
impl<T> Weak<T> {
30363046
/// Constructs a new `Weak<T>`, without allocating any memory.
30373047
/// Calling [`upgrade`] on the return value always gives [`None`].

library/alloc/src/sync.rs

Lines changed: 11 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,11 @@ 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+
// SAFETY: The bitwise copy has the same `ArcInner` pointer as the original, so the clone increments
286+
// the right counts and maintains the invariants.
287+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
288+
unsafe impl<T: ?Sized> CloneFromCopy for Arc<T> {}
289+
284290
impl<T: ?Sized> Arc<T> {
285291
unsafe fn from_inner(ptr: NonNull<ArcInner<T>>) -> Self {
286292
unsafe { Self::from_inner_in(ptr, Global) }
@@ -356,6 +362,11 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Weak<U, A>> f
356362
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
357363
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}
358364

365+
// SAFETY: The bitwise copy has the same `ArcInner` pointer as the original, so the clone increments
366+
// the right counts and maintains the invariants.
367+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
368+
unsafe impl<T: ?Sized> CloneFromCopy for Weak<T> {}
369+
359370
#[stable(feature = "arc_weak", since = "1.4.0")]
360371
impl<T: ?Sized, A: Allocator> fmt::Debug for Weak<T, A> {
361372
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

library/core/src/cell.rs

Lines changed: 58 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,61 @@ impl<T, const N: usize> Cell<[T; N]> {
712713
}
713714
}
714715

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+
715771
/// A mutable memory location with dynamically checked borrow rules
716772
///
717773
/// See the [module-level documentation](self) for more.

library/core/src/tuple.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// See core/src/primitive_docs.rs for documentation.
22

3+
use crate::cell::CloneFromCopy;
34
use crate::cmp::Ordering::{self, *};
45
use crate::marker::{ConstParamTy_, StructuralPartialEq, UnsizedConstParamTy};
56
use crate::ops::ControlFlow::{self, Break, Continue};
@@ -155,6 +156,15 @@ macro_rules! tuple_impls {
155156
}
156157
}
157158
}
159+
160+
maybe_tuple_doc! {
161+
$($T)+ @
162+
// SAFETY: tuples introduce no additional indirection, so they can be copied whenever T
163+
// can.
164+
#[unstable(feature = "cell_get_cloned", issue = "145329")]
165+
unsafe impl<$($T: CloneFromCopy),+> CloneFromCopy for ($($T,)+)
166+
{}
167+
}
158168
}
159169
}
160170

0 commit comments

Comments
 (0)