Skip to content

Commit b2d953a

Browse files
committed
Union support.
1 parent efcc777 commit b2d953a

File tree

5 files changed

+68
-34
lines changed

5 files changed

+68
-34
lines changed

src/codegen/mod.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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_()
@@ -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
}

0 commit comments

Comments
 (0)