Skip to content

Commit d8a9c61

Browse files
committed
Use impl for Weak::as_ptr that works for unsized T
1 parent e4bdf47 commit d8a9c61

File tree

2 files changed

+26
-22
lines changed

2 files changed

+26
-22
lines changed

src/liballoc/rc.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ use core::hash::{Hash, Hasher};
245245
use core::intrinsics::abort;
246246
use core::iter;
247247
use core::marker::{self, PhantomData, Unpin, Unsize};
248-
use core::mem::{self, align_of, align_of_val_raw, forget, size_of_val};
248+
use core::mem::{self, align_of_val_raw, forget, size_of_val};
249249
use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver};
250250
use core::pin::Pin;
251251
use core::ptr::{self, NonNull};
@@ -1704,9 +1704,18 @@ impl<T> Weak<T> {
17041704
/// [`null`]: ../../std/ptr/fn.null.html
17051705
#[stable(feature = "weak_into_raw", since = "1.45.0")]
17061706
pub fn as_ptr(&self) -> *const T {
1707-
let offset = data_offset_sized::<T>();
1708-
let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset);
1709-
ptr as *const T
1707+
let ptr: *mut RcBox<T> = NonNull::as_ptr(self.ptr);
1708+
let fake_ptr = ptr as *mut T;
1709+
1710+
// SAFETY: we must offset the pointer manually, and said pointer may be
1711+
// a dangling weak (usize::MAX). data_offset is safe to call, because we
1712+
// know a pointer to unsized T must be derived from a real unsized T,
1713+
// because dangling weaks are only created for sized T. wrapping_offset
1714+
// is used so that we can use the same code path for dangling weak refs.
1715+
unsafe {
1716+
let offset = data_offset(&raw const (*ptr).value);
1717+
set_data_ptr(fake_ptr, (ptr as *mut u8).wrapping_offset(offset))
1718+
}
17101719
}
17111720

17121721
/// 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 {
21172126
unsafe { data_offset_align(align_of_val_raw(ptr)) }
21182127
}
21192128

2120-
/// Computes the offset of the data field within `RcBox`.
2121-
///
2122-
/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
2123-
fn data_offset_sized<T>() -> isize {
2124-
data_offset_align(align_of::<T>())
2125-
}
2126-
21272129
#[inline]
21282130
fn data_offset_align(align: usize) -> isize {
21292131
let layout = Layout::new::<RcBox<()>>();

src/liballoc/sync.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use core::hash::{Hash, Hasher};
1616
use core::intrinsics::abort;
1717
use core::iter;
1818
use core::marker::{PhantomData, Unpin, Unsize};
19-
use core::mem::{self, align_of, align_of_val, size_of_val};
19+
use core::mem::{self, align_of_val, size_of_val};
2020
use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver};
2121
use core::pin::Pin;
2222
use core::ptr::{self, NonNull};
@@ -1472,9 +1472,18 @@ impl<T> Weak<T> {
14721472
/// [`null`]: ../../std/ptr/fn.null.html
14731473
#[stable(feature = "weak_into_raw", since = "1.45.0")]
14741474
pub fn as_ptr(&self) -> *const T {
1475-
let offset = data_offset_sized::<T>();
1476-
let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset);
1477-
ptr as *const T
1475+
let ptr: *mut ArcInner<T> = NonNull::as_ptr(self.ptr);
1476+
let fake_ptr = ptr as *mut T;
1477+
1478+
// SAFETY: we must offset the pointer manually, and said pointer may be
1479+
// a dangling weak (usize::MAX). data_offset is safe to call, because we
1480+
// know a pointer to unsized T must be derived from a real unsized T,
1481+
// because dangling weaks are only created for sized T. wrapping_offset
1482+
// is used so that we can use the same code path for dangling weak refs.
1483+
unsafe {
1484+
let offset = data_offset(&raw const (*ptr).data);
1485+
set_data_ptr(fake_ptr, (ptr as *mut u8).wrapping_offset(offset))
1486+
}
14781487
}
14791488

14801489
/// 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 {
22752284
unsafe { data_offset_align(align_of_val(&*ptr)) }
22762285
}
22772286

2278-
/// Computes the offset of the data field within `ArcInner`.
2279-
///
2280-
/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
2281-
fn data_offset_sized<T>() -> isize {
2282-
data_offset_align(align_of::<T>())
2283-
}
2284-
22852287
#[inline]
22862288
fn data_offset_align(align: usize) -> isize {
22872289
let layout = Layout::new::<ArcInner<()>>();

0 commit comments

Comments
 (0)