diff options
-rw-r--r-- | src/ir/analysis/derive_copy.rs | 32 | ||||
-rw-r--r-- | tests/expectations/tests/issue-944-derive-copy-and-blacklisting.rs | 28 | ||||
-rw-r--r-- | tests/headers/issue-944-derive-copy-and-blacklisting.hpp | 10 |
3 files changed, 62 insertions, 8 deletions
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/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..ed696c94 --- /dev/null +++ b/tests/expectations/tests/issue-944-derive-copy-and-blacklisting.rs @@ -0,0 +1,28 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + +#[derive(Debug)] pub struct BlacklistMe(u8); + +/// Because this type contains a blacklisted type, it should not derive Copy. +#[repr(C)] +#[derive(Debug)] +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/headers/issue-944-derive-copy-and-blacklisting.hpp b/tests/headers/issue-944-derive-copy-and-blacklisting.hpp new file mode 100644 index 00000000..7e033728 --- /dev/null +++ b/tests/headers/issue-944-derive-copy-and-blacklisting.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --blacklist-type BlacklistMe --raw-line '#[derive(Debug)] pub struct BlacklistMe(u8);' + +struct BlacklistMe {}; + +/** + * Because this type contains a blacklisted type, it should not derive Copy. + */ +struct ShouldNotBeCopy { + BlacklistMe a; +}; |