diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 8df249d7341..36c0f30f0bf 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -1395,10 +1395,16 @@ impl<'a, 'tcx> HashStable> for traits::Goal<'tcx> { impl_stable_hash_for!( impl<'tcx> for struct traits::ProgramClause<'tcx> { - goal, hypotheses + goal, hypotheses, category } ); +impl_stable_hash_for!(enum traits::ProgramClauseCategory { + ImpliedBound, + WellFormed, + Other, +}); + impl<'a, 'tcx> HashStable> for traits::Clause<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 7bfb6f060cd..d129cd486cf 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -341,7 +341,8 @@ impl<'tcx> DomainGoal<'tcx> { pub fn into_program_clause(self) -> ProgramClause<'tcx> { ProgramClause { goal: self, - hypotheses: &ty::List::empty(), + hypotheses: ty::List::empty(), + category: ProgramClauseCategory::Other, } } } @@ -369,6 +370,15 @@ pub enum Clause<'tcx> { ForAll(ty::Binder>), } +impl Clause<'tcx> { + pub fn category(self) -> ProgramClauseCategory { + match self { + Clause::Implies(clause) => clause.category, + Clause::ForAll(clause) => clause.skip_binder().category, + } + } +} + /// Multiple clauses. pub type Clauses<'tcx> = &'tcx List>; @@ -385,6 +395,16 @@ pub struct ProgramClause<'tcx> { /// ...if we can prove these hypotheses (there may be no hypotheses at all): pub hypotheses: Goals<'tcx>, + + /// Useful for filtering clauses. + pub category: ProgramClauseCategory, +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +pub enum ProgramClauseCategory { + ImpliedBound, + WellFormed, + Other, } /// A set of clauses that we assume to be true. diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 7b7446e27d2..c50c9703eb5 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -496,7 +496,7 @@ impl<'tcx> fmt::Display for traits::Goal<'tcx> { impl<'tcx> fmt::Display for traits::ProgramClause<'tcx> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let traits::ProgramClause { goal, hypotheses } = self; + let traits::ProgramClause { goal, hypotheses, .. } = self; write!(fmt, "{}", goal)?; if !hypotheses.is_empty() { write!(fmt, " :- ")?; @@ -647,10 +647,15 @@ impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> { BraceStructTypeFoldableImpl! { impl<'tcx> TypeFoldable<'tcx> for traits::ProgramClause<'tcx> { goal, - hypotheses + hypotheses, + category, } } +CloneTypeFoldableAndLiftImpls! { + traits::ProgramClauseCategory, +} + EnumTypeFoldableImpl! { impl<'tcx> TypeFoldable<'tcx> for traits::Clause<'tcx> { (traits::Clause::Implies)(clause), diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs index 1f3fec46990..a1cdb622f37 100644 --- a/src/librustc_traits/lowering/environment.rs +++ b/src/librustc_traits/lowering/environment.rs @@ -14,6 +14,7 @@ use rustc::traits::{ DomainGoal, FromEnv, ProgramClause, + ProgramClauseCategory, Environment, }; use rustc::ty::{self, TyCtxt, Ty}; @@ -39,6 +40,7 @@ impl ClauseVisitor<'set, 'a, 'tcx> { self.round.extend( self.tcx.program_clauses_for(data.item_def_id) .iter() + .filter(|c| c.category() == ProgramClauseCategory::ImpliedBound) .cloned() ); } @@ -56,6 +58,7 @@ impl ClauseVisitor<'set, 'a, 'tcx> { self.round.extend( self.tcx.program_clauses_for(def.did) .iter() + .filter(|c| c.category() == ProgramClauseCategory::ImpliedBound) .cloned() ); } @@ -68,6 +71,7 @@ impl ClauseVisitor<'set, 'a, 'tcx> { self.round.extend( self.tcx.program_clauses_for(def_id) .iter() + .filter(|c| c.category() == ProgramClauseCategory::ImpliedBound) .cloned() ); } @@ -98,6 +102,7 @@ impl ClauseVisitor<'set, 'a, 'tcx> { self.round.extend( self.tcx.program_clauses_for(predicate.def_id()) .iter() + .filter(|c| c.category() == ProgramClauseCategory::ImpliedBound) .cloned() ); } @@ -176,7 +181,7 @@ crate fn environment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> En // Compute the bounds on `Self` and the type parameters. let ty::InstantiatedPredicates { predicates } = tcx.predicates_of(def_id).instantiate_identity(tcx); - + let clauses = predicates.into_iter() .map(|predicate| predicate.lower()) .map(|domain_goal| domain_goal.map_bound(|bound| bound.into_from_env_goal())) @@ -185,7 +190,7 @@ crate fn environment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> En // `ForAll` because each `domain_goal` is a `PolyDomainGoal` and // could bound lifetimes. .map(Clause::ForAll); - + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); let node = tcx.hir.get(node_id); @@ -243,7 +248,7 @@ crate fn environment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> En .map(|domain_goal| domain_goal.into_program_clause()) .map(Clause::Implies) ); - + Environment { clauses: tcx.mk_clauses(clauses), } diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index a6bf28b6ad8..fb598a33548 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -22,6 +22,7 @@ use rustc::traits::{ GoalKind, PolyDomainGoal, ProgramClause, + ProgramClauseCategory, WellFormed, WhereClause, }; @@ -204,6 +205,7 @@ fn program_clauses_for_trait<'a, 'tcx>( let implemented_from_env = ProgramClause { goal: impl_trait, hypotheses, + category: ProgramClauseCategory::ImpliedBound, }; let clauses = iter::once(Clause::ForAll(ty::Binder::dummy(implemented_from_env))); @@ -231,6 +233,7 @@ fn program_clauses_for_trait<'a, 'tcx>( .map(|wc| wc.map_bound(|goal| ProgramClause { goal: goal.into_from_env_goal(), hypotheses, + category: ProgramClauseCategory::ImpliedBound, })) .map(Clause::ForAll); @@ -257,6 +260,7 @@ fn program_clauses_for_trait<'a, 'tcx>( hypotheses: tcx.mk_goals( wf_conditions.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))), ), + category: ProgramClauseCategory::WellFormed, }; let wf_clause = iter::once(Clause::ForAll(ty::Binder::dummy(wf_clause))); @@ -299,6 +303,7 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId where_clauses .map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))), ), + category: ProgramClauseCategory::Other, }; tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause)))) } @@ -335,6 +340,7 @@ pub fn program_clauses_for_type_def<'a, 'tcx>( .cloned() .map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))), ), + category: ProgramClauseCategory::WellFormed, }; let well_formed_clause = iter::once(Clause::ForAll(ty::Binder::dummy(well_formed))); @@ -360,6 +366,7 @@ pub fn program_clauses_for_type_def<'a, 'tcx>( .map(|wc| wc.map_bound(|goal| ProgramClause { goal: goal.into_from_env_goal(), hypotheses, + category: ProgramClauseCategory::ImpliedBound, })) .map(Clause::ForAll); @@ -407,7 +414,8 @@ pub fn program_clauses_for_associated_type_def<'a, 'tcx>( let projection_eq_clause = ProgramClause { goal: DomainGoal::Holds(projection_eq), - hypotheses: &ty::List::empty(), + hypotheses: ty::List::empty(), + category: ProgramClauseCategory::Other, }; // Rule WellFormed-AssocTy @@ -425,6 +433,7 @@ pub fn program_clauses_for_associated_type_def<'a, 'tcx>( let wf_clause = ProgramClause { goal: DomainGoal::WellFormed(WellFormed::Ty(placeholder_ty)), hypotheses: tcx.mk_goals(iter::once(hypothesis)), + category: ProgramClauseCategory::Other, }; // Rule Implied-Trait-From-AssocTy @@ -441,6 +450,7 @@ pub fn program_clauses_for_associated_type_def<'a, 'tcx>( let from_env_clause = ProgramClause { goal: DomainGoal::FromEnv(FromEnv::Trait(trait_predicate)), hypotheses: tcx.mk_goals(iter::once(hypothesis)), + category: ProgramClauseCategory::ImpliedBound, }; let clauses = iter::once(projection_eq_clause) @@ -506,6 +516,7 @@ pub fn program_clauses_for_associated_type_value<'a, 'tcx>( .into_iter() .map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))), ), + category: ProgramClauseCategory::Other, }; tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause)))) }