Skip to content

Commit 4720589

Browse files
committed
normalizing where-clauses is also coinductive, add tests
1 parent 630e440 commit 4720589

File tree

12 files changed

+238
-19
lines changed

12 files changed

+238
-19
lines changed

Diff for: compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs

+28-8
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,10 @@ where
264264

265265
pub(super) fn step_kind_for_source(&self, source: GoalSource) -> PathKind {
266266
match (self.current_goal_kind, source) {
267-
(CurrentGoalKind::CoinductiveTrait, GoalSource::ImplWhereBound) => PathKind::Coinductive,
267+
(
268+
CurrentGoalKind::CoinductiveTrait,
269+
GoalSource::ImplWhereBound | GoalSource::NormalizeImplWhereBound,
270+
) => PathKind::Coinductive,
268271
_ => PathKind::Inductive,
269272
}
270273
}
@@ -670,16 +673,19 @@ where
670673

671674
#[instrument(level = "trace", skip(self))]
672675
pub(super) fn add_normalizes_to_goal(&mut self, mut goal: Goal<I, ty::NormalizesTo<I>>) {
673-
goal.predicate =
674-
goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, goal.param_env));
676+
goal.predicate = goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(
677+
self,
678+
GoalSource::Misc,
679+
goal.param_env,
680+
));
675681
self.inspect.add_normalizes_to_goal(self.delegate, self.max_input_universe, goal);
676682
self.nested_goals.normalizes_to_goals.push(goal);
677683
}
678684

679685
#[instrument(level = "debug", skip(self))]
680686
pub(super) fn add_goal(&mut self, source: GoalSource, mut goal: Goal<I, I::Predicate>) {
681687
goal.predicate =
682-
goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, goal.param_env));
688+
goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, source, goal.param_env));
683689
self.inspect.add_goal(self.delegate, self.max_input_universe, source, goal);
684690
self.nested_goals.goals.push((source, goal));
685691
}
@@ -1100,6 +1106,7 @@ where
11001106
{
11011107
ecx: &'me mut EvalCtxt<'a, D>,
11021108
param_env: I::ParamEnv,
1109+
normalization_goal_source: GoalSource,
11031110
cache: HashMap<I::Ty, I::Ty>,
11041111
}
11051112

@@ -1108,8 +1115,21 @@ where
11081115
D: SolverDelegate<Interner = I>,
11091116
I: Interner,
11101117
{
1111-
fn new(ecx: &'me mut EvalCtxt<'a, D>, param_env: I::ParamEnv) -> Self {
1112-
ReplaceAliasWithInfer { ecx, param_env, cache: Default::default() }
1118+
fn new(
1119+
ecx: &'me mut EvalCtxt<'a, D>,
1120+
for_goal_source: GoalSource,
1121+
param_env: I::ParamEnv,
1122+
) -> Self {
1123+
let normalization_goal_source = match for_goal_source {
1124+
GoalSource::ImplWhereBound => GoalSource::NormalizeImplWhereBound,
1125+
_ => GoalSource::Misc,
1126+
};
1127+
ReplaceAliasWithInfer {
1128+
ecx,
1129+
param_env,
1130+
normalization_goal_source,
1131+
cache: Default::default(),
1132+
}
11131133
}
11141134
}
11151135

@@ -1132,7 +1152,7 @@ where
11321152
ty::AliasRelationDirection::Equate,
11331153
);
11341154
self.ecx.add_goal(
1135-
GoalSource::Misc,
1155+
self.normalization_goal_source,
11361156
Goal::new(self.cx(), self.param_env, normalizes_to),
11371157
);
11381158
infer_ty
@@ -1161,7 +1181,7 @@ where
11611181
ty::AliasRelationDirection::Equate,
11621182
);
11631183
self.ecx.add_goal(
1164-
GoalSource::Misc,
1184+
self.normalization_goal_source,
11651185
Goal::new(self.cx(), self.param_env, normalizes_to),
11661186
);
11671187
infer_ct

Diff for: compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,10 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
438438

439439
let obligation;
440440
match (child_mode, nested_goal.source()) {
441-
(ChildMode::Trait(_) | ChildMode::Host(_), GoalSource::Misc) => {
441+
(
442+
ChildMode::Trait(_) | ChildMode::Host(_),
443+
GoalSource::Misc | GoalSource::NormalizeImplWhereBound,
444+
) => {
442445
continue;
443446
}
444447
(ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => {

Diff for: compiler/rustc_type_ir/src/solve/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ pub enum GoalSource {
6868
/// FIXME(-Znext-solver=coinductive): Explain how and why this
6969
/// changes whether cycles are coinductive.
7070
ImplWhereBound,
71+
/// When eagerly replacing aliases with impl where-bounds, we also
72+
/// have to consider these normalization goals to be coinductive.
73+
///
74+
/// This is necessary for tests/ui/sized/coinductive-1.rs to compile.
75+
NormalizeImplWhereBound,
7176
/// Const conditions that need to hold for `~const` alias bounds to hold.
7277
///
7378
/// FIXME(-Znext-solver=coinductive): Are these even coinductive?

Diff for: tests/ui/const-generics/issues/issue-88119.stderr

+68-8
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,90 @@ LL | #![feature(const_trait_impl, generic_const_exprs)]
66
|
77
= help: remove one of these features
88

9-
error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::<T>()` can be evaluated`
9+
error[E0275]: overflow evaluating the requirement `&T: ~const ConstName`
10+
--> $DIR/issue-88119.rs:19:49
11+
|
12+
LL | impl<T: ?Sized + ConstName> const ConstName for &T
13+
| ^^
14+
15+
error[E0275]: overflow evaluating the requirement `&T: ConstName`
16+
--> $DIR/issue-88119.rs:19:49
17+
|
18+
LL | impl<T: ?Sized + ConstName> const ConstName for &T
19+
| ^^
20+
21+
error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed`
1022
--> $DIR/issue-88119.rs:21:5
1123
|
1224
LL | [(); name_len::<T>()]:,
13-
| ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::<T>()` can be evaluated`
25+
| ^^^^^^^^^^^^^^^^^^^^^
1426
|
1527
note: required by a bound in `<&T as ConstName>`
28+
--> $DIR/issue-88119.rs:21:5
29+
|
30+
LL | [(); name_len::<T>()]:,
31+
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>`
32+
33+
error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed`
1634
--> $DIR/issue-88119.rs:21:10
1735
|
1836
LL | [(); name_len::<T>()]:,
19-
| ^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>`
37+
| ^^^^^^^^^^^^^^^
38+
|
39+
note: required by a bound in `<&T as ConstName>`
40+
--> $DIR/issue-88119.rs:21:5
41+
|
42+
LL | [(); name_len::<T>()]:,
43+
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>`
44+
45+
error[E0275]: overflow evaluating the requirement `&mut T: ~const ConstName`
46+
--> $DIR/issue-88119.rs:26:49
47+
|
48+
LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
49+
| ^^^^^^
2050

21-
error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::<T>()` can be evaluated`
51+
error[E0275]: overflow evaluating the requirement `&mut T: ConstName`
52+
--> $DIR/issue-88119.rs:26:49
53+
|
54+
LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
55+
| ^^^^^^
56+
57+
error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed`
2258
--> $DIR/issue-88119.rs:28:5
2359
|
2460
LL | [(); name_len::<T>()]:,
25-
| ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::<T>()` can be evaluated`
61+
| ^^^^^^^^^^^^^^^^^^^^^
2662
|
2763
note: required by a bound in `<&mut T as ConstName>`
64+
--> $DIR/issue-88119.rs:28:5
65+
|
66+
LL | [(); name_len::<T>()]:,
67+
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>`
68+
69+
error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed`
2870
--> $DIR/issue-88119.rs:28:10
2971
|
3072
LL | [(); name_len::<T>()]:,
31-
| ^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>`
73+
| ^^^^^^^^^^^^^^^
74+
|
75+
note: required by a bound in `<&mut T as ConstName>`
76+
--> $DIR/issue-88119.rs:28:5
77+
|
78+
LL | [(); name_len::<T>()]:,
79+
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>`
80+
81+
error[E0275]: overflow evaluating the requirement `&&mut u8: ConstName`
82+
--> $DIR/issue-88119.rs:33:35
83+
|
84+
LL | pub const ICE_1: &'static [u8] = <&&mut u8 as ConstName>::NAME_BYTES;
85+
| ^^^^^^^^
86+
87+
error[E0275]: overflow evaluating the requirement `&mut &u8: ConstName`
88+
--> $DIR/issue-88119.rs:34:35
89+
|
90+
LL | pub const ICE_2: &'static [u8] = <&mut &u8 as ConstName>::NAME_BYTES;
91+
| ^^^^^^^^
3292

33-
error: aborting due to 3 previous errors
93+
error: aborting due to 11 previous errors
3494

35-
For more information about this error, try `rustc --explain E0284`.
95+
For more information about this error, try `rustc --explain E0275`.

Diff for: tests/ui/sized/coinductive-1.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
//@ check-pass
2+
//@ revisions: current next
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
4+
//@[next] compile-flags: -Znext-solver
25
struct Node<C: Trait<Self>>(C::Assoc);
36

47
trait Trait<T> {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0275]: overflow evaluating the requirement `Vec<u8>: Trait<String>`
2+
--> $DIR/item-bound-via-impl-where-clause.rs:31:21
3+
|
4+
LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: required for `Vec<u8>` to implement `Trait<String>`
8+
--> $DIR/item-bound-via-impl-where-clause.rs:22:12
9+
|
10+
LL | impl<L, R> Trait<R> for L
11+
| ^^^^^^^^ ^
12+
LL | where
13+
LL | L: Trait<R>,
14+
| -------- unsatisfied trait bound introduced here
15+
note: required by a bound in `transmute`
16+
--> $DIR/item-bound-via-impl-where-clause.rs:29:17
17+
|
18+
LL | fn transmute<L: Trait<R>, R>(r: L) -> <L::Proof as Trait<R>>::Proof { r }
19+
| ^^^^^^^^ required by this bound in `transmute`
20+
21+
error: aborting due to 1 previous error
22+
23+
For more information about this error, try `rustc --explain E0275`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
error[E0275]: overflow evaluating the requirement `Vec<u8>: Trait<String>`
2+
--> $DIR/item-bound-via-impl-where-clause.rs:31:33
3+
|
4+
LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]);
5+
| ^
6+
|
7+
note: required by a bound in `transmute`
8+
--> $DIR/item-bound-via-impl-where-clause.rs:29:17
9+
|
10+
LL | fn transmute<L: Trait<R>, R>(r: L) -> <L::Proof as Trait<R>>::Proof { r }
11+
| ^^^^^^^^ required by this bound in `transmute`
12+
13+
error[E0275]: overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof == _`
14+
--> $DIR/item-bound-via-impl-where-clause.rs:31:21
15+
|
16+
LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]);
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
19+
error[E0275]: overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof == String`
20+
--> $DIR/item-bound-via-impl-where-clause.rs:31:21
21+
|
22+
LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]);
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24+
25+
error[E0275]: overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof: Sized`
26+
--> $DIR/item-bound-via-impl-where-clause.rs:31:21
27+
|
28+
LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]);
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30+
|
31+
= note: the return type of a function must have a statically known size
32+
33+
error[E0275]: overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof well-formed`
34+
--> $DIR/item-bound-via-impl-where-clause.rs:31:21
35+
|
36+
LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]);
37+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
38+
39+
error[E0275]: overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof == _`
40+
--> $DIR/item-bound-via-impl-where-clause.rs:31:21
41+
|
42+
LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]);
43+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44+
|
45+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
46+
47+
error: aborting due to 6 previous errors
48+
49+
For more information about this error, try `rustc --explain E0275`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//@ revisions: current next
2+
//@ ignore-compare-mode-next-solver (explicit revisions)
3+
//@[next] compile-flags: -Znext-solver
4+
5+
// A variation of #135246 where the cyclic bounds are part of
6+
// the impl instead of the impl associated item.
7+
8+
trait Trait<R>: Sized {
9+
type Proof: Trait<R, Proof = Self>;
10+
}
11+
12+
// We need to use indirection here as we otherwise normalize
13+
// `<L::Proof as Trait<R>>::Proof` before recursing into
14+
// `R: Trait<R, Proof = <L::Proof as Trait<R>>::Proof>`.
15+
trait Indir<L: Trait<R>, R>: Trait<R, Proof = <L::Proof as Trait<R>>::Proof> {}
16+
impl<L, R> Indir<L, R> for R
17+
where
18+
L: Trait<R>,
19+
R: Trait<R, Proof = <L::Proof as Trait<R>>::Proof>,
20+
{}
21+
22+
impl<L, R> Trait<R> for L
23+
where
24+
L: Trait<R>,
25+
R: Indir<L, R>,
26+
{
27+
type Proof = R;
28+
}
29+
fn transmute<L: Trait<R>, R>(r: L) -> <L::Proof as Trait<R>>::Proof { r }
30+
fn main() {
31+
let s: String = transmute::<_, String>(vec![65_u8, 66, 67]);
32+
//~^ ERROR overflow evaluating the requirement `Vec<u8>: Trait<String>`
33+
//[next]~| ERROR overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof == _`
34+
//[next]~| ERROR overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof == String`
35+
//[next]~| ERROR overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof: Sized`
36+
//[next]~| ERROR overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof well-formed`
37+
//[next]~| ERROR overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof == _`
38+
println!("{}", s); // ABC
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error[E0391]: cycle detected when computing layout of `<[Hello] as Normalize>::Assoc`
2+
|
3+
= note: ...which requires computing layout of `Hello`...
4+
= note: ...which again requires computing layout of `<[Hello] as Normalize>::Assoc`, completing the cycle
5+
= note: cycle used when computing layout of `Hello`
6+
= 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
7+
8+
error: aborting due to 1 previous error
9+
10+
For more information about this error, try `rustc --explain E0391`.

Diff for: tests/ui/traits/solver-cycles/129541-recursive-enum-and-array-impl.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
// Regression test for #129541
22
//~^ ERROR cycle detected when computing layout of `<[Hello] as Normalize>::Assoc` [E0391]
33

4+
//@ revisions: current next
5+
//@ ignore-compare-mode-next-solver (explicit revisions)
6+
//@[next] compile-flags: -Znext-solver
7+
48
trait Bound {}
59
trait Normalize {
610
type Assoc;

Diff for: tests/ui/traits/solver-cycles/129541-recursive-struct.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
// Regression test for #129541
22

3-
//@ revisions: unique multiple
3+
//@ revisions: unique_curr unique_next multiple_curr multiple_next
4+
//@ ignore-compare-mode-next-solver (explicit revisions)
5+
//@[unique_next] compile-flags: -Znext-solver
6+
//@[multiple_next] compile-flags: -Znext-solver
47
//@ check-pass
58

69
trait Bound {}
710
trait Normalize {
811
type Assoc;
912
}
1013

11-
#[cfg(multiple)]
14+
#[cfg(any(multiple_curr, multiple_next))]
1215
impl<T: Bound> Normalize for T {
1316
type Assoc = T;
1417
}

0 commit comments

Comments
 (0)