From c1a188c865952771865834848c7f84f2652985c9 Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Sun, 29 Oct 2017 16:06:00 +0300 Subject: Rename derive_partialeq_or_partialord --- .../analysis/derive_partial_eq_or_partial_ord.rs | 424 --------------------- src/ir/analysis/derive_partialeq_or_partialord.rs | 424 +++++++++++++++++++++ src/ir/analysis/mod.rs | 4 +- 3 files changed, 426 insertions(+), 426 deletions(-) delete mode 100644 src/ir/analysis/derive_partial_eq_or_partial_ord.rs create mode 100644 src/ir/analysis/derive_partialeq_or_partialord.rs diff --git a/src/ir/analysis/derive_partial_eq_or_partial_ord.rs b/src/ir/analysis/derive_partial_eq_or_partial_ord.rs deleted file mode 100644 index f54650dd..00000000 --- a/src/ir/analysis/derive_partial_eq_or_partial_ord.rs +++ /dev/null @@ -1,424 +0,0 @@ -//! Determining which types for which we cannot emit `#[derive(PartialEq, -//! PartialOrd)]`. - -use super::{ConstrainResult, MonotoneFramework, generate_dependencies}; -use ir::comp::CompKind; -use ir::context::{BindgenContext, ItemId}; -use ir::derive::{CanTriviallyDerivePartialEqOrPartialOrd, CanDerive, CannotDeriveReason}; -use ir::item::{Item, IsOpaque}; -use ir::traversal::{EdgeKind, Trace}; -use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT; -use ir::ty::{TypeKind, Type}; -use std::collections::HashMap; - -/// An analysis that finds for each IR item whether `PartialEq`/`PartialOrd` -/// cannot be derived. -/// -/// 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` or partialord cannot be derived if the array is incomplete, if the length of -/// the array is larger than the limit, or the type of data the array contains cannot derive -/// `PartialEq`/`PartialOrd`. -/// -/// * If T is a type alias, a templated alias or an indirection to another type, -/// `PartialEq`/`PartialOrd` cannot be derived if the type T refers to cannot be -/// derived `PartialEq`/`PartialOrd`. -/// -/// * If T is a compound type, `PartialEq`/`PartialOrd` cannot be derived if any -/// of its base member or field cannot be derived `PartialEq`/`PartialOrd`. -/// -/// * If T is a pointer, T cannot be derived `PartialEq`/`PartialOrd` if T is a -/// function pointer and the function signature cannot be derived -/// `PartialEq`/`PartialOrd`. -/// -/// * If T is an instantiation of an abstract template definition, T cannot be -/// derived `PartialEq`/`PartialOrd` if any of the template arguments or -/// template definition cannot derive `PartialEq`/`PartialOrd`. -#[derive(Debug, Clone)] -pub struct CannotDerivePartialEqOrPartialOrd<'ctx> { - ctx: &'ctx BindgenContext, - - // The incremental result of this analysis's computation. Everything in this - // set cannot derive `PartialEq`/`PartialOrd`. - cannot_derive_partialeq_or_partialord: HashMap, - - // Dependencies saying that if a key ItemId has been inserted into the - // `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`/`PartialOrd`. - dependencies: HashMap>, -} - -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`/`PartialOrd`. - 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: Id, - reason: CannotDeriveReason, - ) -> ConstrainResult { - let id = id.into(); - trace!( - "inserting {:?} into the cannot_derive_partialeq_or_partialord because {:?}", - id, - reason - ); - let existing = self.cannot_derive_partialeq_or_partialord - .insert(id, reason); - assert!(can_supersede(existing, Some(reason))); - ConstrainResult::Changed - } - - fn constrain_type( - &mut self, - item: &Item, - ty: &Type, - ) -> Option { - if !self.ctx.whitelisted_items().contains(&item.id()) { - return Some(CannotDeriveReason::Other); - } - - if self.ctx.no_partialeq_by_name(&item) { - return Some(CannotDeriveReason::Other); - } - - trace!("ty: {:?}", ty); - if item.is_opaque(self.ctx, &()) { - if ty.is_union() - && self.ctx.options().rust_features().untagged_union() - { - trace!( - " cannot derive `PartialEq`/`PartialOrd` for Rust unions" - ); - return Some(CannotDeriveReason::Other); - } - - let layout_can_derive = ty.layout(self.ctx) - .map_or(CanDerive::Yes, |l| { - l.opaque().can_trivially_derive_partialeq_or_partialord() - }); - - return match layout_can_derive { - CanDerive::Yes => { - trace!( - " we can trivially derive `PartialEq`/`PartialOrd` for the layout" - ); - None - } - CanDerive::No(reason) => { - trace!( - " we cannot derive `PartialEq`/`PartialOrd` for the layout" - ); - Some(reason) - } - }; - } - - 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::TypeParam | - TypeKind::UnresolvedTypeRef(..) | - TypeKind::BlockPointer | - TypeKind::Reference(..) | - TypeKind::ObjCInterface(..) | - TypeKind::ObjCId | - TypeKind::ObjCSel => { - trace!( - " simple type that can always derive `PartialEq`/`PartialOrd`" - ); - return None; - } - - TypeKind::Array(t, len) => { - if self.cannot_derive_partialeq_or_partialord.contains_key(&t.into()) { - trace!( - " arrays of T for which we cannot derive `PartialEq`/`PartialOrd` \ - also cannot derive `PartialEq`/`PartialOrd`" - ); - return Some(CannotDeriveReason::Other); - } - - if len == 0 { - trace!( - " cannot derive `PartialEq`/`PartialOrd` for incomplete arrays" - ); - return Some(CannotDeriveReason::Other); - } else if len <= RUST_DERIVE_IN_ARRAY_LIMIT { - trace!( - " array is small enough to derive `PartialEq`/`PartialOrd`" - ); - return None; - } else { - trace!( - " array is too large to derive `PartialEq`/`PartialOrd`" - ); - return Some(CannotDeriveReason::ArrayTooLarge); - } - } - - 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 let CanDerive::No(_) = - sig.can_trivially_derive_partialeq_or_partialord() - { - trace!( - " function pointer that can't trivially derive `PartialEq`/`PartialOrd`" - ); - return Some(CannotDeriveReason::Other); - } - } - trace!(" pointers can derive `PartialEq`/`PartialOrd`"); - return None; - } - - TypeKind::Function(ref sig) => { - if let CanDerive::No(_) = - sig.can_trivially_derive_partialeq_or_partialord() - { - trace!( - " function that can't trivially derive `PartialEq`/`PartialOrd`" - ); - return Some(CannotDeriveReason::Other); - } - trace!(" function can derive `PartialEq`/`PartialOrd`"); - return None; - } - - 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`/`PartialOrd` for Rust unions" - ); - return Some(CannotDeriveReason::Other); - } - - let layout_can_derive = ty.layout(self.ctx).map_or( - CanDerive::Yes, - |l| { - l.opaque() - .can_trivially_derive_partialeq_or_partialord() - }, - ); - return match layout_can_derive { - CanDerive::Yes => { - trace!( - " union layout can trivially derive `PartialEq`/`PartialOrd`" - ); - None - } - CanDerive::No(reason) => { - trace!( - " union layout cannot derive `PartialEq`/`PartialOrd`" - ); - Some(reason) - } - }; - } - return self.constrain_join(item); - } - - TypeKind::ResolvedTypeRef(..) | - TypeKind::TemplateAlias(..) | - TypeKind::Alias(..) | - TypeKind::TemplateInstantiation(..) => { - return self.constrain_join(item); - } - - TypeKind::Opaque => unreachable!( - "The early ty.is_opaque check should have handled this case" - ), - } - } - - fn constrain_join(&mut self, item: &Item) -> Option { - let mut candidate = None; - - item.trace( - self.ctx, - &mut |sub_id, edge_kind| { - // Ignore ourselves, since union with ourself is a - // no-op. Ignore edges that aren't relevant to the - // analysis. - if sub_id == item.id() || !Self::consider_edge(edge_kind) { - return; - } - - let reason = self.cannot_derive_partialeq_or_partialord - .get(&sub_id) - .cloned(); - - if can_supersede(candidate, reason) { - candidate = reason; - } - }, - &(), - ); - - candidate - } -} - -/// Check if the one reason could supersede another. -/// -/// To keep this analysis monotone we should go only in one direction. -/// If the abscence of the reason is at the bottom and `CannotDeriveReason::Other` -/// is at the top, then we can only go upwards. -/// -/// Other -/// ^ -/// | -/// ArrayTooLarge -/// ^ -/// | -/// None -/// -fn can_supersede(from: Option, to: Option) -> bool { - fn rank(maybe_reason: Option) -> usize { - match maybe_reason { - None => 0, - Some(CannotDeriveReason::ArrayTooLarge) => 1, - Some(CannotDeriveReason::Other) => 2, - } - } - rank(from) <= rank(to) -} - -impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { - type Node = ItemId; - type Extra = &'ctx BindgenContext; - type Output = HashMap; - - fn new( - ctx: &'ctx BindgenContext, - ) -> CannotDerivePartialEqOrPartialOrd<'ctx> { - let cannot_derive_partialeq_or_partialord = HashMap::new(); - let dependencies = generate_dependencies(ctx, Self::consider_edge); - - CannotDerivePartialEqOrPartialOrd { - ctx, - cannot_derive_partialeq_or_partialord, - dependencies, - } - } - - fn initial_worklist(&self) -> Vec { - // The transitive closure of all whitelisted items, including explicitly - // blacklisted items. - self.ctx - .whitelisted_items() - .iter() - .cloned() - .flat_map(|i| { - let mut reachable = vec![i]; - i.trace( - self.ctx, - &mut |s, _| { - reachable.push(s); - }, - &(), - ); - reachable - }) - .collect() - } - - fn constrain(&mut self, id: ItemId) -> ConstrainResult { - trace!("constrain: {:?}", id); - - if let Some(CannotDeriveReason::Other) = - self.cannot_derive_partialeq_or_partialord.get(&id).cloned() - { - trace!(" already know it cannot derive `PartialEq`/`PartialOrd`"); - return ConstrainResult::Same; - } - - let item = self.ctx.resolve_item(id); - let maybe_reason = match item.as_type() { - Some(ty) => { - self.constrain_type(item, ty).or_else(|| { - 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. - Some(CannotDeriveReason::ArrayTooLarge) - } else { - None - } - }) - } - None => self.constrain_join(item), - }; - - if let Some(reason) = maybe_reason { - self.insert(id, reason) - } else { - ConstrainResult::Same - } - } - - fn each_depending_on(&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> From> for HashMap { - fn from(analysis: CannotDerivePartialEqOrPartialOrd<'ctx>) -> Self { - analysis.cannot_derive_partialeq_or_partialord - } -} diff --git a/src/ir/analysis/derive_partialeq_or_partialord.rs b/src/ir/analysis/derive_partialeq_or_partialord.rs new file mode 100644 index 00000000..f54650dd --- /dev/null +++ b/src/ir/analysis/derive_partialeq_or_partialord.rs @@ -0,0 +1,424 @@ +//! Determining which types for which we cannot emit `#[derive(PartialEq, +//! PartialOrd)]`. + +use super::{ConstrainResult, MonotoneFramework, generate_dependencies}; +use ir::comp::CompKind; +use ir::context::{BindgenContext, ItemId}; +use ir::derive::{CanTriviallyDerivePartialEqOrPartialOrd, CanDerive, CannotDeriveReason}; +use ir::item::{Item, IsOpaque}; +use ir::traversal::{EdgeKind, Trace}; +use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT; +use ir::ty::{TypeKind, Type}; +use std::collections::HashMap; + +/// An analysis that finds for each IR item whether `PartialEq`/`PartialOrd` +/// cannot be derived. +/// +/// 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` or partialord cannot be derived if the array is incomplete, if the length of +/// the array is larger than the limit, or the type of data the array contains cannot derive +/// `PartialEq`/`PartialOrd`. +/// +/// * If T is a type alias, a templated alias or an indirection to another type, +/// `PartialEq`/`PartialOrd` cannot be derived if the type T refers to cannot be +/// derived `PartialEq`/`PartialOrd`. +/// +/// * If T is a compound type, `PartialEq`/`PartialOrd` cannot be derived if any +/// of its base member or field cannot be derived `PartialEq`/`PartialOrd`. +/// +/// * If T is a pointer, T cannot be derived `PartialEq`/`PartialOrd` if T is a +/// function pointer and the function signature cannot be derived +/// `PartialEq`/`PartialOrd`. +/// +/// * If T is an instantiation of an abstract template definition, T cannot be +/// derived `PartialEq`/`PartialOrd` if any of the template arguments or +/// template definition cannot derive `PartialEq`/`PartialOrd`. +#[derive(Debug, Clone)] +pub struct CannotDerivePartialEqOrPartialOrd<'ctx> { + ctx: &'ctx BindgenContext, + + // The incremental result of this analysis's computation. Everything in this + // set cannot derive `PartialEq`/`PartialOrd`. + cannot_derive_partialeq_or_partialord: HashMap, + + // Dependencies saying that if a key ItemId has been inserted into the + // `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`/`PartialOrd`. + dependencies: HashMap>, +} + +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`/`PartialOrd`. + 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: Id, + reason: CannotDeriveReason, + ) -> ConstrainResult { + let id = id.into(); + trace!( + "inserting {:?} into the cannot_derive_partialeq_or_partialord because {:?}", + id, + reason + ); + let existing = self.cannot_derive_partialeq_or_partialord + .insert(id, reason); + assert!(can_supersede(existing, Some(reason))); + ConstrainResult::Changed + } + + fn constrain_type( + &mut self, + item: &Item, + ty: &Type, + ) -> Option { + if !self.ctx.whitelisted_items().contains(&item.id()) { + return Some(CannotDeriveReason::Other); + } + + if self.ctx.no_partialeq_by_name(&item) { + return Some(CannotDeriveReason::Other); + } + + trace!("ty: {:?}", ty); + if item.is_opaque(self.ctx, &()) { + if ty.is_union() + && self.ctx.options().rust_features().untagged_union() + { + trace!( + " cannot derive `PartialEq`/`PartialOrd` for Rust unions" + ); + return Some(CannotDeriveReason::Other); + } + + let layout_can_derive = ty.layout(self.ctx) + .map_or(CanDerive::Yes, |l| { + l.opaque().can_trivially_derive_partialeq_or_partialord() + }); + + return match layout_can_derive { + CanDerive::Yes => { + trace!( + " we can trivially derive `PartialEq`/`PartialOrd` for the layout" + ); + None + } + CanDerive::No(reason) => { + trace!( + " we cannot derive `PartialEq`/`PartialOrd` for the layout" + ); + Some(reason) + } + }; + } + + 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::TypeParam | + TypeKind::UnresolvedTypeRef(..) | + TypeKind::BlockPointer | + TypeKind::Reference(..) | + TypeKind::ObjCInterface(..) | + TypeKind::ObjCId | + TypeKind::ObjCSel => { + trace!( + " simple type that can always derive `PartialEq`/`PartialOrd`" + ); + return None; + } + + TypeKind::Array(t, len) => { + if self.cannot_derive_partialeq_or_partialord.contains_key(&t.into()) { + trace!( + " arrays of T for which we cannot derive `PartialEq`/`PartialOrd` \ + also cannot derive `PartialEq`/`PartialOrd`" + ); + return Some(CannotDeriveReason::Other); + } + + if len == 0 { + trace!( + " cannot derive `PartialEq`/`PartialOrd` for incomplete arrays" + ); + return Some(CannotDeriveReason::Other); + } else if len <= RUST_DERIVE_IN_ARRAY_LIMIT { + trace!( + " array is small enough to derive `PartialEq`/`PartialOrd`" + ); + return None; + } else { + trace!( + " array is too large to derive `PartialEq`/`PartialOrd`" + ); + return Some(CannotDeriveReason::ArrayTooLarge); + } + } + + 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 let CanDerive::No(_) = + sig.can_trivially_derive_partialeq_or_partialord() + { + trace!( + " function pointer that can't trivially derive `PartialEq`/`PartialOrd`" + ); + return Some(CannotDeriveReason::Other); + } + } + trace!(" pointers can derive `PartialEq`/`PartialOrd`"); + return None; + } + + TypeKind::Function(ref sig) => { + if let CanDerive::No(_) = + sig.can_trivially_derive_partialeq_or_partialord() + { + trace!( + " function that can't trivially derive `PartialEq`/`PartialOrd`" + ); + return Some(CannotDeriveReason::Other); + } + trace!(" function can derive `PartialEq`/`PartialOrd`"); + return None; + } + + 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`/`PartialOrd` for Rust unions" + ); + return Some(CannotDeriveReason::Other); + } + + let layout_can_derive = ty.layout(self.ctx).map_or( + CanDerive::Yes, + |l| { + l.opaque() + .can_trivially_derive_partialeq_or_partialord() + }, + ); + return match layout_can_derive { + CanDerive::Yes => { + trace!( + " union layout can trivially derive `PartialEq`/`PartialOrd`" + ); + None + } + CanDerive::No(reason) => { + trace!( + " union layout cannot derive `PartialEq`/`PartialOrd`" + ); + Some(reason) + } + }; + } + return self.constrain_join(item); + } + + TypeKind::ResolvedTypeRef(..) | + TypeKind::TemplateAlias(..) | + TypeKind::Alias(..) | + TypeKind::TemplateInstantiation(..) => { + return self.constrain_join(item); + } + + TypeKind::Opaque => unreachable!( + "The early ty.is_opaque check should have handled this case" + ), + } + } + + fn constrain_join(&mut self, item: &Item) -> Option { + let mut candidate = None; + + item.trace( + self.ctx, + &mut |sub_id, edge_kind| { + // Ignore ourselves, since union with ourself is a + // no-op. Ignore edges that aren't relevant to the + // analysis. + if sub_id == item.id() || !Self::consider_edge(edge_kind) { + return; + } + + let reason = self.cannot_derive_partialeq_or_partialord + .get(&sub_id) + .cloned(); + + if can_supersede(candidate, reason) { + candidate = reason; + } + }, + &(), + ); + + candidate + } +} + +/// Check if the one reason could supersede another. +/// +/// To keep this analysis monotone we should go only in one direction. +/// If the abscence of the reason is at the bottom and `CannotDeriveReason::Other` +/// is at the top, then we can only go upwards. +/// +/// Other +/// ^ +/// | +/// ArrayTooLarge +/// ^ +/// | +/// None +/// +fn can_supersede(from: Option, to: Option) -> bool { + fn rank(maybe_reason: Option) -> usize { + match maybe_reason { + None => 0, + Some(CannotDeriveReason::ArrayTooLarge) => 1, + Some(CannotDeriveReason::Other) => 2, + } + } + rank(from) <= rank(to) +} + +impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { + type Node = ItemId; + type Extra = &'ctx BindgenContext; + type Output = HashMap; + + fn new( + ctx: &'ctx BindgenContext, + ) -> CannotDerivePartialEqOrPartialOrd<'ctx> { + let cannot_derive_partialeq_or_partialord = HashMap::new(); + let dependencies = generate_dependencies(ctx, Self::consider_edge); + + CannotDerivePartialEqOrPartialOrd { + ctx, + cannot_derive_partialeq_or_partialord, + dependencies, + } + } + + fn initial_worklist(&self) -> Vec { + // The transitive closure of all whitelisted items, including explicitly + // blacklisted items. + self.ctx + .whitelisted_items() + .iter() + .cloned() + .flat_map(|i| { + let mut reachable = vec![i]; + i.trace( + self.ctx, + &mut |s, _| { + reachable.push(s); + }, + &(), + ); + reachable + }) + .collect() + } + + fn constrain(&mut self, id: ItemId) -> ConstrainResult { + trace!("constrain: {:?}", id); + + if let Some(CannotDeriveReason::Other) = + self.cannot_derive_partialeq_or_partialord.get(&id).cloned() + { + trace!(" already know it cannot derive `PartialEq`/`PartialOrd`"); + return ConstrainResult::Same; + } + + let item = self.ctx.resolve_item(id); + let maybe_reason = match item.as_type() { + Some(ty) => { + self.constrain_type(item, ty).or_else(|| { + 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. + Some(CannotDeriveReason::ArrayTooLarge) + } else { + None + } + }) + } + None => self.constrain_join(item), + }; + + if let Some(reason) = maybe_reason { + self.insert(id, reason) + } else { + ConstrainResult::Same + } + } + + fn each_depending_on(&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> From> for HashMap { + 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 44ca4279..64958c07 100644 --- a/src/ir/analysis/mod.rs +++ b/src/ir/analysis/mod.rs @@ -54,8 +54,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_or_partial_ord; -pub use self::derive_partial_eq_or_partial_ord::CannotDerivePartialEqOrPartialOrd; +mod derive_partialeq_or_partialord; +pub use self::derive_partialeq_or_partialord::CannotDerivePartialEqOrPartialOrd; mod has_float; pub use self::has_float::HasFloat; mod sizedness; -- cgit v1.2.3 From 230545e7c9d135bbf338642b69ac01c5d1e0bf2d Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Sun, 29 Oct 2017 17:50:02 +0300 Subject: Refactor derive_partialeq_or_partialord. --- src/codegen/mod.rs | 7 +- src/ir/analysis/derive_partialeq_or_partialord.rs | 197 ++++++++++------------ src/ir/context.rs | 20 ++- src/ir/derive.rs | 79 +++++++-- src/ir/function.rs | 6 +- src/ir/item.rs | 25 +-- src/ir/layout.rs | 6 +- 7 files changed, 185 insertions(+), 155 deletions(-) diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 53ed24ff..d36decb0 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -17,7 +17,7 @@ use ir::comp::{Base, Bitfield, BitfieldUnit, CompInfo, CompKind, Field, use ir::context::{BindgenContext, ItemId}; use ir::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveHash, CanDerivePartialOrd, CanDeriveOrd, - CanDerivePartialEq, CanDeriveEq, CannotDeriveReason}; + CanDerivePartialEq, CanDeriveEq, CanDerive}; use ir::dot; use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue}; use ir::function::{Abi, Function, FunctionSig, Linkage}; @@ -1676,10 +1676,7 @@ impl CodeGenerator for CompInfo { needs_partialeq_impl = ctx.options().derive_partialeq && ctx.options().impl_partialeq && - ctx.lookup_can_derive_partialeq_or_partialord(item.id()) - .map_or(true, |x| { - x == CannotDeriveReason::ArrayTooLarge - }); + ctx.lookup_can_derive_partialeq_or_partialord(item.id()) == CanDerive::ArrayTooLarge; } if item.can_derive_eq(ctx) { diff --git a/src/ir/analysis/derive_partialeq_or_partialord.rs b/src/ir/analysis/derive_partialeq_or_partialord.rs index f54650dd..92861341 100644 --- a/src/ir/analysis/derive_partialeq_or_partialord.rs +++ b/src/ir/analysis/derive_partialeq_or_partialord.rs @@ -4,12 +4,13 @@ use super::{ConstrainResult, MonotoneFramework, generate_dependencies}; use ir::comp::CompKind; use ir::context::{BindgenContext, ItemId}; -use ir::derive::{CanTriviallyDerivePartialEqOrPartialOrd, CanDerive, CannotDeriveReason}; +use ir::derive::{CanTriviallyDerivePartialEqOrPartialOrd, CanDerive}; use ir::item::{Item, IsOpaque}; use ir::traversal::{EdgeKind, Trace}; use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT; use ir::ty::{TypeKind, Type}; use std::collections::HashMap; +use std::collections::hash_map::Entry; /// An analysis that finds for each IR item whether `PartialEq`/`PartialOrd` /// cannot be derived. @@ -21,7 +22,7 @@ use std::collections::HashMap; /// type and check whether it can be derived using trivial checks. /// /// * If T is Array type, `PartialEq` or partialord cannot be derived if the array is incomplete, if the length of -/// the array is larger than the limit, or the type of data the array contains cannot derive +/// the array is larger than the limit, or the type of data the array contains cannot derive /// `PartialEq`/`PartialOrd`. /// /// * If T is a type alias, a templated alias or an indirection to another type, @@ -42,9 +43,9 @@ use std::collections::HashMap; pub struct CannotDerivePartialEqOrPartialOrd<'ctx> { ctx: &'ctx BindgenContext, - // The incremental result of this analysis's computation. Everything in this - // set cannot derive `PartialEq`/`PartialOrd`. - cannot_derive_partialeq_or_partialord: HashMap, + // The incremental result of this analysis's computation. + // Contains information whether particular item can derive `PartialEq`/`PartialOrd`. + can_derive_partialeq_or_partialord: HashMap, // Dependencies saying that if a key ItemId has been inserted into the // `cannot_derive_partialeq_or_partialord` set, then each of the ids @@ -83,31 +84,36 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> { fn insert>( &mut self, id: Id, - reason: CannotDeriveReason, + can_derive: CanDerive, ) -> ConstrainResult { let id = id.into(); - trace!( - "inserting {:?} into the cannot_derive_partialeq_or_partialord because {:?}", - id, - reason - ); - let existing = self.cannot_derive_partialeq_or_partialord - .insert(id, reason); - assert!(can_supersede(existing, Some(reason))); - ConstrainResult::Changed + trace!("inserting {:?} can_derive={:?}", id, can_derive); + + if let CanDerive::Yes = can_derive { + return ConstrainResult::Same; + } + + match self.can_derive_partialeq_or_partialord.entry(id) { + Entry::Occupied(mut entry) => if *entry.get() < can_derive { + entry.insert(can_derive); + ConstrainResult::Changed + } else { + ConstrainResult::Same + }, + Entry::Vacant(entry) => { + entry.insert(can_derive); + ConstrainResult::Changed + } + } } - fn constrain_type( - &mut self, - item: &Item, - ty: &Type, - ) -> Option { + fn constrain_type(&mut self, item: &Item, ty: &Type) -> CanDerive { if !self.ctx.whitelisted_items().contains(&item.id()) { - return Some(CannotDeriveReason::Other); + return CanDerive::No; } if self.ctx.no_partialeq_by_name(&item) { - return Some(CannotDeriveReason::Other); + return CanDerive::No; } trace!("ty: {:?}", ty); @@ -118,7 +124,7 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> { trace!( " cannot derive `PartialEq`/`PartialOrd` for Rust unions" ); - return Some(CannotDeriveReason::Other); + return CanDerive::No; } let layout_can_derive = ty.layout(self.ctx) @@ -126,20 +132,19 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> { l.opaque().can_trivially_derive_partialeq_or_partialord() }); - return match layout_can_derive { + match layout_can_derive { CanDerive::Yes => { trace!( " we can trivially derive `PartialEq`/`PartialOrd` for the layout" ); - None } - CanDerive::No(reason) => { + _ => { trace!( " we cannot derive `PartialEq`/`PartialOrd` for the layout" ); - Some(reason) } }; + return layout_can_derive; } match *ty.kind() { @@ -161,33 +166,37 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> { trace!( " simple type that can always derive `PartialEq`/`PartialOrd`" ); - return None; + return CanDerive::Yes; } TypeKind::Array(t, len) => { - if self.cannot_derive_partialeq_or_partialord.contains_key(&t.into()) { + let inner_type = self.can_derive_partialeq_or_partialord + .get(&t.into()) + .cloned() + .unwrap_or(CanDerive::Yes); + if inner_type != CanDerive::Yes { trace!( " arrays of T for which we cannot derive `PartialEq`/`PartialOrd` \ also cannot derive `PartialEq`/`PartialOrd`" ); - return Some(CannotDeriveReason::Other); + return CanDerive::No; } if len == 0 { trace!( " cannot derive `PartialEq`/`PartialOrd` for incomplete arrays" ); - return Some(CannotDeriveReason::Other); + return CanDerive::No; } else if len <= RUST_DERIVE_IN_ARRAY_LIMIT { trace!( " array is small enough to derive `PartialEq`/`PartialOrd`" ); - return None; + return CanDerive::Yes; } else { trace!( " array is too large to derive `PartialEq`/`PartialOrd`" ); - return Some(CannotDeriveReason::ArrayTooLarge); + return CanDerive::ArrayTooLarge; } } @@ -195,30 +204,30 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> { let inner_type = self.ctx.resolve_type(inner).canonical_type(self.ctx); if let TypeKind::Function(ref sig) = *inner_type.kind() { - if let CanDerive::No(_) = - sig.can_trivially_derive_partialeq_or_partialord() + if sig.can_trivially_derive_partialeq_or_partialord() + != CanDerive::Yes { trace!( " function pointer that can't trivially derive `PartialEq`/`PartialOrd`" ); - return Some(CannotDeriveReason::Other); + return CanDerive::No; } } trace!(" pointers can derive `PartialEq`/`PartialOrd`"); - return None; + return CanDerive::Yes; } TypeKind::Function(ref sig) => { - if let CanDerive::No(_) = - sig.can_trivially_derive_partialeq_or_partialord() + if sig.can_trivially_derive_partialeq_or_partialord() + != CanDerive::Yes { trace!( " function that can't trivially derive `PartialEq`/`PartialOrd`" ); - return Some(CannotDeriveReason::Other); + return CanDerive::No; } trace!(" function can derive `PartialEq`/`PartialOrd`"); - return None; + return CanDerive::Yes; } TypeKind::Comp(ref info) => { @@ -232,30 +241,27 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> { trace!( " cannot derive `PartialEq`/`PartialOrd` for Rust unions" ); - return Some(CannotDeriveReason::Other); + return CanDerive::No; } - let layout_can_derive = ty.layout(self.ctx).map_or( - CanDerive::Yes, - |l| { + let layout_can_derive = + ty.layout(self.ctx).map_or(CanDerive::Yes, |l| { l.opaque() .can_trivially_derive_partialeq_or_partialord() - }, - ); - return match layout_can_derive { + }); + match layout_can_derive { CanDerive::Yes => { trace!( " union layout can trivially derive `PartialEq`/`PartialOrd`" ); - None } - CanDerive::No(reason) => { + _ => { trace!( " union layout cannot derive `PartialEq`/`PartialOrd`" ); - Some(reason) } }; + return layout_can_derive; } return self.constrain_join(item); } @@ -273,8 +279,8 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> { } } - fn constrain_join(&mut self, item: &Item) -> Option { - let mut candidate = None; + fn constrain_join(&mut self, item: &Item) -> CanDerive { + let mut candidate = CanDerive::Yes; item.trace( self.ctx, @@ -286,13 +292,12 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> { return; } - let reason = self.cannot_derive_partialeq_or_partialord + let can_derive = self.can_derive_partialeq_or_partialord .get(&sub_id) - .cloned(); + .cloned() + .unwrap_or_default(); - if can_supersede(candidate, reason) { - candidate = reason; - } + candidate |= can_derive; }, &(), ); @@ -301,45 +306,20 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> { } } -/// Check if the one reason could supersede another. -/// -/// To keep this analysis monotone we should go only in one direction. -/// If the abscence of the reason is at the bottom and `CannotDeriveReason::Other` -/// is at the top, then we can only go upwards. -/// -/// Other -/// ^ -/// | -/// ArrayTooLarge -/// ^ -/// | -/// None -/// -fn can_supersede(from: Option, to: Option) -> bool { - fn rank(maybe_reason: Option) -> usize { - match maybe_reason { - None => 0, - Some(CannotDeriveReason::ArrayTooLarge) => 1, - Some(CannotDeriveReason::Other) => 2, - } - } - rank(from) <= rank(to) -} - impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { type Node = ItemId; type Extra = &'ctx BindgenContext; - type Output = HashMap; + type Output = HashMap; fn new( ctx: &'ctx BindgenContext, ) -> CannotDerivePartialEqOrPartialOrd<'ctx> { - let cannot_derive_partialeq_or_partialord = HashMap::new(); + let can_derive_partialeq_or_partialord = HashMap::new(); let dependencies = generate_dependencies(ctx, Self::consider_edge); CannotDerivePartialEqOrPartialOrd { ctx, - cannot_derive_partialeq_or_partialord, + can_derive_partialeq_or_partialord, dependencies, } } @@ -365,43 +345,40 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { .collect() } - fn constrain(&mut self, id: ItemId) -> ConstrainResult { + fn constrain(&mut self, id: ItemId) -> ConstrainResult { trace!("constrain: {:?}", id); - if let Some(CannotDeriveReason::Other) = - self.cannot_derive_partialeq_or_partialord.get(&id).cloned() + if let Some(CanDerive::No) = + self.can_derive_partialeq_or_partialord.get(&id).cloned() { - trace!(" already know it cannot derive `PartialEq`/`PartialOrd`"); + trace!( + " already know it cannot derive `PartialEq`/`PartialOrd`" + ); return ConstrainResult::Same; } let item = self.ctx.resolve_item(id); - let maybe_reason = match item.as_type() { + let can_derive = match item.as_type() { Some(ty) => { - self.constrain_type(item, ty).or_else(|| { - if ty.layout(self.ctx).map_or(false, |l| { - l.align > RUST_DERIVE_IN_ARRAY_LIMIT - }) + let mut can_derive = self.constrain_type(item, ty); + if let CanDerive::Yes = can_derive { + 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. - Some(CannotDeriveReason::ArrayTooLarge) - } else { - None + can_derive = CanDerive::ArrayTooLarge; } - }) + } + can_derive } None => self.constrain_join(item), }; - if let Some(reason) = maybe_reason { - self.insert(id, reason) - } else { - ConstrainResult::Same - } + self.insert(id, can_derive) } fn each_depending_on(&self, id: ItemId, mut f: F) @@ -417,8 +394,16 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { } } -impl<'ctx> From> for HashMap { +impl<'ctx> From> + for HashMap { fn from(analysis: CannotDerivePartialEqOrPartialOrd<'ctx>) -> Self { - analysis.cannot_derive_partialeq_or_partialord + extra_assert!( + analysis + .can_derive_partialeq_or_partialord + .values() + .all(|v| { *v != CanDerive::Yes }) + ); + + analysis.can_derive_partialeq_or_partialord } } diff --git a/src/ir/context.rs b/src/ir/context.rs index 138a69b9..b2ebb929 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -8,7 +8,7 @@ use super::analysis::{CannotDeriveCopy, CannotDeriveDebug, CannotDeriveDefault, SizednessResult, analyze}; use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveHash, CanDerivePartialOrd, CanDeriveOrd, - CanDerivePartialEq, CanDeriveEq, CannotDeriveReason}; + CanDerivePartialEq, CanDeriveEq, CanDerive}; use super::int::IntKind; use super::item::{IsOpaque, Item, ItemAncestors, ItemCanonicalPath, ItemSet}; use super::item_kind::ItemKind; @@ -251,7 +251,7 @@ where { fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool { ctx.options().derive_partialord && - ctx.lookup_can_derive_partialeq_or_partialord(*self).is_none() + ctx.lookup_can_derive_partialeq_or_partialord(*self) == CanDerive::Yes } } @@ -261,7 +261,7 @@ where { fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool { ctx.options().derive_partialeq && - ctx.lookup_can_derive_partialeq_or_partialord(*self).is_none() + ctx.lookup_can_derive_partialeq_or_partialord(*self) == CanDerive::Yes } } @@ -271,7 +271,7 @@ where { fn can_derive_eq(&self, ctx: &BindgenContext) -> bool { ctx.options().derive_eq && - ctx.lookup_can_derive_partialeq_or_partialord(*self).is_none() && + ctx.lookup_can_derive_partialeq_or_partialord(*self) == CanDerive::Yes && !ctx.lookup_has_float(*self) } } @@ -282,7 +282,7 @@ where { fn can_derive_ord(&self, ctx: &BindgenContext) -> bool { ctx.options().derive_ord && - ctx.lookup_can_derive_partialeq_or_partialord(*self).is_none() && + ctx.lookup_can_derive_partialeq_or_partialord(*self) == CanDerive::Yes && !ctx.lookup_has_float(*self) } } @@ -427,7 +427,7 @@ pub struct BindgenContext { /// This is populated when we enter codegen by /// `compute_cannot_derive_partialord_partialeq_or_eq` and is always `None` /// before that and `Some` after. - cannot_derive_partialeq_or_partialord: Option>, + cannot_derive_partialeq_or_partialord: Option>, /// The sizedness of types. /// @@ -2419,7 +2419,7 @@ impl BindgenContext { } /// Look up whether the item with `id` can derive `Partial{Eq,Ord}`. - pub fn lookup_can_derive_partialeq_or_partialord>(&self, id: Id) -> Option { + pub fn lookup_can_derive_partialeq_or_partialord>(&self, id: Id) -> CanDerive { let id = id.into(); assert!( self.in_codegen_phase(), @@ -2428,7 +2428,11 @@ impl BindgenContext { // Look up the computed value for whether the item with `id` can // derive partialeq or not. - self.cannot_derive_partialeq_or_partialord.as_ref().unwrap().get(&id).cloned() + self.cannot_derive_partialeq_or_partialord.as_ref() + .unwrap() + .get(&id) + .cloned() + .unwrap_or(CanDerive::Yes) } /// Look up whether the item with `id` can derive `Copy` or not. diff --git a/src/ir/derive.rs b/src/ir/derive.rs index 52e61133..b0a6912f 100644 --- a/src/ir/derive.rs +++ b/src/ir/derive.rs @@ -13,6 +13,9 @@ use super::context::BindgenContext; +use std::cmp; +use std::ops; + /// A trait that encapsulates the logic for whether or not we can derive `Debug` /// for a given thing. pub trait CanDeriveDebug { @@ -115,29 +118,79 @@ pub trait CanTriviallyDeriveHash { /// derive `PartialEq` or `PartialOrd` without looking at any other types or /// results of fix point analyses. This is a helper for the fix point analysis. pub trait CanTriviallyDerivePartialEqOrPartialOrd { - /// Return `true` if `PartialEq` or `PartialOrd` can trivially be derived - /// for this thing, `false` otherwise. + /// Return `Yes` if `PartialEq` or `PartialOrd` can trivially be derived + /// for this thing. fn can_trivially_derive_partialeq_or_partialord(&self) -> CanDerive; } -/// Reason why exactly we cannot automatically derive a trait. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum CannotDeriveReason { +/// Whether it is possible or not to automatically derive trait for an item. +/// +/// ```ignore +/// No +/// ^ +/// | +/// ArrayTooLarge +/// ^ +/// | +/// Yes +/// ``` +/// +/// Initially we assume that we can derive trait for all types and then +/// update our understanding as we learn more about each type. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord)] +pub enum CanDerive { + /// No, we cannot. + No, + /// The only thing that stops us from automatically deriving is that /// array with more than maximum number of elements is used. /// /// This means we probably can "manually" implement such trait. ArrayTooLarge, - /// Any other reason. - Other, + /// Yes, we can derive automatically. + Yes, } -/// Whether it is possible or not to derive trait automatically. -pub enum CanDerive { - /// Yes, we can! - Yes, +impl Default for CanDerive { + fn default() -> CanDerive { + CanDerive::Yes + } +} + +impl cmp::PartialOrd for CanDerive { + fn partial_cmp(&self, rhs: &Self) -> Option { + use self::CanDerive::*; + + let ordering = match (*self, *rhs) { + (x, y) if x == y => cmp::Ordering::Equal, + (No, _) => cmp::Ordering::Greater, + (_, No) => cmp::Ordering::Less, + (ArrayTooLarge, _) => cmp::Ordering::Greater, + (_, ArrayTooLarge) => cmp::Ordering::Less, + _ => unreachable!() + }; + Some(ordering) + } +} + +impl CanDerive { + /// Take the least upper bound of `self` and `rhs`. + pub fn join(self, rhs: Self) -> Self { + cmp::max(self, rhs) + } +} + +impl ops::BitOr for CanDerive { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + self.join(rhs) + } +} - /// No, we cannot. Contains reason why exactly we can't derive. - No(CannotDeriveReason) +impl ops::BitOrAssign for CanDerive { + fn bitor_assign(&mut self, rhs: Self) { + *self = self.join(rhs) + } } diff --git a/src/ir/function.rs b/src/ir/function.rs index 60a7effd..62792484 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, - CanTriviallyDerivePartialEqOrPartialOrd, CanDerive, CannotDeriveReason}; + CanTriviallyDerivePartialEqOrPartialOrd, CanDerive}; use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult}; use quote; use std::io; @@ -566,12 +566,12 @@ impl CanTriviallyDeriveHash for FunctionSig { impl CanTriviallyDerivePartialEqOrPartialOrd for FunctionSig { fn can_trivially_derive_partialeq_or_partialord(&self) -> CanDerive { if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT { - return CanDerive::No(CannotDeriveReason::Other); + return CanDerive::No; } match self.abi { Abi::C | Abi::Unknown(..) => CanDerive::Yes, - _ => CanDerive::No(CannotDeriveReason::Other), + _ => CanDerive::No, } } } diff --git a/src/ir/item.rs b/src/ir/item.rs index 9ed7267d..d863d907 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -319,58 +319,49 @@ impl Trace for Item { impl CanDeriveDebug for Item { fn can_derive_debug(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_debug && - ctx.lookup_can_derive_debug(self.id()) + self.id().can_derive_debug(ctx) } } impl CanDeriveDefault for Item { fn can_derive_default(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_default && - ctx.lookup_can_derive_default(self.id()) + self.id().can_derive_default(ctx) } } impl<'a> CanDeriveCopy<'a> for Item { fn can_derive_copy(&self, ctx: &BindgenContext) -> bool { - ctx.lookup_can_derive_copy(self.id()) + self.id().can_derive_copy(ctx) } } impl CanDeriveHash for Item { fn can_derive_hash(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_hash && - ctx.lookup_can_derive_hash(self.id()) + self.id().can_derive_hash(ctx) } } impl CanDerivePartialOrd for Item { fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_partialord && - ctx.lookup_can_derive_partialeq_or_partialord(self.id()).is_none() + self.id().can_derive_partialord(ctx) } } impl CanDerivePartialEq for Item { fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_partialeq && - ctx.lookup_can_derive_partialeq_or_partialord(self.id()).is_none() + self.id().can_derive_partialeq(ctx) } } impl CanDeriveEq for Item { fn can_derive_eq(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_eq && - ctx.lookup_can_derive_partialeq_or_partialord(self.id()).is_none() && - !ctx.lookup_has_float(self.id()) + self.id().can_derive_eq(ctx) } } impl CanDeriveOrd for Item { fn can_derive_ord(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_ord && - ctx.lookup_can_derive_partialeq_or_partialord(self.id()).is_none() && - !ctx.lookup_has_float(self.id()) + self.id().can_derive_ord(ctx) } } diff --git a/src/ir/layout.rs b/src/ir/layout.rs index ac875ca4..0c99c7e7 100644 --- a/src/ir/layout.rs +++ b/src/ir/layout.rs @@ -2,7 +2,7 @@ use super::derive::{CanTriviallyDeriveCopy, CanTriviallyDeriveDebug, CanTriviallyDeriveDefault, CanTriviallyDeriveHash, - CanTriviallyDerivePartialEqOrPartialOrd, CanDerive, CannotDeriveReason}; + CanTriviallyDerivePartialEqOrPartialOrd, CanDerive}; use super::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, Type, TypeKind}; use clang; use std::{cmp, mem}; @@ -141,11 +141,11 @@ impl CanTriviallyDeriveHash for Opaque { impl CanTriviallyDerivePartialEqOrPartialOrd for Opaque { fn can_trivially_derive_partialeq_or_partialord(&self) -> CanDerive { - self.array_size().map_or(CanDerive::No(CannotDeriveReason::Other), |size| { + self.array_size().map_or(CanDerive::No, |size| { if size <= RUST_DERIVE_IN_ARRAY_LIMIT { CanDerive::Yes } else { - CanDerive::No(CannotDeriveReason::ArrayTooLarge) + CanDerive::ArrayTooLarge } }) } -- cgit v1.2.3