Skip to content

Commit 80ccddc

Browse files
committed
weak-into-raw: as_raw -> as_ptr + dangling garbage
* Rename Weak::as_raw to Weak::as_ptr for consistency with some other types. * The as_ptr for a dangling Weak pointer might return whatever garbage (and takes that advantage to avoid a conditional). * Don't guarantee to be able to do `Weak::from_raw(weak.as_ptr())` (even though it'll still work fine).
1 parent 4d1fbac commit 80ccddc

File tree

2 files changed

+30
-52
lines changed

2 files changed

+30
-52
lines changed

src/liballoc/rc.rs

+15-26
Original file line numberDiff line numberDiff line change
@@ -1644,8 +1644,8 @@ impl<T> Weak<T> {
16441644

16451645
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
16461646
///
1647-
/// The pointer is valid only if there are some strong references. The pointer may be dangling
1648-
/// or even [`null`] otherwise.
1647+
/// The pointer is valid only if there are some strong references. The pointer may be dangling,
1648+
/// unaligned or even [`null`] otherwise.
16491649
///
16501650
/// # Examples
16511651
///
@@ -1658,31 +1658,22 @@ impl<T> Weak<T> {
16581658
/// let strong = Rc::new("hello".to_owned());
16591659
/// let weak = Rc::downgrade(&strong);
16601660
/// // Both point to the same object
1661-
/// assert!(ptr::eq(&*strong, weak.as_raw()));
1661+
/// assert!(ptr::eq(&*strong, weak.as_ptr()));
16621662
/// // The strong here keeps it alive, so we can still access the object.
1663-
/// assert_eq!("hello", unsafe { &*weak.as_raw() });
1663+
/// assert_eq!("hello", unsafe { &*weak.as_ptr() });
16641664
///
16651665
/// drop(strong);
1666-
/// // But not any more. We can do weak.as_raw(), but accessing the pointer would lead to
1666+
/// // But not any more. We can do weak.as_ptr(), but accessing the pointer would lead to
16671667
/// // undefined behaviour.
1668-
/// // assert_eq!("hello", unsafe { &*weak.as_raw() });
1668+
/// // assert_eq!("hello", unsafe { &*weak.as_ptr() });
16691669
/// ```
16701670
///
16711671
/// [`null`]: ../../std/ptr/fn.null.html
16721672
#[unstable(feature = "weak_into_raw", issue = "60728")]
1673-
pub fn as_raw(&self) -> *const T {
1674-
match self.inner() {
1675-
None => ptr::null(),
1676-
Some(inner) => {
1677-
let offset = data_offset_sized::<T>();
1678-
let ptr = inner as *const RcBox<T>;
1679-
// Note: while the pointer we create may already point to dropped value, the
1680-
// allocation still lives (it must hold the weak point as long as we are alive).
1681-
// Therefore, the offset is OK to do, it won't get out of the allocation.
1682-
let ptr = unsafe { (ptr as *const u8).offset(offset) };
1683-
ptr as *const T
1684-
}
1685-
}
1673+
pub fn as_ptr(&self) -> *const T {
1674+
let offset = data_offset_sized::<T>();
1675+
let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset);
1676+
ptr as *const T
16861677
}
16871678

16881679
/// Consumes the `Weak<T>` and turns it into a raw pointer.
@@ -1691,7 +1682,7 @@ impl<T> Weak<T> {
16911682
/// can be turned back into the `Weak<T>` with [`from_raw`].
16921683
///
16931684
/// The same restrictions of accessing the target of the pointer as with
1694-
/// [`as_raw`] apply.
1685+
/// [`as_ptr`] apply.
16951686
///
16961687
/// # Examples
16971688
///
@@ -1712,10 +1703,10 @@ impl<T> Weak<T> {
17121703
/// ```
17131704
///
17141705
/// [`from_raw`]: struct.Weak.html#method.from_raw
1715-
/// [`as_raw`]: struct.Weak.html#method.as_raw
1706+
/// [`as_ptr`]: struct.Weak.html#method.as_ptr
17161707
#[unstable(feature = "weak_into_raw", issue = "60728")]
17171708
pub fn into_raw(self) -> *const T {
1718-
let result = self.as_raw();
1709+
let result = self.as_ptr();
17191710
mem::forget(self);
17201711
result
17211712
}
@@ -1730,9 +1721,8 @@ impl<T> Weak<T> {
17301721
///
17311722
/// # Safety
17321723
///
1733-
/// The pointer must have originated from the [`into_raw`] (or [`as_raw`], provided there was
1734-
/// a corresponding [`forget`] on the `Weak<T>`) and must still own its potential weak reference
1735-
/// count.
1724+
/// The pointer must have originated from the [`into_raw`] and must still own its potential
1725+
/// weak reference count.
17361726
///
17371727
/// It is allowed for the strong count to be 0 at the time of calling this, but the weak count
17381728
/// must be non-zero or the pointer must have originated from a dangling `Weak<T>` (one created
@@ -1765,7 +1755,6 @@ impl<T> Weak<T> {
17651755
/// [`upgrade`]: struct.Weak.html#method.upgrade
17661756
/// [`Rc`]: struct.Rc.html
17671757
/// [`Weak`]: struct.Weak.html
1768-
/// [`as_raw`]: struct.Weak.html#method.as_raw
17691758
/// [`new`]: struct.Weak.html#method.new
17701759
/// [`forget`]: ../../std/mem/fn.forget.html
17711760
#[unstable(feature = "weak_into_raw", issue = "60728")]

src/liballoc/sync.rs

+15-26
Original file line numberDiff line numberDiff line change
@@ -1340,8 +1340,8 @@ impl<T> Weak<T> {
13401340

13411341
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
13421342
///
1343-
/// The pointer is valid only if there are some strong references. The pointer may be dangling
1344-
/// or even [`null`] otherwise.
1343+
/// The pointer is valid only if there are some strong references. The pointer may be dangling,
1344+
/// unaligned or even [`null`] otherwise.
13451345
///
13461346
/// # Examples
13471347
///
@@ -1354,31 +1354,22 @@ impl<T> Weak<T> {
13541354
/// let strong = Arc::new("hello".to_owned());
13551355
/// let weak = Arc::downgrade(&strong);
13561356
/// // Both point to the same object
1357-
/// assert!(ptr::eq(&*strong, weak.as_raw()));
1357+
/// assert!(ptr::eq(&*strong, weak.as_ptr()));
13581358
/// // The strong here keeps it alive, so we can still access the object.
1359-
/// assert_eq!("hello", unsafe { &*weak.as_raw() });
1359+
/// assert_eq!("hello", unsafe { &*weak.as_ptr() });
13601360
///
13611361
/// drop(strong);
1362-
/// // But not any more. We can do weak.as_raw(), but accessing the pointer would lead to
1362+
/// // But not any more. We can do weak.as_ptr(), but accessing the pointer would lead to
13631363
/// // undefined behaviour.
1364-
/// // assert_eq!("hello", unsafe { &*weak.as_raw() });
1364+
/// // assert_eq!("hello", unsafe { &*weak.as_ptr() });
13651365
/// ```
13661366
///
13671367
/// [`null`]: ../../std/ptr/fn.null.html
13681368
#[unstable(feature = "weak_into_raw", issue = "60728")]
1369-
pub fn as_raw(&self) -> *const T {
1370-
match self.inner() {
1371-
None => ptr::null(),
1372-
Some(inner) => {
1373-
let offset = data_offset_sized::<T>();
1374-
let ptr = inner as *const ArcInner<T>;
1375-
// Note: while the pointer we create may already point to dropped value, the
1376-
// allocation still lives (it must hold the weak point as long as we are alive).
1377-
// Therefore, the offset is OK to do, it won't get out of the allocation.
1378-
let ptr = unsafe { (ptr as *const u8).offset(offset) };
1379-
ptr as *const T
1380-
}
1381-
}
1369+
pub fn as_ptr(&self) -> *const T {
1370+
let offset = data_offset_sized::<T>();
1371+
let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset);
1372+
ptr as *const T
13821373
}
13831374

13841375
/// Consumes the `Weak<T>` and turns it into a raw pointer.
@@ -1387,7 +1378,7 @@ impl<T> Weak<T> {
13871378
/// can be turned back into the `Weak<T>` with [`from_raw`].
13881379
///
13891380
/// The same restrictions of accessing the target of the pointer as with
1390-
/// [`as_raw`] apply.
1381+
/// [`as_ptr`] apply.
13911382
///
13921383
/// # Examples
13931384
///
@@ -1408,10 +1399,10 @@ impl<T> Weak<T> {
14081399
/// ```
14091400
///
14101401
/// [`from_raw`]: struct.Weak.html#method.from_raw
1411-
/// [`as_raw`]: struct.Weak.html#method.as_raw
1402+
/// [`as_ptr`]: struct.Weak.html#method.as_ptr
14121403
#[unstable(feature = "weak_into_raw", issue = "60728")]
14131404
pub fn into_raw(self) -> *const T {
1414-
let result = self.as_raw();
1405+
let result = self.as_ptr();
14151406
mem::forget(self);
14161407
result
14171408
}
@@ -1427,9 +1418,8 @@ impl<T> Weak<T> {
14271418
///
14281419
/// # Safety
14291420
///
1430-
/// The pointer must have originated from the [`into_raw`] (or [`as_raw'], provided there was
1431-
/// a corresponding [`forget`] on the `Weak<T>`) and must still own its potential weak reference
1432-
/// count.
1421+
/// The pointer must have originated from the [`into_raw`] and must still own its potential
1422+
/// weak reference count.
14331423
///
14341424
/// It is allowed for the strong count to be 0 at the time of calling this, but the weak count
14351425
/// must be non-zero or the pointer must have originated from a dangling `Weak<T>` (one created
@@ -1458,7 +1448,6 @@ impl<T> Weak<T> {
14581448
/// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none());
14591449
/// ```
14601450
///
1461-
/// [`as_raw`]: struct.Weak.html#method.as_raw
14621451
/// [`new`]: struct.Weak.html#method.new
14631452
/// [`into_raw`]: struct.Weak.html#method.into_raw
14641453
/// [`upgrade`]: struct.Weak.html#method.upgrade

0 commit comments

Comments
 (0)