Skip to content

Commit 931edfc

Browse files
committed
Do not derive Copy for blacklisted types
Presumably they are blacklisted because we can't understand them properly, so be pessimistic about what we can derive for it. Fixes #944.
1 parent d23db77 commit 931edfc

File tree

3 files changed

+62
-8
lines changed

3 files changed

+62
-8
lines changed

src/ir/analysis/derive_copy.rs

+24-8
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ impl<'ctx, 'gen> CannotDeriveCopy<'ctx, 'gen> {
8888

8989
ConstrainResult::Changed
9090
}
91+
92+
/// A type is not `Copy` if we've determined it is not copy, or if it is
93+
/// blacklisted.
94+
fn is_not_copy(&self, id: ItemId) -> bool {
95+
self.cannot_derive_copy.contains(&id) ||
96+
!self.ctx.whitelisted_items().contains(&id)
97+
}
9198
}
9299

93100
impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> {
@@ -118,6 +125,15 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> {
118125
return ConstrainResult::Same;
119126
}
120127

128+
// If an item is reachable from the whitelisted items set, but isn't
129+
// itself whitelisted, then it must be blacklisted. We assume that
130+
// blacklisted items are not `Copy`, since they are presumably
131+
// blacklisted because they are too complicated for us to understand.
132+
if !self.ctx.whitelisted_items().contains(&id) {
133+
trace!(" blacklisted items are assumed not to be Copy");
134+
return ConstrainResult::Same;
135+
}
136+
121137
let item = self.ctx.resolve_item(id);
122138
let ty = match item.as_type() {
123139
Some(ty) => ty,
@@ -163,7 +179,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> {
163179
}
164180

165181
TypeKind::Array(t, len) => {
166-
let cant_derive_copy = self.cannot_derive_copy.contains(&t);
182+
let cant_derive_copy = self.is_not_copy(t);
167183
if cant_derive_copy {
168184
trace!(
169185
" arrays of T for which we cannot derive Copy \
@@ -184,7 +200,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> {
184200
TypeKind::ResolvedTypeRef(t) |
185201
TypeKind::TemplateAlias(t, _) |
186202
TypeKind::Alias(t) => {
187-
let cant_derive_copy = self.cannot_derive_copy.contains(&t);
203+
let cant_derive_copy = self.is_not_copy(t);
188204
if cant_derive_copy {
189205
trace!(
190206
" arrays of T for which we cannot derive Copy \
@@ -237,7 +253,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> {
237253

238254
let bases_cannot_derive =
239255
info.base_members().iter().any(|base| {
240-
self.cannot_derive_copy.contains(&base.ty)
256+
self.is_not_copy(base.ty)
241257
});
242258
if bases_cannot_derive {
243259
trace!(
@@ -250,11 +266,11 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> {
250266
let fields_cannot_derive =
251267
info.fields().iter().any(|f| match *f {
252268
Field::DataMember(ref data) => {
253-
self.cannot_derive_copy.contains(&data.ty())
269+
self.is_not_copy(data.ty())
254270
}
255271
Field::Bitfields(ref bfu) => {
256272
bfu.bitfields().iter().any(|b| {
257-
self.cannot_derive_copy.contains(&b.ty())
273+
self.is_not_copy(b.ty())
258274
})
259275
}
260276
});
@@ -270,7 +286,7 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> {
270286
TypeKind::TemplateInstantiation(ref template) => {
271287
let args_cannot_derive =
272288
template.template_arguments().iter().any(|arg| {
273-
self.cannot_derive_copy.contains(&arg)
289+
self.is_not_copy(*arg)
274290
});
275291
if args_cannot_derive {
276292
trace!(
@@ -284,8 +300,8 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> {
284300
!template.template_definition().is_opaque(self.ctx, &()),
285301
"The early ty.is_opaque check should have handled this case"
286302
);
287-
let def_cannot_derive = self.cannot_derive_copy.contains(
288-
&template.template_definition(),
303+
let def_cannot_derive = self.is_not_copy(
304+
template.template_definition(),
289305
);
290306
if def_cannot_derive {
291307
trace!(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
5+
6+
#[derive(Debug)] pub struct BlacklistMe(u8);
7+
8+
/// Because this type contains a blacklisted type, it should not derive Copy.
9+
#[repr(C)]
10+
#[derive(Debug)]
11+
pub struct ShouldNotBeCopy {
12+
pub a: BlacklistMe,
13+
}
14+
#[test]
15+
fn bindgen_test_layout_ShouldNotBeCopy() {
16+
assert_eq!(::std::mem::size_of::<ShouldNotBeCopy>() , 1usize , concat ! (
17+
"Size of: " , stringify ! ( ShouldNotBeCopy ) ));
18+
assert_eq! (::std::mem::align_of::<ShouldNotBeCopy>() , 1usize , concat !
19+
( "Alignment of " , stringify ! ( ShouldNotBeCopy ) ));
20+
assert_eq! (unsafe {
21+
& ( * ( 0 as * const ShouldNotBeCopy ) ) . a as * const _ as
22+
usize } , 0usize , concat ! (
23+
"Alignment of field: " , stringify ! ( ShouldNotBeCopy ) ,
24+
"::" , stringify ! ( a ) ));
25+
}
26+
impl Default for ShouldNotBeCopy {
27+
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// bindgen-flags: --blacklist-type BlacklistMe --raw-line '#[derive(Debug)] pub struct BlacklistMe(u8);'
2+
3+
struct BlacklistMe {};
4+
5+
/**
6+
* Because this type contains a blacklisted type, it should not derive Copy.
7+
*/
8+
struct ShouldNotBeCopy {
9+
BlacklistMe a;
10+
};

0 commit comments

Comments
 (0)