Skip to content

Commit 7289383

Browse files
committed
Adjust rc::Weak::from_raw to support unsized T
1 parent 85109af commit 7289383

File tree

1 file changed

+12
-11
lines changed

1 file changed

+12
-11
lines changed

library/alloc/src/rc.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,17 +1841,18 @@ impl<T> Weak<T> {
18411841
/// [`new`]: Weak::new
18421842
#[stable(feature = "weak_into_raw", since = "1.45.0")]
18431843
pub unsafe fn from_raw(ptr: *const T) -> Self {
1844-
if ptr.is_null() {
1845-
Self::new()
1846-
} else {
1847-
// See Rc::from_raw for details
1848-
unsafe {
1849-
let offset = data_offset(ptr);
1850-
let fake_ptr = ptr as *mut RcBox<T>;
1851-
let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
1852-
Weak { ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw") }
1853-
}
1854-
}
1844+
// SAFETY: data_offset is safe to call, because this pointer originates from a Weak.
1845+
// See Weak::as_ptr for context on how the input pointer is derived.
1846+
let offset = unsafe { data_offset(ptr) };
1847+
1848+
// Reverse the offset to find the original RcBox.
1849+
// SAFETY: we use wrapping_offset here because the pointer may be dangling (iff T: Sized).
1850+
let ptr = unsafe {
1851+
set_data_ptr(ptr as *mut RcBox<T>, (ptr as *mut u8).wrapping_offset(-offset))
1852+
};
1853+
1854+
// SAFETY: we now have recovered the original Weak pointer, so can create the Weak.
1855+
Weak { ptr: unsafe { NonNull::new_unchecked(ptr) } }
18551856
}
18561857
}
18571858

0 commit comments

Comments
 (0)