summaryrefslogtreecommitdiff
path: root/src/codegen/impl_partialeq.rs
diff options
context:
space:
mode:
authorSergey Pepyakin <s.pepyakin@gmail.com>2017-09-23 01:48:19 +0300
committerSergey Pepyakin <s.pepyakin@gmail.com>2017-10-03 00:37:09 +0300
commitdde9376cf32511debbb4b0e068c6ca776d13349b (patch)
treed47244770a0fe187e7c2fec0db0366cfdbd17092 /src/codegen/impl_partialeq.rs
parentc66598d28b7ffe8b8e30a58e9268db50dd109986 (diff)
Derive partialeq "manually" when possible
Remove derive-partialeq-template-inst test. Add comments. Don't implement PartialEq for incomplete arrays Handle opaque bases and template instantiations Extract constrain_type. Extract `is whitelisted?` check Add failing partialeq-anonfield join for comps Fix: return insert if not whitelisted Delegate TypeRefs and alias to constrain_join. Delegate Template instantiations to constrain_join Add derive-partialeq-pointer.hpp test Update comment. Fix layout alignment larger that array limit Add missing test for derive-partialeq-anonfield.rs Clean Clean Fix typo in opaque-template-inst-member test Remove redudant stmt Add comment on can_supersede. Format impl_partialeq and leave a comment Extract requires_storage into it's own function. Clean
Diffstat (limited to 'src/codegen/impl_partialeq.rs')
-rw-r--r--src/codegen/impl_partialeq.rs121
1 files changed, 121 insertions, 0 deletions
diff --git a/src/codegen/impl_partialeq.rs b/src/codegen/impl_partialeq.rs
new file mode 100644
index 00000000..15a8953e
--- /dev/null
+++ b/src/codegen/impl_partialeq.rs
@@ -0,0 +1,121 @@
+
+use ir::comp::{CompInfo, CompKind, Field, FieldMethods};
+use ir::context::BindgenContext;
+use ir::item::{IsOpaque, Item};
+use ir::ty::{TypeKind, RUST_DERIVE_IN_ARRAY_LIMIT};
+use quote;
+
+/// Generate a manual implementation of `PartialEq` trait for the
+/// specified compound type.
+pub fn gen_partialeq_impl(
+ ctx: &BindgenContext,
+ comp_info: &CompInfo,
+ item: &Item,
+ ty_for_impl: &quote::Tokens,
+) -> Option<quote::Tokens> {
+ let mut tokens = vec![];
+
+ if item.is_opaque(ctx, &()) {
+ tokens.push(quote! {
+ &self._bindgen_opaque_blob[..] == &other._bindgen_opaque_blob[..]
+ });
+ } else if comp_info.kind() == CompKind::Union {
+ tokens.push(quote! {
+ &self.bindgen_union_field[..] == &other.bindgen_union_field[..]
+ });
+ } else {
+ for base in comp_info.base_members().iter() {
+ if !base.requires_storage(ctx) {
+ continue;
+ }
+
+ let ty_item = ctx.resolve_item(base.ty);
+ let field_name = &base.field_name;
+
+ if ty_item.is_opaque(ctx, &()) {
+ let field_name = ctx.rust_ident(field_name);
+ tokens.push(quote! {
+ &self. #field_name [..] == &other. #field_name [..]
+ });
+ } else {
+ tokens.push(gen_field(ctx, ty_item, field_name));
+ }
+ }
+
+ for field in comp_info.fields() {
+ match *field {
+ Field::DataMember(ref fd) => {
+ let ty_item = ctx.resolve_item(fd.ty());
+ let name = fd.name().unwrap();
+ tokens.push(gen_field(ctx, ty_item, name));
+ }
+ Field::Bitfields(ref bu) => for bitfield in bu.bitfields() {
+ let name_ident = ctx.rust_ident_raw(bitfield.name());
+ tokens.push(quote! {
+ self.#name_ident () == other.#name_ident ()
+ });
+ },
+ }
+ }
+ }
+
+ Some(quote! {
+ fn eq(&self, other: & #ty_for_impl) -> bool {
+ #( #tokens )&&*
+ }
+ })
+}
+
+fn gen_field(ctx: &BindgenContext, ty_item: &Item, name: &str) -> quote::Tokens {
+ fn quote_equals(name_ident: quote::Ident) -> quote::Tokens {
+ quote! { self.#name_ident == other.#name_ident }
+ }
+
+ let name_ident = ctx.rust_ident(name);
+ let ty = ty_item.expect_type();
+
+ match *ty.kind() {
+ TypeKind::Void |
+ TypeKind::NullPtr |
+ TypeKind::Int(..) |
+ TypeKind::Complex(..) |
+ TypeKind::Float(..) |
+ TypeKind::Enum(..) |
+ TypeKind::TypeParam |
+ TypeKind::UnresolvedTypeRef(..) |
+ TypeKind::BlockPointer |
+ TypeKind::Reference(..) |
+ TypeKind::ObjCInterface(..) |
+ TypeKind::ObjCId |
+ TypeKind::ObjCSel |
+ TypeKind::Comp(..) |
+ TypeKind::Pointer(_) |
+ TypeKind::Function(..) |
+ TypeKind::Opaque => quote_equals(name_ident),
+
+ TypeKind::TemplateInstantiation(ref inst) => {
+ if inst.is_opaque(ctx, &ty_item) {
+ quote! {
+ &self. #name_ident [..] == &other. #name_ident [..]
+ }
+ } else {
+ quote_equals(name_ident)
+ }
+ }
+
+ TypeKind::Array(_, len) => if len <= RUST_DERIVE_IN_ARRAY_LIMIT {
+ quote_equals(name_ident)
+ } else {
+ quote! {
+ &self. #name_ident [..] == &other. #name_ident [..]
+ }
+ },
+
+ TypeKind::ResolvedTypeRef(t) |
+ TypeKind::TemplateAlias(t, _) |
+ TypeKind::Alias(t) => {
+ let inner_item = ctx.resolve_item(t);
+ gen_field(ctx, inner_item, name)
+ }
+ }
+}