Skip to content

Commit 3a0c405

Browse files
committed
Auto merge of #140558 - lcnr:wf-emit-projection, r=<try>
wf: emit projection goal for aliases To check that their normalization succeeds in the current environment. This eagerly detects ambiguous and diverging aliases. Fixes #102252, fixes #126268 by removing the assertion in `min_specialization.rs`. r? `@compiler-errors`
2 parents 163cb4e + 5d05aa1 commit 3a0c405

File tree

38 files changed

+460
-128
lines changed

38 files changed

+460
-128
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,12 +1508,14 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
15081508
// E.g: `struct Foo<const N: usize, const M: usize = { 1 - 2 }>;`. Here, we should
15091509
// eagerly error but we don't as we have `ConstKind::Unevaluated(.., [N, M])`.
15101510
if !default.has_param() {
1511-
wfcx.register_wf_obligation(
1512-
tcx.def_span(param.def_id),
1513-
matches!(param.kind, GenericParamDefKind::Type { .. })
1514-
.then(|| WellFormedLoc::Ty(param.def_id.expect_local())),
1515-
default.as_term().unwrap(),
1516-
);
1511+
let span = tcx.def_span(param.def_id);
1512+
let wf_loc = matches!(param.kind, GenericParamDefKind::Type { .. })
1513+
.then(|| WellFormedLoc::Ty(param.def_id.expect_local()));
1514+
// We manually normalize the default to detect diverging or ambiguous aliases.
1515+
// This is not necessary with the new solver as it adds a requirement that
1516+
// aliases can be normalized when proving the `WellFormed` goal itself.
1517+
let _ = wfcx.normalize(span, wf_loc, default);
1518+
wfcx.register_wf_obligation(span, wf_loc, default.as_term().unwrap());
15171519
} else {
15181520
// If we've got a generic const parameter we still want to check its
15191521
// type is correct in case both it and the param type are fully concrete.

compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,8 +381,6 @@ fn check_predicates<'tcx>(
381381
let obligations =
382382
wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, term, span)
383383
.unwrap();
384-
385-
assert!(!obligations.has_infer());
386384
impl2_predicates
387385
.extend(traits::elaborate(tcx, obligations).map(|obligation| obligation.predicate))
388386
}

compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3939
self.type_matches_expected_vid(expected_vid, data.self_ty())
4040
}
4141
ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
42-
self.type_matches_expected_vid(expected_vid, data.projection_term.self_ty())
42+
match data.projection_term.kind(self.tcx) {
43+
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => {
44+
self.type_matches_expected_vid(expected_vid, data.projection_term.self_ty())
45+
}
46+
ty::AliasTermKind::InherentTy
47+
| ty::AliasTermKind::InherentConst
48+
| ty::AliasTermKind::OpaqueTy
49+
| ty::AliasTermKind::FreeTy
50+
| ty::AliasTermKind::FreeConst
51+
| ty::AliasTermKind::UnevaluatedConst => false,
52+
}
4353
}
4454
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
4555
| ty::PredicateKind::Subtype(..)

compiler/rustc_trait_selection/src/traits/wf.rs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -510,8 +510,6 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
510510
let obligations = self.nominal_obligations(data.def_id, args);
511511
self.out.extend(obligations);
512512
}
513-
514-
data.args.visit_with(self);
515513
}
516514

517515
fn add_wf_preds_for_projection_args(&mut self, args: GenericArgsRef<'tcx>) {
@@ -772,13 +770,35 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
772770
// Simple cases that are WF if their type args are WF.
773771
}
774772

775-
ty::Alias(ty::Projection | ty::Opaque | ty::Free, data) => {
776-
let obligations = self.nominal_obligations(data.def_id, data.args);
777-
self.out.extend(obligations);
778-
}
779-
ty::Alias(ty::Inherent, data) => {
780-
self.add_wf_preds_for_inherent_projection(data.into());
781-
return; // Subtree handled by compute_inherent_projection.
773+
ty::Alias(kind, data) => {
774+
// The new solver require aliases to normalize successfully.
775+
// Adding this `ProjectionPredicate` makes sure that ambiguous or
776+
// overflowing aliases cause an error in wf-check.
777+
if self.infcx.next_trait_solver() && !data.has_escaping_bound_vars() {
778+
let code = ObligationCauseCode::Misc;
779+
let cause = self.cause(code);
780+
let inf = self.infcx.next_ty_var(cause.span);
781+
let obligation: traits::PredicateObligation<'tcx> =
782+
traits::Obligation::with_depth(
783+
self.tcx(),
784+
cause,
785+
self.recursion_depth,
786+
self.param_env,
787+
ty::ProjectionPredicate {
788+
projection_term: data.into(),
789+
term: inf.into(),
790+
},
791+
);
792+
self.out.push(obligation);
793+
}
794+
795+
match kind {
796+
ty::Projection | ty::Opaque | ty::Free => {
797+
let obligations = self.nominal_obligations(data.def_id, data.args);
798+
self.out.extend(obligations);
799+
}
800+
ty::Inherent => self.add_wf_preds_for_inherent_projection(data.into()),
801+
}
782802
}
783803

784804
ty::Adt(def, args) => {

tests/crashes/102252.rs

Lines changed: 0 additions & 14 deletions
This file was deleted.

tests/crashes/126268.rs

Lines changed: 0 additions & 18 deletions
This file was deleted.

tests/ui/associated-inherent-types/normalization-overflow.stderr renamed to tests/ui/associated-inherent-types/normalization-overflow.current.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: overflow evaluating associated type `T::This`
2-
--> $DIR/normalization-overflow.rs:9:17
2+
--> $DIR/normalization-overflow.rs:12:17
33
|
44
LL | type This = Self::This;
55
| ^^^^^^^^^^
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0271]: type mismatch resolving `T::This normalizes-to _`
2+
--> $DIR/normalization-overflow.rs:12:17
3+
|
4+
LL | type This = Self::This;
5+
| ^^^^^^^^^^ types differ
6+
7+
error[E0271]: type mismatch resolving `T::This normalizes-to _`
8+
--> $DIR/normalization-overflow.rs:12:17
9+
|
10+
LL | type This = Self::This;
11+
| ^^^^^^^^^^ types differ
12+
|
13+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
14+
15+
error: aborting due to 2 previous errors
16+
17+
For more information about this error, try `rustc --explain E0271`.
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//@ revisions: current next
2+
//@[next] compile-flags: -Znext-solver
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
14
#![feature(inherent_associated_types)]
25
#![allow(incomplete_features)]
36

@@ -6,7 +9,9 @@
69
struct T;
710

811
impl T {
9-
type This = Self::This; //~ ERROR overflow evaluating associated type `T::This`
12+
type This = Self::This;
13+
//[current]~^ ERROR overflow evaluating associated type `T::This`
14+
//[next]~^^ ERROR type mismatch resolving `T::This normalizes-to _`
1015
}
1116

1217
fn main() {}

tests/ui/auto-traits/assoc-ty.next.stderr

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,15 @@ LL | let _: <() as Trait>::Output = ();
3535
|
3636
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
3737

38-
error: aborting due to 4 previous errors
38+
error[E0271]: type mismatch resolving `<() as Trait>::Output normalizes-to _`
39+
--> $DIR/assoc-ty.rs:15:12
40+
|
41+
LL | let _: <() as Trait>::Output = ();
42+
| ^^^^^^^^^^^^^^^^^^^^^ types differ
43+
|
44+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
45+
46+
error: aborting due to 5 previous errors
3947

4048
Some errors have detailed explanations: E0271, E0380, E0658.
4149
For more information about an error, try `rustc --explain E0271`.

tests/ui/auto-traits/assoc-ty.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ fn main() {
1616
//[current]~^ ERROR mismatched types
1717
//[next]~^^ ERROR type mismatch resolving `<() as Trait>::Output normalizes-to _`
1818
//[next]~| ERROR type mismatch resolving `<() as Trait>::Output normalizes-to _`
19+
//[next]~| ERROR type mismatch resolving `<() as Trait>::Output normalizes-to _`
1920
}

tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@ help: this trait has no implementations, consider adding one
1818
|
1919
LL | trait Foo {}
2020
| ^^^^^^^^^
21-
note: required by a bound in `A`
22-
--> $DIR/alias-bounds-when-not-wf.rs:8:11
23-
|
24-
LL | type A<T: Foo> = T;
25-
| ^^^ required by this bound in `A`
2621

2722
error[E0277]: the trait bound `usize: Foo` is not satisfied
2823
--> $DIR/alias-bounds-when-not-wf.rs:16:10

tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ LL | fn build2<T>(x: T) -> impl Sized {
1111
| ^^^^^^^^^^
1212

1313
error[E0720]: cannot resolve opaque type
14-
--> $DIR/recursive-in-exhaustiveness.rs:39:23
14+
--> $DIR/recursive-in-exhaustiveness.rs:40:23
1515
|
1616
LL | fn build3<T>(x: T) -> impl Sized {
1717
| ^^^^^^^^^^

tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
1010
LL | (build2(x),)
1111
| ^^^^^^^^^ types differ
1212

13+
error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
14+
--> $DIR/recursive-in-exhaustiveness.rs:30:6
15+
|
16+
LL | (build2(x),)
17+
| ^^^^^^^^^ types differ
18+
|
19+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
20+
1321
error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
1422
--> $DIR/recursive-in-exhaustiveness.rs:30:5
1523
|
@@ -26,13 +34,21 @@ LL | (build2(x),)
2634
= note: tuples must have a statically known size to be initialized
2735

2836
error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
29-
--> $DIR/recursive-in-exhaustiveness.rs:41:17
37+
--> $DIR/recursive-in-exhaustiveness.rs:42:17
3038
|
3139
LL | let (x,) = (build3((x,)),);
3240
| ^^^^^^^^^^^^ types differ
3341

42+
error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
43+
--> $DIR/recursive-in-exhaustiveness.rs:42:17
44+
|
45+
LL | let (x,) = (build3((x,)),);
46+
| ^^^^^^^^^^^^ types differ
47+
|
48+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
49+
3450
error[E0277]: the size for values of type `(impl Sized,)` cannot be known at compilation time
35-
--> $DIR/recursive-in-exhaustiveness.rs:41:16
51+
--> $DIR/recursive-in-exhaustiveness.rs:42:16
3652
|
3753
LL | let (x,) = (build3((x,)),);
3854
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -41,7 +57,7 @@ LL | let (x,) = (build3((x,)),);
4157
= note: tuples must have a statically known size to be initialized
4258

4359
error[E0308]: mismatched types
44-
--> $DIR/recursive-in-exhaustiveness.rs:41:16
60+
--> $DIR/recursive-in-exhaustiveness.rs:42:16
4561
|
4662
LL | fn build3<T>(x: T) -> impl Sized {
4763
| ---------- the found opaque type
@@ -53,28 +69,28 @@ LL | let (x,) = (build3((x,)),);
5369
found tuple `(impl Sized,)`
5470

5571
error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
56-
--> $DIR/recursive-in-exhaustiveness.rs:41:17
72+
--> $DIR/recursive-in-exhaustiveness.rs:42:17
5773
|
5874
LL | let (x,) = (build3((x,)),);
5975
| ^^^^^^^^^^^^ types differ
6076
|
6177
= note: the return type of a function must have a statically known size
6278

6379
error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
64-
--> $DIR/recursive-in-exhaustiveness.rs:41:16
80+
--> $DIR/recursive-in-exhaustiveness.rs:42:16
6581
|
6682
LL | let (x,) = (build3((x,)),);
6783
| ^^^^^^^^^^^^^^^ types differ
6884

6985
error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
70-
--> $DIR/recursive-in-exhaustiveness.rs:41:17
86+
--> $DIR/recursive-in-exhaustiveness.rs:42:17
7187
|
7288
LL | let (x,) = (build3((x,)),);
7389
| ^^^^^^^^^^^^ types differ
7490
|
7591
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
7692

77-
error: aborting due to 10 previous errors
93+
error: aborting due to 12 previous errors
7894

7995
Some errors have detailed explanations: E0271, E0277, E0284, E0308.
8096
For more information about an error, try `rustc --explain E0271`.

tests/ui/impl-trait/recursive-in-exhaustiveness.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ fn build2<T>(x: T) -> impl Sized {
3131
//[next]~^ ERROR type mismatch resolving
3232
//[next]~| ERROR type mismatch resolving
3333
//[next]~| ERROR the size for values of type
34+
//[next]~| ERROR type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
3435
}
3536

3637
// Opaque<T> = Opaque<(T,)>
@@ -43,6 +44,7 @@ fn build3<T>(x: T) -> impl Sized {
4344
//[next]~| ERROR type mismatch resolving
4445
//[next]~| ERROR type mismatch resolving
4546
//[next]~| ERROR type mismatch resolving
47+
//[next]~| ERROR type mismatch resolving
4648
//[next]~| ERROR the size for values of type
4749
//[next]~| ERROR mismatched types
4850
build3(x)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0275]: overflow normalizing the type alias `X2`
2+
--> $DIR/infinite-type-alias-mutual-recursion.rs:9:11
3+
|
4+
LL | type X1 = X2;
5+
| ^^
6+
|
7+
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
8+
9+
error[E0275]: overflow normalizing the type alias `X3`
10+
--> $DIR/infinite-type-alias-mutual-recursion.rs:14:11
11+
|
12+
LL | type X2 = X3;
13+
| ^^
14+
|
15+
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
16+
17+
error[E0275]: overflow normalizing the type alias `X1`
18+
--> $DIR/infinite-type-alias-mutual-recursion.rs:18:11
19+
|
20+
LL | type X3 = X1;
21+
| ^^
22+
|
23+
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
24+
25+
error: aborting due to 3 previous errors
26+
27+
For more information about this error, try `rustc --explain E0275`.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
error[E0391]: cycle detected when expanding type alias `X1`
2+
--> $DIR/infinite-type-alias-mutual-recursion.rs:9:11
3+
|
4+
LL | type X1 = X2;
5+
| ^^
6+
|
7+
note: ...which requires expanding type alias `X2`...
8+
--> $DIR/infinite-type-alias-mutual-recursion.rs:14:11
9+
|
10+
LL | type X2 = X3;
11+
| ^^
12+
note: ...which requires expanding type alias `X3`...
13+
--> $DIR/infinite-type-alias-mutual-recursion.rs:18:11
14+
|
15+
LL | type X3 = X1;
16+
| ^^
17+
= note: ...which again requires expanding type alias `X1`, completing the cycle
18+
= note: type aliases cannot be recursive
19+
= help: consider using a struct, enum, or union instead to break the cycle
20+
= help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
21+
note: cycle used when checking that `X1` is well-formed
22+
--> $DIR/infinite-type-alias-mutual-recursion.rs:9:1
23+
|
24+
LL | type X1 = X2;
25+
| ^^^^^^^
26+
= 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
27+
28+
error: aborting due to 1 previous error
29+
30+
For more information about this error, try `rustc --explain E0391`.

0 commit comments

Comments
 (0)