Rollup merge of #68099 - lukaslueg:into_raw_unsafe, r=LukasKalbertodt

Amend Rc/Arc::from_raw() docs regarding unsafety

[This](https://stackoverflow.com/questions/59671647/is-it-safe-to-clone-a-type-erased-arc-via-raw-pointer) question on SO boils down to "is it safe to `::from_raw()` a `Rc<T>`/`Arc<T>` using a dummy `T` even if `T` is never dereferenced via the new `Rc`/`Arc`?". It almost never is.

This PR amends the docs of `from_raw()` regarding this point.
This commit is contained in:
Dylan DPC 2020-03-22 15:48:28 +01:00 committed by GitHub
commit 0bc5fc99d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 10 deletions

View File

@ -259,6 +259,10 @@ use crate::vec::Vec;
#[cfg(test)]
mod tests;
// This is repr(C) to future-proof against possible field-reordering, which
// would interfere with otherwise safe [into|from]_raw() of transmutable
// inner types.
#[repr(C)]
struct RcBox<T: ?Sized> {
strong: Cell<usize>,
weak: Cell<usize>,
@ -580,15 +584,24 @@ impl<T: ?Sized> Rc<T> {
}
}
/// Constructs an `Rc` from a raw pointer.
/// Constructs an `Rc<T>` from a raw pointer.
///
/// The raw pointer must have been previously returned by a call to a
/// [`Rc::into_raw`][into_raw].
/// The raw pointer must have been previously returned by a call to
/// [`Rc<U>::into_raw`][into_raw] where `U` must have the same size
/// and alignment as `T`. This is trivially true if `U` is `T`.
/// Note that if `U` is not `T` but has the same size and alignment, this is
/// basically like transmuting references of different types. See
/// [`mem::transmute`][transmute] for more information on what
/// restrictions apply in this case.
///
/// This function is unsafe because improper use may lead to memory problems. For example, a
/// double-free may occur if the function is called twice on the same raw pointer.
/// The user of `from_raw` has to make sure a specific value of `T` is only
/// dropped once.
///
/// This function is unsafe because improper use may lead to memory unsafety,
/// even if the returned `Rc<T>` is never accessed.
///
/// [into_raw]: struct.Rc.html#method.into_raw
/// [transmute]: ../../std/mem/fn.transmute.html
///
/// # Examples
///

View File

@ -287,6 +287,10 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
}
}
// This is repr(C) to future-proof against possible field-reordering, which
// would interfere with otherwise safe [into|from]_raw() of transmutable
// inner types.
#[repr(C)]
struct ArcInner<T: ?Sized> {
strong: atomic::AtomicUsize,
@ -577,15 +581,24 @@ impl<T: ?Sized> Arc<T> {
}
}
/// Constructs an `Arc` from a raw pointer.
/// Constructs an `Arc<T>` from a raw pointer.
///
/// The raw pointer must have been previously returned by a call to a
/// [`Arc::into_raw`][into_raw].
/// The raw pointer must have been previously returned by a call to
/// [`Arc<U>::into_raw`][into_raw] where `U` must have the same size and
/// alignment as `T`. This is trivially true if `U` is `T`.
/// Note that if `U` is not `T` but has the same size and alignment, this is
/// basically like transmuting references of different types. See
/// [`mem::transmute`][transmute] for more information on what
/// restrictions apply in this case.
///
/// This function is unsafe because improper use may lead to memory problems. For example, a
/// double-free may occur if the function is called twice on the same raw pointer.
/// The user of `from_raw` has to make sure a specific value of `T` is only
/// dropped once.
///
/// This function is unsafe because improper use may lead to memory unsafety,
/// even if the returned `Arc<T>` is never accessed.
///
/// [into_raw]: struct.Arc.html#method.into_raw
/// [transmute]: ../../std/mem/fn.transmute.html
///
/// # Examples
///