From 36a763320889e70768787ae1d606bdde872e58a5 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 23 Nov 2017 14:00:30 +0100 Subject: [PATCH] =?UTF-8?q?Don=E2=80=99t=20recommend=20empty=20enums=20for?= =?UTF-8?q?=20opaque=20types?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix https://github.com/rust-lang-nursery/nomicon/issues/29 --- src/ffi.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/ffi.md b/src/ffi.md index 03693bb..8c2ed29 100644 --- a/src/ffi.md +++ b/src/ffi.md @@ -737,11 +737,11 @@ void foo(struct Foo *arg); void bar(struct Bar *arg); ``` -To do this in Rust, let’s create our own opaque types with `enum`: +To do this in Rust, let’s create our own opaque types: ```rust -pub enum Foo {} -pub enum Bar {} +#[repr(C)] pub struct Foo { private: [u8; 0] } +#[repr(C)] pub struct Bar { private: [u8; 0] } extern "C" { pub fn foo(arg: *mut Foo); @@ -750,7 +750,9 @@ extern "C" { # fn main() {} ``` -By using an `enum` with no variants, we create an opaque type that we can’t -instantiate, as it has no variants. But because our `Foo` and `Bar` types are +By including a private field and no constructor, +we create an opaque type that we can’t instantiate outside of this module. +An empty array is both zero-size and compatible with `#[repr(C)]`. +But because our `Foo` and `Bar` types are different, we’ll get type safety between the two of them, so we cannot accidentally pass a pointer to `Foo` to `bar()`.