diff options
| author | lcnr <rust@lcnr.de> | 2024-10-21 16:25:42 +0200 |
|---|---|---|
| committer | lcnr <rust@lcnr.de> | 2024-10-21 16:25:42 +0200 |
| commit | b64b25b99e738f4c68a83f987b203979eaad4fbf (patch) | |
| tree | cfd6dcf5ec17acc6be09c24a8e9d4e3f4fdef692 | |
| parent | 3e33bda0326586a6e1e34d0f5c060ca6d116e6a4 (diff) | |
| download | rust-b64b25b99e738f4c68a83f987b203979eaad4fbf.tar.gz rust-b64b25b99e738f4c68a83f987b203979eaad4fbf.zip | |
normalizes-to disable infer var check
4 files changed, 74 insertions, 14 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..bc691a8aa2b 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,21 @@ 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()).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>], diff --git a/tests/ui/traits/next-solver/normalize/normalize-allow-too-many-vars.rs b/tests/ui/traits/next-solver/normalize/normalize-allow-too-many-vars.rs new file mode 100644 index 00000000000..5284220ac38 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/normalize-allow-too-many-vars.rs @@ -0,0 +1,52 @@ +//@ check-pass + +// When canonicalizing a response in the trait solver, we bail with overflow +// if there are too many non-region inference variables. Doing so in normalizes-to +// goals ends up hiding inference constraints in cases which we want to support, +// see #131969. To prevent this issue we do not check for too many inference +// variables in normalizes-to goals. +#![recursion_limit = "8"] + +trait Bound {} +trait Trait { + type Assoc; +} + + +impl<T0, T1, T2, T3, T4, T5, T6, T7> Trait for (T0, T1, T2, T3, T4, T5, T6, T7) +where + T0: Trait, + T1: Trait, + T2: Trait, + T3: Trait, + T4: Trait, + T5: Trait, + T6: Trait, + T7: Trait, + ( + T0::Assoc, + T1::Assoc, + T2::Assoc, + T3::Assoc, + T4::Assoc, + T5::Assoc, + T6::Assoc, + T7::Assoc, + ): Clone, +{ + type Assoc = ( + T0::Assoc, + T1::Assoc, + T2::Assoc, + T3::Assoc, + T4::Assoc, + T5::Assoc, + T6::Assoc, + T7::Assoc, + ); +} + +trait Overlap {} +impl<T: Trait<Assoc = ()>> Overlap for T {} +impl<T0, T1, T2, T3, T4, T5, T6, T7> Overlap for (T0, T1, T2, T3, T4, T5, T6, T7) {} +fn main() {} diff --git a/tests/ui/traits/next-solver/overflow/coherence-alias-hang.rs b/tests/ui/traits/next-solver/overflow/coherence-alias-hang.rs index 0d5f42231e4..f88f74680b9 100644 --- a/tests/ui/traits/next-solver/overflow/coherence-alias-hang.rs +++ b/tests/ui/traits/next-solver/overflow/coherence-alias-hang.rs @@ -1,8 +1,5 @@ //@ check-pass -//@ revisions: ai_current ai_next ia_current ia_next ii_current ii_next -//@[ai_next] compile-flags: -Znext-solver -//@[ia_next] compile-flags: -Znext-solver -//@[ii_next] compile-flags: -Znext-solver +//@ revisions: ai ia ii // Regression test for nalgebra hang <https://github.com/rust-lang/rust/issues/130056>. @@ -17,11 +14,11 @@ trait Trait { type Assoc: ?Sized; } impl<T: ?Sized + Trait> Trait for W<T, T> { - #[cfg(any(ai_current, ai_next))] + #[cfg(ai)] type Assoc = W<T::Assoc, Id<T::Assoc>>; - #[cfg(any(ia_current, ia_next))] + #[cfg(ia)] type Assoc = W<Id<T::Assoc>, T::Assoc>; - #[cfg(any(ii_current, ii_next))] + #[cfg(ii)] type Assoc = W<Id<T::Assoc>, Id<T::Assoc>>; } |
