diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/codegen/mod.rs | 26 | ||||
-rw-r--r-- | src/ir/comp.rs | 52 | ||||
-rw-r--r-- | src/ir/context.rs | 2 | ||||
-rw-r--r-- | src/ir/item.rs | 8 | ||||
-rw-r--r-- | src/ir/ty.rs | 14 |
5 files changed, 68 insertions, 34 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 36f20689..d95364a2 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -546,13 +546,14 @@ impl CodeGenerator for CompInfo { attributes.push(attributes::repr("C")); } + let is_union = self.kind() == CompKind::Union; let mut derives = vec![]; let ty = item.expect_type(); if ty.can_derive_debug(ctx) { derives.push("Debug"); } - if ty.can_derive_copy(ctx) && !item.annotations().disallow_copy() { + if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() { derives.push("Copy"); if !applicable_template_args.is_empty() { // FIXME: This requires extra logic if you have a big array in a @@ -573,9 +574,15 @@ impl CodeGenerator for CompInfo { let mut template_args_used = vec![false; applicable_template_args.len()]; let canonical_name = item.canonical_name(ctx); - let builder = aster::AstBuilder::new().item().pub_() - .with_attrs(attributes) - .struct_(&canonical_name); + let builder = if is_union && ctx.options().unstable_rust { + aster::AstBuilder::new().item().pub_() + .with_attrs(attributes) + .union_(&canonical_name) + } else { + aster::AstBuilder::new().item().pub_() + .with_attrs(attributes) + .struct_(&canonical_name) + }; // Generate the vtable from the method list if appropriate. // TODO: I don't know how this could play with virtual methods that are @@ -633,8 +640,6 @@ impl CodeGenerator for CompInfo { .pub_().build_ty(inner); fields.push(field); } - - let is_union = self.kind() == CompKind::Union; if is_union { result.saw_union(); } @@ -705,7 +710,8 @@ impl CodeGenerator for CompInfo { let ty = field.ty().to_rust_ty(ctx); - let ty = if is_union { + // NB: In unstable rust we use proper `union` types. + let ty = if is_union && !ctx.options().unstable_rust { quote_ty!(ctx.ext_cx(), __BindgenUnionField<$ty>) } else { ty @@ -817,7 +823,7 @@ impl CodeGenerator for CompInfo { } debug_assert!(current_bitfield_fields.is_empty()); - if is_union { + if is_union && !ctx.options().unstable_rust { let layout = layout.expect("Unable to get layout information?"); let ty = BlobTyBuilder::new(layout).build(); let field = StructFieldBuilder::named("bindgen_union_field").pub_() @@ -1375,7 +1381,7 @@ impl ToRustTy for Type { } None => { warn!("Couldn't compute layout for a type with non \ - template params or opaque, expect dragons!"); + type template params or opaque, expect dragons!"); aster::AstBuilder::new().ty().unit() } } @@ -1756,7 +1762,7 @@ pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> { } let saw_union = result.saw_union; let mut result = result.items; - if saw_union { + if saw_union && !context.options().unstable_rust { utils::prepend_union_types(context, &mut result); } result diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 1e6bf555..d31b7adf 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -215,6 +215,10 @@ impl CompInfo { } if self.kind == CompKind::Union { + if type_resolver.options().unstable_rust { + return false; + } + let layout = layout.unwrap_or_else(Layout::zero); let size_divisor = cmp::max(1, layout.align); return layout.size / size_divisor <= RUST_DERIVE_IN_ARRAY_LIMIT; @@ -223,6 +227,10 @@ impl CompInfo { self.detect_derive_debug_cycle.set(true); let can_derive_debug = + self.base_members.iter().all(|ty| { + type_resolver.resolve_type(*ty) + .can_derive_debug(type_resolver) + }) && self.template_args.iter().all(|ty| { type_resolver.resolve_type(*ty) .can_derive_debug(type_resolver) @@ -230,6 +238,10 @@ impl CompInfo { self.fields.iter().all(|field| { type_resolver.resolve_type(field.ty) .can_derive_debug(type_resolver) + }) && + self.ref_template.map_or(true, |template| { + type_resolver.resolve_type(template) + .can_derive_debug(type_resolver) }); self.detect_derive_debug_cycle.set(false); @@ -287,7 +299,7 @@ impl CompInfo { has_destructor } - pub fn can_derive_copy(&self, type_resolver: &TypeResolver) -> bool { + pub fn can_derive_copy(&self, type_resolver: &TypeResolver, item: &Item) -> bool { // NOTE: Take into account that while unions in C and C++ are copied by // default, the may have an explicit destructor in C++, so we can't // defer this check just for the union case. @@ -295,23 +307,31 @@ impl CompInfo { return false; } - match self.kind { - CompKind::Union => true, - CompKind::Struct => { - // With template args, use a safe subset of the types, - // since copyability depends on the types itself. - self.ref_template.as_ref().map_or(true, |t| { - type_resolver.resolve_type(*t).can_derive_copy(type_resolver) - }) && - self.base_members.iter().all(|t| { - type_resolver.resolve_type(*t).can_derive_copy(type_resolver) - }) && - self.fields.iter().all(|field| { - type_resolver.resolve_type(field.ty) - .can_derive_copy(type_resolver) - }) + if self.kind == CompKind::Union { + if !type_resolver.options().unstable_rust { + return true; + } + + // https://github.com/rust-lang/rust/issues/36640 + if !self.template_args.is_empty() || + self.ref_template.is_some() || + !item.applicable_template_args(type_resolver).is_empty() { + return false; } } + + // With template args, use a safe subset of the types, + // since copyability depends on the types itself. + self.ref_template.as_ref().map_or(true, |t| { + type_resolver.resolve_item(*t).can_derive_copy(type_resolver) + }) && + self.base_members.iter().all(|t| { + type_resolver.resolve_item(*t).can_derive_copy(type_resolver) + }) && + self.fields.iter().all(|field| { + type_resolver.resolve_item(field.ty) + .can_derive_copy(type_resolver) + }) } pub fn is_template_specialization(&self) -> bool { diff --git a/src/ir/context.rs b/src/ir/context.rs index 559dd2ba..4842eb94 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -333,7 +333,7 @@ impl<'ctx> BindgenContext<'ctx> { let cfg = ExpansionConfig::default("xxx".to_owned()); let sess = parse::ParseSess::new(); - let mut loader = base::DummyMacroLoader; + let mut loader = base::DummyResolver; let mut ctx = GenContext(base::ExtCtxt::new(&sess, vec![], cfg, &mut loader)); diff --git a/src/ir/item.rs b/src/ir/item.rs index 75c3b857..80085c8b 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -338,6 +338,14 @@ impl Item { _ => None, } } + + pub fn can_derive_copy(&self, ctx: &BindgenContext) -> bool { + self.expect_type().can_derive_copy(ctx, self) + } + + pub fn can_derive_copy_in_array(&self, ctx: &BindgenContext) -> bool { + self.expect_type().can_derive_copy_in_array(ctx, self) + } } impl ClangItemParser for Item { diff --git a/src/ir/ty.rs b/src/ir/ty.rs index 97cdf925..74452243 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -175,32 +175,32 @@ impl Type { // is an error. // // That's the point of the existence of can_derive_copy_in_array(). - pub fn can_derive_copy_in_array(&self, type_resolver: &TypeResolver) -> bool { + pub fn can_derive_copy_in_array(&self, type_resolver: &TypeResolver, item: &Item) -> bool { match self.kind { TypeKind::ResolvedTypeRef(t) | TypeKind::Alias(_, t) | TypeKind::Array(t, _) => { - type_resolver.resolve_type(t) + type_resolver.resolve_item(t) .can_derive_copy_in_array(type_resolver) } TypeKind::Named(..) => false, - _ => self.can_derive_copy(type_resolver), + _ => self.can_derive_copy(type_resolver, item), } } - pub fn can_derive_copy(&self, type_resolver: &TypeResolver) -> bool { + pub fn can_derive_copy(&self, type_resolver: &TypeResolver, item: &Item) -> bool { !self.is_opaque(type_resolver) && match self.kind { TypeKind::Array(t, len) => { len <= RUST_DERIVE_IN_ARRAY_LIMIT && - type_resolver.resolve_type(t).can_derive_copy_in_array(type_resolver) + type_resolver.resolve_item(t).can_derive_copy_in_array(type_resolver) } TypeKind::ResolvedTypeRef(t) | TypeKind::TemplateRef(t, _) | TypeKind::Alias(_, t) => { - type_resolver.resolve_type(t).can_derive_copy(type_resolver) + type_resolver.resolve_item(t).can_derive_copy(type_resolver) } TypeKind::Comp(ref info) => { - info.can_derive_copy(type_resolver) + info.can_derive_copy(type_resolver, item) } _ => true, } |