diff options
29 files changed, 425 insertions, 98 deletions
diff --git a/book/src/blacklisting.md b/book/src/blacklisting.md index 990947ab..3553d8b2 100644 --- a/book/src/blacklisting.md +++ b/book/src/blacklisting.md @@ -8,6 +8,10 @@ appear in the bindings at all, [make it opaque](./opaque.html) instead of blacklisting it.) +Blacklisted types are pessimistically assumed not to be able to `derive` any +traits, which can transitively affect other types' ability to `derive` traits or +not. + ### Library * [`bindgen::Builder::hide_type`](https://docs.rs/bindgen/0.23.1/bindgen/struct.Builder.html#method.hide_type) diff --git a/src/codegen/derive_debug.rs b/src/codegen/derive_debug.rs index 066af339..82456797 100644 --- a/src/codegen/derive_debug.rs +++ b/src/codegen/derive_debug.rs @@ -53,7 +53,7 @@ pub fn gen_debug_impl( impl X { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { write!(f, $format_string $tokens) - } + } }); match impl_.unwrap().node { @@ -127,6 +127,12 @@ impl<'a> ImplDebug<'a> for Item { ) -> Option<(String, Vec<TokenTree>)> { let name_ident = ctx.rust_ident_raw(name); + // We don't know if blacklisted items `impl Debug` or not, so we can't + // add them to the format string we're building up. + if !ctx.whitelisted_items().contains(&self.id()) { + return None; + } + let ty = match self.as_type() { Some(ty) => ty, None => { @@ -168,7 +174,7 @@ impl<'a> ImplDebug<'a> for Item { } else { debug_print(ctx, name, name_ident) } - } + } // The generic is not required to implement Debug, so we can not debug print that type TypeKind::TypeParam => { diff --git a/src/ir/analysis/derive_copy.rs b/src/ir/analysis/derive_copy.rs index c108a961..1890dcec 100644 --- a/src/ir/analysis/derive_copy.rs +++ b/src/ir/analysis/derive_copy.rs @@ -88,6 +88,13 @@ impl<'ctx, 'gen> CannotDeriveCopy<'ctx, 'gen> { ConstrainResult::Changed } + + /// A type is not `Copy` if we've determined it is not copy, or if it is + /// blacklisted. + fn is_not_copy(&self, id: ItemId) -> bool { + self.cannot_derive_copy.contains(&id) || + !self.ctx.whitelisted_items().contains(&id) + } } impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> { @@ -118,6 +125,15 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> { return ConstrainResult::Same; } + // If an item is reachable from the whitelisted items set, but isn't + // itself whitelisted, then it must be blacklisted. We assume that + // blacklisted items are not `Copy`, since they are presumably + // blacklisted because they are too complicated for us to understand. + if !self.ctx.whitelisted_items().contains(&id) { + trace!(" blacklisted items are assumed not to be Copy"); + return ConstrainResult::Same; + } + let item = self.ctx.resolve_item(id); let ty = match item.as_type() { Some(ty) => ty, @@ -163,7 +179,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> { } TypeKind::Array(t, len) => { - let cant_derive_copy = self.cannot_derive_copy.contains(&t); + let cant_derive_copy = self.is_not_copy(t); if cant_derive_copy { trace!( " arrays of T for which we cannot derive Copy \ @@ -184,7 +200,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> { TypeKind::ResolvedTypeRef(t) | TypeKind::TemplateAlias(t, _) | TypeKind::Alias(t) => { - let cant_derive_copy = self.cannot_derive_copy.contains(&t); + let cant_derive_copy = self.is_not_copy(t); if cant_derive_copy { trace!( " arrays of T for which we cannot derive Copy \ @@ -237,7 +253,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> { let bases_cannot_derive = info.base_members().iter().any(|base| { - self.cannot_derive_copy.contains(&base.ty) + self.is_not_copy(base.ty) }); if bases_cannot_derive { trace!( @@ -250,11 +266,11 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> { let fields_cannot_derive = info.fields().iter().any(|f| match *f { Field::DataMember(ref data) => { - self.cannot_derive_copy.contains(&data.ty()) + self.is_not_copy(data.ty()) } Field::Bitfields(ref bfu) => { bfu.bitfields().iter().any(|b| { - self.cannot_derive_copy.contains(&b.ty()) + self.is_not_copy(b.ty()) }) } }); @@ -270,7 +286,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> { TypeKind::TemplateInstantiation(ref template) => { let args_cannot_derive = template.template_arguments().iter().any(|arg| { - self.cannot_derive_copy.contains(&arg) + self.is_not_copy(*arg) }); if args_cannot_derive { trace!( @@ -284,8 +300,8 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> { !template.template_definition().is_opaque(self.ctx, &()), "The early ty.is_opaque check should have handled this case" ); - let def_cannot_derive = self.cannot_derive_copy.contains( - &template.template_definition(), + let def_cannot_derive = self.is_not_copy( + template.template_definition(), ); if def_cannot_derive { trace!( diff --git a/src/ir/analysis/derive_debug.rs b/src/ir/analysis/derive_debug.rs index 14630155..b7a35132 100644 --- a/src/ir/analysis/derive_debug.rs +++ b/src/ir/analysis/derive_debug.rs @@ -90,6 +90,13 @@ impl<'ctx, 'gen> CannotDeriveDebug<'ctx, 'gen> { ConstrainResult::Changed } + + /// A type is not `Debug` if we've determined it is not debug, or if it is + /// blacklisted. + fn is_not_debug(&self, id: ItemId) -> bool { + self.cannot_derive_debug.contains(&id) || + !self.ctx.whitelisted_items().contains(&id) + } } impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> { @@ -120,6 +127,15 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> { return ConstrainResult::Same; } + // If an item is reachable from the whitelisted items set, but isn't + // itself whitelisted, then it must be blacklisted. We assume that + // blacklisted items are not `Copy`, since they are presumably + // blacklisted because they are too complicated for us to understand. + if !self.ctx.whitelisted_items().contains(&id) { + trace!(" blacklisted items are assumed not to be Debug"); + return ConstrainResult::Same; + } + let item = self.ctx.resolve_item(id); let ty = match item.as_type() { Some(ty) => ty, @@ -129,11 +145,13 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> { } }; - if ty.is_opaque(self.ctx, item) { + if item.is_opaque(self.ctx, &()) { let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| { l.opaque().can_trivially_derive_debug() }); - return if layout_can_derive { + return if layout_can_derive && + !(ty.is_union() && + self.ctx.options().rust_features().untagged_union()) { trace!(" we can trivially derive Debug for the layout"); ConstrainResult::Same } else { @@ -176,7 +194,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> { } TypeKind::Array(t, len) => { - if self.cannot_derive_debug.contains(&t) { + if self.is_not_debug(t) { trace!( " arrays of T for which we cannot derive Debug \ also cannot derive Debug" @@ -196,7 +214,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> { TypeKind::ResolvedTypeRef(t) | TypeKind::TemplateAlias(t, _) | TypeKind::Alias(t) => { - if self.cannot_derive_debug.contains(&t) { + if self.is_not_debug(t) { trace!( " aliases and type refs to T which cannot derive \ Debug also cannot derive Debug" @@ -237,7 +255,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> { let bases_cannot_derive = info.base_members().iter().any(|base| { - self.cannot_derive_debug.contains(&base.ty) + self.is_not_debug(base.ty) }); if bases_cannot_derive { trace!( @@ -250,11 +268,11 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> { let fields_cannot_derive = info.fields().iter().any(|f| match *f { Field::DataMember(ref data) => { - self.cannot_derive_debug.contains(&data.ty()) + self.is_not_debug(data.ty()) } Field::Bitfields(ref bfu) => { bfu.bitfields().iter().any(|b| { - self.cannot_derive_debug.contains(&b.ty()) + self.is_not_debug(b.ty()) }) } }); @@ -287,7 +305,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> { TypeKind::TemplateInstantiation(ref template) => { let args_cannot_derive = template.template_arguments().iter().any(|arg| { - self.cannot_derive_debug.contains(&arg) + self.is_not_debug(*arg) }); if args_cannot_derive { trace!( @@ -301,8 +319,8 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> { !template.template_definition().is_opaque(self.ctx, &()), "The early ty.is_opaque check should have handled this case" ); - let def_cannot_derive = self.cannot_derive_debug.contains( - &template.template_definition(), + let def_cannot_derive = self.is_not_debug( + template.template_definition(), ); if def_cannot_derive { trace!( diff --git a/src/ir/analysis/derive_default.rs b/src/ir/analysis/derive_default.rs index 74e05cd6..19f4a842 100644 --- a/src/ir/analysis/derive_default.rs +++ b/src/ir/analysis/derive_default.rs @@ -87,6 +87,11 @@ impl<'ctx, 'gen> CannotDeriveDefault<'ctx, 'gen> { ConstrainResult::Changed } + + fn is_not_default(&self, id: ItemId) -> bool { + self.cannot_derive_default.contains(&id) || + !self.ctx.whitelisted_items().contains(&id) + } } impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDefault<'ctx, 'gen> { @@ -153,6 +158,11 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDefault<'ctx, 'gen> { return ConstrainResult::Same; } + if !self.ctx.whitelisted_items().contains(&id) { + trace!(" blacklisted items pessimistically cannot derive Default"); + return ConstrainResult::Same; + } + let item = self.ctx.resolve_item(id); let ty = match item.as_type() { Some(ty) => ty, @@ -166,7 +176,9 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDefault<'ctx, 'gen> { let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| { l.opaque().can_trivially_derive_default() }); - return if layout_can_derive { + return if layout_can_derive && + !(ty.is_union() && + self.ctx.options().rust_features().untagged_union()) { trace!(" we can trivially derive Default for the layout"); ConstrainResult::Same } else { @@ -213,7 +225,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDefault<'ctx, 'gen> { } TypeKind::Array(t, len) => { - if self.cannot_derive_default.contains(&t) { + if self.is_not_default(t) { trace!( " arrays of T for which we cannot derive Default \ also cannot derive Default" @@ -233,7 +245,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDefault<'ctx, 'gen> { TypeKind::ResolvedTypeRef(t) | TypeKind::TemplateAlias(t, _) | TypeKind::Alias(t) => { - if self.cannot_derive_default.contains(&t) { + if self.is_not_default(t) { trace!( " aliases and type refs to T which cannot derive \ Default also cannot derive Default" @@ -280,7 +292,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDefault<'ctx, 'gen> { let bases_cannot_derive = info.base_members().iter().any(|base| { !self.ctx.whitelisted_items().contains(&base.ty) || - self.cannot_derive_default.contains(&base.ty) + self.is_not_default(base.ty) }); if bases_cannot_derive { trace!( @@ -296,14 +308,14 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDefault<'ctx, 'gen> { !self.ctx.whitelisted_items().contains( &data.ty(), ) || - self.cannot_derive_default.contains(&data.ty()) + self.is_not_default(data.ty()) } Field::Bitfields(ref bfu) => { bfu.bitfields().iter().any(|b| { !self.ctx.whitelisted_items().contains( &b.ty(), ) || - self.cannot_derive_default.contains(&b.ty()) + self.is_not_default(b.ty()) }) } }); @@ -319,45 +331,34 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDefault<'ctx, 'gen> { } TypeKind::TemplateInstantiation(ref template) => { - if self.ctx.whitelisted_items().contains( - &template.template_definition(), - ) - { - let args_cannot_derive = - template.template_arguments().iter().any(|arg| { - self.cannot_derive_default.contains(&arg) - }); - if args_cannot_derive { - trace!( - " template args cannot derive Default, so \ - insantiation can't either" - ); - return self.insert(id); - } - - assert!( - !template.template_definition().is_opaque(self.ctx, &()), - "The early ty.is_opaque check should have handled this case" + let args_cannot_derive = + template.template_arguments().iter().any(|arg| { + self.is_not_default(*arg) + }); + if args_cannot_derive { + trace!( + " template args cannot derive Default, so \ + insantiation can't either" ); - let def_cannot_derive = - self.cannot_derive_default.contains(&template - .template_definition()); - if def_cannot_derive { - trace!( - " template definition cannot derive Default, so \ - insantiation can't either" - ); - return self.insert(id); - } + return self.insert(id); + } - trace!(" template instantiation can derive Default"); - ConstrainResult::Same - } else { + assert!( + !template.template_definition().is_opaque(self.ctx, &()), + "The early ty.is_opaque check should have handled this case" + ); + let def_cannot_derive = + self.is_not_default(template.template_definition()); + if def_cannot_derive { trace!( - " blacklisted template instantiation cannot derive default" + " template definition cannot derive Default, so \ + insantiation can't either" ); return self.insert(id); } + + trace!(" template instantiation can derive Default"); + ConstrainResult::Same } TypeKind::Opaque => { diff --git a/src/ir/analysis/derive_hash.rs b/src/ir/analysis/derive_hash.rs index d0ab3762..ee9cb23a 100644 --- a/src/ir/analysis/derive_hash.rs +++ b/src/ir/analysis/derive_hash.rs @@ -133,7 +133,9 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveHash<'ctx, 'gen> { let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| { l.opaque().can_trivially_derive_hash() }); - return if layout_can_derive { + return if layout_can_derive && + !(ty.is_union() && + self.ctx.options().rust_features().untagged_union()) { trace!(" we can trivially derive Hash for the layout"); ConstrainResult::Same } else { diff --git a/src/ir/analysis/derive_partial_eq.rs b/src/ir/analysis/derive_partial_eq.rs index 030c4c48..45ba67a5 100644 --- a/src/ir/analysis/derive_partial_eq.rs +++ b/src/ir/analysis/derive_partial_eq.rs @@ -136,7 +136,9 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDerivePartialEq<'ctx, 'gen> { let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| { l.opaque().can_trivially_derive_partialeq() }); - return if layout_can_derive { + return if layout_can_derive && + !(ty.is_union() && + self.ctx.options().rust_features().untagged_union()) { trace!(" we can trivially derive PartialEq for the layout"); ConstrainResult::Same } else { diff --git a/src/ir/dot.rs b/src/ir/dot.rs index 6d666f09..1181c32c 100644 --- a/src/ir/dot.rs +++ b/src/ir/dot.rs @@ -32,10 +32,17 @@ where let mut err: Option<io::Result<_>> = None; for (id, item) in ctx.items() { + let is_whitelisted = ctx.whitelisted_items().contains(id); + try!(writeln!( &mut dot_file, - r#"{} [fontname="courier", label=< <table border="0" align="left">"#, - id.as_usize() + r#"{} [fontname="courier", color={}, label=< <table border="0" align="left">"#, + id.as_usize(), + if is_whitelisted { + "black" + } else { + "gray" + } )); try!(item.dot_attributes(ctx, &mut dot_file)); try!(writeln!(&mut dot_file, r#"</table> >];"#)); @@ -49,10 +56,15 @@ where match writeln!( &mut dot_file, - "{} -> {} [label={:?}];", + "{} -> {} [label={:?}, color={}];", id.as_usize(), sub_id.as_usize(), - edge_kind + edge_kind, + if is_whitelisted { + "black" + } else { + "gray" + } ) { Ok(_) => {} Err(e) => err = Some(Err(e)), @@ -69,7 +81,7 @@ where for child in module.children() { try!(writeln!( &mut dot_file, - "{} -> {} [style=dotted]", + "{} -> {} [style=dotted, color=gray]", item.id().as_usize(), child.as_usize() )); diff --git a/src/ir/ty.rs b/src/ir/ty.rs index da1cc6d7..b588dbb4 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -99,6 +99,14 @@ impl Type { } } + /// Is this a union? + pub fn is_union(&self) -> bool { + match self.kind { + TypeKind::Comp(ref comp) => comp.is_union(), + _ => false, + } + } + /// Is this type of kind `TypeKind::TypeParam`? pub fn is_type_param(&self) -> bool { match self.kind { diff --git a/tests/expectations/tests/blacklist-and-impl-debug.rs b/tests/expectations/tests/blacklist-and-impl-debug.rs new file mode 100644 index 00000000..d84b0256 --- /dev/null +++ b/tests/expectations/tests/blacklist-and-impl-debug.rs @@ -0,0 +1,34 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + +pub struct BlacklistMe(u8); + +/// Because this type contains a blacklisted type, it should not derive Debug. +#[repr(C)] +pub struct ShouldManuallyImplDebug { + pub a: BlacklistMe, +} +#[test] +fn bindgen_test_layout_ShouldManuallyImplDebug() { + assert_eq!(::std::mem::size_of::<ShouldManuallyImplDebug>() , 1usize , + concat ! ( + "Size of: " , stringify ! ( ShouldManuallyImplDebug ) )); + assert_eq! (::std::mem::align_of::<ShouldManuallyImplDebug>() , 1usize , + concat ! ( + "Alignment of " , stringify ! ( ShouldManuallyImplDebug ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ShouldManuallyImplDebug ) ) . a as * + const _ as usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( ShouldManuallyImplDebug + ) , "::" , stringify ! ( a ) )); +} +impl Default for ShouldManuallyImplDebug { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +impl ::std::fmt::Debug for ShouldManuallyImplDebug { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f , "ShouldManuallyImplDebug {{ }}") + } +} diff --git a/tests/expectations/tests/derive-default-and-blacklist.rs b/tests/expectations/tests/derive-default-and-blacklist.rs new file mode 100644 index 00000000..e811bd05 --- /dev/null +++ b/tests/expectations/tests/derive-default-and-blacklist.rs @@ -0,0 +1,30 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + +pub struct BlacklistMe(u8); + +/// Because this type contains a blacklisted type, it should not derive +/// Default. Instead, we should emit a `mem::zeroed` implementation. +#[repr(C)] +pub struct ShouldNotDeriveDefault { + pub a: BlacklistMe, +} +#[test] +fn bindgen_test_layout_ShouldNotDeriveDefault() { + assert_eq!(::std::mem::size_of::<ShouldNotDeriveDefault>() , 1usize , + concat ! ( "Size of: " , stringify ! ( ShouldNotDeriveDefault ) + )); + assert_eq! (::std::mem::align_of::<ShouldNotDeriveDefault>() , 1usize , + concat ! ( + "Alignment of " , stringify ! ( ShouldNotDeriveDefault ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ShouldNotDeriveDefault ) ) . a as * const + _ as usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( ShouldNotDeriveDefault + ) , "::" , stringify ! ( a ) )); +} +impl Default for ShouldNotDeriveDefault { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} diff --git a/tests/expectations/tests/derive-hash-and-blacklist.rs b/tests/expectations/tests/derive-hash-and-blacklist.rs new file mode 100644 index 00000000..e5a66376 --- /dev/null +++ b/tests/expectations/tests/derive-hash-and-blacklist.rs @@ -0,0 +1,28 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + +pub struct BlacklistMe(u8); + +/// Because this type contains a blacklisted type, it should not derive Hash. +#[repr(C)] +pub struct ShouldNotDeriveHash { + pub a: BlacklistMe, +} +#[test] +fn bindgen_test_layout_ShouldNotDeriveHash() { + assert_eq!(::std::mem::size_of::<ShouldNotDeriveHash>() , 1usize , concat + ! ( "Size of: " , stringify ! ( ShouldNotDeriveHash ) )); + assert_eq! (::std::mem::align_of::<ShouldNotDeriveHash>() , 1usize , + concat ! ( + "Alignment of " , stringify ! ( ShouldNotDeriveHash ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ShouldNotDeriveHash ) ) . a as * const _ + as usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( ShouldNotDeriveHash ) , + "::" , stringify ! ( a ) )); +} +impl Default for ShouldNotDeriveHash { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} diff --git a/tests/expectations/tests/derive-hash-blacklisting.rs b/tests/expectations/tests/derive-hash-blacklisting.rs index d24586be..5d1a8d37 100644 --- a/tests/expectations/tests/derive-hash-blacklisting.rs +++ b/tests/expectations/tests/derive-hash-blacklisting.rs @@ -8,7 +8,6 @@ /// This would derive(Hash, Eq, PartialEq) if it didn't contain a blacklisted type, /// causing us to conservatively avoid deriving hash/Eq/PartialEq for it. #[repr(C)] -#[derive(Debug, Copy)] pub struct WhitelistedOne { pub a: Blacklisted<::std::os::raw::c_int>, } @@ -24,15 +23,11 @@ fn bindgen_test_layout_WhitelistedOne() { "Alignment of field: " , stringify ! ( WhitelistedOne ) , "::" , stringify ! ( a ) )); } -impl Clone for WhitelistedOne { - fn clone(&self) -> Self { *self } -} impl Default for WhitelistedOne { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } /// This can't derive(Hash/Eq) even if it didn't contain a blacklisted type. #[repr(C)] -#[derive(Debug, Copy)] pub struct WhitelistedTwo { pub b: Blacklisted<f32>, } @@ -48,9 +43,6 @@ fn bindgen_test_layout_WhitelistedTwo() { "Alignment of field: " , stringify ! ( WhitelistedTwo ) , "::" , stringify ! ( b ) )); } -impl Clone for WhitelistedTwo { - fn clone(&self) -> Self { *self } -} impl Default for WhitelistedTwo { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } diff --git a/tests/expectations/tests/derive-partialeq-and-blacklist.rs b/tests/expectations/tests/derive-partialeq-and-blacklist.rs new file mode 100644 index 00000000..4aac3c8c --- /dev/null +++ b/tests/expectations/tests/derive-partialeq-and-blacklist.rs @@ -0,0 +1,30 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + +pub struct BlacklistMe(u8); + +/// Because this type contains a blacklisted type, it should not derive +/// PartialEq. +#[repr(C)] +pub struct ShouldNotDerivePartialEq { + pub a: BlacklistMe, +} +#[test] +fn bindgen_test_layout_ShouldNotDerivePartialEq() { + assert_eq!(::std::mem::size_of::<ShouldNotDerivePartialEq>() , 1usize , + concat ! ( + "Size of: " , stringify ! ( ShouldNotDerivePartialEq ) )); + assert_eq! (::std::mem::align_of::<ShouldNotDerivePartialEq>() , 1usize , + concat ! ( + "Alignment of " , stringify ! ( ShouldNotDerivePartialEq ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ShouldNotDerivePartialEq ) ) . a as * + const _ as usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( + ShouldNotDerivePartialEq ) , "::" , stringify ! ( a ) )); +} +impl Default for ShouldNotDerivePartialEq { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} diff --git a/tests/expectations/tests/doggo-or-null.rs b/tests/expectations/tests/doggo-or-null.rs new file mode 100644 index 00000000..292533d9 --- /dev/null +++ b/tests/expectations/tests/doggo-or-null.rs @@ -0,0 +1,65 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +#[derive(Debug, Default, Copy, Hash, PartialEq)] +pub struct Doggo { + pub x: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_Doggo() { + assert_eq!(::std::mem::size_of::<Doggo>() , 4usize , concat ! ( + "Size of: " , stringify ! ( Doggo ) )); + assert_eq! (::std::mem::align_of::<Doggo>() , 4usize , concat ! ( + "Alignment of " , stringify ! ( Doggo ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Doggo ) ) . x as * const _ as usize } , + 0usize , concat ! ( + "Alignment of field: " , stringify ! ( Doggo ) , "::" , + stringify ! ( x ) )); +} +impl Clone for Doggo { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Hash, PartialEq)] +pub struct Null { + pub _address: u8, +} +#[test] +fn bindgen_test_layout_Null() { + assert_eq!(::std::mem::size_of::<Null>() , 1usize , concat ! ( + "Size of: " , stringify ! ( Null ) )); + assert_eq! (::std::mem::align_of::<Null>() , 1usize , concat ! ( + "Alignment of " , stringify ! ( Null ) )); +} +impl Clone for Null { + fn clone(&self) -> Self { *self } +} +/// This type is an opaque union. Unions can't derive anything interesting like +/// Debug or Default, even if their layout can, because it would require knowing +/// which variant is in use. Opaque unions still end up as a `union` in the Rust +/// bindings, but they just have one variant. Even so, can't derive. We should +/// probably emit an opaque struct for opaque unions... but until then, we have +/// this test to make sure that opaque unions don't derive and still compile. +#[repr(C)] +#[derive(Copy)] +pub union DoggoOrNull { + pub _bindgen_opaque_blob: u32, +} +#[test] +fn bindgen_test_layout_DoggoOrNull() { + assert_eq!(::std::mem::size_of::<DoggoOrNull>() , 4usize , concat ! ( + "Size of: " , stringify ! ( DoggoOrNull ) )); + assert_eq! (::std::mem::align_of::<DoggoOrNull>() , 4usize , concat ! ( + "Alignment of " , stringify ! ( DoggoOrNull ) )); +} +impl Clone for DoggoOrNull { + fn clone(&self) -> Self { *self } +} +impl Default for DoggoOrNull { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} diff --git a/tests/expectations/tests/issue-584-stylo-template-analysis-panic.rs b/tests/expectations/tests/issue-584-stylo-template-analysis-panic.rs index 540b5e7f..d0ccacef 100644 --- a/tests/expectations/tests/issue-584-stylo-template-analysis-panic.rs +++ b/tests/expectations/tests/issue-584-stylo-template-analysis-panic.rs @@ -22,7 +22,6 @@ impl Clone for A { fn clone(&self) -> Self { *self } } #[repr(C)] -#[derive(Debug, Copy, Clone)] pub struct e<c> { pub d: RefPtr<c>, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<c>>, @@ -36,7 +35,6 @@ pub struct f { pub _address: u8, } #[repr(C)] -#[derive(Debug, Copy)] pub struct g { pub h: f, } @@ -51,14 +49,10 @@ fn bindgen_test_layout_g() { "Alignment of field: " , stringify ! ( g ) , "::" , stringify ! ( h ) )); } -impl Clone for g { - fn clone(&self) -> Self { *self } -} impl Default for g { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } #[repr(C)] -#[derive(Debug, Copy)] pub struct b { pub _base: g, } @@ -69,9 +63,6 @@ fn bindgen_test_layout_b() { assert_eq! (::std::mem::align_of::<b>() , 1usize , concat ! ( "Alignment of " , stringify ! ( b ) )); } -impl Clone for b { - fn clone(&self) -> Self { *self } -} impl Default for b { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } diff --git a/tests/expectations/tests/issue-645-cannot-find-type-T-in-this-scope.rs b/tests/expectations/tests/issue-645-cannot-find-type-T-in-this-scope.rs index d705ffa3..87228ec6 100644 --- a/tests/expectations/tests/issue-645-cannot-find-type-T-in-this-scope.rs +++ b/tests/expectations/tests/issue-645-cannot-find-type-T-in-this-scope.rs @@ -6,7 +6,6 @@ #[derive(Clone, Copy, Debug)] pub struct RefPtr<T>(T); #[repr(C)] -#[derive(Debug, Copy, Clone)] pub struct HasRefPtr<T> { pub refptr_member: RefPtr<HasRefPtr_TypedefOfT<T>>, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>, diff --git a/tests/expectations/tests/issue-662-part-2.rs b/tests/expectations/tests/issue-662-part-2.rs index 8225cf18..a1b97ca6 100644 --- a/tests/expectations/tests/issue-662-part-2.rs +++ b/tests/expectations/tests/issue-662-part-2.rs @@ -15,7 +15,6 @@ impl <T> Default for nsMainThreadPtrHolder<T> { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } #[repr(C)] -#[derive(Debug, Copy, Clone)] pub struct nsMainThreadPtrHandle<U> { pub mPtr: RefPtr<nsMainThreadPtrHolder<U>>, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<U>>, diff --git a/tests/expectations/tests/issue-944-derive-copy-and-blacklisting.rs b/tests/expectations/tests/issue-944-derive-copy-and-blacklisting.rs new file mode 100644 index 00000000..10e54056 --- /dev/null +++ b/tests/expectations/tests/issue-944-derive-copy-and-blacklisting.rs @@ -0,0 +1,27 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + +pub struct BlacklistMe(u8); + +/// Because this type contains a blacklisted type, it should not derive Copy. +#[repr(C)] +pub struct ShouldNotBeCopy { + pub a: BlacklistMe, +} +#[test] +fn bindgen_test_layout_ShouldNotBeCopy() { + assert_eq!(::std::mem::size_of::<ShouldNotBeCopy>() , 1usize , concat ! ( + "Size of: " , stringify ! ( ShouldNotBeCopy ) )); + assert_eq! (::std::mem::align_of::<ShouldNotBeCopy>() , 1usize , concat ! + ( "Alignment of " , stringify ! ( ShouldNotBeCopy ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const ShouldNotBeCopy ) ) . a as * const _ as + usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( ShouldNotBeCopy ) , + "::" , stringify ! ( a ) )); +} +impl Default for ShouldNotBeCopy { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} diff --git a/tests/expectations/tests/no-derive-debug.rs b/tests/expectations/tests/no-derive-debug.rs index 311b3767..f1616e64 100644 --- a/tests/expectations/tests/no-derive-debug.rs +++ b/tests/expectations/tests/no-derive-debug.rs @@ -9,7 +9,6 @@ /// and replacement for another type that doesn't implement it would prevent it /// from building if --no-derive-debug didn't work. #[repr(C)] -#[derive(Copy)] pub struct bar { pub foo: foo, pub baz: ::std::os::raw::c_int, @@ -31,9 +30,6 @@ fn bindgen_test_layout_bar() { "Alignment of field: " , stringify ! ( bar ) , "::" , stringify ! ( baz ) )); } -impl Clone for bar { - fn clone(&self) -> Self { *self } -} impl Default for bar { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } diff --git a/tests/expectations/tests/no-derive-default.rs b/tests/expectations/tests/no-derive-default.rs index c212f4bd..cdb89eb1 100644 --- a/tests/expectations/tests/no-derive-default.rs +++ b/tests/expectations/tests/no-derive-default.rs @@ -9,7 +9,6 @@ /// and replacement for another type that doesn't implement it would prevent it /// from building if --no-derive-default didn't work. #[repr(C)] -#[derive(Debug, Copy)] pub struct bar { pub foo: foo, pub baz: ::std::os::raw::c_int, @@ -31,6 +30,3 @@ fn bindgen_test_layout_bar() { "Alignment of field: " , stringify ! ( bar ) , "::" , stringify ! ( baz ) )); } -impl Clone for bar { - fn clone(&self) -> Self { *self } -} diff --git a/tests/expectations/tests/no-recursive-whitelisting.rs b/tests/expectations/tests/no-recursive-whitelisting.rs index e2aba543..30dc9e69 100644 --- a/tests/expectations/tests/no-recursive-whitelisting.rs +++ b/tests/expectations/tests/no-recursive-whitelisting.rs @@ -6,7 +6,6 @@ pub enum Bar {} #[repr(C)] -#[derive(Debug, Copy)] pub struct Foo { pub baz: *mut Bar, } @@ -22,9 +21,6 @@ fn bindgen_test_layout_Foo() { "Alignment of field: " , stringify ! ( Foo ) , "::" , stringify ! ( baz ) )); } -impl Clone for Foo { - fn clone(&self) -> Self { *self } -} impl Default for Foo { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } diff --git a/tests/expectations/tests/opaque-template-inst-member.rs b/tests/expectations/tests/opaque-template-inst-member.rs index 32995873..0bef4c86 100644 --- a/tests/expectations/tests/opaque-template-inst-member.rs +++ b/tests/expectations/tests/opaque-template-inst-member.rs @@ -5,7 +5,7 @@ #[repr(C)] -#[derive(Default, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] pub struct OpaqueTemplate { } /// This should not end up deriving Debug/Hash/PartialEq because its `mBlah` field cannot derive diff --git a/tests/headers/blacklist-and-impl-debug.hpp b/tests/headers/blacklist-and-impl-debug.hpp new file mode 100644 index 00000000..b4b39fe4 --- /dev/null +++ b/tests/headers/blacklist-and-impl-debug.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --impl-debug --blacklist-type BlacklistMe --raw-line 'pub struct BlacklistMe(u8);' + +struct BlacklistMe {}; + +/** + * Because this type contains a blacklisted type, it should not derive Debug. + */ +struct ShouldManuallyImplDebug { + BlacklistMe a; +}; diff --git a/tests/headers/derive-default-and-blacklist.hpp b/tests/headers/derive-default-and-blacklist.hpp new file mode 100644 index 00000000..7a2b7505 --- /dev/null +++ b/tests/headers/derive-default-and-blacklist.hpp @@ -0,0 +1,14 @@ +// bindgen-flags: --blacklist-type BlacklistMe --raw-line 'pub struct BlacklistMe(u8);' + +// Note that we do not explicitly provide the `--with-derive-default` flag +// above, since it is added by the test runner implicitly. + +struct BlacklistMe {}; + +/** + * Because this type contains a blacklisted type, it should not derive + * Default. Instead, we should emit a `mem::zeroed` implementation. + */ +struct ShouldNotDeriveDefault { + BlacklistMe a; +}; diff --git a/tests/headers/derive-hash-and-blacklist.hpp b/tests/headers/derive-hash-and-blacklist.hpp new file mode 100644 index 00000000..4b3a4a53 --- /dev/null +++ b/tests/headers/derive-hash-and-blacklist.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --with-derive-hash --blacklist-type BlacklistMe --raw-line 'pub struct BlacklistMe(u8);' + +struct BlacklistMe {}; + +/** + * Because this type contains a blacklisted type, it should not derive Hash. + */ +struct ShouldNotDeriveHash { + BlacklistMe a; +}; diff --git a/tests/headers/derive-partialeq-and-blacklist.hpp b/tests/headers/derive-partialeq-and-blacklist.hpp new file mode 100644 index 00000000..a996eee8 --- /dev/null +++ b/tests/headers/derive-partialeq-and-blacklist.hpp @@ -0,0 +1,11 @@ +// bindgen-flags: --with-derive-partialeq --blacklist-type BlacklistMe --raw-line 'pub struct BlacklistMe(u8);' + +struct BlacklistMe {}; + +/** + * Because this type contains a blacklisted type, it should not derive + * PartialEq. + */ +struct ShouldNotDerivePartialEq { + BlacklistMe a; +}; diff --git a/tests/headers/doggo-or-null.hpp b/tests/headers/doggo-or-null.hpp new file mode 100644 index 00000000..9146e189 --- /dev/null +++ b/tests/headers/doggo-or-null.hpp @@ -0,0 +1,20 @@ +// bindgen-flags: --opaque-type DoggoOrNull --with-derive-partialeq --with-derive-hash -- -std=c++14 + +class Doggo { + int x; +}; + +class Null {}; + +/** + * This type is an opaque union. Unions can't derive anything interesting like + * Debug or Default, even if their layout can, because it would require knowing + * which variant is in use. Opaque unions still end up as a `union` in the Rust + * bindings, but they just have one variant. Even so, can't derive. We should + * probably emit an opaque struct for opaque unions... but until then, we have + * this test to make sure that opaque unions don't derive and still compile. + */ +union DoggoOrNull { + Doggo doggo; + Null none; +}; diff --git a/tests/headers/issue-944-derive-copy-and-blacklisting.hpp b/tests/headers/issue-944-derive-copy-and-blacklisting.hpp new file mode 100644 index 00000000..657e0d84 --- /dev/null +++ b/tests/headers/issue-944-derive-copy-and-blacklisting.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --blacklist-type BlacklistMe --raw-line 'pub struct BlacklistMe(u8);' + +struct BlacklistMe {}; + +/** + * Because this type contains a blacklisted type, it should not derive Copy. + */ +struct ShouldNotBeCopy { + BlacklistMe a; +}; |