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`.
///
/// 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))
}
}

View file

@ -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<Self::Lifted> {
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),
}
}
}

View file

@ -897,6 +897,9 @@ impl<T> Binder<T> {
/// 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<T>
where
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)) {
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.

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::{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<TyOrConstInferVar<'tcx>>,
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
let infcx = self.selcx.infcx();