Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Opaque type should not have pub member #3097

Open
wmmc88 opened this issue Jan 24, 2025 · 3 comments
Open

Opaque type should not have pub member #3097

wmmc88 opened this issue Jan 24, 2025 · 3 comments

Comments

@wmmc88
Copy link

wmmc88 commented Jan 24, 2025

For a type that is explicitly marked opaque via .opaque_type("Foo"), bindgen generates a type with a public member:

#[repr(C)]
#[repr(align(4))]
#[derive(Debug, Default, Copy, Clone)]
pub struct BAR__ {
    pub _bindgen_opaque_blob: u32,
}

Shouldn't _bindgen_opaque_blob be generated without pub? Making it pub allows the user to directly instantiate an instance of BAR__ which is most likely invalid, which defeats the purpose of it being an opaque type

Other Information
rust-bindgen 0.71.1
clang version 19.1.7
Target: x86_64-pc-windows-msvc

Full Code Sample
build.rs:

use std::env;
use std::path::PathBuf;

fn main() {
    tracing_subscriber::fmt::init();

    let builder = bindgen::Builder::default()
        .header_contents(
            "input.h",
            r#"
struct Foo;

struct BAR__{int unused;};
typedef struct BAR__ *BAR;
"#,
        )
        .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
        .derive_default(true);

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());

    builder
        .clone()
        .generate()
        .expect("Unable to generate bindings")
        .write_to_file((out_path).join("not-explicit-opaque.rs"))
        .expect("Couldn't write bindings!");

    builder
        .opaque_type("Foo")
        .opaque_type("BAR__") // Only BAR__ should be marked as opaque. The convenience type BAR should remain as a pointer to the opaque BAR__. 
        .generate()
        .expect("Unable to generate bindings")
        .write_to_file((out_path).join("explicit-opaque.rs"))
        .expect("Couldn't write bindings!");
}

Output:
not-explicit-opaque.rs:

/* automatically generated by rust-bindgen 0.71.1 */

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Foo {
    _unused: [u8; 0],
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct BAR__ {
    pub unused: ::std::os::raw::c_int,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
    ["Size of BAR__"][::std::mem::size_of::<BAR__>() - 4usize];
    ["Alignment of BAR__"][::std::mem::align_of::<BAR__>() - 4usize];
    ["Offset of field: BAR__::unused"][::std::mem::offset_of!(BAR__, unused) - 0usize];
};
pub type BAR = *mut BAR__;

explicit-opaque.rs:

/* automatically generated by rust-bindgen 0.71.1 */

#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct Foo {
    _unused: [u8; 0],
}
#[repr(C)]
#[repr(align(4))]
#[derive(Debug, Default, Copy, Clone)]
pub struct BAR__ {
    pub _bindgen_opaque_blob: u32,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
    ["Size of BAR__"][::std::mem::size_of::<BAR__>() - 4usize];
    ["Alignment of BAR__"][::std::mem::align_of::<BAR__>() - 4usize];
};
pub type BAR = *mut BAR__;

Output Diff (left is no explicit opaque. right is explicit opaque):
Image

@wmmc88
Copy link
Author

wmmc88 commented Jan 24, 2025

This is issue may be related to #3096, but I see these as 2 separate problems (#3096: default getting derived on opaque types, #3097: opaque types being generated with a pub member)

@jschwe
Copy link
Contributor

jschwe commented Jan 30, 2025

Related to #1656, since both allow creating an opaque type out of thin air.

@jschwe
Copy link
Contributor

jschwe commented Feb 5, 2025

It is probably worth noting, that bindgen makes the difference between "Forward declared types" (i.e. layout is unknown) and "opaque". In bindgen terms, opaque implies that the memory layout (size and alignment) of the type is known, just the internals are hidden.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants