rust-lang / nomicon

The Dark Arts of Advanced and Unsafe Rust Programming
https://doc.rust-lang.org/nomicon/
Apache License 2.0
1.85k stars 268 forks source link

Described opaque type pattern has issues #250

Closed skade closed 3 years ago

skade commented 3 years ago

It was recently pointed out that the current suggestion around representing opaque types in Rust has issues.

https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs

#[repr(C)] pub struct Bar { _private: [u8; 0] }

This type ends up being Send, Sync and Unpin, all properties which might not hold for the type hidden.

A type I came up with @dtolnay and @nvzqz to fix those issues is the following:

#[repr(C)]
pub struct opaque_example {
    // Required for FFI-safe 0-sized type.
    //
    // In the future, this should refer to an extern type.
    // See https://github.com/rust-lang/rust/issues/43467.
    _data: [u8; 0],

    // Required for !Send & !Sync & !Unpin.
    //
    // - `*mut u8` is !Send & !Sync. It must be in `PhantomData` to not
    //   affect alignment.
    //
    // - `PhantomPinned` is !Unpin. It must be in `PhantomData` because
    //   its memory representation is not considered FFI-safe.
    _marker:
        core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
}

(An implementation can be found here: https://github.com/skade/ffi-opaque/)

For reference, this matches the current behaviour of RFC 1861 extern types: https://github.com/rust-lang/rust/pull/44295#issue-139057745

JohnTitor commented 3 years ago

Makes sense, @skade do you have time to update the docs? If not I'm happy to work on it instead :)