Skip to content

Commit 716cec7

Browse files
author
bors-servo
authored
Auto merge of #1099 - hallfox:no-copy, r=fitzgen
Resolve #962 - implement --no-copy with tests Allows types to not have the copy trait automatically derived.
2 parents 1cb1101 + f7e370a commit 716cec7

11 files changed

+186
-0
lines changed

book/src/nocopy.md

+10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ Clone)]` to a translated type definition will compile, it still shouldn't do
66
that for reasons it can't know. In these cases, the `nocopy` annotation can be
77
used to prevent bindgen to autoderive the `Copy` and `Clone` traits for a type.
88

9+
###Library
10+
11+
* [`bindgen::Builder::no_copy`](https://docs.rs/bindgen/0.23.1/bindgen/struct.Builder.html#method.no_copy)
12+
13+
### Command Line
14+
15+
* `--no-copy <regex>`
16+
17+
### Annotations
18+
919
```c
1020
/**
1121
* Although bindgen can't know, this struct is not safe to move because pthread

src/ir/analysis/derive_copy.rs

+4
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> {
143143
}
144144
};
145145

146+
if self.ctx.no_copy_by_name(&item) {
147+
return self.insert(id);
148+
}
149+
146150
if item.is_opaque(self.ctx, &()) {
147151
let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
148152
l.opaque().can_trivially_derive_copy()

src/ir/context.rs

+6
Original file line numberDiff line numberDiff line change
@@ -2489,6 +2489,12 @@ impl BindgenContext {
24892489
let name = item.canonical_path(self)[1..].join("::");
24902490
self.options().no_partialeq_types.matches(&name)
24912491
}
2492+
2493+
/// Check if `--no-copy` flag is enabled for this item.
2494+
pub fn no_copy_by_name(&self, item: &Item) -> bool {
2495+
let name = item.canonical_path(self)[1..].join("::");
2496+
self.options().no_copy_types.matches(&name)
2497+
}
24922498
}
24932499

24942500
/// A builder struct for configuring item resolution options.

src/lib.rs

+26
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,20 @@ impl Builder {
522522
})
523523
.count();
524524

525+
self.options
526+
.no_copy_types
527+
.get_items()
528+
.iter()
529+
.map(|item| {
530+
output_vector.push("--no-copy".into());
531+
output_vector.push(
532+
item.trim_left_matches("^")
533+
.trim_right_matches("$")
534+
.into(),
535+
);
536+
})
537+
.count();
538+
525539
output_vector
526540
}
527541

@@ -1158,6 +1172,13 @@ impl Builder {
11581172
self.options.no_partialeq_types.insert(arg);
11591173
self
11601174
}
1175+
1176+
/// Don't derive `Copy` for a given type. Regular
1177+
/// expressions are supported.
1178+
pub fn no_copy(mut self, arg: String) -> Self {
1179+
self.options.no_copy_types.insert(arg);
1180+
self
1181+
}
11611182
}
11621183

11631184
/// Configuration options for generated bindings.
@@ -1345,6 +1366,9 @@ struct BindgenOptions {
13451366

13461367
/// The set of types that we should not derive `PartialEq` for.
13471368
no_partialeq_types: RegexSet,
1369+
1370+
/// The set of types that we should not derive `Copy` for.
1371+
no_copy_types: RegexSet,
13481372
}
13491373

13501374
/// TODO(emilio): This is sort of a lie (see the error message that results from
@@ -1363,6 +1387,7 @@ impl BindgenOptions {
13631387
self.constified_enum_modules.build();
13641388
self.rustified_enums.build();
13651389
self.no_partialeq_types.build();
1390+
self.no_copy_types.build();
13661391
}
13671392

13681393
/// Update rust target version
@@ -1434,6 +1459,7 @@ impl Default for BindgenOptions {
14341459
rustfmt_bindings: true,
14351460
rustfmt_configuration_file: None,
14361461
no_partialeq_types: Default::default(),
1462+
no_copy_types: Default::default(),
14371463
}
14381464
}
14391465
}

src/options.rs

+13
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,13 @@ where
285285
.takes_value(true)
286286
.multiple(true)
287287
.number_of_values(1),
288+
Arg::with_name("no-copy")
289+
.long("no-copy")
290+
.help("Avoid deriving Copy for types matching <regex>.")
291+
.value_name("regex")
292+
.takes_value(true)
293+
.multiple(true)
294+
.number_of_values(1),
288295
]) // .args()
289296
.get_matches_from(args);
290297

@@ -579,6 +586,12 @@ where
579586
}
580587
}
581588

589+
if let Some(no_partialeq) = matches.values_of("no-copy") {
590+
for regex in no_partialeq {
591+
builder = builder.no_copy(String::from(regex));
592+
}
593+
}
594+
582595
let verbose = matches.is_present("verbose");
583596

584597
Ok((builder, output, verbose))
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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+
7+
#[repr(C)]
8+
#[derive(Debug, Default)]
9+
pub struct NoCopy {
10+
pub _bindgen_opaque_blob: u32,
11+
}
12+
#[test]
13+
fn bindgen_test_layout_NoCopy() {
14+
assert_eq!(
15+
::std::mem::size_of::<NoCopy>(),
16+
4usize,
17+
concat!("Size of: ", stringify!(NoCopy))
18+
);
19+
assert_eq!(
20+
::std::mem::align_of::<NoCopy>(),
21+
4usize,
22+
concat!("Alignment of ", stringify!(NoCopy))
23+
);
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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+
7+
#[repr(C)]
8+
#[derive(Debug, Default)]
9+
pub struct NoCopy {
10+
pub i: ::std::os::raw::c_int,
11+
}
12+
#[test]
13+
fn bindgen_test_layout_NoCopy() {
14+
assert_eq!(
15+
::std::mem::size_of::<NoCopy>(),
16+
4usize,
17+
concat!("Size of: ", stringify!(NoCopy))
18+
);
19+
assert_eq!(
20+
::std::mem::align_of::<NoCopy>(),
21+
4usize,
22+
concat!("Alignment of ", stringify!(NoCopy))
23+
);
24+
assert_eq!(
25+
unsafe { &(*(0 as *const NoCopy)).i as *const _ as usize },
26+
0usize,
27+
concat!(
28+
"Alignment of field: ",
29+
stringify!(NoCopy),
30+
"::",
31+
stringify!(i)
32+
)
33+
);
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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+
7+
#[repr(C)]
8+
#[derive(Debug, Default)]
9+
pub struct NoCopy {
10+
pub _address: u8,
11+
}
12+
#[test]
13+
fn bindgen_test_layout_NoCopy() {
14+
assert_eq!(
15+
::std::mem::size_of::<NoCopy>(),
16+
1usize,
17+
concat!("Size of: ", stringify!(NoCopy))
18+
);
19+
assert_eq!(
20+
::std::mem::align_of::<NoCopy>(),
21+
1usize,
22+
concat!("Alignment of ", stringify!(NoCopy))
23+
);
24+
}
25+
#[repr(C)]
26+
#[derive(Debug, Default)]
27+
pub struct WhitelistMe {
28+
pub a: NoCopy,
29+
}
30+
#[test]
31+
fn bindgen_test_layout_WhitelistMe() {
32+
assert_eq!(
33+
::std::mem::size_of::<WhitelistMe>(),
34+
1usize,
35+
concat!("Size of: ", stringify!(WhitelistMe))
36+
);
37+
assert_eq!(
38+
::std::mem::align_of::<WhitelistMe>(),
39+
1usize,
40+
concat!("Alignment of ", stringify!(WhitelistMe))
41+
);
42+
assert_eq!(
43+
unsafe { &(*(0 as *const WhitelistMe)).a as *const _ as usize },
44+
0usize,
45+
concat!(
46+
"Alignment of field: ",
47+
stringify!(WhitelistMe),
48+
"::",
49+
stringify!(a)
50+
)
51+
);
52+
}

tests/headers/no_copy_opaque.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// bindgen-flags: --opaque-type "NoCopy" --no-copy "NoCopy"
2+
3+
class NoCopy {
4+
int i;
5+
};

tests/headers/no_copy_whitelisted.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// bindgen-flags: --whitelist-type "NoCopy" --no-copy "NoCopy"
2+
3+
class NoCopy {
4+
int i;
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// bindgen-flags: --whitelist-type "WhitelistMe" --no-copy "NoCopy"
2+
3+
struct NoCopy {};
4+
5+
class WhitelistMe {
6+
NoCopy a;
7+
};

0 commit comments

Comments
 (0)