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).
This commit is contained in:
parent
4d1fbaccb8
commit
80ccddc0ed
|
@ -1644,8 +1644,8 @@ impl<T> Weak<T> {
|
||||||
|
|
||||||
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
|
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
|
||||||
///
|
///
|
||||||
/// The pointer is valid only if there are some strong references. The pointer may be dangling
|
/// The pointer is valid only if there are some strong references. The pointer may be dangling,
|
||||||
/// or even [`null`] otherwise.
|
/// unaligned or even [`null`] otherwise.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -1658,31 +1658,22 @@ impl<T> Weak<T> {
|
||||||
/// let strong = Rc::new("hello".to_owned());
|
/// let strong = Rc::new("hello".to_owned());
|
||||||
/// let weak = Rc::downgrade(&strong);
|
/// let weak = Rc::downgrade(&strong);
|
||||||
/// // Both point to the same object
|
/// // Both point to the same object
|
||||||
/// assert!(ptr::eq(&*strong, weak.as_raw()));
|
/// assert!(ptr::eq(&*strong, weak.as_ptr()));
|
||||||
/// // The strong here keeps it alive, so we can still access the object.
|
/// // The strong here keeps it alive, so we can still access the object.
|
||||||
/// assert_eq!("hello", unsafe { &*weak.as_raw() });
|
/// assert_eq!("hello", unsafe { &*weak.as_ptr() });
|
||||||
///
|
///
|
||||||
/// drop(strong);
|
/// drop(strong);
|
||||||
/// // But not any more. We can do weak.as_raw(), but accessing the pointer would lead to
|
/// // But not any more. We can do weak.as_ptr(), but accessing the pointer would lead to
|
||||||
/// // undefined behaviour.
|
/// // undefined behaviour.
|
||||||
/// // assert_eq!("hello", unsafe { &*weak.as_raw() });
|
/// // assert_eq!("hello", unsafe { &*weak.as_ptr() });
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`null`]: ../../std/ptr/fn.null.html
|
/// [`null`]: ../../std/ptr/fn.null.html
|
||||||
#[unstable(feature = "weak_into_raw", issue = "60728")]
|
#[unstable(feature = "weak_into_raw", issue = "60728")]
|
||||||
pub fn as_raw(&self) -> *const T {
|
pub fn as_ptr(&self) -> *const T {
|
||||||
match self.inner() {
|
let offset = data_offset_sized::<T>();
|
||||||
None => ptr::null(),
|
let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset);
|
||||||
Some(inner) => {
|
ptr as *const T
|
||||||
let offset = data_offset_sized::<T>();
|
|
||||||
let ptr = inner as *const RcBox<T>;
|
|
||||||
// Note: while the pointer we create may already point to dropped value, the
|
|
||||||
// allocation still lives (it must hold the weak point as long as we are alive).
|
|
||||||
// Therefore, the offset is OK to do, it won't get out of the allocation.
|
|
||||||
let ptr = unsafe { (ptr as *const u8).offset(offset) };
|
|
||||||
ptr as *const T
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consumes the `Weak<T>` and turns it into a raw pointer.
|
/// Consumes the `Weak<T>` and turns it into a raw pointer.
|
||||||
|
@ -1691,7 +1682,7 @@ impl<T> Weak<T> {
|
||||||
/// can be turned back into the `Weak<T>` with [`from_raw`].
|
/// can be turned back into the `Weak<T>` with [`from_raw`].
|
||||||
///
|
///
|
||||||
/// The same restrictions of accessing the target of the pointer as with
|
/// The same restrictions of accessing the target of the pointer as with
|
||||||
/// [`as_raw`] apply.
|
/// [`as_ptr`] apply.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -1712,10 +1703,10 @@ impl<T> Weak<T> {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`from_raw`]: struct.Weak.html#method.from_raw
|
/// [`from_raw`]: struct.Weak.html#method.from_raw
|
||||||
/// [`as_raw`]: struct.Weak.html#method.as_raw
|
/// [`as_ptr`]: struct.Weak.html#method.as_ptr
|
||||||
#[unstable(feature = "weak_into_raw", issue = "60728")]
|
#[unstable(feature = "weak_into_raw", issue = "60728")]
|
||||||
pub fn into_raw(self) -> *const T {
|
pub fn into_raw(self) -> *const T {
|
||||||
let result = self.as_raw();
|
let result = self.as_ptr();
|
||||||
mem::forget(self);
|
mem::forget(self);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -1730,9 +1721,8 @@ impl<T> Weak<T> {
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The pointer must have originated from the [`into_raw`] (or [`as_raw`], provided there was
|
/// The pointer must have originated from the [`into_raw`] and must still own its potential
|
||||||
/// a corresponding [`forget`] on the `Weak<T>`) and must still own its potential weak reference
|
/// weak reference count.
|
||||||
/// count.
|
|
||||||
///
|
///
|
||||||
/// It is allowed for the strong count to be 0 at the time of calling this, but the weak count
|
/// It is allowed for the strong count to be 0 at the time of calling this, but the weak count
|
||||||
/// must be non-zero or the pointer must have originated from a dangling `Weak<T>` (one created
|
/// 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> {
|
||||||
/// [`upgrade`]: struct.Weak.html#method.upgrade
|
/// [`upgrade`]: struct.Weak.html#method.upgrade
|
||||||
/// [`Rc`]: struct.Rc.html
|
/// [`Rc`]: struct.Rc.html
|
||||||
/// [`Weak`]: struct.Weak.html
|
/// [`Weak`]: struct.Weak.html
|
||||||
/// [`as_raw`]: struct.Weak.html#method.as_raw
|
|
||||||
/// [`new`]: struct.Weak.html#method.new
|
/// [`new`]: struct.Weak.html#method.new
|
||||||
/// [`forget`]: ../../std/mem/fn.forget.html
|
/// [`forget`]: ../../std/mem/fn.forget.html
|
||||||
#[unstable(feature = "weak_into_raw", issue = "60728")]
|
#[unstable(feature = "weak_into_raw", issue = "60728")]
|
||||||
|
|
|
@ -1340,8 +1340,8 @@ impl<T> Weak<T> {
|
||||||
|
|
||||||
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
|
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
|
||||||
///
|
///
|
||||||
/// The pointer is valid only if there are some strong references. The pointer may be dangling
|
/// The pointer is valid only if there are some strong references. The pointer may be dangling,
|
||||||
/// or even [`null`] otherwise.
|
/// unaligned or even [`null`] otherwise.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -1354,31 +1354,22 @@ impl<T> Weak<T> {
|
||||||
/// let strong = Arc::new("hello".to_owned());
|
/// let strong = Arc::new("hello".to_owned());
|
||||||
/// let weak = Arc::downgrade(&strong);
|
/// let weak = Arc::downgrade(&strong);
|
||||||
/// // Both point to the same object
|
/// // Both point to the same object
|
||||||
/// assert!(ptr::eq(&*strong, weak.as_raw()));
|
/// assert!(ptr::eq(&*strong, weak.as_ptr()));
|
||||||
/// // The strong here keeps it alive, so we can still access the object.
|
/// // The strong here keeps it alive, so we can still access the object.
|
||||||
/// assert_eq!("hello", unsafe { &*weak.as_raw() });
|
/// assert_eq!("hello", unsafe { &*weak.as_ptr() });
|
||||||
///
|
///
|
||||||
/// drop(strong);
|
/// drop(strong);
|
||||||
/// // But not any more. We can do weak.as_raw(), but accessing the pointer would lead to
|
/// // But not any more. We can do weak.as_ptr(), but accessing the pointer would lead to
|
||||||
/// // undefined behaviour.
|
/// // undefined behaviour.
|
||||||
/// // assert_eq!("hello", unsafe { &*weak.as_raw() });
|
/// // assert_eq!("hello", unsafe { &*weak.as_ptr() });
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`null`]: ../../std/ptr/fn.null.html
|
/// [`null`]: ../../std/ptr/fn.null.html
|
||||||
#[unstable(feature = "weak_into_raw", issue = "60728")]
|
#[unstable(feature = "weak_into_raw", issue = "60728")]
|
||||||
pub fn as_raw(&self) -> *const T {
|
pub fn as_ptr(&self) -> *const T {
|
||||||
match self.inner() {
|
let offset = data_offset_sized::<T>();
|
||||||
None => ptr::null(),
|
let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset);
|
||||||
Some(inner) => {
|
ptr as *const T
|
||||||
let offset = data_offset_sized::<T>();
|
|
||||||
let ptr = inner as *const ArcInner<T>;
|
|
||||||
// Note: while the pointer we create may already point to dropped value, the
|
|
||||||
// allocation still lives (it must hold the weak point as long as we are alive).
|
|
||||||
// Therefore, the offset is OK to do, it won't get out of the allocation.
|
|
||||||
let ptr = unsafe { (ptr as *const u8).offset(offset) };
|
|
||||||
ptr as *const T
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consumes the `Weak<T>` and turns it into a raw pointer.
|
/// Consumes the `Weak<T>` and turns it into a raw pointer.
|
||||||
|
@ -1387,7 +1378,7 @@ impl<T> Weak<T> {
|
||||||
/// can be turned back into the `Weak<T>` with [`from_raw`].
|
/// can be turned back into the `Weak<T>` with [`from_raw`].
|
||||||
///
|
///
|
||||||
/// The same restrictions of accessing the target of the pointer as with
|
/// The same restrictions of accessing the target of the pointer as with
|
||||||
/// [`as_raw`] apply.
|
/// [`as_ptr`] apply.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -1408,10 +1399,10 @@ impl<T> Weak<T> {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`from_raw`]: struct.Weak.html#method.from_raw
|
/// [`from_raw`]: struct.Weak.html#method.from_raw
|
||||||
/// [`as_raw`]: struct.Weak.html#method.as_raw
|
/// [`as_ptr`]: struct.Weak.html#method.as_ptr
|
||||||
#[unstable(feature = "weak_into_raw", issue = "60728")]
|
#[unstable(feature = "weak_into_raw", issue = "60728")]
|
||||||
pub fn into_raw(self) -> *const T {
|
pub fn into_raw(self) -> *const T {
|
||||||
let result = self.as_raw();
|
let result = self.as_ptr();
|
||||||
mem::forget(self);
|
mem::forget(self);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -1427,9 +1418,8 @@ impl<T> Weak<T> {
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The pointer must have originated from the [`into_raw`] (or [`as_raw'], provided there was
|
/// The pointer must have originated from the [`into_raw`] and must still own its potential
|
||||||
/// a corresponding [`forget`] on the `Weak<T>`) and must still own its potential weak reference
|
/// weak reference count.
|
||||||
/// count.
|
|
||||||
///
|
///
|
||||||
/// It is allowed for the strong count to be 0 at the time of calling this, but the weak count
|
/// It is allowed for the strong count to be 0 at the time of calling this, but the weak count
|
||||||
/// must be non-zero or the pointer must have originated from a dangling `Weak<T>` (one created
|
/// 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> {
|
||||||
/// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none());
|
/// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none());
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`as_raw`]: struct.Weak.html#method.as_raw
|
|
||||||
/// [`new`]: struct.Weak.html#method.new
|
/// [`new`]: struct.Weak.html#method.new
|
||||||
/// [`into_raw`]: struct.Weak.html#method.into_raw
|
/// [`into_raw`]: struct.Weak.html#method.into_raw
|
||||||
/// [`upgrade`]: struct.Weak.html#method.upgrade
|
/// [`upgrade`]: struct.Weak.html#method.upgrade
|
||||||
|
|
Loading…
Reference in New Issue