about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs24
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs2
2 files changed, 19 insertions, 7 deletions
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
index f49f3a1a3bf..71ce0cce772 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
@@ -16,7 +16,7 @@ use rustc_type_ir::fold::TypeFoldable;
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::relate::solver_relating::RelateExt;
 use rustc_type_ir::{self as ty, Canonical, CanonicalVarValues, InferCtxtLike, Interner};
-use tracing::{instrument, trace};
+use tracing::{debug, instrument, trace};
 
 use crate::canonicalizer::{CanonicalizeMode, Canonicalizer};
 use crate::delegate::SolverDelegate;
@@ -165,12 +165,22 @@ where
         // HACK: We bail with overflow if the response would have too many non-region
         // inference variables. This tends to only happen if we encounter a lot of
         // ambiguous alias types which get replaced with fresh inference variables
-        // during generalization. This prevents a hang in nalgebra.
-        let num_non_region_vars = canonical.variables.iter().filter(|c| !c.is_region()).count();
-        if num_non_region_vars > self.cx().recursion_limit() {
-            return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow {
-                suggest_increasing_limit: true,
-            }));
+        // during generalization. This prevents hangs caused by an exponential blowup,
+        // see tests/ui/traits/next-solver/coherence-alias-hang.rs.
+        //
+        // We don't do so for `NormalizesTo` goals as we erased the expected term and
+        // bailing with overflow here would prevent us from detecting a type-mismatch,
+        // causing a coherence error in diesel, see #131969. We still bail with verflow
+        // when later returning from the parent AliasRelate goal.
+        if !self.is_normalizes_to_goal {
+            let num_non_region_vars =
+                canonical.variables.iter().filter(|c| !c.is_region() && c.is_existential()).count();
+            if num_non_region_vars > self.cx().recursion_limit() {
+                debug!(?num_non_region_vars, "too many inference variables -> overflow");
+                return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow {
+                    suggest_increasing_limit: true,
+                }));
+            }
         }
 
         Ok(canonical)
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index f4a2483cebf..f8fb297e36c 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -298,6 +298,7 @@ fn equate_impl_headers<'tcx>(
 }
 
 /// The result of [fn impl_intersection_has_impossible_obligation].
+#[derive(Debug)]
 enum IntersectionHasImpossibleObligations<'tcx> {
     Yes,
     No {
@@ -328,6 +329,7 @@ enum IntersectionHasImpossibleObligations<'tcx> {
 /// of the two impls above to be empty.
 ///
 /// Importantly, this works even if there isn't a `impl !Error for MyLocalType`.
+#[instrument(level = "debug", skip(selcx), ret)]
 fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligations: &'a [PredicateObligation<'tcx>],