diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/codegen/mod.rs | 40 | ||||
-rw-r--r-- | src/features.rs | 8 | ||||
-rw-r--r-- | src/ir/context.rs | 6 | ||||
-rw-r--r-- | src/ir/traversal.rs | 12 |
4 files changed, 46 insertions, 20 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 63e1e11e..6483412e 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -2127,7 +2127,7 @@ impl EnumVariation { fn is_bitfield(&self) -> bool { match *self { - EnumVariation::Bitfield => true, + EnumVariation::Bitfield {..} => true, _ => false } } @@ -2248,6 +2248,7 @@ impl<'a> EnumBuilder<'a> { mangling_prefix: Option<&str>, rust_ty: quote::Tokens, result: &mut CodegenResult<'b>, + is_ty_named: bool, ) -> Self { let variant_name = ctx.rust_mangle(variant.name()); let expr = match variant.val() { @@ -2279,19 +2280,28 @@ impl<'a> EnumBuilder<'a> { } } - EnumBuilder::Bitfield { .. } => { - let constant_name = match mangling_prefix { - Some(prefix) => { - Cow::Owned(format!("{}_{}", prefix, variant_name)) - } - None => variant_name, - }; - - let ident = ctx.rust_ident(constant_name); - result.push(quote! { - #doc - pub const #ident : #rust_ty = #rust_ty ( #expr ); - }); + EnumBuilder::Bitfield { canonical_name, .. } => { + if ctx.options().rust_features().associated_const && is_ty_named { + let enum_ident = ctx.rust_ident(canonical_name); + let variant_ident = ctx.rust_ident(variant_name); + result.push(quote! { + impl #enum_ident { + #doc + pub const #variant_ident : #rust_ty = #rust_ty ( #expr ); + } + }); + } else { + let ident = ctx.rust_ident(match mangling_prefix { + Some(prefix) => { + Cow::Owned(format!("{}_{}", prefix, variant_name)) + } + None => variant_name, + }); + result.push(quote! { + #doc + pub const #ident : #rust_ty = #rust_ty ( #expr ); + }); + } self } @@ -2626,6 +2636,7 @@ impl CodeGenerator for Enum { constant_mangling_prefix, enum_rust_ty.clone(), result, + enum_ty.name().is_some(), ); } } @@ -2636,6 +2647,7 @@ impl CodeGenerator for Enum { constant_mangling_prefix, enum_rust_ty.clone(), result, + enum_ty.name().is_some(), ); let variant_name = ctx.rust_ident(variant.name()); diff --git a/src/features.rs b/src/features.rs index 866d7126..93ebbc34 100644 --- a/src/features.rs +++ b/src/features.rs @@ -90,6 +90,8 @@ macro_rules! rust_target_base { => Stable_1_0 => 1.0; /// Rust stable 1.19 => Stable_1_19 => 1.19; + /// Rust stable 1.20 + => Stable_1_20 => 1.20; /// Rust stable 1.21 => Stable_1_21 => 1.21; /// Rust stable 1.25 @@ -142,6 +144,8 @@ rust_feature_def!( => builtin_clone_impls; /// repr(align) https://github.com/rust-lang/rust/pull/47006 => repr_align; + /// associated constants https://github.com/rust-lang/rust/issues/29646 + => associated_const; ); impl From<RustTarget> for RustFeatures { @@ -152,6 +156,10 @@ impl From<RustTarget> for RustFeatures { features.untagged_union = true; } + if rust_target >= RustTarget::Stable_1_20 { + features.associated_const = true; + } + if rust_target >= RustTarget::Stable_1_21 { features.builtin_clone_impls = true; } diff --git a/src/ir/context.rs b/src/ir/context.rs index 6ced43e8..58a90ba6 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -2316,7 +2316,11 @@ impl BindgenContext { if self.options().whitelist_recursively { traversal::all_edges } else { - traversal::no_edges + // Only follow InnerType edges from the whitelisted roots. + // Such inner types (e.g. anonymous structs/unions) are + // always emitted by codegen, and they need to be whitelisted + // to make sure they are processed by e.g. the derive analysis. + traversal::only_inner_type_edges }; let whitelisted = WhitelistedItemsTraversal::new( diff --git a/src/ir/traversal.rs b/src/ir/traversal.rs index 491a15f8..c37b0b5f 100644 --- a/src/ir/traversal.rs +++ b/src/ir/traversal.rs @@ -201,11 +201,13 @@ pub fn all_edges(_: &BindgenContext, _: Edge) -> bool { true } -/// A `TraversalPredicate` implementation that never follows any edges, and -/// therefore traversals using this predicate will only visit the traversal's -/// roots. -pub fn no_edges(_: &BindgenContext, _: Edge) -> bool { - false +/// A `TraversalPredicate` implementation that only follows +/// `EdgeKind::InnerType` edges, and therefore traversals using this predicate +/// will only visit the traversal's roots and their inner types. This is used +/// in no-recursive-whitelist mode, where inner types such as anonymous +/// structs/unions still need to be processed. +pub fn only_inner_type_edges(_: &BindgenContext, edge: Edge) -> bool { + edge.kind == EdgeKind::InnerType } /// A `TraversalPredicate` implementation that only follows edges to items that |