diff --git a/src/lib.rs b/src/lib.rs index 94d7a3580f3d9ce66aea183773d4b646d9b15ca7..46b9828c185d081a60cb0d45a29d713a2e1fb868 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,7 @@ use core::marker::PhantomPinned; use core::mem::{self, MaybeUninit}; use core::ops::{Deref, DerefMut}; use core::pin::Pin; -use core::ptr::NonNull; +use core::ptr::{self, NonNull}; pub trait Reclaim: Sized { fn reclaim(self, unclaimed: Unclaimed<Self>); @@ -80,7 +80,15 @@ impl<T> Root<T> { panic!("unclaimed called multiple times"); } self.state.set(STATE_UNCLAIMED); + let ptr = unsafe { NonNull::from(self.get_unchecked_mut()) }; + let ptr_erased = ptr.cast::<Root<Erased>>(); + + unsafe { + let target_root = ptr::addr_of_mut!((*(*ptr.as_ptr()).target.as_mut_ptr()).root); + target_root.write(Cell::new(Some(ptr_erased))); + } + Unclaimed { ptr } } } @@ -126,20 +134,18 @@ pub struct Unclaimed<T> { impl<T> Unclaimed<T> { pub fn claim(self, value: T) -> Xrc<T> { - let root_erased = self.ptr.cast::<Root<Erased>>(); - let target = unsafe { - (*self.ptr.as_ptr()).target.write(ProjectTarget { - root: Cell::new(Some(root_erased)), - value, - }) - }; - unsafe { (*self.ptr.as_ptr()).state.set(STATE_SHARED_INIT); } - // shared reborrow - let ptr = NonNull::from(&*target); + unsafe { + let target_value = ptr::addr_of_mut!((*(*self.ptr.as_ptr()).target.as_mut_ptr()).value); + target_value.write(value); + } + + // shared read-only reborrow + let target = unsafe { (*self.ptr.as_ptr()).target.assume_init_ref() }; + let ptr = NonNull::from(target); Xrc { ptr } } }