diff options
| author | CAD97 <cad97@cad97.com> | 2020-07-14 15:17:55 -0400 |
|---|---|---|
| committer | CAD97 <cad97@cad97.com> | 2020-09-12 10:38:32 -0500 |
| commit | 5e7406c9569dce75a042ce079918cf03cfca842a (patch) | |
| tree | 3badd15845e69aa4a359aaf1c4ffa9cd25f99f01 | |
| parent | 0c61ce2cf0560577923abafab2e5bfce14516525 (diff) | |
| download | rust-5e7406c9569dce75a042ce079918cf03cfca842a.tar.gz rust-5e7406c9569dce75a042ce079918cf03cfca842a.zip | |
Adjust sync::Weak::from_raw to support unsized T
| -rw-r--r-- | library/alloc/src/sync.rs | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 6a240fbb42a..06dec6f01f8 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1629,17 +1629,18 @@ impl<T> Weak<T> { /// [`forget`]: std::mem::forget #[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 Arc::from_raw for details - unsafe { - let offset = data_offset(ptr); - let fake_ptr = ptr as *mut ArcInner<T>; - 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 ArcInner. + // SAFETY: we use wrapping_offset here because the pointer may be dangling (iff T: Sized) + let ptr = unsafe { + set_data_ptr(ptr as *mut ArcInner<T>, (ptr as *mut u8).wrapping_offset(-offset)) + }; + + // SAFETY: we now have recovered the original Weak pointer, so can create the Weak. + unsafe { Weak { ptr: NonNull::new_unchecked(ptr) } } } } |
