Skip to content

Commit 20b2ce1

Browse files
committed
stepping into NormalizesTo where-clauses may be productive
1 parent 2d0faf8 commit 20b2ce1

6 files changed

Lines changed: 52 additions & 71 deletions

File tree

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

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -323,18 +323,10 @@ where
323323
// We currently only consider a cycle coinductive if it steps
324324
// into a where-clause of a coinductive trait.
325325
CurrentGoalKind::CoinductiveTrait => PathKind::Coinductive,
326-
// While normalizing via an impl does step into a where-clause of
327-
// an impl, accessing the associated item immediately steps out of
328-
// it again. This means cycles/recursive calls are not guarded
329-
// by impls used for normalization.
330-
//
331-
// See tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs
332-
// for how this can go wrong.
333-
CurrentGoalKind::ProjectionComputeAssocTermCandidate => PathKind::Inductive,
334326
// We probably want to make all traits coinductive in the future,
335327
// so we treat cycles involving where-clauses of not-yet coinductive
336328
// traits as ambiguous for now.
337-
CurrentGoalKind::Misc => PathKind::Unknown,
329+
CurrentGoalKind::Misc | CurrentGoalKind::ProjectionComputeAssocTermCandidate => PathKind::Unknown,
338330
},
339331
// Relating types is always unproductive. If we were to map proof trees to
340332
// corecursive functions as explained in #136824, relating types never

tests/ui/specialization/min_specialization/next-solver-region-resolution.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
#![feature(min_specialization)]
55

6-
trait Foo {
6+
trait Foo { //~ ERROR cycle detected when coherence checking all impls of trait `Foo`
77
type Item;
88
}
99

@@ -16,7 +16,6 @@ where
1616
}
1717

1818
impl<'a, T> Foo for &T
19-
//~^ ERROR: cycle detected when computing normalized predicates of `<impl at $DIR/next-solver-region-resolution.rs:18:1: 21:21>`
2019
where
2120
Self::Item: Baz,
2221
{

tests/ui/specialization/min_specialization/next-solver-region-resolution.stderr

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
1-
error[E0391]: cycle detected when computing normalized predicates of `<impl at $DIR/next-solver-region-resolution.rs:18:1: 21:21>`
1+
error[E0391]: cycle detected when coherence checking all impls of trait `Foo`
2+
--> $DIR/next-solver-region-resolution.rs:6:1
3+
|
4+
LL | trait Foo {
5+
| ^^^^^^^^^
6+
|
7+
= note: ...which requires building specialization graph of trait `Foo`...
8+
note: ...which requires computing whether impls specialize one another...
9+
--> $DIR/next-solver-region-resolution.rs:12:1
10+
|
11+
LL | / impl<'a, T> Foo for &'a T
12+
LL | | where
13+
LL | | Self::Item: 'a,
14+
| |___________________^
15+
note: ...which requires computing normalized predicates of `<impl at $DIR/next-solver-region-resolution.rs:18:1: 20:21>`...
216
--> $DIR/next-solver-region-resolution.rs:18:1
317
|
418
LL | / impl<'a, T> Foo for &T
5-
LL | |
619
LL | | where
720
LL | | Self::Item: Baz,
821
| |____________________^
9-
|
10-
= note: ...which immediately requires computing normalized predicates of `<impl at $DIR/next-solver-region-resolution.rs:18:1: 21:21>` again
11-
note: cycle used when computing whether impls specialize one another
22+
= note: ...which again requires coherence checking all impls of trait `Foo`, completing the cycle
23+
note: cycle used when checking that `<impl at $DIR/next-solver-region-resolution.rs:12:1: 14:20>` is well-formed
1224
--> $DIR/next-solver-region-resolution.rs:12:1
1325
|
1426
LL | / impl<'a, T> Foo for &'a T

tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive-2.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//@[next] compile-flags: -Znext-solver
44
//@ check-pass
55

6-
// Regression test for trait-system-refactor-initiative#176.
6+
// Test from trait-system-refactor-initiative#176.
77
//
88
// Normalizing `<Vec<T> as IntoIterator>::IntoIter` has two candidates
99
// inside of the function:
@@ -13,7 +13,11 @@
1313
// - where-clause requires `<Vec<T> as IntoIterator>::IntoIter eq Vec<T>`
1414
// - normalize `<Vec<T> as IntoIterator>::IntoIter` again, cycle
1515
//
16-
// We need to treat this cycle as an error to be able to use the actual impl.
16+
// The blanket impl is unfortunately also a productive cycle, so we have to
17+
// break this code, see trait-system-refactor-initiative#273.
18+
//
19+
// As we currently incorrectly treat aliases in the environment as rigid, this compiles
20+
// even with the new solver, see #158643.
1721

1822
fn test<T>()
1923
where

tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
//@ ignore-compare-mode-next-solver (explicit)
22
//@ compile-flags: -Znext-solver
33

4-
// Make sure that stepping into impl where-clauses of `NormalizesTo`
5-
// goals is unproductive. This must not compile, see the inline
6-
// comments.
4+
// A test for the cycle handling when stepping into where-clauses of `NormalizesTo`.
5+
// Whether stepping into where-clauses is productive depends on how they are used.
6+
//
7+
// In this concrete test, the cycle must not be productive.
78

89
trait Bound {
910
fn method();
@@ -30,7 +31,7 @@ fn impls_bound<T: Bound>() {
3031

3132
// The where-clause requires `Foo: Trait<T>` to hold to be wf.
3233
// If stepping into where-clauses during normalization is considered
33-
// to be productive, this would be the case:
34+
// to be productive here, this would be the case:
3435
//
3536
// - `Foo: Trait<T>`
3637
// - via blanket impls, requires `Foo: Bound`
@@ -41,12 +42,13 @@ fn generic<T>()
4142
//~^ ERROR the trait bound `Foo: Bound` is not satisfied
4243
where
4344
<Foo as Trait<T>>::Assoc: Bound,
44-
//~^ ERROR the trait bound `Foo: Bound` is not satisfied
45+
//~^ ERROR overflow evaluating the requirement `<Foo as Trait<T>>::Assoc: Bound`
46+
//~| ERROR overflow evaluating whether `<Foo as Trait<T>>::Assoc` is well-formed
4547
{
4648
// Requires proving `Foo: Bound` by normalizing
4749
// `<Foo as Trait<T>>::Assoc` to `Foo`.
4850
impls_bound::<Foo>();
49-
//~^ ERROR the trait bound `Foo: Bound` is not satisfied
51+
//~^ ERROR overflow evaluating the requirement `Foo: Bound`
5052
}
5153
fn main() {
5254
// Requires proving `<Foo as Trait<u32>>::Assoc: Bound`.
Lines changed: 19 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: the trait bound `Foo: Bound` is not satisfied
2-
--> $DIR/normalizes-to-is-not-productive.rs:40:1
2+
--> $DIR/normalizes-to-is-not-productive.rs:41:1
33
|
44
LL | / fn generic<T>()
55
LL | |
@@ -8,76 +8,48 @@ LL | | <Foo as Trait<T>>::Assoc: Bound,
88
| |____________________________________^ unsatisfied trait bound
99
|
1010
help: the trait `Bound` is not implemented for `Foo`
11-
--> $DIR/normalizes-to-is-not-productive.rs:18:1
11+
--> $DIR/normalizes-to-is-not-productive.rs:19:1
1212
|
1313
LL | struct Foo;
1414
| ^^^^^^^^^^
1515
help: the trait `Bound` is implemented for `u32`
16-
--> $DIR/normalizes-to-is-not-productive.rs:11:1
16+
--> $DIR/normalizes-to-is-not-productive.rs:12:1
1717
|
1818
LL | impl Bound for u32 {
1919
| ^^^^^^^^^^^^^^^^^^
2020
note: required for `Foo` to implement `Trait<T>`
21-
--> $DIR/normalizes-to-is-not-productive.rs:23:19
21+
--> $DIR/normalizes-to-is-not-productive.rs:24:19
2222
|
2323
LL | impl<T: Bound, U> Trait<U> for T {
2424
| ----- ^^^^^^^^ ^
2525
| |
2626
| unsatisfied trait bound introduced here
2727

28-
error[E0277]: the trait bound `Foo: Bound` is not satisfied
29-
--> $DIR/normalizes-to-is-not-productive.rs:43:31
28+
error[E0275]: overflow evaluating the requirement `<Foo as Trait<T>>::Assoc: Bound`
29+
--> $DIR/normalizes-to-is-not-productive.rs:44:31
3030
|
3131
LL | <Foo as Trait<T>>::Assoc: Bound,
32-
| ^^^^^ unsatisfied trait bound
33-
|
34-
help: the trait `Bound` is not implemented for `Foo`
35-
--> $DIR/normalizes-to-is-not-productive.rs:18:1
36-
|
37-
LL | struct Foo;
38-
| ^^^^^^^^^^
39-
help: the trait `Bound` is implemented for `u32`
40-
--> $DIR/normalizes-to-is-not-productive.rs:11:1
41-
|
42-
LL | impl Bound for u32 {
43-
| ^^^^^^^^^^^^^^^^^^
44-
note: required for `Foo` to implement `Trait<T>`
45-
--> $DIR/normalizes-to-is-not-productive.rs:23:19
46-
|
47-
LL | impl<T: Bound, U> Trait<U> for T {
48-
| ----- ^^^^^^^^ ^
49-
| |
50-
| unsatisfied trait bound introduced here
51-
note: required by a bound in `Bound`
52-
--> $DIR/normalizes-to-is-not-productive.rs:8:1
32+
| ^^^^^
33+
34+
error[E0275]: overflow evaluating whether `<Foo as Trait<T>>::Assoc` is well-formed
35+
--> $DIR/normalizes-to-is-not-productive.rs:44:31
5336
|
54-
LL | / trait Bound {
55-
LL | | fn method();
56-
LL | | }
57-
| |_^ required by this bound in `Bound`
37+
LL | <Foo as Trait<T>>::Assoc: Bound,
38+
| ^^^^^
5839

59-
error[E0277]: the trait bound `Foo: Bound` is not satisfied
60-
--> $DIR/normalizes-to-is-not-productive.rs:48:19
40+
error[E0275]: overflow evaluating the requirement `Foo: Bound`
41+
--> $DIR/normalizes-to-is-not-productive.rs:50:19
6142
|
6243
LL | impls_bound::<Foo>();
63-
| ^^^ unsatisfied trait bound
64-
|
65-
help: the trait `Bound` is not implemented for `Foo`
66-
--> $DIR/normalizes-to-is-not-productive.rs:18:1
44+
| ^^^
6745
|
68-
LL | struct Foo;
69-
| ^^^^^^^^^^
70-
help: the trait `Bound` is implemented for `u32`
71-
--> $DIR/normalizes-to-is-not-productive.rs:11:1
72-
|
73-
LL | impl Bound for u32 {
74-
| ^^^^^^^^^^^^^^^^^^
7546
note: required by a bound in `impls_bound`
76-
--> $DIR/normalizes-to-is-not-productive.rs:27:19
47+
--> $DIR/normalizes-to-is-not-productive.rs:28:19
7748
|
7849
LL | fn impls_bound<T: Bound>() {
7950
| ^^^^^ required by this bound in `impls_bound`
8051

81-
error: aborting due to 3 previous errors
52+
error: aborting due to 4 previous errors
8253

83-
For more information about this error, try `rustc --explain E0277`.
54+
Some errors have detailed explanations: E0275, E0277.
55+
For more information about an error, try `rustc --explain E0275`.

0 commit comments

Comments
 (0)