Rollup merge of #145685 - Qelxiros:cell_get_cloned, r=programmerjake,tgross35
add CloneFromCell and Cell::get_cloned Tracking issue: rust-lang/rust#145329
This commit is contained in:
commit
47bd38c2f1
5 changed files with 119 additions and 3 deletions
|
|
@ -96,6 +96,7 @@
|
|||
#![feature(bstr)]
|
||||
#![feature(bstr_internals)]
|
||||
#![feature(cast_maybe_uninit)]
|
||||
#![feature(cell_get_cloned)]
|
||||
#![feature(char_internals)]
|
||||
#![feature(char_max_len)]
|
||||
#![feature(clone_to_uninit)]
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@
|
|||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use core::any::Any;
|
||||
use core::cell::Cell;
|
||||
use core::cell::{Cell, CloneFromCell};
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::clone::CloneToUninit;
|
||||
use core::clone::UseCloned;
|
||||
|
|
@ -340,6 +340,10 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Rc<U, A>> for
|
|||
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Rc<U>> for Rc<T> {}
|
||||
|
||||
// SAFETY: `Rc::clone` doesn't access any `Cell`s which could contain the `Rc` being cloned.
|
||||
#[unstable(feature = "cell_get_cloned", issue = "145329")]
|
||||
unsafe impl<T: ?Sized> CloneFromCell for Rc<T> {}
|
||||
|
||||
impl<T: ?Sized> Rc<T> {
|
||||
#[inline]
|
||||
unsafe fn from_inner(ptr: NonNull<RcInner<T>>) -> Self {
|
||||
|
|
@ -3013,6 +3017,10 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Weak<U, A>> f
|
|||
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}
|
||||
|
||||
// SAFETY: `Weak::clone` doesn't access any `Cell`s which could contain the `Weak` being cloned.
|
||||
#[unstable(feature = "cell_get_cloned", issue = "145329")]
|
||||
unsafe impl<T: ?Sized> CloneFromCell for Weak<T> {}
|
||||
|
||||
impl<T> Weak<T> {
|
||||
/// Constructs a new `Weak<T>`, without allocating any memory.
|
||||
/// Calling [`upgrade`] on the return value always gives [`None`].
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
//! `#[cfg(target_has_atomic = "ptr")]`.
|
||||
|
||||
use core::any::Any;
|
||||
use core::cell::CloneFromCell;
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::clone::CloneToUninit;
|
||||
use core::clone::UseCloned;
|
||||
|
|
@ -281,6 +282,10 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Arc<U, A>> fo
|
|||
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Arc<U>> for Arc<T> {}
|
||||
|
||||
// SAFETY: `Arc::clone` doesn't access any `Cell`s which could contain the `Arc` being cloned.
|
||||
#[unstable(feature = "cell_get_cloned", issue = "145329")]
|
||||
unsafe impl<T: ?Sized> CloneFromCell for Arc<T> {}
|
||||
|
||||
impl<T: ?Sized> Arc<T> {
|
||||
unsafe fn from_inner(ptr: NonNull<ArcInner<T>>) -> Self {
|
||||
unsafe { Self::from_inner_in(ptr, Global) }
|
||||
|
|
@ -356,6 +361,10 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Weak<U, A>> f
|
|||
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}
|
||||
|
||||
// SAFETY: `Weak::clone` doesn't access any `Cell`s which could contain the `Weak` being cloned.
|
||||
#[unstable(feature = "cell_get_cloned", issue = "145329")]
|
||||
unsafe impl<T: ?Sized> CloneFromCell for Weak<T> {}
|
||||
|
||||
#[stable(feature = "arc_weak", since = "1.4.0")]
|
||||
impl<T: ?Sized, A: Allocator> fmt::Debug for Weak<T, A> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
|
|
|||
|
|
@ -253,11 +253,12 @@
|
|||
use crate::cmp::Ordering;
|
||||
use crate::fmt::{self, Debug, Display};
|
||||
use crate::marker::{PhantomData, Unsize};
|
||||
use crate::mem;
|
||||
use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn};
|
||||
use crate::mem::{self, ManuallyDrop};
|
||||
use crate::ops::{self, CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn};
|
||||
use crate::panic::const_panic;
|
||||
use crate::pin::PinCoerceUnsized;
|
||||
use crate::ptr::{self, NonNull};
|
||||
use crate::range;
|
||||
|
||||
mod lazy;
|
||||
mod once;
|
||||
|
|
@ -713,6 +714,93 @@ impl<T, const N: usize> Cell<[T; N]> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Types for which cloning `Cell<Self>` is sound.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Implementing this trait for a type is sound if and only if the following code is sound for T =
|
||||
/// that type.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(cell_get_cloned)]
|
||||
/// # use std::cell::{CloneFromCell, Cell};
|
||||
/// fn clone_from_cell<T: CloneFromCell>(cell: &Cell<T>) -> T {
|
||||
/// unsafe { T::clone(&*cell.as_ptr()) }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Importantly, you can't just implement `CloneFromCell` for any arbitrary `Copy` type, e.g. the
|
||||
/// following is unsound:
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(cell_get_cloned)]
|
||||
/// # use std::cell::Cell;
|
||||
///
|
||||
/// #[derive(Copy, Debug)]
|
||||
/// pub struct Bad<'a>(Option<&'a Cell<Bad<'a>>>, u8);
|
||||
///
|
||||
/// impl Clone for Bad<'_> {
|
||||
/// fn clone(&self) -> Self {
|
||||
/// let a: &u8 = &self.1;
|
||||
/// // when self.0 points to self, we write to self.1 while we have a live `&u8` pointing to
|
||||
/// // it -- this is UB
|
||||
/// self.0.unwrap().set(Self(None, 1));
|
||||
/// dbg!((a, self));
|
||||
/// Self(None, 0)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // this is not sound
|
||||
/// // unsafe impl CloneFromCell for Bad<'_> {}
|
||||
/// ```
|
||||
#[unstable(feature = "cell_get_cloned", issue = "145329")]
|
||||
// Allow potential overlapping implementations in user code
|
||||
#[marker]
|
||||
pub unsafe trait CloneFromCell: Clone {}
|
||||
|
||||
// `CloneFromCell` can be implemented for types that don't have indirection and which don't access
|
||||
// `Cell`s in their `Clone` implementation. A commonly-used subset is covered here.
|
||||
#[unstable(feature = "cell_get_cloned", issue = "145329")]
|
||||
unsafe impl<T: CloneFromCell, const N: usize> CloneFromCell for [T; N] {}
|
||||
#[unstable(feature = "cell_get_cloned", issue = "145329")]
|
||||
unsafe impl<T: CloneFromCell> CloneFromCell for Option<T> {}
|
||||
#[unstable(feature = "cell_get_cloned", issue = "145329")]
|
||||
unsafe impl<T: CloneFromCell, E: CloneFromCell> CloneFromCell for Result<T, E> {}
|
||||
#[unstable(feature = "cell_get_cloned", issue = "145329")]
|
||||
unsafe impl<T: ?Sized> CloneFromCell for PhantomData<T> {}
|
||||
#[unstable(feature = "cell_get_cloned", issue = "145329")]
|
||||
unsafe impl<T: CloneFromCell> CloneFromCell for ManuallyDrop<T> {}
|
||||
#[unstable(feature = "cell_get_cloned", issue = "145329")]
|
||||
unsafe impl<T: CloneFromCell> CloneFromCell for ops::Range<T> {}
|
||||
#[unstable(feature = "cell_get_cloned", issue = "145329")]
|
||||
unsafe impl<T: CloneFromCell> CloneFromCell for range::Range<T> {}
|
||||
|
||||
#[unstable(feature = "cell_get_cloned", issue = "145329")]
|
||||
impl<T: CloneFromCell> Cell<T> {
|
||||
/// Get a clone of the `Cell` that contains a copy of the original value.
|
||||
///
|
||||
/// This allows a cheaply `Clone`-able type like an `Rc` to be stored in a `Cell`, exposing the
|
||||
/// cheaper `clone()` method.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(cell_get_cloned)]
|
||||
///
|
||||
/// use core::cell::Cell;
|
||||
/// use std::rc::Rc;
|
||||
///
|
||||
/// let rc = Rc::new(1usize);
|
||||
/// let c1 = Cell::new(rc);
|
||||
/// let c2 = c1.get_cloned();
|
||||
/// assert_eq!(*c2.into_inner(), 1);
|
||||
/// ```
|
||||
pub fn get_cloned(&self) -> Self {
|
||||
// SAFETY: T is CloneFromCell, which guarantees that this is sound.
|
||||
Cell::new(T::clone(unsafe { &*self.as_ptr() }))
|
||||
}
|
||||
}
|
||||
|
||||
/// A mutable memory location with dynamically checked borrow rules
|
||||
///
|
||||
/// See the [module-level documentation](self) for more.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// See core/src/primitive_docs.rs for documentation.
|
||||
|
||||
use crate::cell::CloneFromCell;
|
||||
use crate::cmp::Ordering::{self, *};
|
||||
use crate::marker::{ConstParamTy_, StructuralPartialEq};
|
||||
use crate::ops::ControlFlow::{self, Break, Continue};
|
||||
|
|
@ -155,6 +156,15 @@ macro_rules! tuple_impls {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
maybe_tuple_doc! {
|
||||
$($T)+ @
|
||||
// SAFETY: tuples introduce no additional indirection, so they can be copied whenever T
|
||||
// can.
|
||||
#[unstable(feature = "cell_get_cloned", issue = "145329")]
|
||||
unsafe impl<$($T: CloneFromCell),+> CloneFromCell for ($($T,)+)
|
||||
{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue