@alexcrichton I meant this:
impl<T> MoveCell<Option<T>> { #[inline] pub fn is_none(&self) -> bool { unsafe { (*self.0.get()).is_none() } } #[inline] pub fn take(&self) -> Option<T> { unsafe { (*self.0.get()).take() } } } impl<T> MoveCell<Option<Weak<T>>> { #[inline] pub fn upgrade(&self) -> Option<Rc<T>> { unsafe { match *self.0.get() { Some(ref weak) => weak.upgrade(), None => None, } } } } impl<T> MoveCell<Option<Rc<T>>> { /// Return `Some` if this `Rc` is the only strong reference count, /// even if there are weak references. #[inline] pub fn take_if_unique_strong(&self) -> Option<Rc<T>> { unsafe { match *self.0.get() { None => None, Some(ref rc) if Rc::strong_count(rc) > 1 => None, // Not borrowing the `Rc<T>` here // as we would be invalidating that borrow while it is outstanding: Some(_) => self.take(), } } } }
Coherence rules would not allow me to write these impls with a MoveCell defined in the standard library (and they’re specific-purpose enough that they don’t necessarily make sense to define in the standard library). But now that I think about it, I could define extension traits that use as_unsafe_cell.
By the way, the key to these method’s safety is that they’re known not to exercise the cell’s interior mutability (e.g. through reference cycles) while a &T reference to the inside of the cell exists. Another example is:
impl<T> MoveCell<T> where T: WellBehavedClone { #[inline] pub fn clone_inner(&self) -> T { unsafe { (*self.0.get()).clone() } } } /** A Clone impl that will not access the cell again through reference cycles, which would introduce mutable aliasing. Incorrect example: ```rust struct Evil(Box<u32>, Rc<MoveCell<Option<Evil>>>); impl Clone for Evil { fn clone(&self) -> Self { mem::drop(self.1.take()); // Mess with the "other" node, which might be `self`. Evil( self.0.clone(), // use after free! Rc::new(MoveCell::new(None)) ) } } unsafe impl WellBehavedClone for Evil {} // Wrong. let a = Rc::new(MoveCell::new(None)); a.set(Some(Evil(Box::new(5), a.clone()))); // Make a reference cycle. a.clone_inner(); ``` */ pub unsafe trait WellBehavedClone: Clone {} unsafe impl<T> WellBehavedClone for Rc<T> {} unsafe impl<T> WellBehavedClone for Weak<T> {} unsafe impl<T> WellBehavedClone for Option<T> where T: WellBehavedClone {}
In this case T::clone can have arbitrary behavior as far as this module is concern, so we add a bound on an unsafe trait.