summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/codegen/mod.rs18
-rw-r--r--src/ir/analysis/derive_partial_eq.rs334
-rw-r--r--src/ir/analysis/mod.rs2
-rw-r--r--src/ir/context.rs35
-rw-r--r--src/ir/derive.rs27
-rw-r--r--src/ir/function.rs16
-rw-r--r--src/ir/item.rs9
-rw-r--r--src/ir/layout.rs10
-rw-r--r--src/lib.rs15
-rw-r--r--src/options.rs7
10 files changed, 466 insertions, 7 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 6113e5d5..1e4a5d48 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -14,7 +14,7 @@ use ir::comment;
use ir::comp::{Base, Bitfield, BitfieldUnit, CompInfo, CompKind, Field,
FieldData, FieldMethods, Method, MethodKind};
use ir::context::{BindgenContext, ItemId};
-use ir::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveHash};
+use ir::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveHash, CanDerivePartialEq};
use ir::dot;
use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue};
use ir::function::{Abi, Function, FunctionSig};
@@ -1495,6 +1495,10 @@ impl CodeGenerator for CompInfo {
derives.push("Hash");
}
+ if item.can_derive_partialeq(ctx) {
+ derives.push("PartialEq");
+ }
+
if !derives.is_empty() {
attributes.push(attributes::derives(&derives))
}
@@ -3569,13 +3573,23 @@ mod utils {
)
.unwrap();
+ let union_field_partialeq_impl = quote_item!(&ctx.ext_cx(),
+ impl<T> ::$prefix::cmp::PartialEq for __BindgenUnionField<T> {
+ fn eq(&self, _other: &__BindgenUnionField<T>) -> bool {
+ true
+ }
+ }
+ )
+ .unwrap();
+
let items = vec![union_field_decl,
union_field_impl,
union_field_default_impl,
union_field_clone_impl,
union_field_copy_impl,
union_field_debug_impl,
- union_field_hash_impl];
+ union_field_hash_impl,
+ union_field_partialeq_impl];
let old_items = mem::replace(result, items);
result.extend(old_items.into_iter());
diff --git a/src/ir/analysis/derive_partial_eq.rs b/src/ir/analysis/derive_partial_eq.rs
new file mode 100644
index 00000000..f8624d1f
--- /dev/null
+++ b/src/ir/analysis/derive_partial_eq.rs
@@ -0,0 +1,334 @@
+//! Determining which types for which we can emit `#[derive(PartialEq)]`.
+
+use super::{ConstrainResult, MonotoneFramework, generate_dependencies};
+use std::collections::HashSet;
+use std::collections::HashMap;
+use ir::context::{BindgenContext, ItemId};
+use ir::item::IsOpaque;
+use ir::traversal::EdgeKind;
+use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
+use ir::ty::TypeKind;
+use ir::comp::Field;
+use ir::comp::FieldMethods;
+use ir::derive::CanTriviallyDerivePartialEq;
+use ir::comp::CompKind;
+
+/// An analysis that finds for each IR item whether partialeq cannot be derived.
+///
+/// We use the monotone constraint function `cannot_derive_partial_eq`, defined as
+/// follows:
+///
+/// * If T is Opaque and layout of the type is known, get this layout as opaque
+/// type and check whether it can be derived using trivial checks.
+/// * If T is Array type, partialeq cannot be derived if the length of the array is
+/// larger than the limit or the type of data the array contains cannot derive
+/// partialeq.
+/// * If T is a type alias, a templated alias or an indirection to another type,
+/// partialeq cannot be derived if the type T refers to cannot be derived partialeq.
+/// * If T is a compound type, partialeq cannot be derived if any of its base member
+/// or field cannot be derived partialeq.
+/// * If T is a pointer, T cannot be derived partialeq if T is a function pointer
+/// and the function signature cannot be derived partialeq.
+/// * If T is an instantiation of an abstract template definition, T cannot be
+/// derived partialeq if any of the template arguments or template definition
+/// cannot derive partialeq.
+#[derive(Debug, Clone)]
+pub struct CannotDerivePartialEq<'ctx, 'gen>
+ where 'gen: 'ctx
+{
+ ctx: &'ctx BindgenContext<'gen>,
+
+ // The incremental result of this analysis's computation. Everything in this
+ // set cannot derive partialeq.
+ cannot_derive_partialeq: HashSet<ItemId>,
+
+ // Dependencies saying that if a key ItemId has been inserted into the
+ // `cannot_derive_partialeq` set, then each of the ids in Vec<ItemId> need to be
+ // considered again.
+ //
+ // This is a subset of the natural IR graph with reversed edges, where we
+ // only include the edges from the IR graph that can affect whether a type
+ // can derive partialeq or not.
+ dependencies: HashMap<ItemId, Vec<ItemId>>,
+}
+
+impl<'ctx, 'gen> CannotDerivePartialEq<'ctx, 'gen> {
+ fn consider_edge(kind: EdgeKind) -> bool {
+ match kind {
+ // These are the only edges that can affect whether a type can derive
+ // partialeq or not.
+ EdgeKind::BaseMember |
+ EdgeKind::Field |
+ EdgeKind::TypeReference |
+ EdgeKind::VarType |
+ EdgeKind::TemplateArgument |
+ EdgeKind::TemplateDeclaration |
+ EdgeKind::TemplateParameterDefinition => true,
+
+ EdgeKind::Constructor |
+ EdgeKind::Destructor |
+ EdgeKind::FunctionReturn |
+ EdgeKind::FunctionParameter |
+ EdgeKind::InnerType |
+ EdgeKind::InnerVar |
+ EdgeKind::Method => false,
+ EdgeKind::Generic => false,
+ }
+ }
+
+ fn insert(&mut self, id: ItemId) -> ConstrainResult {
+ trace!("inserting {:?} into the cannot_derive_partialeq set", id);
+
+ let was_not_already_in_set = self.cannot_derive_partialeq.insert(id);
+ assert!(
+ was_not_already_in_set,
+ "We shouldn't try and insert {:?} twice because if it was \
+ already in the set, `constrain` should have exited early.",
+ id
+ );
+
+ ConstrainResult::Changed
+ }
+}
+
+impl<'ctx, 'gen> MonotoneFramework for CannotDerivePartialEq<'ctx, 'gen> {
+ type Node = ItemId;
+ type Extra = &'ctx BindgenContext<'gen>;
+ type Output = HashSet<ItemId>;
+
+ fn new(ctx: &'ctx BindgenContext<'gen>) -> CannotDerivePartialEq<'ctx, 'gen> {
+ let cannot_derive_partialeq = HashSet::new();
+ let dependencies = generate_dependencies(ctx, Self::consider_edge);
+
+ CannotDerivePartialEq {
+ ctx,
+ cannot_derive_partialeq,
+ dependencies,
+ }
+ }
+
+ fn initial_worklist(&self) -> Vec<ItemId> {
+ self.ctx.whitelisted_items().iter().cloned().collect()
+ }
+
+ fn constrain(&mut self, id: ItemId) -> ConstrainResult {
+ trace!("constrain: {:?}", id);
+
+ if self.cannot_derive_partialeq.contains(&id) {
+ trace!(" already know it cannot derive PartialEq");
+ return ConstrainResult::Same;
+ }
+
+ let item = self.ctx.resolve_item(id);
+ let ty = match item.as_type() {
+ Some(ty) => ty,
+ None => {
+ trace!(" not a type; ignoring");
+ return ConstrainResult::Same;
+ }
+ };
+
+ trace!("ty: {:?}", ty);
+ if item.is_opaque(self.ctx, &()) {
+ let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
+ l.opaque().can_trivially_derive_partialeq()
+ });
+ return if layout_can_derive {
+ trace!(" we can trivially derive PartialEq for the layout");
+ ConstrainResult::Same
+ } else {
+ trace!(" we cannot derive PartialEq for the layout");
+ self.insert(id)
+ };
+ }
+
+ if ty.layout(self.ctx).map_or(false, |l| l.align > RUST_DERIVE_IN_ARRAY_LIMIT) {
+ // We have to be conservative: the struct *could* have enough
+ // padding that we emit an array that is longer than
+ // `RUST_DERIVE_IN_ARRAY_LIMIT`. If we moved padding calculations
+ // into the IR and computed them before this analysis, then we could
+ // be precise rather than conservative here.
+ return self.insert(id);
+ }
+
+ match *ty.kind() {
+ // Handle the simple cases. These can derive partialeq without further
+ // information.
+ TypeKind::Void |
+ TypeKind::NullPtr |
+ TypeKind::Int(..) |
+ TypeKind::Complex(..) |
+ TypeKind::Float(..) |
+ TypeKind::Enum(..) |
+ TypeKind::Named |
+ TypeKind::UnresolvedTypeRef(..) |
+ TypeKind::BlockPointer |
+ TypeKind::Reference(..) |
+ TypeKind::ObjCInterface(..) |
+ TypeKind::ObjCId |
+ TypeKind::ObjCSel => {
+ trace!(" simple type that can always derive PartialEq");
+ ConstrainResult::Same
+ }
+
+ TypeKind::Array(t, len) => {
+ if self.cannot_derive_partialeq.contains(&t) {
+ trace!(" arrays of T for which we cannot derive PartialEq \
+ also cannot derive PartialEq");
+ return self.insert(id);
+ }
+
+ if len <= RUST_DERIVE_IN_ARRAY_LIMIT {
+ trace!(" array is small enough to derive PartialEq");
+ ConstrainResult::Same
+ } else {
+ trace!(" array is too large to derive PartialEq");
+ self.insert(id)
+ }
+ }
+
+ TypeKind::Pointer(inner) => {
+ let inner_type = self.ctx.resolve_type(inner).canonical_type(self.ctx);
+ if let TypeKind::Function(ref sig) = *inner_type.kind() {
+ if !sig.can_trivially_derive_partialeq() {
+ trace!(" function pointer that can't trivially derive PartialEq");
+ return self.insert(id);
+ }
+ }
+ trace!(" pointers can derive PartialEq");
+ ConstrainResult::Same
+ }
+
+ TypeKind::Function(ref sig) => {
+ if !sig.can_trivially_derive_partialeq() {
+ trace!(" function that can't trivially derive PartialEq");
+ return self.insert(id);
+ }
+ trace!(" function can derive PartialEq");
+ ConstrainResult::Same
+ }
+
+ TypeKind::ResolvedTypeRef(t) |
+ TypeKind::TemplateAlias(t, _) |
+ TypeKind::Alias(t) => {
+ if self.cannot_derive_partialeq.contains(&t) {
+ trace!(" aliases and type refs to T which cannot derive \
+ PartialEq also cannot derive PartialEq");
+ self.insert(id)
+ } else {
+ trace!(" aliases and type refs to T which can derive \
+ PartialEq can also derive PartialEq");
+ ConstrainResult::Same
+ }
+ }
+
+ TypeKind::Comp(ref info) => {
+ assert!(
+ !info.has_non_type_template_params(),
+ "The early ty.is_opaque check should have handled this case"
+ );
+
+ if info.kind() == CompKind::Union {
+ if self.ctx.options().rust_features().untagged_union() {
+ trace!(" cannot derive PartialEq for Rust unions");
+ return self.insert(id);
+ }
+
+ if ty.layout(self.ctx)
+ .map_or(true,
+ |l| l.opaque().can_trivially_derive_partialeq()) {
+ trace!(" union layout can trivially derive PartialEq");
+ return ConstrainResult::Same;
+ } else {
+ trace!(" union layout cannot derive PartialEq");
+ return self.insert(id);
+ }
+ }
+
+ let bases_cannot_derive = info.base_members()
+ .iter()
+ .any(|base| !self.ctx.whitelisted_items().contains(&base.ty) ||
+ self.cannot_derive_partialeq.contains(&base.ty));
+ if bases_cannot_derive {
+ trace!(" base members cannot derive PartialEq, so we can't \
+ either");
+ return self.insert(id);
+ }
+
+ let fields_cannot_derive = info.fields()
+ .iter()
+ .any(|f| {
+ match *f {
+ Field::DataMember(ref data) => {
+ !self.ctx.whitelisted_items().contains(&data.ty()) ||
+ self.cannot_derive_partialeq.contains(&data.ty())
+ }
+ Field::Bitfields(ref bfu) => {
+ bfu.bitfields()
+ .iter().any(|b| {
+ !self.ctx.whitelisted_items().contains(&b.ty()) ||
+ self.cannot_derive_partialeq.contains(&b.ty())
+ })
+ }
+ }
+ });
+ if fields_cannot_derive {
+ trace!(" fields cannot derive PartialEq, so we can't either");
+ return self.insert(id);
+ }
+
+ trace!(" comp can derive PartialEq");
+ ConstrainResult::Same
+ }
+
+ TypeKind::TemplateInstantiation(ref template) => {
+ let args_cannot_derive = template.template_arguments()
+ .iter()
+ .any(|arg| self.cannot_derive_partialeq.contains(&arg));
+ if args_cannot_derive {
+ trace!(" template args cannot derive PartialEq, so \
+ insantiation can't either");
+ return self.insert(id);
+ }
+
+ assert!(
+ !template.template_definition().is_opaque(self.ctx, &()),
+ "The early ty.is_opaque check should have handled this case"
+ );
+ let def_cannot_derive = self.cannot_derive_partialeq
+ .contains(&template.template_definition());
+ if def_cannot_derive {
+ trace!(" template definition cannot derive PartialEq, so \
+ insantiation can't either");
+ return self.insert(id);
+ }
+
+ trace!(" template instantiation can derive PartialEq");
+ ConstrainResult::Same
+ }
+
+ TypeKind::Opaque => {
+ unreachable!(
+ "The early ty.is_opaque check should have handled this case"
+ )
+ }
+ }
+ }
+
+ fn each_depending_on<F>(&self, id: ItemId, mut f: F)
+ where F: FnMut(ItemId),
+ {
+ if let Some(edges) = self.dependencies.get(&id) {
+ for item in edges {
+ trace!("enqueue {:?} into worklist", item);
+ f(*item);
+ }
+ }
+ }
+}
+
+impl<'ctx, 'gen> From<CannotDerivePartialEq<'ctx, 'gen>> for HashSet<ItemId> {
+ fn from(analysis: CannotDerivePartialEq<'ctx, 'gen>) -> Self {
+ analysis.cannot_derive_partialeq
+ }
+}
diff --git a/src/ir/analysis/mod.rs b/src/ir/analysis/mod.rs
index 28ca09aa..ef42e58d 100644
--- a/src/ir/analysis/mod.rs
+++ b/src/ir/analysis/mod.rs
@@ -53,6 +53,8 @@ mod has_type_param_in_array;
pub use self::has_type_param_in_array::HasTypeParameterInArray;
mod derive_hash;
pub use self::derive_hash::CannotDeriveHash;
+mod derive_partial_eq;
+pub use self::derive_partial_eq::CannotDerivePartialEq;
use ir::context::{BindgenContext, ItemId};
use ir::traversal::{EdgeKind, Trace};
diff --git a/src/ir/context.rs b/src/ir/context.rs
index a2493aee..edf320bf 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -1,13 +1,13 @@
//! Common context that is passed around during parsing and codegen.
-use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveHash};
+use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveHash, CanDerivePartialEq};
use super::int::IntKind;
use super::item::{IsOpaque, HasTypeParamInArray, Item, ItemAncestors, ItemCanonicalPath, ItemSet};
use super::item_kind::ItemKind;
use super::module::{Module, ModuleKind};
use super::analysis::{analyze, UsedTemplateParameters, CannotDeriveDebug, HasVtableAnalysis,
CannotDeriveDefault, CannotDeriveCopy, HasTypeParameterInArray,
- CannotDeriveHash};
+ CannotDeriveHash, CannotDerivePartialEq};
use super::template::{TemplateInstantiation, TemplateParameters};
use super::traversal::{self, Edge, ItemTraversal};
use super::ty::{FloatKind, Type, TypeKind};
@@ -65,6 +65,12 @@ impl CanDeriveHash for ItemId {
}
}
+impl CanDerivePartialEq for ItemId {
+ fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool {
+ ctx.options().derive_partialeq && ctx.lookup_item_id_can_derive_partialeq(*self)
+ }
+}
+
/// A key used to index a resolved type, so we only process it once.
///
/// This is almost always a USR string (an unique identifier generated by
@@ -207,6 +213,12 @@ pub struct BindgenContext<'ctx> {
/// and is always `None` before that and `Some` after.
cannot_derive_hash: Option<HashSet<ItemId>>,
+ /// The set of (`ItemId`s of) types that can't derive hash.
+ ///
+ /// This is populated when we enter codegen by `compute_can_derive_partialeq`
+ /// and is always `None` before that and `Some` after.
+ cannot_derive_partialeq: Option<HashSet<ItemId>>,
+
/// The set of (`ItemId's of`) types that has vtable.
///
/// Populated when we enter codegen by `compute_has_vtable`; always `None`
@@ -348,6 +360,7 @@ impl<'ctx> BindgenContext<'ctx> {
cannot_derive_copy: None,
cannot_derive_copy_in_array: None,
cannot_derive_hash: None,
+ cannot_derive_partialeq: None,
have_vtable: None,
has_type_param_in_array: None,
};
@@ -827,6 +840,7 @@ impl<'ctx> BindgenContext<'ctx> {
self.compute_cannot_derive_copy();
self.compute_has_type_param_in_array();
self.compute_cannot_derive_hash();
+ self.compute_cannot_derive_partialeq();
let ret = cb(self);
self.gen_ctx = None;
@@ -1844,6 +1858,23 @@ impl<'ctx> BindgenContext<'ctx> {
!self.cannot_derive_hash.as_ref().unwrap().contains(&id)
}
+ /// Compute whether we can derive hash.
+ fn compute_cannot_derive_partialeq(&mut self) {
+ assert!(self.cannot_derive_partialeq.is_none());
+ self.cannot_derive_partialeq = Some(analyze::<CannotDerivePartialEq>(self));
+ }
+
+ /// Look up whether the item with `id` can
+ /// derive partialeq or not.
+ pub fn lookup_item_id_can_derive_partialeq(&self, id: ItemId) -> bool {
+ assert!(self.in_codegen_phase(),
+ "We only compute can_derive_debug when we enter codegen");
+
+ // Look up the computed value for whether the item with `id` can
+ // derive partialeq or not.
+ !self.cannot_derive_partialeq.as_ref().unwrap().contains(&id)
+ }
+
/// Look up whether the item with `id` can
/// derive copy or not.
pub fn lookup_item_id_can_derive_copy(&self, id: ItemId) -> bool {
diff --git a/src/ir/derive.rs b/src/ir/derive.rs
index 128ef9f2..acbe20fd 100644
--- a/src/ir/derive.rs
+++ b/src/ir/derive.rs
@@ -88,6 +88,22 @@ pub trait CanDeriveHash {
-> bool;
}
+/// A trait that encapsulates the logic for whether or not we can derive `PartialEq`
+/// for a given thing.
+///
+/// This should ideally be a no-op that just returns `true`, but instead needs
+/// to be a recursive method that checks whether all the proper members can
+/// derive default or not, because of the limit rust has on 32 items as max in the
+/// array.
+pub trait CanDerivePartialEq {
+
+ /// Return `true` if `Default` can be derived for this thing, `false`
+ /// otherwise.
+ fn can_derive_partialeq(&self,
+ ctx: &BindgenContext)
+ -> bool;
+}
+
/// A trait that encapsulates the logic for whether or not we can derive `Hash`.
/// The difference between this trait and the CanDeriveHash is that the type
/// implementing this trait cannot use recursion or lookup result from fix point
@@ -98,3 +114,14 @@ pub trait CanTriviallyDeriveHash {
/// otherwise.
fn can_trivially_derive_hash(&self) -> bool;
}
+
+/// A trait that encapsulates the logic for whether or not we can derive `PartialEq`.
+/// The difference between this trait and the CanDerivePartialEq is that the type
+/// implementing this trait cannot use recursion or lookup result from fix point
+/// analysis. It's a helper trait for fix point analysis.
+pub trait CanTriviallyDerivePartialEq {
+
+ /// Return `true` if `PartialEq` can be derived for this thing, `false`
+ /// otherwise.
+ fn can_trivially_derive_partialeq(&self) -> bool;
+}
diff --git a/src/ir/function.rs b/src/ir/function.rs
index 20c026a4..241dcefe 100644
--- a/src/ir/function.rs
+++ b/src/ir/function.rs
@@ -8,7 +8,7 @@ use super::traversal::{EdgeKind, Trace, Tracer};
use super::ty::TypeKind;
use clang;
use clang_sys::{self, CXCallingConv};
-use ir::derive::{CanTriviallyDeriveDebug, CanTriviallyDeriveHash};
+use ir::derive::{CanTriviallyDeriveDebug, CanTriviallyDeriveHash, CanTriviallyDerivePartialEq};
use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
use std::io;
use syntax::abi;
@@ -508,3 +508,17 @@ impl CanTriviallyDeriveHash for FunctionSig {
}
}
}
+
+impl CanTriviallyDerivePartialEq for FunctionSig {
+ fn can_trivially_derive_partialeq(&self) -> bool {
+ if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT {
+ return false;
+ }
+
+ match self.abi {
+ Abi::Known(abi::Abi::C) |
+ Abi::Unknown(..) => true,
+ _ => false,
+ }
+ }
+}
diff --git a/src/ir/item.rs b/src/ir/item.rs
index b51a45ac..4109b5e8 100644
--- a/src/ir/item.rs
+++ b/src/ir/item.rs
@@ -5,7 +5,8 @@ use super::annotations::Annotations;
use super::comment;
use super::comp::MethodKind;
use super::context::{BindgenContext, ItemId, PartialType};
-use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveHash};
+use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveHash,
+ CanDerivePartialEq};
use super::dot::DotAttributes;
use super::function::{Function, FunctionKind};
use super::item_kind::ItemKind;
@@ -300,6 +301,12 @@ impl CanDeriveHash for Item {
}
}
+impl CanDerivePartialEq for Item {
+ fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool {
+ ctx.options().derive_partialeq && ctx.lookup_item_id_can_derive_partialeq(self.id())
+ }
+}
+
/// An item is the base of the bindgen representation, it can be either a
/// module, a type, a function, or a variable (see `ItemKind` for more
/// information).
diff --git a/src/ir/layout.rs b/src/ir/layout.rs
index bac664f1..60cf4678 100644
--- a/src/ir/layout.rs
+++ b/src/ir/layout.rs
@@ -2,7 +2,7 @@
use super::derive::{CanTriviallyDeriveDebug,
CanTriviallyDeriveDefault, CanTriviallyDeriveCopy,
- CanTriviallyDeriveHash};
+ CanTriviallyDeriveHash, CanTriviallyDerivePartialEq};
use super::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, Type, TypeKind};
use clang;
use std::{cmp, mem};
@@ -132,3 +132,11 @@ impl CanTriviallyDeriveHash for Opaque {
.map_or(false, |size| size <= RUST_DERIVE_IN_ARRAY_LIMIT)
}
}
+
+impl CanTriviallyDerivePartialEq for Opaque {
+
+ fn can_trivially_derive_partialeq(&self) -> bool {
+ self.array_size()
+ .map_or(false, |size| size <= RUST_DERIVE_IN_ARRAY_LIMIT)
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 12ab8ac2..74a20292 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -262,6 +262,10 @@ impl Builder {
output_vector.push("--with-derive-hash".into());
}
+ if self.options.derive_partialeq {
+ output_vector.push("--with-derive-partialeq".into());
+ }
+
if !self.options.generate_comments {
output_vector.push("--no-doc-comments".into());
}
@@ -721,6 +725,12 @@ impl Builder {
self
}
+ /// Set whether `PartialEq` should be derived by default.
+ pub fn derive_partialeq(mut self, doit: bool) -> Self {
+ self.options.derive_partialeq = doit;
+ self
+ }
+
/// Emit Clang AST.
pub fn emit_clang_ast(mut self) -> Builder {
self.options.emit_ast = true;
@@ -1055,6 +1065,10 @@ pub struct BindgenOptions {
/// and types.
pub derive_hash: bool,
+ /// True if we should derive PartialEq trait implementations for C/C++ structures
+ /// and types.
+ pub derive_partialeq: bool,
+
/// True if we should avoid using libstd to use libcore instead.
pub use_core: bool,
@@ -1198,6 +1212,7 @@ impl Default for BindgenOptions {
impl_debug: false,
derive_default: false,
derive_hash: false,
+ derive_partialeq: false,
enable_cxx_namespaces: false,
disable_name_namespacing: false,
use_core: false,
diff --git a/src/options.rs b/src/options.rs
index 7b5169b7..6640fad4 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -76,6 +76,9 @@ where
Arg::with_name("with-derive-hash")
.long("with-derive-hash")
.help("Derive hash on any type."),
+ Arg::with_name("with-derive-partialeq")
+ .long("with-derive-partialeq")
+ .help("Derive partialeq on any type."),
Arg::with_name("no-doc-comments")
.long("no-doc-comments")
.help("Avoid including doc comments in the output, see: \
@@ -314,6 +317,10 @@ where
builder = builder.derive_hash(true);
}
+ if matches.is_present("with-derive-partialeq") {
+ builder = builder.derive_partialeq(true);
+ }
+
if matches.is_present("no-derive-default") {
builder = builder.derive_default(false);
}