From 728938346b02a9688c44253c19b15baa7551fd80 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Wed, 8 Jul 2020 16:23:38 -0400 Subject: [PATCH] Adjust rc::Weak::from_raw to support unsized T --- library/alloc/src/rc.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index f998e49dcfc..27e6e110903 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1841,17 +1841,18 @@ impl Weak { /// [`new`]: Weak::new #[stable(feature = "weak_into_raw", since = "1.45.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { - if ptr.is_null() { - Self::new() - } else { - // See Rc::from_raw for details - unsafe { - let offset = data_offset(ptr); - let fake_ptr = ptr as *mut RcBox; - let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)); - Weak { ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw") } - } - } + // SAFETY: data_offset is safe to call, because this pointer originates from a Weak. + // See Weak::as_ptr for context on how the input pointer is derived. + let offset = unsafe { data_offset(ptr) }; + + // Reverse the offset to find the original RcBox. + // SAFETY: we use wrapping_offset here because the pointer may be dangling (iff T: Sized). + let ptr = unsafe { + set_data_ptr(ptr as *mut RcBox, (ptr as *mut u8).wrapping_offset(-offset)) + }; + + // SAFETY: we now have recovered the original Weak pointer, so can create the Weak. + Weak { ptr: unsafe { NonNull::new_unchecked(ptr) } } } }