Skip to content

Commit

Permalink
Rollup merge of rust-lang#104269 - compiler-errors:hang-in-where-clau…
Browse files Browse the repository at this point in the history
…se-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 rust-lang#104225
  • Loading branch information
matthiaskrgr authored Nov 21, 2022
2 parents 736c675 + 65b3a30 commit 2263e0d
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2557,7 +2557,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let obligation =
Obligation::new(self.tcx, ObligationCause::dummy(), param_env, cleaned_pred);

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1340,9 +1340,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
obligation.param_env,
trait_pred_and_suggested_ty,
);
let suggested_ty_would_satisfy_obligation = self
.evaluate_obligation_no_overflow(&new_obligation)
.must_apply_modulo_regions();
let suggested_ty_would_satisfy_obligation =
self.predicate_must_hold_modulo_regions(&new_obligation);
if suggested_ty_would_satisfy_obligation {
let sp = self
.tcx
Expand Down
6 changes: 6 additions & 0 deletions src/test/ui/traits/predicate_can_apply-hang.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fn f<B>(x: Vec<[[[B; 1]; 1]; 1]>) -> impl PartialEq<B> {
//~^ ERROR can't compare `Vec<[[[B; 1]; 1]; 1]>` with `B`
x
}

fn main() {}
21 changes: 21 additions & 0 deletions src/test/ui/traits/predicate_can_apply-hang.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0277]: can't compare `Vec<[[[B; 1]; 1]; 1]>` with `B`
--> $DIR/predicate_can_apply-hang.rs:1:38
|
LL | fn f<B>(x: Vec<[[[B; 1]; 1]; 1]>) -> impl PartialEq<B> {
| ^^^^^^^^^^^^^^^^^ no implementation for `Vec<[[[B; 1]; 1]; 1]> == B`
LL |
LL | x
| - return type was inferred to be `Vec<[[[B; 1]; 1]; 1]>` here
|
= help: the trait `PartialEq<B>` is not implemented for `Vec<[[[B; 1]; 1]; 1]>`
= help: the following other types implement trait `PartialEq<Rhs>`:
<Vec<T, A1> as PartialEq<Vec<U, A2>>>
<Vec<T, A> as PartialEq<&[U; N]>>
<Vec<T, A> as PartialEq<&[U]>>
<Vec<T, A> as PartialEq<&mut [U]>>
<Vec<T, A> as PartialEq<[U; N]>>
<Vec<T, A> as PartialEq<[U]>>

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
18 changes: 18 additions & 0 deletions src/test/ui/typeck/hang-in-overflow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// normalize-stderr-test "the requirement `.*`" -> "the requirement `...`"
// normalize-stderr-test "required for `.*` to implement `.*`" -> "required for `...` to implement `...`"

// Currently this fatally aborts instead of hanging.
// Make sure at least that this doesn't turn into a hang.

fn f() {
foo::<_>();
//~^ ERROR overflow evaluating the requirement
}

fn foo<B>()
where
Vec<[[[B; 1]; 1]; 1]>: PartialEq<B>,
{
}

fn main() {}
22 changes: 22 additions & 0 deletions src/test/ui/typeck/hang-in-overflow.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error[E0275]: overflow evaluating the requirement `...`
--> $DIR/hang-in-overflow.rs:8:5
|
LL | foo::<_>();
| ^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`hang_in_overflow`)
= note: required for `...` to implement `...`
= note: 127 redundant requirements hidden
= note: required for `...` to implement `...`
note: required by a bound in `foo`
--> $DIR/hang-in-overflow.rs:14:28
|
LL | fn foo<B>()
| --- required by a bound in this
LL | where
LL | Vec<[[[B; 1]; 1]; 1]>: PartialEq<B>,
| ^^^^^^^^^^^^ required by this bound in `foo`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0275`.

0 comments on commit 2263e0d

Please sign in to comment.