Description
There seems to be inconsistent behavior for derive_default
based on whether the type is detected to be opaque by bindgen or explicitly marked as opaque by bindgen.
For a C definition of struct Foo;
for an opaque struct, bindgen
will generate the following with derive_default(true)
:
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Foo {
_unused: [u8; 0],
}
When Foo
is also explicitly marked opaque with .opaque_type("Foo")
, it generates the following:
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct Foo {
_unused: [u8; 0],
}
I don't see why explicitly marking the type as opaque should change whether or not Default
is derived. I also think that it makes even less sense that Default
gets derived for a type that is supposed to be Opaque, since opaque types should never be directly accessed and should be handled only via pointers.
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):