diff --git a/bindgen-tests/tests/expectations/tests/issue-3268-newtype-deref-union-debug.rs b/bindgen-tests/tests/expectations/tests/issue-3268-newtype-deref-union-debug.rs new file mode 100644 index 0000000000..79a4e4d421 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-3268-newtype-deref-union-debug.rs @@ -0,0 +1,80 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone)] +pub union Union { + pub bytes: [::std::os::raw::c_uchar; 4usize], + pub word: ::std::os::raw::c_uint, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Union"][::std::mem::size_of::() - 4usize]; + ["Alignment of Union"][::std::mem::align_of::() - 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::::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 + } +} +impl ::std::fmt::Debug for UnionAlias { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + f.debug_tuple(stringify!(UnionAlias)).field(&self.0).finish() + } +} +#[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::() - 4usize]; + [ + "Alignment of StructContainingUnionAlias", + ][::std::mem::align_of::() - 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::::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) + } +} diff --git a/bindgen-tests/tests/headers/issue-3268-newtype-deref-union-debug.h b/bindgen-tests/tests/headers/issue-3268-newtype-deref-union-debug.h new file mode 100644 index 0000000000..884b1dbf29 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-3268-newtype-deref-union-debug.h @@ -0,0 +1,12 @@ +// bindgen-flags: --impl-debug --default-alias-style=new_type_deref + +union Union { + unsigned char bytes[4]; + unsigned int word; +}; + +typedef union Union UnionAlias; + +struct StructContainingUnionAlias { + UnionAlias ua; +}; diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index 6034b0e6ba..d61f87c901 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -1076,6 +1076,7 @@ impl CodeGenerator for Type { }; let alias_style = item.alias_style(ctx); + let mut needs_debug_impl = false; // We prefer using `pub use` over `pub type` because of: // https://github.com/rust-lang/rust/issues/26264 @@ -1107,6 +1108,12 @@ impl CodeGenerator for Type { let packed = false; // Types can't be packed in Rust. let derivable_traits = derives_of_item(item, ctx, packed); + if !derivable_traits.contains(DerivableTraits::DEBUG) { + needs_debug_impl = ctx.options().derive_debug && + ctx.options().impl_debug && + !ctx.no_debug_by_name(item) && + !item.annotations().disallow_debug(); + } let mut derives: Vec<_> = derivable_traits.into(); // The custom derives callback may return a list of derive attributes; // add them to the end of the list. @@ -1238,6 +1245,17 @@ impl CodeGenerator for Type { }); } + if needs_debug_impl { + let prefix = ctx.trait_prefix(); + tokens.append_all(quote! { + impl ::#prefix::fmt::Debug for #rust_name { + fn fmt(&self, f: &mut ::#prefix::fmt::Formatter<'_>) -> ::#prefix::fmt::Result { + f.debug_tuple(stringify!(#rust_name)).field(&self.0).finish() + } + } + }); + } + result.push(tokens); } TypeKind::Enum(ref ei) => ei.codegen(ctx, result, item),