Skip to content

Commit

Permalink
Auto merge of #61421 - vorner:string-in-rc-into-raw-docs, r=RalfJung
Browse files Browse the repository at this point in the history
docs: Use String in Rc::into_raw examples

It is unclear if accessing an integer after `drop_in_place` has been
called on it is undefined behaviour or not, as demonstrated by the
discussion in
#60766 (review).

Avoid these uncertainties by using String which frees memory in its
`drop_in_place` to make sure this is undefined behaviour. The message in
the docs should be to watch out and not access the data after that, not
discussing when one maybe could get away with it O:-).
  • Loading branch information
bors committed Jun 13, 2019
2 parents 96636f3 + e5af0e5 commit ab0c4b9
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 28 deletions.
28 changes: 14 additions & 14 deletions src/liballoc/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,9 +375,9 @@ impl<T: ?Sized> Rc<T> {
/// ```
/// use std::rc::Rc;
///
/// let x = Rc::new(10);
/// let x = Rc::new("hello".to_owned());
/// let x_ptr = Rc::into_raw(x);
/// assert_eq!(unsafe { *x_ptr }, 10);
/// assert_eq!(unsafe { &*x_ptr }, "hello");
/// ```
#[stable(feature = "rc_raw", since = "1.17.0")]
pub fn into_raw(this: Self) -> *const T {
Expand All @@ -401,13 +401,13 @@ impl<T: ?Sized> Rc<T> {
/// ```
/// use std::rc::Rc;
///
/// let x = Rc::new(10);
/// let x = Rc::new("hello".to_owned());
/// let x_ptr = Rc::into_raw(x);
///
/// unsafe {
/// // Convert back to an `Rc` to prevent leak.
/// let x = Rc::from_raw(x_ptr);
/// assert_eq!(*x, 10);
/// assert_eq!(&*x, "hello");
///
/// // Further calls to `Rc::from_raw(x_ptr)` would be memory unsafe.
/// }
Expand Down Expand Up @@ -437,10 +437,10 @@ impl<T: ?Sized> Rc<T> {
///
/// use std::rc::Rc;
///
/// let x = Rc::new(10);
/// let x = Rc::new("hello".to_owned());
/// let ptr = Rc::into_raw_non_null(x);
/// let deref = unsafe { *ptr.as_ref() };
/// assert_eq!(deref, 10);
/// let deref = unsafe { ptr.as_ref() };
/// assert_eq!(deref, "hello");
/// ```
#[unstable(feature = "rc_into_raw_non_null", issue = "47336")]
#[inline]
Expand Down Expand Up @@ -1294,17 +1294,17 @@ impl<T> Weak<T> {
/// use std::rc::{Rc, Weak};
/// use std::ptr;
///
/// let strong = Rc::new(42);
/// let strong = Rc::new("hello".to_owned());
/// let weak = Rc::downgrade(&strong);
/// // Both point to the same object
/// assert!(ptr::eq(&*strong, Weak::as_raw(&weak)));
/// // The strong here keeps it alive, so we can still access the object.
/// assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
/// assert_eq!("hello", unsafe { &*Weak::as_raw(&weak) });
///
/// drop(strong);
/// // But not any more. We can do Weak::as_raw(&weak), but accessing the pointer would lead to
/// // undefined behaviour.
/// // assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
/// // assert_eq!("hello", unsafe { &*Weak::as_raw(&weak) });
/// ```
///
/// [`null`]: ../../std/ptr/fn.null.html
Expand Down Expand Up @@ -1339,12 +1339,12 @@ impl<T> Weak<T> {
///
/// use std::rc::{Rc, Weak};
///
/// let strong = Rc::new(42);
/// let strong = Rc::new("hello".to_owned());
/// let weak = Rc::downgrade(&strong);
/// let raw = Weak::into_raw(weak);
///
/// assert_eq!(1, Rc::weak_count(&strong));
/// assert_eq!(42, unsafe { *raw });
/// assert_eq!("hello", unsafe { &*raw });
///
/// drop(unsafe { Weak::from_raw(raw) });
/// assert_eq!(0, Rc::weak_count(&strong));
Expand Down Expand Up @@ -1380,14 +1380,14 @@ impl<T> Weak<T> {
///
/// use std::rc::{Rc, Weak};
///
/// let strong = Rc::new(42);
/// let strong = Rc::new("hello".to_owned());
///
/// let raw_1 = Weak::into_raw(Rc::downgrade(&strong));
/// let raw_2 = Weak::into_raw(Rc::downgrade(&strong));
///
/// assert_eq!(2, Rc::weak_count(&strong));
///
/// assert_eq!(42, *Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap());
/// assert_eq!("hello", &*Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap());
/// assert_eq!(1, Rc::weak_count(&strong));
///
/// drop(strong);
Expand Down
28 changes: 14 additions & 14 deletions src/liballoc/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,9 +356,9 @@ impl<T: ?Sized> Arc<T> {
/// ```
/// use std::sync::Arc;
///
/// let x = Arc::new(10);
/// let x = Arc::new("hello".to_owned());
/// let x_ptr = Arc::into_raw(x);
/// assert_eq!(unsafe { *x_ptr }, 10);
/// assert_eq!(unsafe { &*x_ptr }, "hello");
/// ```
#[stable(feature = "rc_raw", since = "1.17.0")]
pub fn into_raw(this: Self) -> *const T {
Expand All @@ -382,13 +382,13 @@ impl<T: ?Sized> Arc<T> {
/// ```
/// use std::sync::Arc;
///
/// let x = Arc::new(10);
/// let x = Arc::new("hello".to_owned());
/// let x_ptr = Arc::into_raw(x);
///
/// unsafe {
/// // Convert back to an `Arc` to prevent leak.
/// let x = Arc::from_raw(x_ptr);
/// assert_eq!(*x, 10);
/// assert_eq!(&*x, "hello");
///
/// // Further calls to `Arc::from_raw(x_ptr)` would be memory unsafe.
/// }
Expand Down Expand Up @@ -418,10 +418,10 @@ impl<T: ?Sized> Arc<T> {
///
/// use std::sync::Arc;
///
/// let x = Arc::new(10);
/// let x = Arc::new("hello".to_owned());
/// let ptr = Arc::into_raw_non_null(x);
/// let deref = unsafe { *ptr.as_ref() };
/// assert_eq!(deref, 10);
/// let deref = unsafe { ptr.as_ref() };
/// assert_eq!(deref, "hello");
/// ```
#[unstable(feature = "rc_into_raw_non_null", issue = "47336")]
#[inline]
Expand Down Expand Up @@ -1083,17 +1083,17 @@ impl<T> Weak<T> {
/// use std::sync::{Arc, Weak};
/// use std::ptr;
///
/// let strong = Arc::new(42);
/// let strong = Arc::new("hello".to_owned());
/// let weak = Arc::downgrade(&strong);
/// // Both point to the same object
/// assert!(ptr::eq(&*strong, Weak::as_raw(&weak)));
/// // The strong here keeps it alive, so we can still access the object.
/// assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
/// assert_eq!("hello", unsafe { &*Weak::as_raw(&weak) });
///
/// drop(strong);
/// // But not any more. We can do Weak::as_raw(&weak), but accessing the pointer would lead to
/// // undefined behaviour.
/// // assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
/// // assert_eq!("hello", unsafe { &*Weak::as_raw(&weak) });
/// ```
///
/// [`null`]: ../../std/ptr/fn.null.html
Expand Down Expand Up @@ -1128,12 +1128,12 @@ impl<T> Weak<T> {
///
/// use std::sync::{Arc, Weak};
///
/// let strong = Arc::new(42);
/// let strong = Arc::new("hello".to_owned());
/// let weak = Arc::downgrade(&strong);
/// let raw = Weak::into_raw(weak);
///
/// assert_eq!(1, Arc::weak_count(&strong));
/// assert_eq!(42, unsafe { *raw });
/// assert_eq!("hello", unsafe { &*raw });
///
/// drop(unsafe { Weak::from_raw(raw) });
/// assert_eq!(0, Arc::weak_count(&strong));
Expand Down Expand Up @@ -1170,14 +1170,14 @@ impl<T> Weak<T> {
///
/// use std::sync::{Arc, Weak};
///
/// let strong = Arc::new(42);
/// let strong = Arc::new("hello".to_owned());
///
/// let raw_1 = Weak::into_raw(Arc::downgrade(&strong));
/// let raw_2 = Weak::into_raw(Arc::downgrade(&strong));
///
/// assert_eq!(2, Arc::weak_count(&strong));
///
/// assert_eq!(42, *Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap());
/// assert_eq!("hello", &*Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap());
/// assert_eq!(1, Arc::weak_count(&strong));
///
/// drop(strong);
Expand Down

0 comments on commit ab0c4b9

Please sign in to comment.