summaryrefslogtreecommitdiff
path: root/src/codegen/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen/mod.rs')
-rw-r--r--src/codegen/mod.rs149
1 files changed, 106 insertions, 43 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 1cefb9e2..cc9b8b41 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -95,6 +95,93 @@ fn root_import(
}
}
+bitflags! {
+ struct DerivableTraits: u16 {
+ const DEBUG = 1 << 0;
+ const DEFAULT = 1 << 1;
+ const COPY = 1 << 2;
+ const CLONE = 1 << 3;
+ const HASH = 1 << 4;
+ const PARTIAL_ORD = 1 << 5;
+ const ORD = 1 << 6;
+ const PARTIAL_EQ = 1 << 7;
+ const EQ = 1 << 8;
+ }
+}
+
+fn derives_of_item(item: &Item, ctx: &BindgenContext) -> DerivableTraits {
+ let mut derivable_traits = DerivableTraits::empty();
+
+ if item.can_derive_debug(ctx) {
+ derivable_traits |= DerivableTraits::DEBUG;
+ }
+
+ if item.can_derive_default(ctx) {
+ derivable_traits |= DerivableTraits::DEFAULT;
+ }
+
+ let all_template_params = item.all_template_params(ctx);
+
+ if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() {
+ derivable_traits |= DerivableTraits::COPY;
+
+ if ctx.options().rust_features().builtin_clone_impls ||
+ !all_template_params.is_empty()
+ {
+ // FIXME: This requires extra logic if you have a big array in a
+ // templated struct. The reason for this is that the magic:
+ // fn clone(&self) -> Self { *self }
+ // doesn't work for templates.
+ //
+ // It's not hard to fix though.
+ derivable_traits |= DerivableTraits::CLONE;
+ }
+ }
+
+ if item.can_derive_hash(ctx) {
+ derivable_traits |= DerivableTraits::HASH;
+ }
+
+ if item.can_derive_partialord(ctx) {
+ derivable_traits |= DerivableTraits::PARTIAL_ORD;
+ }
+
+ if item.can_derive_ord(ctx) {
+ derivable_traits |= DerivableTraits::ORD;
+ }
+
+ if item.can_derive_partialeq(ctx) {
+ derivable_traits |= DerivableTraits::PARTIAL_EQ;
+ }
+
+ if item.can_derive_eq(ctx) {
+ derivable_traits |= DerivableTraits::EQ;
+ }
+
+ derivable_traits
+}
+
+impl From<DerivableTraits> for Vec<&'static str> {
+ fn from(derivable_traits: DerivableTraits) -> Vec<&'static str> {
+ [
+ (DerivableTraits::DEBUG, "Debug"),
+ (DerivableTraits::DEFAULT, "Default"),
+ (DerivableTraits::COPY, "Copy"),
+ (DerivableTraits::CLONE, "Clone"),
+ (DerivableTraits::HASH, "Hash"),
+ (DerivableTraits::PARTIAL_ORD, "PartialOrd"),
+ (DerivableTraits::ORD, "Ord"),
+ (DerivableTraits::PARTIAL_EQ, "PartialEq"),
+ (DerivableTraits::EQ, "Eq"),
+ ]
+ .iter()
+ .filter_map(|&(flag, derive)| {
+ Some(derive).filter(|_| derivable_traits.contains(flag))
+ })
+ .collect()
+ }
+}
+
struct CodegenResult<'a> {
items: Vec<proc_macro2::TokenStream>,
@@ -793,8 +880,17 @@ impl CodeGenerator for Type {
"repr_transparent feature is required to use {:?}",
alias_style
);
+
+ let mut attributes =
+ vec![attributes::repr("transparent")];
+ let derivable_traits = derives_of_item(item, ctx);
+ if !derivable_traits.is_empty() {
+ let derives: Vec<_> = derivable_traits.into();
+ attributes.push(attributes::derives(&derives))
+ }
+
quote! {
- #[repr(transparent)]
+ #( #attributes )*
pub struct #rust_name
}
}
@@ -1787,66 +1883,33 @@ impl CodeGenerator for CompInfo {
}
}
- let mut derives = vec![];
- if item.can_derive_debug(ctx) {
- derives.push("Debug");
- } else {
+ let derivable_traits = derives_of_item(item, ctx);
+ if !derivable_traits.contains(DerivableTraits::DEBUG) {
needs_debug_impl =
ctx.options().derive_debug && ctx.options().impl_debug
}
- if item.can_derive_default(ctx) {
- derives.push("Default");
- } else {
+ if !derivable_traits.contains(DerivableTraits::DEFAULT) {
needs_default_impl =
ctx.options().derive_default && !self.is_forward_declaration();
}
let all_template_params = item.all_template_params(ctx);
- if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() {
- derives.push("Copy");
-
- if ctx.options().rust_features().builtin_clone_impls ||
- !all_template_params.is_empty()
- {
- // FIXME: This requires extra logic if you have a big array in a
- // templated struct. The reason for this is that the magic:
- // fn clone(&self) -> Self { *self }
- // doesn't work for templates.
- //
- // It's not hard to fix though.
- derives.push("Clone");
- } else {
- needs_clone_impl = true;
- }
- }
-
- if item.can_derive_hash(ctx) {
- derives.push("Hash");
- }
-
- if item.can_derive_partialord(ctx) {
- derives.push("PartialOrd");
- }
-
- if item.can_derive_ord(ctx) {
- derives.push("Ord");
+ if derivable_traits.contains(DerivableTraits::COPY) &&
+ !derivable_traits.contains(DerivableTraits::CLONE)
+ {
+ needs_clone_impl = true;
}
- if item.can_derive_partialeq(ctx) {
- derives.push("PartialEq");
- } else {
+ if !derivable_traits.contains(DerivableTraits::PARTIAL_EQ) {
needs_partialeq_impl = ctx.options().derive_partialeq &&
ctx.options().impl_partialeq &&
ctx.lookup_can_derive_partialeq_or_partialord(item.id()) ==
CanDerive::Manually;
}
- if item.can_derive_eq(ctx) {
- derives.push("Eq");
- }
-
+ let mut derives: Vec<_> = derivable_traits.into();
derives.extend(item.annotations().derives().iter().map(String::as_str));
if !derives.is_empty() {