diff --git a/src/librustc_traits/chalk_context/program_clauses.rs b/src/librustc_traits/chalk_context/program_clauses.rs index 8d5d2b8a9a255..fb7bba32d395e 100644 --- a/src/librustc_traits/chalk_context/program_clauses.rs +++ b/src/librustc_traits/chalk_context/program_clauses.rs @@ -326,15 +326,12 @@ fn wf_clause_for_ref<'tcx>( mutbl, }); - let _outlives: DomainGoal<'_> = ty::OutlivesPredicate(ty, region).lower(); + let outlives: DomainGoal<'_> = ty::OutlivesPredicate(ty, region).lower(); let wf_clause = ProgramClause { goal: DomainGoal::WellFormed(WellFormed::Ty(ref_ty)), - hypotheses: ty::List::empty(), - - // FIXME: restore this later once we get better at handling regions - // hypotheses: tcx.mk_goals( - // iter::once(tcx.mk_goal(outlives.into_goal())) - // ), + hypotheses: tcx.mk_goals( + iter::once(tcx.mk_goal(outlives.into_goal())) + ), category: ProgramClauseCategory::WellFormed, }; let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause)); @@ -432,22 +429,14 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> { clauses } - DomainGoal::Holds(RegionOutlives(..)) => { - // These come from: - // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`) - // * implied bounds from type definitions (rule `Implied-Bound-From-Type`) - - // All of these rules are computed in the environment. - vec![] - } - - DomainGoal::Holds(TypeOutlives(..)) => { - // These come from: - // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`) - // * implied bounds from type definitions (rule `Implied-Bound-From-Type`) - - // All of these rules are computed in the environment. - vec![] + // For outlive requirements, just assume they hold. `ResolventOps::resolvent_clause` + // will register them as actual region constraints later. + DomainGoal::Holds(RegionOutlives(..)) | DomainGoal::Holds(TypeOutlives(..)) => { + vec![Clause::Implies(ProgramClause { + goal, + hypotheses: ty::List::empty(), + category: ProgramClauseCategory::Other, + })] } DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => { @@ -485,7 +474,7 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> { ty::Error | ty::Never => { let wf_clause = ProgramClause { - goal: DomainGoal::WellFormed(WellFormed::Ty(ty)), + goal, hypotheses: ty::List::empty(), category: ProgramClauseCategory::WellFormed, }; diff --git a/src/librustc_traits/chalk_context/resolvent_ops.rs b/src/librustc_traits/chalk_context/resolvent_ops.rs index 932501cc04fe0..41f983e6acac8 100644 --- a/src/librustc_traits/chalk_context/resolvent_ops.rs +++ b/src/librustc_traits/chalk_context/resolvent_ops.rs @@ -8,6 +8,7 @@ use rustc::infer::{InferCtxt, LateBoundRegionConversionTime}; use rustc::infer::canonical::{Canonical, CanonicalVarValues}; use rustc::traits::{ DomainGoal, + WhereClause, Goal, GoalKind, Clause, @@ -75,6 +76,23 @@ impl context::ResolventOps, ChalkArenas<'tcx>> }) ); + // If we have a goal of the form `T: 'a` or `'a: 'b`, then just + // assume it is true (no subgoals) and register it as a constraint + // instead. + match goal { + DomainGoal::Holds(WhereClause::RegionOutlives(pred)) => { + assert_eq!(ex_clause.subgoals.len(), 0); + ex_clause.constraints.push(ty::OutlivesPredicate(pred.0.into(), pred.1)); + } + + DomainGoal::Holds(WhereClause::TypeOutlives(pred)) => { + assert_eq!(ex_clause.subgoals.len(), 0); + ex_clause.constraints.push(ty::OutlivesPredicate(pred.0.into(), pred.1)); + } + + _ => (), + }; + let canonical_ex_clause = self.canonicalize_ex_clause(&ex_clause); Ok(canonical_ex_clause) }); @@ -112,10 +130,8 @@ impl context::ResolventOps, ChalkArenas<'tcx>> substitutor.relate(&answer_table_goal.value, &selected_goal) .map_err(|_| NoSolution)?; - let ex_clause = substitutor.ex_clause; - - // FIXME: restore this later once we get better at handling regions - // ex_clause.constraints.extend(answer_subst.constraints); + let mut ex_clause = substitutor.ex_clause; + ex_clause.constraints.extend(answer_subst.constraints); debug!("apply_answer_subst: ex_clause = {:?}", ex_clause); Ok(ex_clause) diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs index c908c6993e19e..3570cb1024600 100644 --- a/src/librustc_traits/lowering/environment.rs +++ b/src/librustc_traits/lowering/environment.rs @@ -10,9 +10,6 @@ use rustc::traits::{ use rustc::ty::{self, TyCtxt, Ty}; use rustc::hir::def_id::DefId; use rustc_data_structures::fx::FxHashSet; -use super::Lower; -use crate::generic_types; -use std::iter; struct ClauseVisitor<'set, 'a, 'tcx: 'a + 'set> { tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -38,30 +35,6 @@ impl ClauseVisitor<'set, 'a, 'tcx> { ); } - // forall<'a, T> { `Outlives(T: 'a) :- FromEnv(&'a T)` } - ty::Ref(_, _, mutbl) => { - let region = self.tcx.mk_region( - ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0)) - ); - let ty = generic_types::bound(self.tcx, 1); - let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut { - ty, - mutbl, - }); - - let from_env = DomainGoal::FromEnv(FromEnv::Ty(ref_ty)); - - let clause = ProgramClause { - goal: ty::OutlivesPredicate(ty, region).lower(), - hypotheses: self.tcx.mk_goals( - iter::once(self.tcx.mk_goal(from_env.into_goal())) - ), - category: ProgramClauseCategory::ImpliedBound, - }; - let clause = Clause::ForAll(ty::Binder::bind(clause)); - self.round.insert(clause); - } - ty::Dynamic(..) => { // FIXME: trait object rules are not yet implemented } @@ -99,6 +72,7 @@ impl ClauseVisitor<'set, 'a, 'tcx> { ty::RawPtr(..) | ty::FnPtr(..) | ty::Tuple(..) | + ty::Ref(..) | ty::Never | ty::Infer(..) | ty::Placeholder(..) | diff --git a/src/test/ui/chalkify/lower_env3.stderr b/src/test/ui/chalkify/lower_env3.stderr index 46e083686895d..a1fc83bfea8a3 100644 --- a/src/test/ui/chalkify/lower_env3.stderr +++ b/src/test/ui/chalkify/lower_env3.stderr @@ -4,7 +4,6 @@ error: program clause dump LL | #[rustc_dump_env_program_clauses] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: forall<'^0, ^1> { TypeOutlives(^1: '^0) :- FromEnv(&^1). } = note: forall { Implemented(Self: Foo) :- FromEnv(Self: Foo). } error: program clause dump @@ -13,7 +12,6 @@ error: program clause dump LL | #[rustc_dump_env_program_clauses] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: forall<'^0, ^1> { TypeOutlives(^1: '^0) :- FromEnv(&^1). } = note: forall { FromEnv(Self: std::marker::Sized) :- FromEnv(Self: std::clone::Clone). } = note: forall { Implemented(Self: std::clone::Clone) :- FromEnv(Self: std::clone::Clone). } = note: forall { Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). }