it works again 🎉

This commit is contained in:
Bastian Kauschke 2020-07-18 14:37:36 +02:00
parent 825cb5bdc9
commit 072cc45839
5 changed files with 46 additions and 41 deletions

View file

@ -1051,12 +1051,17 @@ impl<'tcx> Predicate<'tcx> {
/// Returns the inner `PredicateAtom`. /// 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. /// Note that this method panics in case this predicate has unbound variables.
pub fn skip_binders(self) -> PredicateAtom<'tcx> { pub fn skip_binders(self) -> PredicateAtom<'tcx> {
// TODO no_escaping_vars
match self.kind() { match self.kind() {
&PredicateKind::ForAll(binder) => binder.skip_binder(), &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> { impl ToPredicate<'tcx> for PredicateAtom<'tcx> {
#[inline(always)] #[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { 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)) tcx.mk_predicate(ty::PredicateKind::Atom(self))
} }
} }

View file

@ -486,11 +486,9 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialProjection<'a> {
impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> { impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> {
type Lifted = ty::PredicateKind<'tcx>; type Lifted = ty::PredicateKind<'tcx>;
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
match *self { match self {
ty::PredicateKind::ForAll(ref binder) => { ty::PredicateKind::ForAll(binder) => tcx.lift(binder).map(ty::PredicateKind::ForAll),
tcx.lift(binder).map(ty::PredicateKind::ForAll) ty::PredicateKind::Atom(atom) => tcx.lift(atom).map(ty::PredicateKind::Atom),
}
ty::PredicateKind::Atom(ref atom) => tcx.lift(atom).map(ty::PredicateKind::Atom),
} }
} }
} }

View file

@ -897,6 +897,9 @@ impl<T> Binder<T> {
/// Wraps `value` in a binder without actually binding any currently /// Wraps `value` in a binder without actually binding any currently
/// unbound variables. /// 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<T> pub fn wrap_nonbinding(tcx: TyCtxt<'tcx>, value: T) -> Binder<T>
where where
T: TypeFoldable<'tcx>, T: TypeFoldable<'tcx>,

View file

@ -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)) { for obligation in super::elaborate_predicates(self.tcx, std::iter::once(cond)) {
if let ty::PredicateAtom::Trait(implication, _) = obligation.predicate.skip_binders() { if let ty::PredicateAtom::Trait(implication, _) = obligation.predicate.skip_binders() {
let error = error.to_poly_trait_ref(); 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. // FIXME: I'm just not taking associated types at all here.
// Eventually I'll need to implement param-env-aware // Eventually I'll need to implement param-env-aware
// `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.

View file

@ -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::{DoCompleted, Error, ForestObligation};
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
use rustc_errors::ErrorReported; 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::mir::interpret::ErrorHandled;
use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::ToPredicate; use rustc_middle::ty::ToPredicate;
@ -320,41 +320,40 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
let infcx = self.selcx.infcx(); let infcx = self.selcx.infcx();
match obligation.predicate.kind() { match obligation.predicate.kind() {
ty::PredicateKind::ForAll(binder) => match binder.skip_binder().kind() { ty::PredicateKind::ForAll(binder) => match binder.skip_binder() {
ty::PredicateKind::ForAll(_) => bug!("unexpected forall"),
// Evaluation will discard candidates using the leak check. // Evaluation will discard candidates using the leak check.
// This means we need to pass it the bound version of our // This means we need to pass it the bound version of our
// predicate. // predicate.
&ty::PredicateKind::Atom(atom) => match atom { ty::PredicateAtom::Trait(trait_ref, _constness) => {
ty::PredicateAtom::Trait(trait_ref, _constness) => { let trait_obligation = obligation.with(Binder::bind(trait_ref));
let trait_obligation = obligation.with(Binder::bind(trait_ref));
self.process_trait_obligation( self.process_trait_obligation(
obligation, obligation,
trait_obligation, trait_obligation,
&mut pending_obligation.stalled_on, &mut pending_obligation.stalled_on,
) )
} }
ty::PredicateAtom::Projection(projection) => { ty::PredicateAtom::Projection(data) => {
let project_obligation = obligation.with(Binder::bind(projection)); let project_obligation = obligation.with(Binder::bind(data));
self.process_projection_obligation( self.process_projection_obligation(
project_obligation, project_obligation,
&mut pending_obligation.stalled_on, &mut pending_obligation.stalled_on,
) )
} }
ty::PredicateAtom::RegionOutlives(_) ty::PredicateAtom::RegionOutlives(_)
| ty::PredicateAtom::TypeOutlives(_) | ty::PredicateAtom::TypeOutlives(_)
| ty::PredicateAtom::WellFormed(_) | ty::PredicateAtom::WellFormed(_)
| ty::PredicateAtom::ObjectSafe(_) | ty::PredicateAtom::ObjectSafe(_)
| ty::PredicateAtom::ClosureKind(..) | ty::PredicateAtom::ClosureKind(..)
| ty::PredicateAtom::Subtype(_) | ty::PredicateAtom::Subtype(_)
| ty::PredicateAtom::ConstEvaluatable(..) | ty::PredicateAtom::ConstEvaluatable(..)
| ty::PredicateAtom::ConstEquate(..) => { | ty::PredicateAtom::ConstEquate(..) => {
let (pred, _) = infcx.replace_bound_vars_with_placeholders(binder); let (pred, _) = infcx.replace_bound_vars_with_placeholders(binder);
ProcessResult::Changed(mk_pending(vec![obligation.with(pred)])) ProcessResult::Changed(mk_pending(vec![
} obligation.with(pred.to_predicate(self.selcx.tcx())),
}, ]))
}
}, },
&ty::PredicateKind::Atom(atom) => match atom { &ty::PredicateKind::Atom(atom) => match atom {
ty::PredicateAtom::Trait(ref data, _) => { ty::PredicateAtom::Trait(ref data, _) => {
@ -560,7 +559,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
fn process_trait_obligation( fn process_trait_obligation(
&mut self, &mut self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
trait_obligation: PolyTraitObligation<'tcx>, trait_obligation: TraitObligation<'tcx>,
stalled_on: &mut Vec<TyOrConstInferVar<'tcx>>, stalled_on: &mut Vec<TyOrConstInferVar<'tcx>>,
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> { ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
let infcx = self.selcx.infcx(); let infcx = self.selcx.infcx();