Skip to content

Commit 9926fa3

Browse files
committed
also filter obligations by sub_root
1 parent 1ddf87c commit 9926fa3

File tree

3 files changed

+57
-7
lines changed

3 files changed

+57
-7
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7676
&self,
7777
self_ty: ty::TyVid,
7878
) -> PredicateObligations<'tcx> {
79-
let obligations = self.fulfillment_cx.borrow().pending_obligations();
79+
// We only look at obligations which may reference the self type.
80+
// This lookup uses the `sub_root` instead of the inference variable
81+
// itself as that's slightly nicer to implement. It shouldn't really
82+
// matter.
83+
//
84+
// This is really impactful when typechecking functions with a lot of
85+
// stalled obligations, e.g. in the `wg-grammar` benchmark.
86+
let sub_root_var = self.sub_unification_table_root_var(self_ty);
87+
let obligations = self
88+
.fulfillment_cx
89+
.borrow()
90+
.pending_obligations_potentially_referencing_sub_root(sub_root_var);
8091
debug!(?obligations);
8192
let mut obligations_for_self_ty = PredicateObligations::new();
8293
for obligation in obligations {

compiler/rustc_infer/src/traits/engine.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::fmt::Debug;
22

33
use rustc_hir::def_id::DefId;
4-
use rustc_middle::ty::{self, Ty, Upcast};
4+
use rustc_middle::ty::{self, Ty, TyVid, Upcast};
55

66
use super::{ObligationCause, PredicateObligation, PredicateObligations};
77
use crate::infer::InferCtxt;
@@ -106,6 +106,15 @@ pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx {
106106
fn has_pending_obligations(&self) -> bool;
107107

108108
fn pending_obligations(&self) -> PredicateObligations<'tcx>;
109+
// Returning all pending obligations which reference an inference
110+
// variable with `_sub_root`. This assumes that no type inference
111+
// progress has been made since the last `select_where_possible` call.
112+
fn pending_obligations_potentially_referencing_sub_root(
113+
&self,
114+
_sub_root: TyVid,
115+
) -> PredicateObligations<'tcx> {
116+
self.pending_obligations()
117+
}
109118

110119
/// Among all pending obligations, collect those are stalled on a inference variable which has
111120
/// changed since the last call to `select_where_possible`. Those obligations are marked as

compiler/rustc_trait_selection/src/solve/fulfill.rs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use rustc_infer::traits::{
1010
FromSolverError, PredicateObligation, PredicateObligations, TraitEngine,
1111
};
1212
use rustc_middle::ty::{
13-
self, DelayedSet, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
14-
TypingMode,
13+
self, DelayedSet, Ty, TyCtxt, TyVid, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
14+
TypeVisitor, TypingMode,
1515
};
1616
use rustc_next_trait_solver::delegate::SolverDelegate as _;
1717
use rustc_next_trait_solver::solve::{
@@ -85,8 +85,30 @@ impl<'tcx> ObligationStorage<'tcx> {
8585
obligations.extend(self.overflowed.iter().cloned());
8686
obligations
8787
}
88+
fn clone_pending_potentially_referencing_sub_root(
89+
&self,
90+
vid: TyVid,
91+
) -> PredicateObligations<'tcx> {
92+
let mut obligations: PredicateObligations<'tcx> = self
93+
.pending
94+
.iter()
95+
.filter(|(_, stalled_on)| {
96+
// This may incorrectly return `false` in case we've made
97+
// inference progress since the last time we tried to evaluate
98+
// this obligation.
99+
if let Some(stalled_on) = stalled_on {
100+
stalled_on.sub_roots.iter().any(|&r| r == vid)
101+
} else {
102+
true
103+
}
104+
})
105+
.map(|(o, _)| o.clone())
106+
.collect();
107+
obligations.extend(self.overflowed.iter().cloned());
108+
obligations
109+
}
88110

89-
fn drain_pending(
111+
fn drain_pending_ignoring_overflowed(
90112
&mut self,
91113
cond: impl Fn(&PredicateObligation<'tcx>) -> bool,
92114
) -> PendingObligations<'tcx> {
@@ -184,7 +206,9 @@ where
184206
let mut errors = Vec::new();
185207
loop {
186208
let mut any_changed = false;
187-
for (mut obligation, stalled_on) in self.obligations.drain_pending(|_| true) {
209+
for (mut obligation, stalled_on) in
210+
self.obligations.drain_pending_ignoring_overflowed(|_| true)
211+
{
188212
if !infcx.tcx.recursion_limit().value_within_limit(obligation.recursion_depth) {
189213
self.obligations.on_fulfillment_overflow(infcx);
190214
// Only return true errors that we have accumulated while processing.
@@ -277,6 +301,12 @@ where
277301
fn pending_obligations(&self) -> PredicateObligations<'tcx> {
278302
self.obligations.clone_pending()
279303
}
304+
fn pending_obligations_potentially_referencing_sub_root(
305+
&self,
306+
vid: ty::TyVid,
307+
) -> PredicateObligations<'tcx> {
308+
self.obligations.clone_pending_potentially_referencing_sub_root(vid)
309+
}
280310

281311
fn drain_stalled_obligations_for_coroutines(
282312
&mut self,
@@ -297,7 +327,7 @@ where
297327
}
298328

299329
self.obligations
300-
.drain_pending(|obl| {
330+
.drain_pending_ignoring_overflowed(|obl| {
301331
infcx.probe(|_| {
302332
infcx
303333
.visit_proof_tree(

0 commit comments

Comments
 (0)