Skip to content

Commit bd91c94

Browse files
authored
Rollup merge of #104269 - compiler-errors:hang-in-where-clause-sugg, r=lcnr
Fix hang in where-clause suggestion with `predicate_can_apply` Using `predicate_may_hold` during error reporting causes an evaluation overflow, which (because we use `evaluate_obligation_no_overflow`) then causes the predicate to need to be re-evaluated locally, which results in a hang. ... but since the "add a where clause" suggestion is best-effort, just throw any overflow errors. No need for 100% accuracy. r? `@lcnr` who has been thinking about overflows... Let me know if you want more context about this issue, and as always, feel free to reassign. Fixes #104225
2 parents 4e0d0d7 + 9decfff commit bd91c94

File tree

6 files changed

+74
-4
lines changed

6 files changed

+74
-4
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -2546,7 +2546,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
25462546
let obligation =
25472547
Obligation::new(self.tcx, ObligationCause::dummy(), param_env, cleaned_pred);
25482548

2549-
self.predicate_may_hold(&obligation)
2549+
// We don't use `InferCtxt::predicate_may_hold` because that
2550+
// will re-run predicates that overflow locally, which ends up
2551+
// taking a really long time to compute.
2552+
self.evaluate_obligation(&obligation).map_or(false, |eval| eval.may_apply())
25502553
})
25512554
}
25522555

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1340,9 +1340,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
13401340
obligation.param_env,
13411341
trait_pred_and_suggested_ty,
13421342
);
1343-
let suggested_ty_would_satisfy_obligation = self
1344-
.evaluate_obligation_no_overflow(&new_obligation)
1345-
.must_apply_modulo_regions();
1343+
let suggested_ty_would_satisfy_obligation =
1344+
self.predicate_must_hold_modulo_regions(&new_obligation);
13461345
if suggested_ty_would_satisfy_obligation {
13471346
let sp = self
13481347
.tcx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fn f<B>(x: Vec<[[[B; 1]; 1]; 1]>) -> impl PartialEq<B> {
2+
//~^ ERROR can't compare `Vec<[[[B; 1]; 1]; 1]>` with `B`
3+
x
4+
}
5+
6+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0277]: can't compare `Vec<[[[B; 1]; 1]; 1]>` with `B`
2+
--> $DIR/predicate_can_apply-hang.rs:1:38
3+
|
4+
LL | fn f<B>(x: Vec<[[[B; 1]; 1]; 1]>) -> impl PartialEq<B> {
5+
| ^^^^^^^^^^^^^^^^^ no implementation for `Vec<[[[B; 1]; 1]; 1]> == B`
6+
LL |
7+
LL | x
8+
| - return type was inferred to be `Vec<[[[B; 1]; 1]; 1]>` here
9+
|
10+
= help: the trait `PartialEq<B>` is not implemented for `Vec<[[[B; 1]; 1]; 1]>`
11+
= help: the following other types implement trait `PartialEq<Rhs>`:
12+
<Vec<T, A1> as PartialEq<Vec<U, A2>>>
13+
<Vec<T, A> as PartialEq<&[U; N]>>
14+
<Vec<T, A> as PartialEq<&[U]>>
15+
<Vec<T, A> as PartialEq<&mut [U]>>
16+
<Vec<T, A> as PartialEq<[U; N]>>
17+
<Vec<T, A> as PartialEq<[U]>>
18+
19+
error: aborting due to previous error
20+
21+
For more information about this error, try `rustc --explain E0277`.
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// normalize-stderr-test "the requirement `.*`" -> "the requirement `...`"
2+
// normalize-stderr-test "required for `.*` to implement `.*`" -> "required for `...` to implement `...`"
3+
// normalize-stderr-test: ".*the full type name has been written to.*\n" -> ""
4+
5+
// Currently this fatally aborts instead of hanging.
6+
// Make sure at least that this doesn't turn into a hang.
7+
8+
fn f() {
9+
foo::<_>();
10+
//~^ ERROR overflow evaluating the requirement
11+
}
12+
13+
fn foo<B>()
14+
where
15+
Vec<[[[B; 1]; 1]; 1]>: PartialEq<B>,
16+
{
17+
}
18+
19+
fn main() {}
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0275]: overflow evaluating the requirement `...`
2+
--> $DIR/hang-in-overflow.rs:9:5
3+
|
4+
LL | foo::<_>();
5+
| ^^^^^^^^
6+
|
7+
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`hang_in_overflow`)
8+
= note: required for `...` to implement `...`
9+
= note: 127 redundant requirements hidden
10+
= note: required for `...` to implement `...`
11+
note: required by a bound in `foo`
12+
--> $DIR/hang-in-overflow.rs:15:28
13+
|
14+
LL | fn foo<B>()
15+
| --- required by a bound in this
16+
LL | where
17+
LL | Vec<[[[B; 1]; 1]; 1]>: PartialEq<B>,
18+
| ^^^^^^^^^^^^ required by this bound in `foo`
19+
20+
error: aborting due to previous error
21+
22+
For more information about this error, try `rustc --explain E0275`.

0 commit comments

Comments
 (0)