mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-04 09:53:04 +03:00
Track per-obligation recursion depth only if there is inference
This commit is contained in:
@@ -163,15 +163,15 @@ fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
|
||||
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
|
||||
assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots());
|
||||
let mut errors = Vec::new();
|
||||
for i in 0.. {
|
||||
if !infcx.tcx.recursion_limit().value_within_limit(i) {
|
||||
self.obligations.on_fulfillment_overflow(infcx);
|
||||
// Only return true errors that we have accumulated while processing.
|
||||
return errors;
|
||||
}
|
||||
|
||||
loop {
|
||||
let mut has_changed = false;
|
||||
for obligation in self.obligations.drain_pending(|_| true) {
|
||||
for mut obligation in self.obligations.drain_pending(|_| true) {
|
||||
if !infcx.tcx.recursion_limit().value_within_limit(obligation.recursion_depth) {
|
||||
self.obligations.on_fulfillment_overflow(infcx);
|
||||
// Only return true errors that we have accumulated while processing.
|
||||
return errors;
|
||||
}
|
||||
|
||||
let goal = obligation.as_goal();
|
||||
let result = <&SolverDelegate<'tcx>>::from(infcx)
|
||||
.evaluate_root_goal(goal, GenerateProofTree::No, obligation.cause.span)
|
||||
@@ -189,6 +189,13 @@ fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
|
||||
};
|
||||
|
||||
if changed == HasChanged::Yes {
|
||||
// We increment the recursion depth here to track the number of times
|
||||
// this goal has resulted in inference progress. This doesn't precisely
|
||||
// model the way that we track recursion depth in the old solver due
|
||||
// to the fact that we only process root obligations, but it is a good
|
||||
// approximation and should only result in fulfillment overflow in
|
||||
// pathological cases.
|
||||
obligation.recursion_depth += 1;
|
||||
has_changed = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
//@ check-pass
|
||||
//@ compile-flags: -Znext-solver
|
||||
|
||||
// Ensure that a stack of coerce predicates doesn't end up overflowing when they get procesed
|
||||
// in *reverse* order, which may require O(N) iterations of the fulfillment loop.
|
||||
|
||||
#![recursion_limit = "16"]
|
||||
|
||||
fn main() {
|
||||
match 0 {
|
||||
0 => None,
|
||||
1 => None,
|
||||
2 => None,
|
||||
3 => None,
|
||||
4 => None,
|
||||
5 => None,
|
||||
6 => None,
|
||||
7 => None,
|
||||
8 => None,
|
||||
9 => None,
|
||||
10 => None,
|
||||
11 => None,
|
||||
12 => None,
|
||||
13 => None,
|
||||
14 => None,
|
||||
15 => None,
|
||||
16 => None,
|
||||
17 => None,
|
||||
_ => Some(1u32),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user