Skip to content

Commit b64b25b

Browse files
committed
normalizes-to disable infer var check
1 parent 3e33bda commit b64b25b

File tree

4 files changed

+74
-14
lines changed

4 files changed

+74
-14
lines changed

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_type_ir::fold::TypeFoldable;
1616
use rustc_type_ir::inherent::*;
1717
use rustc_type_ir::relate::solver_relating::RelateExt;
1818
use rustc_type_ir::{self as ty, Canonical, CanonicalVarValues, InferCtxtLike, Interner};
19-
use tracing::{instrument, trace};
19+
use tracing::{debug, instrument, trace};
2020

2121
use crate::canonicalizer::{CanonicalizeMode, Canonicalizer};
2222
use crate::delegate::SolverDelegate;
@@ -165,12 +165,21 @@ where
165165
// HACK: We bail with overflow if the response would have too many non-region
166166
// inference variables. This tends to only happen if we encounter a lot of
167167
// ambiguous alias types which get replaced with fresh inference variables
168-
// during generalization. This prevents a hang in nalgebra.
169-
let num_non_region_vars = canonical.variables.iter().filter(|c| !c.is_region()).count();
170-
if num_non_region_vars > self.cx().recursion_limit() {
171-
return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow {
172-
suggest_increasing_limit: true,
173-
}));
168+
// during generalization. This prevents hangs caused by an exponential blowup,
169+
// see tests/ui/traits/next-solver/coherence-alias-hang.rs.
170+
//
171+
// We don't do so for `NormalizesTo` goals as we erased the expected term and
172+
// bailing with overflow here would prevent us from detecting a type-mismatch,
173+
// causing a coherence error in diesel, see #131969. We still bail with verflow
174+
// when later returning from the parent AliasRelate goal.
175+
if !self.is_normalizes_to_goal {
176+
let num_non_region_vars = canonical.variables.iter().filter(|c| !c.is_region()).count();
177+
if num_non_region_vars > self.cx().recursion_limit() {
178+
debug!(?num_non_region_vars, "too many inference variables -> overflow");
179+
return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow {
180+
suggest_increasing_limit: true,
181+
}));
182+
}
174183
}
175184

176185
Ok(canonical)

compiler/rustc_trait_selection/src/traits/coherence.rs

+2
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ fn equate_impl_headers<'tcx>(
298298
}
299299

300300
/// The result of [fn impl_intersection_has_impossible_obligation].
301+
#[derive(Debug)]
301302
enum IntersectionHasImpossibleObligations<'tcx> {
302303
Yes,
303304
No {
@@ -328,6 +329,7 @@ enum IntersectionHasImpossibleObligations<'tcx> {
328329
/// of the two impls above to be empty.
329330
///
330331
/// Importantly, this works even if there isn't a `impl !Error for MyLocalType`.
332+
#[instrument(level = "debug", skip(selcx), ret)]
331333
fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
332334
selcx: &mut SelectionContext<'cx, 'tcx>,
333335
obligations: &'a [PredicateObligation<'tcx>],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//@ check-pass
2+
3+
// When canonicalizing a response in the trait solver, we bail with overflow
4+
// if there are too many non-region inference variables. Doing so in normalizes-to
5+
// goals ends up hiding inference constraints in cases which we want to support,
6+
// see #131969. To prevent this issue we do not check for too many inference
7+
// variables in normalizes-to goals.
8+
#![recursion_limit = "8"]
9+
10+
trait Bound {}
11+
trait Trait {
12+
type Assoc;
13+
}
14+
15+
16+
impl<T0, T1, T2, T3, T4, T5, T6, T7> Trait for (T0, T1, T2, T3, T4, T5, T6, T7)
17+
where
18+
T0: Trait,
19+
T1: Trait,
20+
T2: Trait,
21+
T3: Trait,
22+
T4: Trait,
23+
T5: Trait,
24+
T6: Trait,
25+
T7: Trait,
26+
(
27+
T0::Assoc,
28+
T1::Assoc,
29+
T2::Assoc,
30+
T3::Assoc,
31+
T4::Assoc,
32+
T5::Assoc,
33+
T6::Assoc,
34+
T7::Assoc,
35+
): Clone,
36+
{
37+
type Assoc = (
38+
T0::Assoc,
39+
T1::Assoc,
40+
T2::Assoc,
41+
T3::Assoc,
42+
T4::Assoc,
43+
T5::Assoc,
44+
T6::Assoc,
45+
T7::Assoc,
46+
);
47+
}
48+
49+
trait Overlap {}
50+
impl<T: Trait<Assoc = ()>> Overlap for T {}
51+
impl<T0, T1, T2, T3, T4, T5, T6, T7> Overlap for (T0, T1, T2, T3, T4, T5, T6, T7) {}
52+
fn main() {}

tests/ui/traits/next-solver/overflow/coherence-alias-hang.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
//@ check-pass
2-
//@ revisions: ai_current ai_next ia_current ia_next ii_current ii_next
3-
//@[ai_next] compile-flags: -Znext-solver
4-
//@[ia_next] compile-flags: -Znext-solver
5-
//@[ii_next] compile-flags: -Znext-solver
2+
//@ revisions: ai ia ii
63

74
// Regression test for nalgebra hang <https://github.com/rust-lang/rust/issues/130056>.
85

@@ -17,11 +14,11 @@ trait Trait {
1714
type Assoc: ?Sized;
1815
}
1916
impl<T: ?Sized + Trait> Trait for W<T, T> {
20-
#[cfg(any(ai_current, ai_next))]
17+
#[cfg(ai)]
2118
type Assoc = W<T::Assoc, Id<T::Assoc>>;
22-
#[cfg(any(ia_current, ia_next))]
19+
#[cfg(ia)]
2320
type Assoc = W<Id<T::Assoc>, T::Assoc>;
24-
#[cfg(any(ii_current, ii_next))]
21+
#[cfg(ii)]
2522
type Assoc = W<Id<T::Assoc>, Id<T::Assoc>>;
2623
}
2724

0 commit comments

Comments
 (0)