diff options
| author | CAD97 <cad97@cad97.com> | 2020-06-28 14:30:35 -0400 |
|---|---|---|
| committer | CAD97 <cad97@cad97.com> | 2020-06-28 14:33:18 -0400 |
| commit | d8a9c61e1a23b73c04d3058a11d1b8b2a46d635e (patch) | |
| tree | 195ca4652812df625e854155e1fc34a0fbba1033 /src/liballoc | |
| parent | e4bdf47f4c0773bba93f50900612242b929eca0b (diff) | |
| download | rust-d8a9c61e1a23b73c04d3058a11d1b8b2a46d635e.tar.gz rust-d8a9c61e1a23b73c04d3058a11d1b8b2a46d635e.zip | |
Use impl for Weak::as_ptr that works for unsized T
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/rc.rs | 24 | ||||
| -rw-r--r-- | src/liballoc/sync.rs | 24 |
2 files changed, 26 insertions, 22 deletions
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 408278d5b61..423122a6900 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -245,7 +245,7 @@ use core::hash::{Hash, Hasher}; use core::intrinsics::abort; use core::iter; use core::marker::{self, PhantomData, Unpin, Unsize}; -use core::mem::{self, align_of, align_of_val_raw, forget, size_of_val}; +use core::mem::{self, align_of_val_raw, forget, size_of_val}; use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; use core::pin::Pin; use core::ptr::{self, NonNull}; @@ -1704,9 +1704,18 @@ impl<T> Weak<T> { /// [`null`]: ../../std/ptr/fn.null.html #[stable(feature = "weak_into_raw", since = "1.45.0")] pub fn as_ptr(&self) -> *const T { - let offset = data_offset_sized::<T>(); - let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset); - ptr as *const T + let ptr: *mut RcBox<T> = NonNull::as_ptr(self.ptr); + let fake_ptr = ptr as *mut T; + + // SAFETY: we must offset the pointer manually, and said pointer may be + // a dangling weak (usize::MAX). data_offset is safe to call, because we + // know a pointer to unsized T must be derived from a real unsized T, + // because dangling weaks are only created for sized T. wrapping_offset + // is used so that we can use the same code path for dangling weak refs. + unsafe { + let offset = data_offset(&raw const (*ptr).value); + set_data_ptr(fake_ptr, (ptr as *mut u8).wrapping_offset(offset)) + } } /// Consumes the `Weak<T>` and turns it into a raw pointer. @@ -2117,13 +2126,6 @@ unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize { unsafe { data_offset_align(align_of_val_raw(ptr)) } } -/// Computes the offset of the data field within `RcBox`. -/// -/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`. -fn data_offset_sized<T>() -> isize { - data_offset_align(align_of::<T>()) -} - #[inline] fn data_offset_align(align: usize) -> isize { let layout = Layout::new::<RcBox<()>>(); diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 5a9ab24562a..289aea3afcc 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -16,7 +16,7 @@ use core::hash::{Hash, Hasher}; use core::intrinsics::abort; use core::iter; use core::marker::{PhantomData, Unpin, Unsize}; -use core::mem::{self, align_of, align_of_val, size_of_val}; +use core::mem::{self, align_of_val, size_of_val}; use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; use core::pin::Pin; use core::ptr::{self, NonNull}; @@ -1472,9 +1472,18 @@ impl<T> Weak<T> { /// [`null`]: ../../std/ptr/fn.null.html #[stable(feature = "weak_into_raw", since = "1.45.0")] pub fn as_ptr(&self) -> *const T { - let offset = data_offset_sized::<T>(); - let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset); - ptr as *const T + let ptr: *mut ArcInner<T> = NonNull::as_ptr(self.ptr); + let fake_ptr = ptr as *mut T; + + // SAFETY: we must offset the pointer manually, and said pointer may be + // a dangling weak (usize::MAX). data_offset is safe to call, because we + // know a pointer to unsized T must be derived from a real unsized T, + // because dangling weaks are only created for sized T. wrapping_offset + // is used so that we can use the same code path for dangling weak refs. + unsafe { + let offset = data_offset(&raw const (*ptr).data); + set_data_ptr(fake_ptr, (ptr as *mut u8).wrapping_offset(offset)) + } } /// Consumes the `Weak<T>` and turns it into a raw pointer. @@ -2275,13 +2284,6 @@ unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize { unsafe { data_offset_align(align_of_val(&*ptr)) } } -/// Computes the offset of the data field within `ArcInner`. -/// -/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`. -fn data_offset_sized<T>() -> isize { - data_offset_align(align_of::<T>()) -} - #[inline] fn data_offset_align(align: usize) -> isize { let layout = Layout::new::<ArcInner<()>>(); |
