From 072cc458393974f9ff38b1448773c013c604c5fd Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sat, 18 Jul 2020 14:37:36 +0200 Subject: [PATCH] it works again :tada: --- src/librustc_middle/ty/mod.rs | 11 +++- src/librustc_middle/ty/structural_impls.rs | 8 +-- src/librustc_middle/ty/sty.rs | 3 + .../traits/error_reporting/mod.rs | 2 +- .../traits/fulfill.rs | 63 +++++++++---------- 5 files changed, 46 insertions(+), 41 deletions(-) diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 3bae1c131432..6f454e15aad7 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -1051,12 +1051,17 @@ impl<'tcx> Predicate<'tcx> { /// Returns the inner `PredicateAtom`. /// + /// The returned atom may contain unbound variables bound to binders skipped in this method. + /// It is safe to reapply binders to the given atom. + /// /// Note that this method panics in case this predicate has unbound variables. pub fn skip_binders(self) -> PredicateAtom<'tcx> { - // TODO no_escaping_vars match self.kind() { &PredicateKind::ForAll(binder) => binder.skip_binder(), - &ty::PredicateKind::Atom(atom) => atom, + &PredicateKind::Atom(atom) => { + debug_assert!(!atom.has_escaping_bound_vars()); + atom + } } } @@ -1378,7 +1383,7 @@ impl ToPredicate<'tcx> for PredicateKind<'tcx> { impl ToPredicate<'tcx> for PredicateAtom<'tcx> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - debug_assert!(!self.has_escaping_bound_vars(), "excaping bound vars for {:?}", self); + debug_assert!(!self.has_escaping_bound_vars(), "escaping bound vars for {:?}", self); tcx.mk_predicate(ty::PredicateKind::Atom(self)) } } diff --git a/src/librustc_middle/ty/structural_impls.rs b/src/librustc_middle/ty/structural_impls.rs index cfe076e12070..21b8d7101a30 100644 --- a/src/librustc_middle/ty/structural_impls.rs +++ b/src/librustc_middle/ty/structural_impls.rs @@ -486,11 +486,9 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialProjection<'a> { impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> { type Lifted = ty::PredicateKind<'tcx>; fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option { - match *self { - ty::PredicateKind::ForAll(ref binder) => { - tcx.lift(binder).map(ty::PredicateKind::ForAll) - } - ty::PredicateKind::Atom(ref atom) => tcx.lift(atom).map(ty::PredicateKind::Atom), + match self { + ty::PredicateKind::ForAll(binder) => tcx.lift(binder).map(ty::PredicateKind::ForAll), + ty::PredicateKind::Atom(atom) => tcx.lift(atom).map(ty::PredicateKind::Atom), } } } diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index 58a89c7fdb11..df8fa4d73ddf 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -897,6 +897,9 @@ impl Binder { /// Wraps `value` in a binder without actually binding any currently /// unbound variables. + /// + /// Note that this will shift all debrujin indices of escaping bound variables + /// by 1 to avoid accidential captures. pub fn wrap_nonbinding(tcx: TyCtxt<'tcx>, value: T) -> Binder where T: TypeFoldable<'tcx>, diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index 951e0b220266..349fa68a4da9 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -1100,7 +1100,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { for obligation in super::elaborate_predicates(self.tcx, std::iter::once(cond)) { if let ty::PredicateAtom::Trait(implication, _) = obligation.predicate.skip_binders() { let error = error.to_poly_trait_ref(); - let implication = ty::Binder::bind(implication).to_poly_trait_ref(); + let implication = ty::Binder::bind(implication.trait_ref); // FIXME: I'm just not taking associated types at all here. // Eventually I'll need to implement param-env-aware // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. diff --git a/src/librustc_trait_selection/traits/fulfill.rs b/src/librustc_trait_selection/traits/fulfill.rs index 25564d03e837..2b9621c9271e 100644 --- a/src/librustc_trait_selection/traits/fulfill.rs +++ b/src/librustc_trait_selection/traits/fulfill.rs @@ -3,7 +3,7 @@ use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{DoCompleted, Error, ForestObligation}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; use rustc_errors::ErrorReported; -use rustc_infer::traits::{PolyTraitObligation, TraitEngine, TraitEngineExt as _}; +use rustc_infer::traits::{TraitObligation, TraitEngine, TraitEngineExt as _}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::ToPredicate; @@ -320,41 +320,40 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { let infcx = self.selcx.infcx(); match obligation.predicate.kind() { - ty::PredicateKind::ForAll(binder) => match binder.skip_binder().kind() { - ty::PredicateKind::ForAll(_) => bug!("unexpected forall"), + ty::PredicateKind::ForAll(binder) => match binder.skip_binder() { // Evaluation will discard candidates using the leak check. // This means we need to pass it the bound version of our // predicate. - &ty::PredicateKind::Atom(atom) => match atom { - ty::PredicateAtom::Trait(trait_ref, _constness) => { - let trait_obligation = obligation.with(Binder::bind(trait_ref)); + ty::PredicateAtom::Trait(trait_ref, _constness) => { + let trait_obligation = obligation.with(Binder::bind(trait_ref)); - self.process_trait_obligation( - obligation, - trait_obligation, - &mut pending_obligation.stalled_on, - ) - } - ty::PredicateAtom::Projection(projection) => { - let project_obligation = obligation.with(Binder::bind(projection)); + self.process_trait_obligation( + obligation, + trait_obligation, + &mut pending_obligation.stalled_on, + ) + } + ty::PredicateAtom::Projection(data) => { + let project_obligation = obligation.with(Binder::bind(data)); - self.process_projection_obligation( - project_obligation, - &mut pending_obligation.stalled_on, - ) - } - ty::PredicateAtom::RegionOutlives(_) - | ty::PredicateAtom::TypeOutlives(_) - | ty::PredicateAtom::WellFormed(_) - | ty::PredicateAtom::ObjectSafe(_) - | ty::PredicateAtom::ClosureKind(..) - | ty::PredicateAtom::Subtype(_) - | ty::PredicateAtom::ConstEvaluatable(..) - | ty::PredicateAtom::ConstEquate(..) => { - let (pred, _) = infcx.replace_bound_vars_with_placeholders(binder); - ProcessResult::Changed(mk_pending(vec![obligation.with(pred)])) - } - }, + self.process_projection_obligation( + project_obligation, + &mut pending_obligation.stalled_on, + ) + } + ty::PredicateAtom::RegionOutlives(_) + | ty::PredicateAtom::TypeOutlives(_) + | ty::PredicateAtom::WellFormed(_) + | ty::PredicateAtom::ObjectSafe(_) + | ty::PredicateAtom::ClosureKind(..) + | ty::PredicateAtom::Subtype(_) + | ty::PredicateAtom::ConstEvaluatable(..) + | ty::PredicateAtom::ConstEquate(..) => { + let (pred, _) = infcx.replace_bound_vars_with_placeholders(binder); + ProcessResult::Changed(mk_pending(vec![ + obligation.with(pred.to_predicate(self.selcx.tcx())), + ])) + } }, &ty::PredicateKind::Atom(atom) => match atom { ty::PredicateAtom::Trait(ref data, _) => { @@ -560,7 +559,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { fn process_trait_obligation( &mut self, obligation: &PredicateObligation<'tcx>, - trait_obligation: PolyTraitObligation<'tcx>, + trait_obligation: TraitObligation<'tcx>, stalled_on: &mut Vec>, ) -> ProcessResult, FulfillmentErrorCode<'tcx>> { let infcx = self.selcx.infcx();