summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-09-19 12:58:02 -0500
committerGitHub <noreply@github.com>2017-09-19 12:58:02 -0500
commit1906a264c1d3b4620d803dd4030750f981b42978 (patch)
tree55e11b8c7175ca26e9bdda2a9faa0ee04b9e9006
parentda942c43323058024a84af283f2f3de9c596b975 (diff)
parente4a4b47f4481f687f9cd88bd95f617784c2108ba (diff)
Auto merge of #1002 - pepyakin:derive-partialord-when-possible, r=fitzgen
Derive PartialOrd when possible Fixes #882 r? @fitzgen
-rw-r--r--src/codegen/mod.rs7
-rw-r--r--src/ir/analysis/derive_partial_eq_or_partial_ord.rs (renamed from src/ir/analysis/derive_partial_eq.rs)128
-rw-r--r--src/ir/analysis/mod.rs4
-rw-r--r--src/ir/context.rs43
-rw-r--r--src/ir/derive.rs26
-rw-r--r--src/ir/function.rs6
-rw-r--r--src/ir/item.rs14
-rw-r--r--src/ir/layout.rs6
-rw-r--r--src/lib.rs15
-rw-r--r--src/options.rs7
-rw-r--r--tests/expectations/tests/derive-hash-struct-with-anon-struct-float.rs6
-rw-r--r--tests/expectations/tests/derive-hash-struct-with-float-array.rs4
-rw-r--r--tests/expectations/tests/derive-hash-struct-with-pointer.rs10
-rw-r--r--tests/expectations/tests/derive-hash-template-def-float.rs4
-rw-r--r--tests/expectations/tests/derive-hash-template-inst-float.rs34
-rw-r--r--tests/headers/derive-hash-blacklisting.hpp2
-rw-r--r--tests/headers/derive-hash-struct-with-anon-struct-float.h4
-rw-r--r--tests/headers/derive-hash-struct-with-float-array.h4
-rw-r--r--tests/headers/derive-hash-struct-with-pointer.h4
-rw-r--r--tests/headers/derive-hash-template-def-float.hpp4
-rw-r--r--tests/headers/derive-hash-template-inst-float.hpp4
21 files changed, 205 insertions, 131 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index e0d4e46d..810f1367 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -12,7 +12,8 @@ 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, CanDerivePartialEq, CanDeriveEq};
+ CanDeriveHash, CanDerivePartialOrd, CanDerivePartialEq,
+ CanDeriveEq};
use ir::dot;
use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue};
use ir::function::{Abi, Function, FunctionSig};
@@ -1489,6 +1490,10 @@ impl CodeGenerator for CompInfo {
derives.push("Hash");
}
+ if item.can_derive_partialord(ctx) {
+ derives.push("PartialOrd");
+ }
+
if item.can_derive_partialeq(ctx) {
derives.push("PartialEq");
}
diff --git a/src/ir/analysis/derive_partial_eq.rs b/src/ir/analysis/derive_partial_eq_or_partial_ord.rs
index 96689601..876477ab 100644
--- a/src/ir/analysis/derive_partial_eq.rs
+++ b/src/ir/analysis/derive_partial_eq_or_partial_ord.rs
@@ -5,7 +5,7 @@ use ir::comp::CompKind;
use ir::comp::Field;
use ir::comp::FieldMethods;
use ir::context::{BindgenContext, ItemId};
-use ir::derive::CanTriviallyDerivePartialEq;
+use ir::derive::CanTriviallyDerivePartialEqOrPartialOrd;
use ir::item::IsOpaque;
use ir::traversal::EdgeKind;
use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
@@ -13,48 +13,48 @@ use ir::ty::TypeKind;
use std::collections::HashMap;
use std::collections::HashSet;
-/// An analysis that finds for each IR item whether partialeq cannot be derived.
+/// An analysis that finds for each IR item whether partialeq or partialord cannot be derived.
///
-/// We use the monotone constraint function `cannot_derive_partial_eq`, defined as
+/// We use the monotone constraint function `cannot_derive_partialeq_or_partialord`, 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 Array type, partialeq or partialord 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 or partialord.
/// * 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.
+/// partialeq or partialord cannot be derived if the type T refers to cannot be derived partialeq or partialord.
+/// * If T is a compound type, partialeq or partialord cannot be derived if any of its base member
+/// or field cannot be derived partialeq or partialord.
+/// * If T is a pointer, T cannot be derived partialeq or partialord if T is a function pointer
+/// and the function signature cannot be derived partialeq or partialord.
/// * 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.
+/// derived partialeq or partialord if any of the template arguments or template definition
+/// cannot derive partialeq or partialord.
#[derive(Debug, Clone)]
-pub struct CannotDerivePartialEq<'ctx> {
+pub struct CannotDerivePartialEqOrPartialOrd<'ctx> {
ctx: &'ctx BindgenContext,
// The incremental result of this analysis's computation. Everything in this
- // set cannot derive partialeq.
- cannot_derive_partialeq: HashSet<ItemId>,
+ // set cannot derive partialeq or partialord.
+ cannot_derive_partialeq_or_partialord: 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.
+ // `cannot_derive_partialeq_or_partialord` 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.
+ // can derive partialeq or partialord.
dependencies: HashMap<ItemId, Vec<ItemId>>,
}
-impl<'ctx> CannotDerivePartialEq<'ctx> {
+impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
fn consider_edge(kind: EdgeKind) -> bool {
match kind {
// These are the only edges that can affect whether a type can derive
- // partialeq or not.
+ // partialeq or partialord.
EdgeKind::BaseMember |
EdgeKind::Field |
EdgeKind::TypeReference |
@@ -75,9 +75,9 @@ impl<'ctx> CannotDerivePartialEq<'ctx> {
}
fn insert(&mut self, id: ItemId) -> ConstrainResult {
- trace!("inserting {:?} into the cannot_derive_partialeq set", id);
+ trace!("inserting {:?} into the cannot_derive_partialeq_or_partialord set", id);
- let was_not_already_in_set = self.cannot_derive_partialeq.insert(id);
+ let was_not_already_in_set = self.cannot_derive_partialeq_or_partialord.insert(id);
assert!(
was_not_already_in_set,
"We shouldn't try and insert {:?} twice because if it was \
@@ -89,20 +89,20 @@ impl<'ctx> CannotDerivePartialEq<'ctx> {
}
}
-impl<'ctx> MonotoneFramework for CannotDerivePartialEq<'ctx> {
+impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> {
type Node = ItemId;
type Extra = &'ctx BindgenContext;
type Output = HashSet<ItemId>;
fn new(
ctx: &'ctx BindgenContext,
- ) -> CannotDerivePartialEq<'ctx> {
- let cannot_derive_partialeq = HashSet::new();
+ ) -> CannotDerivePartialEqOrPartialOrd<'ctx> {
+ let cannot_derive_partialeq_or_partialord = HashSet::new();
let dependencies = generate_dependencies(ctx, Self::consider_edge);
- CannotDerivePartialEq {
+ CannotDerivePartialEqOrPartialOrd {
ctx,
- cannot_derive_partialeq,
+ cannot_derive_partialeq_or_partialord,
dependencies,
}
}
@@ -114,8 +114,8 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEq<'ctx> {
fn constrain(&mut self, id: ItemId) -> ConstrainResult {
trace!("constrain: {:?}", id);
- if self.cannot_derive_partialeq.contains(&id) {
- trace!(" already know it cannot derive PartialEq");
+ if self.cannot_derive_partialeq_or_partialord.contains(&id) {
+ trace!(" already know it cannot derive PartialEq or PartialOrd");
return ConstrainResult::Same;
}
@@ -131,15 +131,15 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEq<'ctx> {
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()
+ l.opaque().can_trivially_derive_partialeq_or_partialord()
});
return if layout_can_derive &&
!(ty.is_union() &&
self.ctx.options().rust_features().untagged_union()) {
- trace!(" we can trivially derive PartialEq for the layout");
+ trace!(" we can trivially derive PartialEq or PartialOrd for the layout");
ConstrainResult::Same
} else {
- trace!(" we cannot derive PartialEq for the layout");
+ trace!(" we cannot derive PartialEq or PartialOrd for the layout");
self.insert(id)
};
}
@@ -172,24 +172,24 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEq<'ctx> {
TypeKind::ObjCInterface(..) |
TypeKind::ObjCId |
TypeKind::ObjCSel => {
- trace!(" simple type that can always derive PartialEq");
+ trace!(" simple type that can always derive PartialEq or PartialOrd");
ConstrainResult::Same
}
TypeKind::Array(t, len) => {
- if self.cannot_derive_partialeq.contains(&t) {
+ if self.cannot_derive_partialeq_or_partialord.contains(&t) {
trace!(
- " arrays of T for which we cannot derive PartialEq \
- also cannot derive PartialEq"
+ " arrays of T for which we cannot derive PartialEq or PartialOrd \
+ also cannot derive PartialEq or PartialOrd"
);
return self.insert(id);
}
if len <= RUST_DERIVE_IN_ARRAY_LIMIT {
- trace!(" array is small enough to derive PartialEq");
+ trace!(" array is small enough to derive PartialEq or PartialOrd");
ConstrainResult::Same
} else {
- trace!(" array is too large to derive PartialEq");
+ trace!(" array is too large to derive PartialEq or PartialOrd");
self.insert(id)
}
}
@@ -198,9 +198,9 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEq<'ctx> {
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() {
+ if !sig.can_trivially_derive_partialeq_or_partialord() {
trace!(
- " function pointer that can't trivially derive PartialEq"
+ " function pointer that can't trivially derive PartialEq or PartialOrd"
);
return self.insert(id);
}
@@ -210,29 +210,29 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEq<'ctx> {
}
TypeKind::Function(ref sig) => {
- if !sig.can_trivially_derive_partialeq() {
+ if !sig.can_trivially_derive_partialeq_or_partialord() {
trace!(
- " function that can't trivially derive PartialEq"
+ " function that can't trivially derive PartialEq or PartialOrd"
);
return self.insert(id);
}
- trace!(" function can derive PartialEq");
+ trace!(" function can derive PartialEq or PartialOrd");
ConstrainResult::Same
}
TypeKind::ResolvedTypeRef(t) |
TypeKind::TemplateAlias(t, _) |
TypeKind::Alias(t) => {
- if self.cannot_derive_partialeq.contains(&t) {
+ if self.cannot_derive_partialeq_or_partialord.contains(&t) {
trace!(
" aliases and type refs to T which cannot derive \
- PartialEq also cannot derive PartialEq"
+ PartialEq or PartialOrd also cannot derive PartialEq or PartialOrd"
);
self.insert(id)
} else {
trace!(
" aliases and type refs to T which can derive \
- PartialEq can also derive PartialEq"
+ PartialEq or PartialOrd can also derive PartialEq or PartialOrd"
);
ConstrainResult::Same
}
@@ -246,20 +246,20 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEq<'ctx> {
if info.kind() == CompKind::Union {
if self.ctx.options().rust_features().untagged_union() {
- trace!(" cannot derive PartialEq for Rust unions");
+ trace!(" cannot derive PartialEq or PartialOrd for Rust unions");
return self.insert(id);
}
if ty.layout(self.ctx).map_or(true, |l| {
- l.opaque().can_trivially_derive_partialeq()
+ l.opaque().can_trivially_derive_partialeq_or_partialord()
})
{
trace!(
- " union layout can trivially derive PartialEq"
+ " union layout can trivially derive PartialEq or PartialOrd"
);
return ConstrainResult::Same;
} else {
- trace!(" union layout cannot derive PartialEq");
+ trace!(" union layout cannot derive PartialEq or PartialOrd");
return self.insert(id);
}
}
@@ -267,11 +267,11 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEq<'ctx> {
let bases_cannot_derive =
info.base_members().iter().any(|base| {
!self.ctx.whitelisted_items().contains(&base.ty) ||
- self.cannot_derive_partialeq.contains(&base.ty)
+ self.cannot_derive_partialeq_or_partialord.contains(&base.ty)
});
if bases_cannot_derive {
trace!(
- " base members cannot derive PartialEq, so we can't \
+ " base members cannot derive PartialEq or PartialOrd, so we can't \
either"
);
return self.insert(id);
@@ -283,7 +283,7 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEq<'ctx> {
!self.ctx.whitelisted_items().contains(
&data.ty(),
) ||
- self.cannot_derive_partialeq.contains(
+ self.cannot_derive_partialeq_or_partialord.contains(
&data.ty(),
)
}
@@ -292,7 +292,7 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEq<'ctx> {
!self.ctx.whitelisted_items().contains(
&b.ty(),
) ||
- self.cannot_derive_partialeq.contains(
+ self.cannot_derive_partialeq_or_partialord.contains(
&b.ty(),
)
})
@@ -300,7 +300,7 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEq<'ctx> {
});
if fields_cannot_derive {
trace!(
- " fields cannot derive PartialEq, so we can't either"
+ " fields cannot derive PartialEq or PartialOrd, so we can't either"
);
return self.insert(id);
}
@@ -312,11 +312,11 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEq<'ctx> {
TypeKind::TemplateInstantiation(ref template) => {
let args_cannot_derive =
template.template_arguments().iter().any(|arg| {
- self.cannot_derive_partialeq.contains(&arg)
+ self.cannot_derive_partialeq_or_partialord.contains(&arg)
});
if args_cannot_derive {
trace!(
- " template args cannot derive PartialEq, so \
+ " template args cannot derive PartialEq or PartialOrd, so \
insantiation can't either"
);
return self.insert(id);
@@ -326,18 +326,18 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEq<'ctx> {
!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(
+ let def_cannot_derive = self.cannot_derive_partialeq_or_partialord.contains(
&template.template_definition(),
);
if def_cannot_derive {
trace!(
- " template definition cannot derive PartialEq, so \
+ " template definition cannot derive PartialEq or PartialOrd, so \
insantiation can't either"
);
return self.insert(id);
}
- trace!(" template instantiation can derive PartialEq");
+ trace!(" template instantiation can derive PartialEq or PartialOrd");
ConstrainResult::Same
}
@@ -362,8 +362,8 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEq<'ctx> {
}
}
-impl<'ctx> From<CannotDerivePartialEq<'ctx>> for HashSet<ItemId> {
- fn from(analysis: CannotDerivePartialEq<'ctx>) -> Self {
- analysis.cannot_derive_partialeq
+impl<'ctx> From<CannotDerivePartialEqOrPartialOrd<'ctx>> for HashSet<ItemId> {
+ fn from(analysis: CannotDerivePartialEqOrPartialOrd<'ctx>) -> Self {
+ analysis.cannot_derive_partialeq_or_partialord
}
}
diff --git a/src/ir/analysis/mod.rs b/src/ir/analysis/mod.rs
index ab19cb4f..179fa33d 100644
--- a/src/ir/analysis/mod.rs
+++ b/src/ir/analysis/mod.rs
@@ -55,8 +55,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;
+mod derive_partial_eq_or_partial_ord;
+pub use self::derive_partial_eq_or_partial_ord::CannotDerivePartialEqOrPartialOrd;
mod has_float;
pub use self::has_float::HasFloat;
diff --git a/src/ir/context.rs b/src/ir/context.rs
index 031b0329..513cc665 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -2,11 +2,12 @@
use super::analysis::{CannotDeriveCopy, CannotDeriveDebug,
CannotDeriveDefault, CannotDeriveHash,
- CannotDerivePartialEq, HasTypeParameterInArray,
+ CannotDerivePartialEqOrPartialOrd, HasTypeParameterInArray,
HasVtableAnalysis, HasDestructorAnalysis, UsedTemplateParameters,
HasFloat, analyze};
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault,
- CanDeriveHash, CanDerivePartialEq, CanDeriveEq};
+ CanDeriveHash, CanDerivePartialOrd, CanDerivePartialEq,
+ CanDeriveEq};
use super::int::IntKind;
use super::item::{HasTypeParamInArray, IsOpaque, Item, ItemAncestors,
ItemCanonicalPath, ItemSet};
@@ -68,17 +69,24 @@ impl CanDeriveHash for ItemId {
}
}
+impl CanDerivePartialOrd for ItemId {
+ fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool {
+ ctx.options().derive_partialord &&
+ ctx.lookup_item_id_can_derive_partialeq_or_partialord(*self)
+ }
+}
+
impl CanDerivePartialEq for ItemId {
fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool {
ctx.options().derive_partialeq &&
- ctx.lookup_item_id_can_derive_partialeq(*self)
+ ctx.lookup_item_id_can_derive_partialeq_or_partialord(*self)
}
}
impl CanDeriveEq for ItemId {
fn can_derive_eq(&self, ctx: &BindgenContext) -> bool {
ctx.options().derive_eq &&
- ctx.lookup_item_id_can_derive_partialeq(*self) &&
+ ctx.lookup_item_id_can_derive_partialeq_or_partialord(*self) &&
!ctx.lookup_item_id_has_float(&self)
}
}
@@ -225,7 +233,7 @@ pub struct BindgenContext {
///
/// 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>>,
+ cannot_derive_partialeq_or_partialord: Option<HashSet<ItemId>>,
/// The set of (`ItemId's of`) types that has vtable.
///
@@ -392,7 +400,7 @@ impl BindgenContext {
cannot_derive_copy: None,
cannot_derive_copy_in_array: None,
cannot_derive_hash: None,
- cannot_derive_partialeq: None,
+ cannot_derive_partialeq_or_partialord: None,
have_vtable: None,
have_destructor: None,
has_type_param_in_array: None,
@@ -947,7 +955,7 @@ impl BindgenContext {
self.compute_has_type_param_in_array();
self.compute_has_float();
self.compute_cannot_derive_hash();
- self.compute_cannot_derive_partialeq_or_eq();
+ self.compute_cannot_derive_partialord_partialeq_or_eq();
let ret = cb(self);
self.in_codegen = false;
@@ -2123,27 +2131,26 @@ impl BindgenContext {
!self.cannot_derive_hash.as_ref().unwrap().contains(&id)
}
- /// Compute whether we can derive PartialEq. This method is also used in calculating
- /// whether we can derive Eq
- fn compute_cannot_derive_partialeq_or_eq(&mut self) {
- let _t = self.timer("compute_cannot_derive_partialeq_or_eq");
- assert!(self.cannot_derive_partialeq.is_none());
- if self.options.derive_partialeq || self.options.derive_eq {
- self.cannot_derive_partialeq = Some(analyze::<CannotDerivePartialEq>(self));
+ /// Compute whether we can derive PartialOrd, PartialEq or Eq.
+ fn compute_cannot_derive_partialord_partialeq_or_eq(&mut self) {
+ let _t = self.timer("compute_cannot_derive_partialord_partialeq_or_eq");
+ assert!(self.cannot_derive_partialeq_or_partialord.is_none());
+ if self.options.derive_partialord || self.options.derive_partialeq || self.options.derive_eq {
+ self.cannot_derive_partialeq_or_partialord = Some(analyze::<CannotDerivePartialEqOrPartialOrd>(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 {
+ /// derive partialeq or partialord.
+ pub fn lookup_item_id_can_derive_partialeq_or_partialord(&self, id: ItemId) -> bool {
assert!(
self.in_codegen_phase(),
- "We only compute can_derive_debug when we enter codegen"
+ "We only compute can_derive_partialeq_or_partialord 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)
+ !self.cannot_derive_partialeq_or_partialord.as_ref().unwrap().contains(&id)
}
/// Look up whether the item with `id` can
diff --git a/src/ir/derive.rs b/src/ir/derive.rs
index 909d5e42..0d6b2875 100644
--- a/src/ir/derive.rs
+++ b/src/ir/derive.rs
@@ -79,7 +79,7 @@ pub trait CanDeriveHash {
fn can_derive_hash(&self, ctx: &BindgenContext) -> bool;
}
-/// A trait that encapsulates the logic for whether or not we can derive `PartialEq`
+/// 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
@@ -87,11 +87,24 @@ pub trait CanDeriveHash {
/// 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`
+ /// Return `true` if `PartialEq` 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 `PartialOrd`
+/// 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 CanDerivePartialOrd {
+ /// Return `true` if `PartialOrd` can be derived for this thing, `false`
+ /// otherwise.
+ fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool;
+}
+
/// A trait that encapsulates the logic for whether or not we can derive `Eq`
/// for a given thing.
///
@@ -118,12 +131,13 @@ pub trait CanTriviallyDeriveHash {
fn can_trivially_derive_hash(&self) -> bool;
}
-/// A trait that encapsulates the logic for whether or not we can derive `PartialEq`.
+/// A trait that encapsulates the logic for whether or not we can derive `PartialEq`
+/// or `PartialOrd`.
/// 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`
+pub trait CanTriviallyDerivePartialEqOrPartialOrd {
+ /// Return `true` if `PartialEq` or `PartialOrd` can be derived for this thing, `false`
/// otherwise.
- fn can_trivially_derive_partialeq(&self) -> bool;
+ fn can_trivially_derive_partialeq_or_partialord(&self) -> bool;
}
diff --git a/src/ir/function.rs b/src/ir/function.rs
index b08824af..f37f0f3c 100644
--- a/src/ir/function.rs
+++ b/src/ir/function.rs
@@ -9,7 +9,7 @@ use super::ty::TypeKind;
use clang;
use clang_sys::{self, CXCallingConv};
use ir::derive::{CanTriviallyDeriveDebug, CanTriviallyDeriveHash,
- CanTriviallyDerivePartialEq};
+ CanTriviallyDerivePartialEqOrPartialOrd};
use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
use quote;
use std::io;
@@ -556,8 +556,8 @@ impl CanTriviallyDeriveHash for FunctionSig {
}
}
-impl CanTriviallyDerivePartialEq for FunctionSig {
- fn can_trivially_derive_partialeq(&self) -> bool {
+impl CanTriviallyDerivePartialEqOrPartialOrd for FunctionSig {
+ fn can_trivially_derive_partialeq_or_partialord(&self) -> bool {
if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT {
return false;
}
diff --git a/src/ir/item.rs b/src/ir/item.rs
index 2a4df7aa..dbc215cf 100644
--- a/src/ir/item.rs
+++ b/src/ir/item.rs
@@ -6,7 +6,8 @@ use super::comment;
use super::comp::MethodKind;
use super::context::{BindgenContext, ItemId, PartialType};
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault,
- CanDeriveHash, CanDerivePartialEq, CanDeriveEq};
+ CanDeriveHash, CanDerivePartialOrd, CanDerivePartialEq,
+ CanDeriveEq};
use super::dot::DotAttributes;
use super::function::{Function, FunctionKind};
use super::item_kind::ItemKind;
@@ -330,17 +331,24 @@ impl CanDeriveHash for Item {
}
}
+impl CanDerivePartialOrd for Item {
+ fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool {
+ ctx.options().derive_partialord &&
+ ctx.lookup_item_id_can_derive_partialeq_or_partialord(self.id())
+ }
+}
+
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())
+ ctx.lookup_item_id_can_derive_partialeq_or_partialord(self.id())
}
}
impl CanDeriveEq for Item {
fn can_derive_eq(&self, ctx: &BindgenContext) -> bool {
ctx.options().derive_eq &&
- ctx.lookup_item_id_can_derive_partialeq(self.id()) &&
+ ctx.lookup_item_id_can_derive_partialeq_or_partialord(self.id()) &&
!ctx.lookup_item_id_has_float(&self.id())
}
}
diff --git a/src/ir/layout.rs b/src/ir/layout.rs
index 4b0b1769..298fe54a 100644
--- a/src/ir/layout.rs
+++ b/src/ir/layout.rs
@@ -2,7 +2,7 @@
use super::derive::{CanTriviallyDeriveCopy, CanTriviallyDeriveDebug,
CanTriviallyDeriveDefault, CanTriviallyDeriveHash,
- CanTriviallyDerivePartialEq};
+ CanTriviallyDerivePartialEqOrPartialOrd};
use super::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, Type, TypeKind};
use clang;
use std::{cmp, mem};
@@ -138,8 +138,8 @@ impl CanTriviallyDeriveHash for Opaque {
}
}
-impl CanTriviallyDerivePartialEq for Opaque {
- fn can_trivially_derive_partialeq(&self) -> bool {
+impl CanTriviallyDerivePartialEqOrPartialOrd for Opaque {
+ fn can_trivially_derive_partialeq_or_partialord(&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 66d0a6ca..72770411 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -261,6 +261,10 @@ impl Builder {
output_vector.push("--with-derive-hash".into());
}
+ if self.options.derive_partialord {
+ output_vector.push("--with-derive-partialord".into());
+ }
+
if self.options.derive_partialeq {
output_vector.push("--with-derive-partialeq".into());
}
@@ -814,6 +818,12 @@ impl Builder {
self
}
+ /// Set whether `PartialOrd` should be derived by default.
+ pub fn derive_partialord(mut self, doit: bool) -> Self {
+ self.options.derive_partialord = doit;
+ self
+ }
+
/// Set whether `PartialEq` should be derived by default.
/// If we don't compute partialeq, we also cannot compute
/// eq. Set the derive_eq to `false` when doit is `false`.
@@ -1176,6 +1186,10 @@ struct BindgenOptions {
/// and types.
derive_hash: bool,
+ /// True if we should derive PartialOrd trait implementations for C/C++ structures
+ /// and types.
+ derive_partialord: bool,
+
/// True if we should derive PartialEq trait implementations for C/C++ structures
/// and types.
derive_partialeq: bool,
@@ -1325,6 +1339,7 @@ impl Default for BindgenOptions {
impl_debug: false,
derive_default: false,
derive_hash: false,
+ derive_partialord: false,
derive_partialeq: false,
derive_eq: false,
enable_cxx_namespaces: false,
diff --git a/src/options.rs b/src/options.rs
index 9ebedc5d..b3182270 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -83,6 +83,9 @@ where
Arg::with_name("with-derive-partialeq")
.long("with-derive-partialeq")
.help("Derive partialeq on any type."),
+ Arg::with_name("with-derive-partialord")
+ .long("with-derive-partialord")
+ .help("Derive partialord on any type."),
Arg::with_name("with-derive-eq")
.long("with-derive-eq")
.help("Derive eq on any type. Enable this option also enables --with-derive-partialeq"),
@@ -340,6 +343,10 @@ where
builder = builder.derive_partialeq(true);
}
+ if matches.is_present("with-derive-partialord") {
+ builder = builder.derive_partialord(true);
+ }
+
if matches.is_present("with-derive-eq") {
builder = builder.derive_eq(true);
}
diff --git a/tests/expectations/tests/derive-hash-struct-with-anon-struct-float.rs b/tests/expectations/tests/derive-hash-struct-with-anon-struct-float.rs
index 332c1129..da1d2b41 100644
--- a/tests/expectations/tests/derive-hash-struct-with-anon-struct-float.rs
+++ b/tests/expectations/tests/derive-hash-struct-with-anon-struct-float.rs
@@ -5,14 +5,14 @@
-/// A struct containing a struct containing a float that cannot derive hash/eq but can derive partial eq.
+/// A struct containing a struct containing a float that cannot derive hash/eq but can derive partialeq and partialord
#[repr(C)]
-#[derive(Debug, Default, Copy, PartialEq)]
+#[derive(Debug, Default, Copy, PartialOrd, PartialEq)]
pub struct foo {
pub bar: foo__bindgen_ty_1,
}
#[repr(C)]
-#[derive(Debug, Default, Copy, PartialEq)]
+#[derive(Debug, Default, Copy, PartialOrd, PartialEq)]
pub struct foo__bindgen_ty_1 {
pub a: f32,
pub b: f32,
diff --git a/tests/expectations/tests/derive-hash-struct-with-float-array.rs b/tests/expectations/tests/derive-hash-struct-with-float-array.rs
index 43075796..a14a0829 100644
--- a/tests/expectations/tests/derive-hash-struct-with-float-array.rs
+++ b/tests/expectations/tests/derive-hash-struct-with-float-array.rs
@@ -5,9 +5,9 @@
-/// A struct containing an array of floats that cannot derive hash/eq but can derive partialeq.
+/// A struct containing an array of floats that cannot derive hash/eq but can derive partialeq and partialord
#[repr(C)]
-#[derive(Debug, Default, Copy, PartialEq)]
+#[derive(Debug, Default, Copy, PartialOrd, PartialEq)]
pub struct foo {
pub bar: [f32; 3usize],
}
diff --git a/tests/expectations/tests/derive-hash-struct-with-pointer.rs b/tests/expectations/tests/derive-hash-struct-with-pointer.rs
index 28aa1e25..664a19da 100644
--- a/tests/expectations/tests/derive-hash-struct-with-pointer.rs
+++ b/tests/expectations/tests/derive-hash-struct-with-pointer.rs
@@ -5,9 +5,9 @@
-/// Pointers can derive hash/PartialEq/Eq
+/// Pointers can derive Hash/PartialOrd/PartialEq/Eq
#[repr(C)]
-#[derive(Debug, Copy, Hash, PartialEq, Eq)]
+#[derive(Debug, Copy, Hash, PartialOrd, PartialEq, Eq)]
pub struct ConstPtrMutObj {
pub bar: *const ::std::os::raw::c_int,
}
@@ -45,7 +45,7 @@ impl Default for ConstPtrMutObj {
}
}
#[repr(C)]
-#[derive(Debug, Copy, Hash, PartialEq, Eq)]
+#[derive(Debug, Copy, Hash, PartialOrd, PartialEq, Eq)]
pub struct MutPtrMutObj {
pub bar: *mut ::std::os::raw::c_int,
}
@@ -83,7 +83,7 @@ impl Default for MutPtrMutObj {
}
}
#[repr(C)]
-#[derive(Debug, Copy, Hash, PartialEq, Eq)]
+#[derive(Debug, Copy, Hash, PartialOrd, PartialEq, Eq)]
pub struct MutPtrConstObj {
pub bar: *const ::std::os::raw::c_int,
}
@@ -121,7 +121,7 @@ impl Default for MutPtrConstObj {
}
}
#[repr(C)]
-#[derive(Debug, Copy, Hash, PartialEq, Eq)]
+#[derive(Debug, Copy, Hash, PartialOrd, PartialEq, Eq)]
pub struct ConstPtrConstObj {
pub bar: *const ::std::os::raw::c_int,
}
diff --git a/tests/expectations/tests/derive-hash-template-def-float.rs b/tests/expectations/tests/derive-hash-template-def-float.rs
index 7b643901..d882f99d 100644
--- a/tests/expectations/tests/derive-hash-template-def-float.rs
+++ b/tests/expectations/tests/derive-hash-template-def-float.rs
@@ -5,9 +5,9 @@
-/// Template definition containing a float, which cannot derive hash/eq but can derive partialeq.
+/// Template definition containing a float, which cannot derive hash/eq but can derive partialeq and partialord.
#[repr(C)]
-#[derive(Debug, Copy, Clone, PartialEq)]
+#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
pub struct foo<T> {
pub data: T,
pub b: f32,
diff --git a/tests/expectations/tests/derive-hash-template-inst-float.rs b/tests/expectations/tests/derive-hash-template-inst-float.rs
index 7bca45b3..7f79af3e 100644
--- a/tests/expectations/tests/derive-hash-template-inst-float.rs
+++ b/tests/expectations/tests/derive-hash-template-inst-float.rs
@@ -5,9 +5,9 @@
-/// Template definition that doesn't contain float can derive hash/partialeq/eq
+/// Template definition that doesn't contain float can derive hash/partialord/partialeq/eq
#[repr(C)]
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+#[derive(Debug, Copy, Clone, Hash, PartialOrd, PartialEq, Eq)]
pub struct foo<T> {
pub data: T,
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
@@ -19,7 +19,7 @@ impl<T> Default for foo<T> {
}
/// Can derive hash/partialeq/eq when instantiated with int
#[repr(C)]
-#[derive(Debug, Copy, Hash, PartialEq, Eq)]
+#[derive(Debug, Copy, Hash, PartialOrd, PartialEq, Eq)]
pub struct IntStr {
pub a: foo<::std::os::raw::c_int>,
}
@@ -58,7 +58,7 @@ impl Default for IntStr {
}
/// Cannot derive hash/eq when instantiated with float but can derive partialeq
#[repr(C)]
-#[derive(Debug, Copy, PartialEq)]
+#[derive(Debug, Copy, PartialOrd, PartialEq)]
pub struct FloatStr {
pub a: foo<f32>,
}
@@ -102,13 +102,31 @@ fn __bindgen_test_layout_foo_open0_int_close0_instantiation() {
4usize,
concat!(
"Size of template specialization: ",
- stringify ! ( foo < :: std :: os :: raw :: c_int > )
+ stringify!(foo<::std::os::raw::c_int>)
+ )
+ );
+ assert_eq!(
+ ::std::mem::align_of::<foo<::std::os::raw::c_int>>(),
+ 4usize,
+ concat!(
+ "Alignment of template specialization: ",
+ stringify!(foo<::std::os::raw::c_int>)
)
);
- assert_eq ! ( :: std :: mem :: align_of :: < foo < :: std :: os :: raw :: c_int > > ( ) , 4usize , concat ! ( "Alignment of template specialization: " , stringify ! ( foo < :: std :: os :: raw :: c_int > ) ) );
}
#[test]
fn __bindgen_test_layout_foo_open0_float_close0_instantiation() {
- assert_eq ! ( :: std :: mem :: size_of :: < foo < f32 > > ( ) , 4usize , concat ! ( "Size of template specialization: " , stringify ! ( foo < f32 > ) ) );
- assert_eq ! ( :: std :: mem :: align_of :: < foo < f32 > > ( ) , 4usize , concat ! ( "Alignment of template specialization: " , stringify ! ( foo < f32 > ) ) );
+ assert_eq!(
+ ::std::mem::size_of::<foo<f32>>(),
+ 4usize,
+ concat!("Size of template specialization: ", stringify!(foo<f32>))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<foo<f32>>(),
+ 4usize,
+ concat!(
+ "Alignment of template specialization: ",
+ stringify!(foo<f32>)
+ )
+ );
}
diff --git a/tests/headers/derive-hash-blacklisting.hpp b/tests/headers/derive-hash-blacklisting.hpp
index c39c31ad..94a9f783 100644
--- a/tests/headers/derive-hash-blacklisting.hpp
+++ b/tests/headers/derive-hash-blacklisting.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --whitelist-type 'Whitelisted.*' --blacklist-type Blacklisted --raw-line "#[repr(C)] #[derive(Debug, Hash, Copy, Clone, PartialEq, Eq)] pub struct Blacklisted<T> {t: T, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>> }"
+// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-partialeq --with-derive-eq --whitelist-type 'Whitelisted.*' --blacklist-type Blacklisted --raw-line "#[repr(C)] #[derive(Debug, Hash, Copy, Clone, PartialEq, Eq)] pub struct Blacklisted<T> {t: T, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>> }"
//
template <class T>
struct Blacklisted {
diff --git a/tests/headers/derive-hash-struct-with-anon-struct-float.h b/tests/headers/derive-hash-struct-with-anon-struct-float.h
index 64fe7fd9..f96b9449 100644
--- a/tests/headers/derive-hash-struct-with-anon-struct-float.h
+++ b/tests/headers/derive-hash-struct-with-anon-struct-float.h
@@ -1,6 +1,6 @@
-// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq
+// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-partialeq --with-derive-eq
//
-/// A struct containing a struct containing a float that cannot derive hash/eq but can derive partial eq.
+/// A struct containing a struct containing a float that cannot derive hash/eq but can derive partialeq and partialord
struct foo {
struct {
float a;
diff --git a/tests/headers/derive-hash-struct-with-float-array.h b/tests/headers/derive-hash-struct-with-float-array.h
index a34904f7..937217a0 100644
--- a/tests/headers/derive-hash-struct-with-float-array.h
+++ b/tests/headers/derive-hash-struct-with-float-array.h
@@ -1,6 +1,6 @@
-// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq
+// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-partialeq --with-derive-eq
//
-/// A struct containing an array of floats that cannot derive hash/eq but can derive partialeq.
+/// A struct containing an array of floats that cannot derive hash/eq but can derive partialeq and partialord
struct foo {
float bar[3];
};
diff --git a/tests/headers/derive-hash-struct-with-pointer.h b/tests/headers/derive-hash-struct-with-pointer.h
index d7f18a6d..9c8ba0f9 100644
--- a/tests/headers/derive-hash-struct-with-pointer.h
+++ b/tests/headers/derive-hash-struct-with-pointer.h
@@ -1,6 +1,6 @@
-// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq
+// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-partialeq --with-derive-eq
//
-/// Pointers can derive hash/PartialEq/Eq
+/// Pointers can derive Hash/PartialOrd/PartialEq/Eq
struct ConstPtrMutObj {
int* const bar;
};
diff --git a/tests/headers/derive-hash-template-def-float.hpp b/tests/headers/derive-hash-template-def-float.hpp
index 8c1a14d1..2dbe5409 100644
--- a/tests/headers/derive-hash-template-def-float.hpp
+++ b/tests/headers/derive-hash-template-def-float.hpp
@@ -1,6 +1,6 @@
-// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq
+// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-partialeq --with-derive-eq
//
-/// Template definition containing a float, which cannot derive hash/eq but can derive partialeq.
+/// Template definition containing a float, which cannot derive hash/eq but can derive partialeq and partialord.
template <typename T>
struct foo {
T data;
diff --git a/tests/headers/derive-hash-template-inst-float.hpp b/tests/headers/derive-hash-template-inst-float.hpp
index 14fd89a0..d189ba71 100644
--- a/tests/headers/derive-hash-template-inst-float.hpp
+++ b/tests/headers/derive-hash-template-inst-float.hpp
@@ -1,6 +1,6 @@
-// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq
+// bindgen-flags: --with-derive-hash --with-derive-partialord --with-derive-partialeq --with-derive-eq
//
-/// Template definition that doesn't contain float can derive hash/partialeq/eq
+/// Template definition that doesn't contain float can derive hash/partialord/partialeq/eq
template <typename T>
struct foo {
T data;