From cbe932801892da06688b53638622be1c8a1c8974 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Fri, 11 Nov 2022 03:19:02 +0000
Subject: [PATCH 1/3] Do not need to account for overflow in
 predicate_can_apply

---
 .../src/traits/error_reporting/mod.rs         |  5 ++++-
 .../ui/traits/predicate_can_apply-hang.rs     |  6 ++++++
 .../ui/traits/predicate_can_apply-hang.stderr | 21 +++++++++++++++++++
 3 files changed, 31 insertions(+), 1 deletion(-)
 create mode 100644 src/test/ui/traits/predicate_can_apply-hang.rs
 create mode 100644 src/test/ui/traits/predicate_can_apply-hang.stderr

diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 946e6e77a3da0..c2a7be8046762 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -2544,7 +2544,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())
         })
     }
 
diff --git a/src/test/ui/traits/predicate_can_apply-hang.rs b/src/test/ui/traits/predicate_can_apply-hang.rs
new file mode 100644
index 0000000000000..5f01645da5242
--- /dev/null
+++ b/src/test/ui/traits/predicate_can_apply-hang.rs
@@ -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() {}
diff --git a/src/test/ui/traits/predicate_can_apply-hang.stderr b/src/test/ui/traits/predicate_can_apply-hang.stderr
new file mode 100644
index 0000000000000..49fe63b412ac9
--- /dev/null
+++ b/src/test/ui/traits/predicate_can_apply-hang.stderr
@@ -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`.

From a884a9e634b827781e77bddf4082f1196301d86f Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Fri, 11 Nov 2022 03:37:04 +0000
Subject: [PATCH 2/3] Drive-by: Don't manually call
 evaluate_obligation_no_overflow

---
 .../src/traits/error_reporting/suggestions.rs                | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 186109e7075f1..bb6d7d0e8dff1 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -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

From 9decfff6f87d3e5760fd61375c3d27fa45a83e52 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Fri, 18 Nov 2022 17:23:10 +0000
Subject: [PATCH 3/3] Add fatal overflow test

---
 src/test/ui/typeck/hang-in-overflow.rs     | 19 +++++++++++++++++++
 src/test/ui/typeck/hang-in-overflow.stderr | 22 ++++++++++++++++++++++
 2 files changed, 41 insertions(+)
 create mode 100644 src/test/ui/typeck/hang-in-overflow.rs
 create mode 100644 src/test/ui/typeck/hang-in-overflow.stderr

diff --git a/src/test/ui/typeck/hang-in-overflow.rs b/src/test/ui/typeck/hang-in-overflow.rs
new file mode 100644
index 0000000000000..a8330c9b65c31
--- /dev/null
+++ b/src/test/ui/typeck/hang-in-overflow.rs
@@ -0,0 +1,19 @@
+// normalize-stderr-test "the requirement `.*`" -> "the requirement `...`"
+// normalize-stderr-test "required for `.*` to implement `.*`" -> "required for `...` to implement `...`"
+// normalize-stderr-test: ".*the full type name has been written to.*\n" -> ""
+
+// 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() {}
diff --git a/src/test/ui/typeck/hang-in-overflow.stderr b/src/test/ui/typeck/hang-in-overflow.stderr
new file mode 100644
index 0000000000000..7a7b85b19b4ee
--- /dev/null
+++ b/src/test/ui/typeck/hang-in-overflow.stderr
@@ -0,0 +1,22 @@
+error[E0275]: overflow evaluating the requirement `...`
+  --> $DIR/hang-in-overflow.rs:9: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:15: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`.