Skip to content

Commit c8085cf

Browse files
Auto merge of #148939 - adwinwhite:env_normalization_fcw, r=<try>
Show env normalization differences under two solvers
2 parents 217cb73 + 578bcc8 commit c8085cf

File tree

12 files changed

+192
-99
lines changed

12 files changed

+192
-99
lines changed

compiler/rustc_trait_selection/src/solve/normalize.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,10 @@ where
222222
}
223223

224224
let ty::ConstKind::Unevaluated(..) = ct.kind() else { return ct.try_super_fold_with(self) };
225+
// FIXME: `generic_const_exprs` not implemented in the next solver.
226+
if ct.has_non_region_param() {
227+
return Ok(ct);
228+
}
225229

226230
if ct.has_escaping_bound_vars() {
227231
let (ct, mapped_regions, mapped_types, mapped_consts) =
@@ -240,6 +244,14 @@ where
240244
Ok(ensure_sufficient_stack(|| self.normalize_alias_term(ct.into()))?.expect_const())
241245
}
242246
}
247+
248+
#[instrument(level = "trace", skip(self), ret)]
249+
fn try_fold_predicate(
250+
&mut self,
251+
p: ty::Predicate<'tcx>,
252+
) -> Result<ty::Predicate<'tcx>, Self::Error> {
253+
if p.allow_normalization() { p.try_super_fold_with(self) } else { Ok(p) }
254+
}
243255
}
244256

245257
// Deeply normalize a value and return it

compiler/rustc_trait_selection/src/traits/mod.rs

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ fn do_normalize_predicates<'tcx>(
257257
predicates: Vec<ty::Clause<'tcx>>,
258258
) -> Result<Vec<ty::Clause<'tcx>>, ErrorGuaranteed> {
259259
let span = cause.span;
260+
let original_predicates = predicates.clone();
260261

261262
// FIXME. We should really... do something with these region
262263
// obligations. But this call just continues the older
@@ -296,8 +297,8 @@ fn do_normalize_predicates<'tcx>(
296297
);
297298
}
298299

299-
match infcx.fully_resolve(predicates) {
300-
Ok(predicates) => Ok(predicates),
300+
let predicates = match infcx.fully_resolve(predicates) {
301+
Ok(predicates) => predicates,
301302
Err(fixup_err) => {
302303
// If we encounter a fixup error, it means that some type
303304
// variable wound up unconstrained. I actually don't know
@@ -314,7 +315,64 @@ fn do_normalize_predicates<'tcx>(
314315
fixup_err
315316
);
316317
}
318+
};
319+
// The next solver returns nothing for values that contains type error.
320+
// And type error should cause failure later. So we skip the consistency check.
321+
// `generic_const_exprs` is incompatible with next solver now.
322+
if !tcx.next_trait_solver_globally()
323+
&& !predicates.references_error()
324+
&& !tcx.features().generic_const_exprs()
325+
{
326+
let infcx = tcx
327+
.infer_ctxt()
328+
.with_next_trait_solver(true)
329+
.ignoring_regions()
330+
.build(TypingMode::non_body_analysis());
331+
let predicates_by_next: Vec<Option<_>> = original_predicates
332+
.iter()
333+
.cloned()
334+
.map(|p| {
335+
crate::solve::deeply_normalize::<_, ScrubbedTraitError<'tcx>>(
336+
infcx.at(&cause, elaborated_env),
337+
p,
338+
)
339+
.ok()
340+
})
341+
.collect();
342+
343+
// FIXME: next solver adds region constraints that contains placeholders to infcx.
344+
// `infcx.considering_regions` is not checked.
345+
let _errors = infcx.resolve_regions(cause.body_id, elaborated_env, []);
346+
347+
let predicates_by_next = match infcx.fully_resolve(predicates_by_next) {
348+
Ok(predicates) => predicates,
349+
Err(fixup_err) => {
350+
span_bug!(
351+
span,
352+
"inference variables in normalized parameter environment: {}",
353+
fixup_err
354+
);
355+
}
356+
};
357+
358+
for ((orig_pred, old_pred), next_pred) in
359+
original_predicates.iter().zip(&predicates).zip(&predicates_by_next)
360+
{
361+
if let Some(next_pred) = next_pred
362+
&& next_pred == old_pred
363+
{
364+
continue;
365+
}
366+
tcx.dcx().span_err(
367+
span,
368+
format!(
369+
"inconsistency during normalizing env `{:#?}`, old={:#?}, next={:#?}",
370+
orig_pred, old_pred, next_pred
371+
),
372+
);
373+
}
317374
}
375+
Ok(predicates)
318376
}
319377

320378
// FIXME: this is gonna need to be removed ...

tests/ui/specialization/fuzzed/fuzzing-ice-134905.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ where
1414
}
1515

1616
trait Check {}
17-
impl<'a, T> Eq for T where <T as Iterate<'a>>::Ty: Valid {}
17+
impl<'a, T> Eq for T
1818
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
19+
where
20+
T: Iterate<'a>,
21+
<T as Iterate<'a>>::Ty: Valid,
22+
{}
1923

2024
trait Valid {}
2125

tests/ui/specialization/fuzzed/fuzzing-ice-134905.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ LL | default type Ty = ();
1515
| ^^ the trait `Valid` is not implemented for `()`
1616
|
1717
help: this trait has no implementations, consider adding one
18-
--> $DIR/fuzzing-ice-134905.rs:20:1
18+
--> $DIR/fuzzing-ice-134905.rs:24:1
1919
|
2020
LL | trait Valid {}
2121
| ^^^^^^^^^^^
@@ -28,7 +28,7 @@ LL | type Ty: Valid;
2828
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
2929
--> $DIR/fuzzing-ice-134905.rs:17:10
3030
|
31-
LL | impl<'a, T> Eq for T where <T as Iterate<'a>>::Ty: Valid {}
31+
LL | impl<'a, T> Eq for T
3232
| ^ type parameter `T` must be used as the type parameter for some local type
3333
|
3434
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local

tests/ui/specialization/issue-38091-2.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
//@ build-fail
2-
//~^ ERROR overflow evaluating the requirement `i32: Check`
3-
41
#![feature(specialization)]
52
//~^ WARN the feature `specialization` is incomplete
63

@@ -17,7 +14,11 @@ where
1714
}
1815

1916
trait Check {}
20-
impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {}
17+
impl<'a, T> Check for T
18+
//~^ ERROR: overflow evaluating the requirement `T: Check`
19+
where
20+
T: Iterate<'a>,
21+
<T as Iterate<'a>>::Ty: Valid {}
2122

2223
trait Valid {}
2324

tests/ui/specialization/issue-38091-2.stderr

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
2-
--> $DIR/issue-38091-2.rs:4:12
2+
--> $DIR/issue-38091-2.rs:1:12
33
|
44
LL | #![feature(specialization)]
55
| ^^^^^^^^^^^^^^
@@ -8,16 +8,35 @@ LL | #![feature(specialization)]
88
= help: consider using `min_specialization` instead, which is more stable and complete
99
= note: `#[warn(incomplete_features)]` on by default
1010

11-
error[E0275]: overflow evaluating the requirement `i32: Check`
11+
error[E0275]: overflow evaluating the requirement `T: Check`
12+
--> $DIR/issue-38091-2.rs:17:1
1213
|
13-
note: required for `i32` to implement `Iterate<'_>`
14-
--> $DIR/issue-38091-2.rs:11:13
14+
LL | / impl<'a, T> Check for T
15+
LL | |
16+
LL | | where
17+
LL | | T: Iterate<'a>,
18+
LL | | <T as Iterate<'a>>::Ty: Valid {}
19+
| |_________________________________^
20+
|
21+
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_38091_2`)
22+
note: required for `T` to implement `Iterate<'_>`
23+
--> $DIR/issue-38091-2.rs:8:13
1524
|
1625
LL | impl<'a, T> Iterate<'a> for T
1726
| ^^^^^^^^^^^ ^
1827
LL | where
1928
LL | T: Check,
2029
| ----- unsatisfied trait bound introduced here
30+
note: required for `T` to implement `Check`
31+
--> $DIR/issue-38091-2.rs:17:13
32+
|
33+
LL | impl<'a, T> Check for T
34+
| ^^^^^ ^
35+
...
36+
LL | <T as Iterate<'a>>::Ty: Valid {}
37+
| ----- unsatisfied trait bound introduced here
38+
= note: 125 redundant requirements hidden
39+
= note: required for `T` to implement `Iterate<'a>`
2140

2241
error: aborting due to 1 previous error; 1 warning emitted
2342

tests/ui/specialization/issue-38091.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@ where
1515
}
1616

1717
trait Check {}
18-
impl<'a, T> Check for T where <T as Iterate<'a>>::Ty: Valid {}
18+
impl<'a, T> Check for T
19+
//~^ ERROR: overflow evaluating the requirement `T: Check`
20+
where
21+
T: Iterate<'a>,
22+
<T as Iterate<'a>>::Ty: Valid,
23+
{}
1924

2025
trait Valid {}
2126

tests/ui/specialization/issue-38091.stderr

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ LL | default type Ty = ();
1515
| ^^ the trait `Valid` is not implemented for `()`
1616
|
1717
help: this trait has no implementations, consider adding one
18-
--> $DIR/issue-38091.rs:20:1
18+
--> $DIR/issue-38091.rs:25:1
1919
|
2020
LL | trait Valid {}
2121
| ^^^^^^^^^^^
@@ -25,6 +25,37 @@ note: required by a bound in `Iterate::Ty`
2525
LL | type Ty: Valid;
2626
| ^^^^^ required by this bound in `Iterate::Ty`
2727

28-
error: aborting due to 1 previous error; 1 warning emitted
28+
error[E0275]: overflow evaluating the requirement `T: Check`
29+
--> $DIR/issue-38091.rs:18:1
30+
|
31+
LL | / impl<'a, T> Check for T
32+
LL | |
33+
LL | | where
34+
LL | | T: Iterate<'a>,
35+
LL | | <T as Iterate<'a>>::Ty: Valid,
36+
| |__________________________________^
37+
|
38+
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_38091`)
39+
note: required for `T` to implement `Iterate<'_>`
40+
--> $DIR/issue-38091.rs:8:13
41+
|
42+
LL | impl<'a, T> Iterate<'a> for T
43+
| ^^^^^^^^^^^ ^
44+
LL | where
45+
LL | T: Check,
46+
| ----- unsatisfied trait bound introduced here
47+
note: required for `T` to implement `Check`
48+
--> $DIR/issue-38091.rs:18:13
49+
|
50+
LL | impl<'a, T> Check for T
51+
| ^^^^^ ^
52+
...
53+
LL | <T as Iterate<'a>>::Ty: Valid,
54+
| ----- unsatisfied trait bound introduced here
55+
= note: 125 redundant requirements hidden
56+
= note: required for `T` to implement `Iterate<'a>`
57+
58+
error: aborting due to 2 previous errors; 1 warning emitted
2959

30-
For more information about this error, try `rustc --explain E0277`.
60+
Some errors have detailed explanations: E0275, E0277.
61+
For more information about an error, try `rustc --explain E0275`.

tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr

Lines changed: 20 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -6,94 +6,34 @@ LL | #![feature(const_trait_impl, generic_const_exprs)]
66
|
77
= help: remove one of these features
88

9-
error[E0391]: cycle detected when evaluating type-level constant
10-
--> $DIR/unsatisfied-const-trait-bound.rs:28:35
9+
error[E0277]: the trait bound `T: const Trait` is not satisfied
10+
--> $DIR/unsatisfied-const-trait-bound.rs:28:37
1111
|
1212
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
13-
| ^^^^^^^^^^^^^
14-
|
15-
note: ...which requires const-evaluating + checking `accept0::{constant#0}`...
16-
--> $DIR/unsatisfied-const-trait-bound.rs:28:35
17-
|
18-
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
19-
| ^^^^^^^^^^^^^
20-
note: ...which requires checking if `accept0::{constant#0}` is a trivial const...
21-
--> $DIR/unsatisfied-const-trait-bound.rs:28:35
22-
|
23-
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
24-
| ^^^^^^^^^^^^^
25-
note: ...which requires building MIR for `accept0::{constant#0}`...
26-
--> $DIR/unsatisfied-const-trait-bound.rs:28:35
27-
|
28-
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
29-
| ^^^^^^^^^^^^^
30-
note: ...which requires building an abstract representation for `accept0::{constant#0}`...
31-
--> $DIR/unsatisfied-const-trait-bound.rs:28:35
32-
|
33-
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
34-
| ^^^^^^^^^^^^^
35-
note: ...which requires building THIR for `accept0::{constant#0}`...
36-
--> $DIR/unsatisfied-const-trait-bound.rs:28:35
37-
|
38-
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
39-
| ^^^^^^^^^^^^^
40-
note: ...which requires type-checking `accept0::{constant#0}`...
41-
--> $DIR/unsatisfied-const-trait-bound.rs:28:35
42-
|
43-
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
44-
| ^^^^^^^^^^^^^
45-
= note: ...which again requires evaluating type-level constant, completing the cycle
46-
note: cycle used when checking that `accept0` is well-formed
47-
--> $DIR/unsatisfied-const-trait-bound.rs:28:35
48-
|
49-
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
50-
| ^^^^^^^^^^^^^
51-
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
13+
| ^
5214

53-
error[E0391]: cycle detected when checking if `accept1::{constant#0}` is a trivial const
54-
--> $DIR/unsatisfied-const-trait-bound.rs:32:49
55-
|
56-
LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
57-
| ^^^^^^^^^^^^^
58-
|
59-
note: ...which requires building MIR for `accept1::{constant#0}`...
60-
--> $DIR/unsatisfied-const-trait-bound.rs:32:49
15+
error[E0277]: the trait bound `T: const Trait` is not satisfied
16+
--> $DIR/unsatisfied-const-trait-bound.rs:32:51
6117
|
6218
LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
63-
| ^^^^^^^^^^^^^
64-
note: ...which requires building an abstract representation for `accept1::{constant#0}`...
65-
--> $DIR/unsatisfied-const-trait-bound.rs:32:49
66-
|
67-
LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
68-
| ^^^^^^^^^^^^^
69-
note: ...which requires building THIR for `accept1::{constant#0}`...
70-
--> $DIR/unsatisfied-const-trait-bound.rs:32:49
71-
|
72-
LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
73-
| ^^^^^^^^^^^^^
74-
note: ...which requires type-checking `accept1::{constant#0}`...
75-
--> $DIR/unsatisfied-const-trait-bound.rs:32:49
19+
| ^
20+
21+
error[E0277]: the trait bound `Ty: const Trait` is not satisfied
22+
--> $DIR/unsatisfied-const-trait-bound.rs:21:15
7623
|
77-
LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
78-
| ^^^^^^^^^^^^^
79-
note: ...which requires evaluating type-level constant...
80-
--> $DIR/unsatisfied-const-trait-bound.rs:32:49
24+
LL | require::<Ty>();
25+
| ^^
8126
|
82-
LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
83-
| ^^^^^^^^^^^^^
84-
note: ...which requires const-evaluating + checking `accept1::{constant#0}`...
85-
--> $DIR/unsatisfied-const-trait-bound.rs:32:49
27+
note: required by a bound in `require`
28+
--> $DIR/unsatisfied-const-trait-bound.rs:8:15
8629
|
87-
LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
88-
| ^^^^^^^^^^^^^
89-
= note: ...which again requires checking if `accept1::{constant#0}` is a trivial const, completing the cycle
90-
note: cycle used when const-evaluating + checking `accept1::{constant#0}`
91-
--> $DIR/unsatisfied-const-trait-bound.rs:32:49
30+
LL | fn require<T: const Trait>() {}
31+
| ^^^^^^^^^^^ required by this bound in `require`
32+
help: make the `impl` of trait `Trait` `const`
9233
|
93-
LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
94-
| ^^^^^^^^^^^^^
95-
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
34+
LL | impl const Trait for Ty {
35+
| +++++
9636

97-
error: aborting due to 3 previous errors
37+
error: aborting due to 4 previous errors
9838

99-
For more information about this error, try `rustc --explain E0391`.
39+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)