Skip to content

Is Rc’s and Arc’s data_offset correct? #62522

Closed

Description

In the implementation of Arc, we find:

rust/src/liballoc/sync.rs

Lines 258 to 269 in 09ab31b

struct ArcInner<T: ?Sized> {
strong: atomic::AtomicUsize,
// the value usize::MAX acts as a sentinel for temporarily "locking" the
// ability to upgrade weak pointers or downgrade strong ones; this is used
// to avoid races in `make_mut` and `get_mut`.
weak: atomic::AtomicUsize,
data: T,
}

rust/src/liballoc/sync.rs

Lines 2288 to 2304 in 09ab31b

/// Computes the offset of the data field within ArcInner.
unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
// Align the unsized value to the end of the ArcInner.
// Because it is ?Sized, it will always be the last field in memory.
let align = align_of_val(&*ptr);
let layout = Layout::new::<ArcInner<()>>();
(layout.size() + layout.padding_needed_for(align)) as isize
}
/// Computes the offset of the data field within ArcInner.
///
/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
fn data_offset_sized<T>() -> isize {
let align = align_of::<T>();
let layout = Layout::new::<ArcInner<()>>();
(layout.size() + layout.padding_needed_for(align)) as isize
}

(And similarly in rc.rs with struct RcBox.)

Note the comment: Because it is ?Sized, it will always be the last field in memory.

Is this actually true, even for instantiations where T happens to be Sized? Does the language guarantee that there exist no type Foo such that the fields of ArcInner<Foo> would be re-ordered?

Or do we need to add #[repr(C)] to ArcInner and RcBox?

CC @rust-lang/wg-unsafe-code-guidelines

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    T-langRelevant to the language team, which will review and decide on the PR/issue.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions