From 6fa9e4bcf37994b53d986cbf4c0ce71ea2895e45 Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Tue, 19 Sep 2017 16:45:33 +0300 Subject: [PATCH 1/5] =?UTF-8?q?DerivePartialEq=20=E2=86=92=20DerivePartial?= =?UTF-8?q?EqOrPartialOrd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ir/analysis/derive_partial_eq.rs | 128 +++++++++++++-------------- src/ir/analysis/mod.rs | 2 +- src/ir/context.rs | 4 +- src/ir/derive.rs | 26 ++++-- src/ir/function.rs | 6 +- src/ir/layout.rs | 6 +- 6 files changed, 93 insertions(+), 79 deletions(-) diff --git a/src/ir/analysis/derive_partial_eq.rs b/src/ir/analysis/derive_partial_eq.rs index 966896010e..876477abb8 100644 --- a/src/ir/analysis/derive_partial_eq.rs +++ b/src/ir/analysis/derive_partial_eq.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, + // set cannot derive partialeq or partialord. + cannot_derive_partialeq_or_partialord: HashSet, // Dependencies saying that if a key ItemId has been inserted into the - // `cannot_derive_partialeq` set, then each of the ids in Vec need to be - // considered again. + // `cannot_derive_partialeq_or_partialord` set, then each of the ids + // in Vec 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>, } -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; 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> for HashSet { - fn from(analysis: CannotDerivePartialEq<'ctx>) -> Self { - analysis.cannot_derive_partialeq +impl<'ctx> From> for HashSet { + 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 ab19cb4fda..9caf789fae 100644 --- a/src/ir/analysis/mod.rs +++ b/src/ir/analysis/mod.rs @@ -56,7 +56,7 @@ 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; +pub use self::derive_partial_eq::CannotDerivePartialEqOrPartialOrd; mod has_float; pub use self::has_float::HasFloat; diff --git a/src/ir/context.rs b/src/ir/context.rs index 031b03290d..d512b2c89e 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -2,7 +2,7 @@ use super::analysis::{CannotDeriveCopy, CannotDeriveDebug, CannotDeriveDefault, CannotDeriveHash, - CannotDerivePartialEq, HasTypeParameterInArray, + CannotDerivePartialEqOrPartialOrd, HasTypeParameterInArray, HasVtableAnalysis, HasDestructorAnalysis, UsedTemplateParameters, HasFloat, analyze}; use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, @@ -2129,7 +2129,7 @@ impl BindgenContext { 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::(self)); + self.cannot_derive_partialeq = Some(analyze::(self)); } } diff --git a/src/ir/derive.rs b/src/ir/derive.rs index 909d5e4242..0d6b287591 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 b08824af85..f37f0f3c27 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/layout.rs b/src/ir/layout.rs index 4b0b17692e..298fe54a7d 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 }) From f3225ffa8d0504b03d3640fd8012ffedcb11d0c1 Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Tue, 19 Sep 2017 17:13:14 +0300 Subject: [PATCH 2/5] derive_partialord in BindgenOptions and Builder --- src/lib.rs | 15 +++++++++++++++ src/options.rs | 7 +++++++ 2 files changed, 22 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 66d0a6ca2e..727704113c 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 9ebedc5d16..b3182270ca 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); } From d6b4213e0842a766574bb34b673ad3d682c80ccf Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Tue, 19 Sep 2017 17:42:44 +0300 Subject: [PATCH 3/5] Emit derive(PartialOrd) --- src/codegen/mod.rs | 7 ++++++- src/ir/context.rs | 41 ++++++++++++++++++++++++----------------- src/ir/item.rs | 14 +++++++++++--- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index e0d4e46d08..810f13675a 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/context.rs b/src/ir/context.rs index d512b2c89e..513cc665ef 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -6,7 +6,8 @@ use super::analysis::{CannotDeriveCopy, CannotDeriveDebug, 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>, + cannot_derive_partialeq_or_partialord: Option>, /// 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::(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::(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/item.rs b/src/ir/item.rs index 2a4df7aab0..dbc215cf64 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()) } } From 2f4c7567df8fb6694b9ea90c6f8873e559b9baf8 Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Tue, 19 Sep 2017 18:45:31 +0300 Subject: [PATCH 4/5] Rename deriver_partial_eq_or_partial_ord. --- ...rive_partial_eq.rs => derive_partial_eq_or_partial_ord.rs} | 0 src/ir/analysis/mod.rs | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/ir/analysis/{derive_partial_eq.rs => derive_partial_eq_or_partial_ord.rs} (100%) diff --git a/src/ir/analysis/derive_partial_eq.rs b/src/ir/analysis/derive_partial_eq_or_partial_ord.rs similarity index 100% rename from src/ir/analysis/derive_partial_eq.rs rename to src/ir/analysis/derive_partial_eq_or_partial_ord.rs diff --git a/src/ir/analysis/mod.rs b/src/ir/analysis/mod.rs index 9caf789fae..179fa33db0 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::CannotDerivePartialEqOrPartialOrd; +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; From e4a4b47f4481f687f9cd88bd95f617784c2108ba Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Tue, 19 Sep 2017 20:40:42 +0300 Subject: [PATCH 5/5] Add --with-derive-partialord for some tests --- ...rive-hash-struct-with-anon-struct-float.rs | 6 ++-- .../derive-hash-struct-with-float-array.rs | 4 +-- .../tests/derive-hash-struct-with-pointer.rs | 10 +++--- .../tests/derive-hash-template-def-float.rs | 4 +-- .../tests/derive-hash-template-inst-float.rs | 34 ++++++++++++++----- tests/headers/derive-hash-blacklisting.hpp | 2 +- ...erive-hash-struct-with-anon-struct-float.h | 4 +-- .../derive-hash-struct-with-float-array.h | 4 +-- .../headers/derive-hash-struct-with-pointer.h | 4 +-- .../derive-hash-template-def-float.hpp | 4 +-- .../derive-hash-template-inst-float.hpp | 4 +-- 11 files changed, 49 insertions(+), 31 deletions(-) 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 332c1129f7..da1d2b41d1 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 43075796d6..a14a08293e 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 28aa1e253b..664a19dade 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 7b64390137..d882f99d86 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 { 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 7bca45b3d6..7f79af3e14 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 { pub data: T, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, @@ -19,7 +19,7 @@ impl Default for foo { } /// 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, } @@ -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::>(), + 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::>(), + 4usize, + concat!("Size of template specialization: ", stringify!(foo)) + ); + assert_eq!( + ::std::mem::align_of::>(), + 4usize, + concat!( + "Alignment of template specialization: ", + stringify!(foo) + ) + ); } diff --git a/tests/headers/derive-hash-blacklisting.hpp b/tests/headers/derive-hash-blacklisting.hpp index c39c31adcd..94a9f783ec 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, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell> }" +// 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, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell> }" // template 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 64fe7fd937..f96b9449d4 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 a34904f704..937217a0ef 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 d7f18a6d66..9c8ba0f92a 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 8c1a14d1b4..2dbe5409e8 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 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 14fd89a046..d189ba713f 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 struct foo { T data;