Skip to content

Commit 978846c

Browse files
author
bors-servo
authored
Auto merge of rust-lang#61 - emilio:unions, r=nox
Union support Built on top of rust-lang#58, this adds support for untagged unions if not running under the `--no-unstable-rust-flag`. The last commit is an example try run passing with this, but should be reverted (and the `--no-unstable-rust` flag passed by default to our harness). This depends on serde-deprecated/aster#109. r? @nox
2 parents 33debb3 + 9e1ddf9 commit 978846c

File tree

8 files changed

+78
-84
lines changed

8 files changed

+78
-84
lines changed

Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,28 @@ doc = false
1919
name = "bindgen"
2020

2121
[build-dependencies]
22-
quasi_codegen = "0.15"
22+
quasi_codegen = "0.20"
2323

2424
[dependencies]
2525
clang-sys = "0.8.0"
2626
libc = "0.2"
2727
log = "0.3"
2828
env_logger = "0.3"
2929
rustc-serialize = "0.3.19"
30-
syntex_syntax = "0.43"
30+
syntex_syntax = "0.44"
3131
regex = "0.1"
3232

3333
[dependencies.aster]
3434
features = ["with-syntex"]
35-
version = "0.26"
35+
version = "0.28"
3636

3737
[dependencies.clippy]
3838
optional = true
3939
version = "*"
4040

4141
[dependencies.quasi]
4242
features = ["with-syntex"]
43-
version = "0.19"
43+
version = "0.20"
4444

4545
[features]
4646
llvm_stable = []

src/codegen/helpers.rs

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
use aster;
44
use ir::layout::Layout;
55
use syntax::ast;
6-
use syntax::codemap::respan;
76
use syntax::ptr::P;
87

98

@@ -68,46 +67,7 @@ impl BlobTyBuilder {
6867
if data_len == 1 {
6968
inner_ty
7069
} else {
71-
ArrayTyBuilder::new().with_len(data_len).build(inner_ty)
70+
aster::ty::TyBuilder::new().array(data_len).build(inner_ty)
7271
}
7372
}
7473
}
75-
76-
pub struct ArrayTyBuilder {
77-
len: usize,
78-
}
79-
80-
impl ArrayTyBuilder {
81-
pub fn new() -> Self {
82-
ArrayTyBuilder {
83-
len: 0,
84-
}
85-
}
86-
87-
pub fn with_len(mut self, len: usize) -> Self {
88-
self.len = len;
89-
self
90-
}
91-
92-
pub fn build(self, ty: P<ast::Ty>) -> P<ast::Ty> {
93-
use syntax::codemap::DUMMY_SP;
94-
let size =
95-
ast::LitKind::Int(self.len as u64,
96-
ast::LitIntType::Unsigned(ast::UintTy::Us));
97-
let size = ast::ExprKind::Lit(P(respan(DUMMY_SP, size)));
98-
let array_kind = ast::TyKind::FixedLengthVec(ty,
99-
P(ast::Expr {
100-
id: ast::DUMMY_NODE_ID,
101-
node: size,
102-
span: DUMMY_SP,
103-
attrs: ast::ThinVec::new(),
104-
})
105-
);
106-
107-
P(ast::Ty {
108-
id: ast::DUMMY_NODE_ID,
109-
node: array_kind,
110-
span: DUMMY_SP,
111-
})
112-
}
113-
}

src/codegen/mod.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
mod helpers;
22

3-
use self::helpers::{attributes, ArrayTyBuilder, BlobTyBuilder};
3+
use self::helpers::{attributes, BlobTyBuilder};
44

55
use ir::context::BindgenContext;
66
use ir::item::{Item, ItemId, ItemCanonicalName, ItemCanonicalPath};
@@ -546,13 +546,14 @@ impl CodeGenerator for CompInfo {
546546
attributes.push(attributes::repr("C"));
547547
}
548548

549+
let is_union = self.kind() == CompKind::Union;
549550
let mut derives = vec![];
550551
let ty = item.expect_type();
551552
if ty.can_derive_debug(ctx) {
552553
derives.push("Debug");
553554
}
554555

555-
if ty.can_derive_copy(ctx) && !item.annotations().disallow_copy() {
556+
if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() {
556557
derives.push("Copy");
557558
if !applicable_template_args.is_empty() {
558559
// FIXME: This requires extra logic if you have a big array in a
@@ -573,9 +574,15 @@ impl CodeGenerator for CompInfo {
573574

574575
let mut template_args_used = vec![false; applicable_template_args.len()];
575576
let canonical_name = item.canonical_name(ctx);
576-
let builder = aster::AstBuilder::new().item().pub_()
577-
.with_attrs(attributes)
578-
.struct_(&canonical_name);
577+
let builder = if is_union && ctx.options().unstable_rust {
578+
aster::AstBuilder::new().item().pub_()
579+
.with_attrs(attributes)
580+
.union_(&canonical_name)
581+
} else {
582+
aster::AstBuilder::new().item().pub_()
583+
.with_attrs(attributes)
584+
.struct_(&canonical_name)
585+
};
579586

580587
// Generate the vtable from the method list if appropriate.
581588
// TODO: I don't know how this could play with virtual methods that are
@@ -633,8 +640,6 @@ impl CodeGenerator for CompInfo {
633640
.pub_().build_ty(inner);
634641
fields.push(field);
635642
}
636-
637-
let is_union = self.kind() == CompKind::Union;
638643
if is_union {
639644
result.saw_union();
640645
}
@@ -705,7 +710,8 @@ impl CodeGenerator for CompInfo {
705710

706711
let ty = field.ty().to_rust_ty(ctx);
707712

708-
let ty = if is_union {
713+
// NB: In unstable rust we use proper `union` types.
714+
let ty = if is_union && !ctx.options().unstable_rust {
709715
quote_ty!(ctx.ext_cx(), __BindgenUnionField<$ty>)
710716
} else {
711717
ty
@@ -817,7 +823,7 @@ impl CodeGenerator for CompInfo {
817823
}
818824
debug_assert!(current_bitfield_fields.is_empty());
819825

820-
if is_union {
826+
if is_union && !ctx.options().unstable_rust {
821827
let layout = layout.expect("Unable to get layout information?");
822828
let ty = BlobTyBuilder::new(layout).build();
823829
let field = StructFieldBuilder::named("bindgen_union_field").pub_()
@@ -1311,7 +1317,7 @@ impl ToRustTy for Type {
13111317
// can't do better right now. We should be able to use
13121318
// i128/u128 when they're available.
13131319
IntKind::U128 |
1314-
IntKind::I128 => ArrayTyBuilder::new().with_len(2).build(aster::ty::TyBuilder::new().u64()),
1320+
IntKind::I128 => aster::ty::TyBuilder::new().array(2).u64(),
13151321
}
13161322
}
13171323
TypeKind::Float(fk) => {
@@ -1330,7 +1336,7 @@ impl ToRustTy for Type {
13301336
}
13311337
TypeKind::Array(item, len) => {
13321338
let inner = item.to_rust_ty(ctx);
1333-
ArrayTyBuilder::new().with_len(len).build(inner)
1339+
aster::ty::TyBuilder::new().array(len).build(inner)
13341340
}
13351341
TypeKind::Enum(..) => {
13361342
let path = item.canonical_path(ctx);
@@ -1375,7 +1381,7 @@ impl ToRustTy for Type {
13751381
}
13761382
None => {
13771383
warn!("Couldn't compute layout for a type with non \
1378-
template params or opaque, expect dragons!");
1384+
type template params or opaque, expect dragons!");
13791385
aster::AstBuilder::new().ty().unit()
13801386
}
13811387
}
@@ -1756,7 +1762,7 @@ pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> {
17561762
}
17571763
let saw_union = result.saw_union;
17581764
let mut result = result.items;
1759-
if saw_union {
1765+
if saw_union && !context.options().unstable_rust {
17601766
utils::prepend_union_types(context, &mut result);
17611767
}
17621768
result

src/ir/comp.rs

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,10 @@ impl CompInfo {
215215
}
216216

217217
if self.kind == CompKind::Union {
218+
if type_resolver.options().unstable_rust {
219+
return false;
220+
}
221+
218222
let layout = layout.unwrap_or_else(Layout::zero);
219223
let size_divisor = cmp::max(1, layout.align);
220224
return layout.size / size_divisor <= RUST_DERIVE_IN_ARRAY_LIMIT;
@@ -223,13 +227,21 @@ impl CompInfo {
223227
self.detect_derive_debug_cycle.set(true);
224228

225229
let can_derive_debug =
230+
self.base_members.iter().all(|ty| {
231+
type_resolver.resolve_type(*ty)
232+
.can_derive_debug(type_resolver)
233+
}) &&
226234
self.template_args.iter().all(|ty| {
227235
type_resolver.resolve_type(*ty)
228236
.can_derive_debug(type_resolver)
229237
}) &&
230238
self.fields.iter().all(|field| {
231239
type_resolver.resolve_type(field.ty)
232240
.can_derive_debug(type_resolver)
241+
}) &&
242+
self.ref_template.map_or(true, |template| {
243+
type_resolver.resolve_type(template)
244+
.can_derive_debug(type_resolver)
233245
});
234246

235247
self.detect_derive_debug_cycle.set(false);
@@ -287,31 +299,39 @@ impl CompInfo {
287299
has_destructor
288300
}
289301

290-
pub fn can_derive_copy(&self, type_resolver: &TypeResolver) -> bool {
302+
pub fn can_derive_copy(&self, type_resolver: &TypeResolver, item: &Item) -> bool {
291303
// NOTE: Take into account that while unions in C and C++ are copied by
292304
// default, the may have an explicit destructor in C++, so we can't
293305
// defer this check just for the union case.
294306
if self.has_destructor(type_resolver) {
295307
return false;
296308
}
297309

298-
match self.kind {
299-
CompKind::Union => true,
300-
CompKind::Struct => {
301-
// With template args, use a safe subset of the types,
302-
// since copyability depends on the types itself.
303-
self.ref_template.as_ref().map_or(true, |t| {
304-
type_resolver.resolve_type(*t).can_derive_copy(type_resolver)
305-
}) &&
306-
self.base_members.iter().all(|t| {
307-
type_resolver.resolve_type(*t).can_derive_copy(type_resolver)
308-
}) &&
309-
self.fields.iter().all(|field| {
310-
type_resolver.resolve_type(field.ty)
311-
.can_derive_copy(type_resolver)
312-
})
310+
if self.kind == CompKind::Union {
311+
if !type_resolver.options().unstable_rust {
312+
return true;
313+
}
314+
315+
// https://github.com/rust-lang/rust/issues/36640
316+
if !self.template_args.is_empty() ||
317+
self.ref_template.is_some() ||
318+
!item.applicable_template_args(type_resolver).is_empty() {
319+
return false;
313320
}
314321
}
322+
323+
// With template args, use a safe subset of the types,
324+
// since copyability depends on the types itself.
325+
self.ref_template.as_ref().map_or(true, |t| {
326+
type_resolver.resolve_item(*t).can_derive_copy(type_resolver)
327+
}) &&
328+
self.base_members.iter().all(|t| {
329+
type_resolver.resolve_item(*t).can_derive_copy(type_resolver)
330+
}) &&
331+
self.fields.iter().all(|field| {
332+
type_resolver.resolve_item(field.ty)
333+
.can_derive_copy(type_resolver)
334+
})
315335
}
316336

317337
pub fn is_template_specialization(&self) -> bool {

src/ir/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ impl<'ctx> BindgenContext<'ctx> {
333333

334334
let cfg = ExpansionConfig::default("xxx".to_owned());
335335
let sess = parse::ParseSess::new();
336-
let mut loader = base::DummyMacroLoader;
336+
let mut loader = base::DummyResolver;
337337
let mut ctx =
338338
GenContext(base::ExtCtxt::new(&sess, vec![], cfg, &mut loader));
339339

src/ir/item.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,14 @@ impl Item {
338338
_ => None,
339339
}
340340
}
341+
342+
pub fn can_derive_copy(&self, ctx: &BindgenContext) -> bool {
343+
self.expect_type().can_derive_copy(ctx, self)
344+
}
345+
346+
pub fn can_derive_copy_in_array(&self, ctx: &BindgenContext) -> bool {
347+
self.expect_type().can_derive_copy_in_array(ctx, self)
348+
}
341349
}
342350

343351
impl ClangItemParser for Item {

src/ir/ty.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -175,32 +175,32 @@ impl Type {
175175
// is an error.
176176
//
177177
// That's the point of the existence of can_derive_copy_in_array().
178-
pub fn can_derive_copy_in_array(&self, type_resolver: &TypeResolver) -> bool {
178+
pub fn can_derive_copy_in_array(&self, type_resolver: &TypeResolver, item: &Item) -> bool {
179179
match self.kind {
180180
TypeKind::ResolvedTypeRef(t) |
181181
TypeKind::Alias(_, t) |
182182
TypeKind::Array(t, _) => {
183-
type_resolver.resolve_type(t)
183+
type_resolver.resolve_item(t)
184184
.can_derive_copy_in_array(type_resolver)
185185
}
186186
TypeKind::Named(..) => false,
187-
_ => self.can_derive_copy(type_resolver),
187+
_ => self.can_derive_copy(type_resolver, item),
188188
}
189189
}
190190

191-
pub fn can_derive_copy(&self, type_resolver: &TypeResolver) -> bool {
191+
pub fn can_derive_copy(&self, type_resolver: &TypeResolver, item: &Item) -> bool {
192192
!self.is_opaque(type_resolver) && match self.kind {
193193
TypeKind::Array(t, len) => {
194194
len <= RUST_DERIVE_IN_ARRAY_LIMIT &&
195-
type_resolver.resolve_type(t).can_derive_copy_in_array(type_resolver)
195+
type_resolver.resolve_item(t).can_derive_copy_in_array(type_resolver)
196196
}
197197
TypeKind::ResolvedTypeRef(t) |
198198
TypeKind::TemplateRef(t, _) |
199199
TypeKind::Alias(_, t) => {
200-
type_resolver.resolve_type(t).can_derive_copy(type_resolver)
200+
type_resolver.resolve_item(t).can_derive_copy(type_resolver)
201201
}
202202
TypeKind::Comp(ref info) => {
203-
info.can_derive_copy(type_resolver)
203+
info.can_derive_copy(type_resolver, item)
204204
}
205205
_ => true,
206206
}

tests/tools/run-bindgen.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@
1717

1818
[_, bindgen_path, c_path, rust_path] = sys.argv
1919

20-
flags = []
20+
flags = ["--no-unstable-rust"]
2121

2222
with open(sys.argv[2]) as f:
2323
for line in f:
2424
if line.startswith(BINDGEN_FLAGS_PREFIX):
25-
flags = line.strip().split(BINDGEN_FLAGS_PREFIX)[1].split(" ")
25+
flags.extend(line.strip().split(BINDGEN_FLAGS_PREFIX)[1].split(" "))
2626
break
2727

2828
base_command = [bindgen_path, "-o", rust_path]

0 commit comments

Comments
 (0)