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 Weak { /// [`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::(); - let ptr = self.ptr.cast::().as_ptr().wrapping_offset(offset); - ptr as *const T + let ptr: *mut RcBox = 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` and turns it into a raw pointer. @@ -2117,13 +2126,6 @@ unsafe fn data_offset(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() -> isize { - data_offset_align(align_of::()) -} - #[inline] fn data_offset_align(align: usize) -> isize { let layout = Layout::new::>(); 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 Weak { /// [`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::(); - let ptr = self.ptr.cast::().as_ptr().wrapping_offset(offset); - ptr as *const T + let ptr: *mut ArcInner = 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` and turns it into a raw pointer. @@ -2275,13 +2284,6 @@ unsafe fn data_offset(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() -> isize { - data_offset_align(align_of::()) -} - #[inline] fn data_offset_align(align: usize) -> isize { let layout = Layout::new::>();