diff options
author | Sergey Pepyakin <s.pepyakin@gmail.com> | 2017-09-23 01:48:19 +0300 |
---|---|---|
committer | Sergey Pepyakin <s.pepyakin@gmail.com> | 2017-10-03 00:37:09 +0300 |
commit | dde9376cf32511debbb4b0e068c6ca776d13349b (patch) | |
tree | d47244770a0fe187e7c2fec0db0366cfdbd17092 /src/codegen/mod.rs | |
parent | c66598d28b7ffe8b8e30a58e9268db50dd109986 (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/mod.rs')
-rw-r--r-- | src/codegen/mod.rs | 91 |
1 files changed, 56 insertions, 35 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 264b701b..9ccd79c1 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1,4 +1,5 @@ mod impl_debug; +mod impl_partialeq; mod error; mod helpers; pub mod struct_layout; @@ -14,7 +15,7 @@ use ir::comp::{Base, Bitfield, BitfieldUnit, CompInfo, CompKind, Field, use ir::context::{BindgenContext, ItemId}; use ir::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveHash, CanDerivePartialOrd, CanDeriveOrd, - CanDerivePartialEq, CanDeriveEq}; + CanDerivePartialEq, CanDeriveEq, CannotDeriveReason}; use ir::dot; use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue}; use ir::function::{Abi, Function, FunctionSig}; @@ -1420,6 +1421,7 @@ impl CodeGenerator for CompInfo { let mut needs_clone_impl = false; let mut needs_default_impl = false; let mut needs_debug_impl = false; + let mut needs_partialeq_impl = false; if let Some(comment) = item.comment(ctx) { attributes.push(attributes::doc(comment)); } @@ -1475,6 +1477,14 @@ impl CodeGenerator for CompInfo { if item.can_derive_partialeq(ctx) { derives.push("PartialEq"); + } else { + needs_partialeq_impl = + ctx.options().derive_partialeq && + ctx.options().impl_partialeq && + ctx.lookup_can_derive_partialeq_or_partialord(item.id()) + .map_or(true, |x| { + x == CannotDeriveReason::ArrayTooLarge + }); } if item.can_derive_eq(ctx) { @@ -1535,25 +1545,14 @@ impl CodeGenerator for CompInfo { } for base in self.base_members() { - // Virtual bases are already taken into account by the vtable - // pointer. - // - // FIXME(emilio): Is this always right? - if base.is_virtual() { - continue; - } - - let base_ty = ctx.resolve_type(base.ty); - // NB: We won't include unsized types in our base chain because they - // would contribute to our size given the dummy field we insert for - // unsized types. - if base_ty.is_unsized(ctx, base.ty) { + if !base.requires_storage(ctx) { continue; } let inner = base.ty.to_rust_ty_or_opaque(ctx, &()); let field_name = ctx.rust_ident(&base.field_name); + let base_ty = ctx.resolve_type(base.ty); struct_layout.saw_base(base_ty); fields.push(quote! { @@ -1667,33 +1666,34 @@ impl CodeGenerator for CompInfo { } } - let mut generics = quote! {}; + let mut generic_param_names = vec![]; if let Some(ref params) = used_template_params { - if !params.is_empty() { - let mut param_names = vec![]; + for (idx, ty) in params.iter().enumerate() { + let param = ctx.resolve_type(*ty); + let name = param.name().unwrap(); + let ident = ctx.rust_ident(name); + generic_param_names.push(ident.clone()); - for (idx, ty) in params.iter().enumerate() { - let param = ctx.resolve_type(*ty); - let name = param.name().unwrap(); - let ident = ctx.rust_ident(name); - param_names.push(ident.clone()); - - let prefix = ctx.trait_prefix(); - let field_name = ctx.rust_ident(format!("_phantom_{}", idx)); - fields.push(quote! { - pub #field_name : ::#prefix::marker::PhantomData< - ::#prefix::cell::UnsafeCell<#ident> - > , - }); - } - - generics = quote! { - < #( #param_names ),* > - }; + let prefix = ctx.trait_prefix(); + let field_name = ctx.rust_ident(format!("_phantom_{}", idx)); + fields.push(quote! { + pub #field_name : ::#prefix::marker::PhantomData< + ::#prefix::cell::UnsafeCell<#ident> + > , + }); } } + let generics = if !generic_param_names.is_empty() { + let generic_param_names = generic_param_names.clone(); + quote! { + < #( #generic_param_names ),* > + } + } else { + quote! { } + }; + tokens.append(quote! { #generics { #( #fields )* @@ -1896,6 +1896,27 @@ impl CodeGenerator for CompInfo { }); } + if needs_partialeq_impl { + if let Some(impl_) = impl_partialeq::gen_partialeq_impl(ctx, self, item, &ty_for_impl) { + + let partialeq_bounds = if !generic_param_names.is_empty() { + let bounds = generic_param_names.iter().map(|t| { + quote! { #t: PartialEq } + }); + quote! { where #( #bounds ),* } + } else { + quote! { } + }; + + let prefix = ctx.trait_prefix(); + result.push(quote! { + impl #generics ::#prefix::cmp::PartialEq for #ty_for_impl #partialeq_bounds { + #impl_ + } + }); + } + } + if !methods.is_empty() { result.push(quote! { impl #generics #ty_for_impl { |