-
Notifications
You must be signed in to change notification settings - Fork 763
Description
When using impl_debug(true)
together with default_alias_style(bindgen::AliasVariation::NewTypeDeref)
and generating bindings to a C union which has a typedef alias, the generated Rust code has a Debug
implementation for the C union but does NOT have a Debug
implementation for the newtype alias of the C union. If there are any structs defined which contain the aliased type, then the generated bindings won't even compile! I know it's a weird case, but this is actually preventing me from using default_alias_style(bindgen::AliasVariation::NewTypeDeref)
in a real project.
Very simple example:
// foo.h
union Union {
uint8_t bytes[4];
uint32_t word;
};
typedef union Union UnionAlias;
struct StructContainingUnionAlias {
UnionAlias ua;
};
// build.rs
use std::env;
use std::path::PathBuf;
fn main() {
let crate_dir = &env::var("CARGO_MANIFEST_DIR").unwrap();
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
let bindings = bindgen::Builder::default()
.derive_default(true)
.impl_debug(true)
.default_alias_style(bindgen::AliasVariation::NewTypeDeref)
.header(format!("{crate_dir}/src/foo.h"))
.allowlist_file(".*foo.h.*")
.generate()
.expect("Unable to generate bindings");
bindings
.write_to_file(out_path.join("foo_bindings.rs"))
.expect("Couldn't write bindings");
}
// foo_bindings.rs, generated by bindgen
/* automatically generated by rust-bindgen 0.72.0 */
#[repr(C)]
#[derive(Copy, Clone)]
pub union Union {
pub bytes: [u8; 4usize],
pub word: u32,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of Union"][::std::mem::size_of::<Union>() - 4usize];
["Alignment of Union"][::std::mem::align_of::<Union>() - 4usize];
["Offset of field: Union::bytes"][::std::mem::offset_of!(Union, bytes) - 0usize];
["Offset of field: Union::word"][::std::mem::offset_of!(Union, word) - 0usize];
};
impl Default for Union {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
impl ::std::fmt::Debug for Union {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
write!(f, "Union {{ union }}")
}
}
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct UnionAlias(pub Union);
impl ::std::ops::Deref for UnionAlias {
type Target = Union;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl ::std::ops::DerefMut for UnionAlias {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct StructContainingUnionAlias {
pub ua: UnionAlias,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of StructContainingUnionAlias"]
[::std::mem::size_of::<StructContainingUnionAlias>() - 4usize];
["Alignment of StructContainingUnionAlias"]
[::std::mem::align_of::<StructContainingUnionAlias>() - 4usize];
["Offset of field: StructContainingUnionAlias::ua"]
[::std::mem::offset_of!(StructContainingUnionAlias, ua) - 0usize];
};
impl Default for StructContainingUnionAlias {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
impl ::std::fmt::Debug for StructContainingUnionAlias {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
write!(f, "StructContainingUnionAlias {{ ua: {:?} }}", self.ua)
}
}
The generated file does not compile, since it's trying to derive Debug
for StructContainingUnionAlias
, but the field self.ua
does not derive or implement Debug
. Compilation error is:
$ cargo build
Compiling bindgen-bug v0.1.0 (/Users/ivmaykov/Development/experiments/bindgen-bug)
error[E0277]: `UnionAlias` doesn't implement `Debug`
--> /Users/ivmaykov/Development/experiments/bindgen-bug/target/debug/build/bindgen-bug-d43f6c4a8531d2b1/out/foo_bindings.rs:71:64
|
71 | write!(f, "StructContainingUnionAlias {{ ua: {:?} }}", self.ua)
| ---- ^^^^^^^ `UnionAlias` cannot be formatted using `{:?}` because it doesn't implement `Debug`
| |
| required by this formatting parameter
|
= help: the trait `Debug` is not implemented for `UnionAlias`
= note: add `#[derive(Debug)]` to `UnionAlias` or manually `impl Debug for UnionAlias`
= note: this error originates in the macro `$crate::format_args` which comes from the expansion of the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `UnionAlias` with `#[derive(Debug)]`
|
32 + #[derive(Debug)]
33 | pub struct UnionAlias(pub Union);
|
For more information about this error, try `rustc --explain E0277`.
error: could not compile `bindgen-bug` (lib) due to 1 previous error
I'm using bindgen 0.72.0 and rustc 1.90.0-nightly on MacOS.
See https://github.com/ivmaykov/bindgen-bug for a minimal project which reproduces the issue.