Skip to content

Commit 0bc5fc9

Browse files
authored
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.
2 parents 94d43d6 + 586c7e3 commit 0bc5fc9

File tree

2 files changed

+36
-10
lines changed

2 files changed

+36
-10
lines changed

src/liballoc/rc.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ use crate::vec::Vec;
259259
#[cfg(test)]
260260
mod tests;
261261

262+
// This is repr(C) to future-proof against possible field-reordering, which
263+
// would interfere with otherwise safe [into|from]_raw() of transmutable
264+
// inner types.
265+
#[repr(C)]
262266
struct RcBox<T: ?Sized> {
263267
strong: Cell<usize>,
264268
weak: Cell<usize>,
@@ -580,15 +584,24 @@ impl<T: ?Sized> Rc<T> {
580584
}
581585
}
582586

583-
/// Constructs an `Rc` from a raw pointer.
587+
/// Constructs an `Rc<T>` from a raw pointer.
584588
///
585-
/// The raw pointer must have been previously returned by a call to a
586-
/// [`Rc::into_raw`][into_raw].
589+
/// The raw pointer must have been previously returned by a call to
590+
/// [`Rc<U>::into_raw`][into_raw] where `U` must have the same size
591+
/// and alignment as `T`. This is trivially true if `U` is `T`.
592+
/// Note that if `U` is not `T` but has the same size and alignment, this is
593+
/// basically like transmuting references of different types. See
594+
/// [`mem::transmute`][transmute] for more information on what
595+
/// restrictions apply in this case.
587596
///
588-
/// This function is unsafe because improper use may lead to memory problems. For example, a
589-
/// double-free may occur if the function is called twice on the same raw pointer.
597+
/// The user of `from_raw` has to make sure a specific value of `T` is only
598+
/// dropped once.
599+
///
600+
/// This function is unsafe because improper use may lead to memory unsafety,
601+
/// even if the returned `Rc<T>` is never accessed.
590602
///
591603
/// [into_raw]: struct.Rc.html#method.into_raw
604+
/// [transmute]: ../../std/mem/fn.transmute.html
592605
///
593606
/// # Examples
594607
///

src/liballoc/sync.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,10 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
287287
}
288288
}
289289

290+
// This is repr(C) to future-proof against possible field-reordering, which
291+
// would interfere with otherwise safe [into|from]_raw() of transmutable
292+
// inner types.
293+
#[repr(C)]
290294
struct ArcInner<T: ?Sized> {
291295
strong: atomic::AtomicUsize,
292296

@@ -577,15 +581,24 @@ impl<T: ?Sized> Arc<T> {
577581
}
578582
}
579583

580-
/// Constructs an `Arc` from a raw pointer.
584+
/// Constructs an `Arc<T>` from a raw pointer.
581585
///
582-
/// The raw pointer must have been previously returned by a call to a
583-
/// [`Arc::into_raw`][into_raw].
586+
/// The raw pointer must have been previously returned by a call to
587+
/// [`Arc<U>::into_raw`][into_raw] where `U` must have the same size and
588+
/// alignment as `T`. This is trivially true if `U` is `T`.
589+
/// Note that if `U` is not `T` but has the same size and alignment, this is
590+
/// basically like transmuting references of different types. See
591+
/// [`mem::transmute`][transmute] for more information on what
592+
/// restrictions apply in this case.
584593
///
585-
/// This function is unsafe because improper use may lead to memory problems. For example, a
586-
/// double-free may occur if the function is called twice on the same raw pointer.
594+
/// The user of `from_raw` has to make sure a specific value of `T` is only
595+
/// dropped once.
596+
///
597+
/// This function is unsafe because improper use may lead to memory unsafety,
598+
/// even if the returned `Arc<T>` is never accessed.
587599
///
588600
/// [into_raw]: struct.Arc.html#method.into_raw
601+
/// [transmute]: ../../std/mem/fn.transmute.html
589602
///
590603
/// # Examples
591604
///

0 commit comments

Comments
 (0)