Skip to content

wf: emit projection goal for aliases #140558

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1508,12 +1508,14 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
// E.g: `struct Foo<const N: usize, const M: usize = { 1 - 2 }>;`. Here, we should
// eagerly error but we don't as we have `ConstKind::Unevaluated(.., [N, M])`.
if !default.has_param() {
wfcx.register_wf_obligation(
tcx.def_span(param.def_id),
matches!(param.kind, GenericParamDefKind::Type { .. })
.then(|| WellFormedLoc::Ty(param.def_id.expect_local())),
default.as_term().unwrap(),
);
let span = tcx.def_span(param.def_id);
let wf_loc = matches!(param.kind, GenericParamDefKind::Type { .. })
.then(|| WellFormedLoc::Ty(param.def_id.expect_local()));
// We manually normalize the default to detect diverging or ambiguous aliases.
// This is not necessary with the new solver as it adds a requirement that
// aliases can be normalized when proving the `WellFormed` goal itself.
let _ = wfcx.normalize(span, wf_loc, default);
wfcx.register_wf_obligation(span, wf_loc, default.as_term().unwrap());
} else {
// If we've got a generic const parameter we still want to check its
// type is correct in case both it and the param type are fully concrete.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,8 +381,6 @@ fn check_predicates<'tcx>(
let obligations =
wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, term, span)
.unwrap();

assert!(!obligations.has_infer());
impl2_predicates
.extend(traits::elaborate(tcx, obligations).map(|obligation| obligation.predicate))
}
Expand Down
12 changes: 11 additions & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.type_matches_expected_vid(expected_vid, data.self_ty())
}
ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
self.type_matches_expected_vid(expected_vid, data.projection_term.self_ty())
match data.projection_term.kind(self.tcx) {
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => {
self.type_matches_expected_vid(expected_vid, data.projection_term.self_ty())
}
ty::AliasTermKind::InherentTy
| ty::AliasTermKind::InherentConst
| ty::AliasTermKind::OpaqueTy
| ty::AliasTermKind::FreeTy
| ty::AliasTermKind::FreeConst
| ty::AliasTermKind::UnevaluatedConst => false,
}
}
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
| ty::PredicateKind::Subtype(..)
Expand Down
38 changes: 29 additions & 9 deletions compiler/rustc_trait_selection/src/traits/wf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -510,8 +510,6 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
let obligations = self.nominal_obligations(data.def_id, args);
self.out.extend(obligations);
}

data.args.visit_with(self);
}

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

ty::Alias(ty::Projection | ty::Opaque | ty::Free, data) => {
let obligations = self.nominal_obligations(data.def_id, data.args);
self.out.extend(obligations);
}
ty::Alias(ty::Inherent, data) => {
self.add_wf_preds_for_inherent_projection(data.into());
return; // Subtree handled by compute_inherent_projection.
ty::Alias(kind, data) => {
// The new solver require aliases to normalize successfully.
// Adding this `ProjectionPredicate` makes sure that ambiguous or
// overflowing aliases cause an error in wf-check.
if self.infcx.next_trait_solver() && !data.has_escaping_bound_vars() {
let code = ObligationCauseCode::Misc;
let cause = self.cause(code);
let inf = self.infcx.next_ty_var(cause.span);
let obligation: traits::PredicateObligation<'tcx> =
traits::Obligation::with_depth(
self.tcx(),
cause,
self.recursion_depth,
self.param_env,
ty::ProjectionPredicate {
projection_term: data.into(),
term: inf.into(),
},
);
self.out.push(obligation);
}

match kind {
ty::Projection | ty::Opaque | ty::Free => {
let obligations = self.nominal_obligations(data.def_id, data.args);
self.out.extend(obligations);
}
ty::Inherent => self.add_wf_preds_for_inherent_projection(data.into()),
}
}

ty::Adt(def, args) => {
Expand Down
14 changes: 0 additions & 14 deletions tests/crashes/102252.rs

This file was deleted.

18 changes: 0 additions & 18 deletions tests/crashes/126268.rs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: overflow evaluating associated type `T::This`
--> $DIR/normalization-overflow.rs:9:17
--> $DIR/normalization-overflow.rs:12:17
|
LL | type This = Self::This;
| ^^^^^^^^^^
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error[E0271]: type mismatch resolving `T::This normalizes-to _`
--> $DIR/normalization-overflow.rs:12:17
|
LL | type This = Self::This;
| ^^^^^^^^^^ types differ

error[E0271]: type mismatch resolving `T::This normalizes-to _`
--> $DIR/normalization-overflow.rs:12:17
|
LL | type This = Self::This;
| ^^^^^^^^^^ types differ
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0271`.
7 changes: 6 additions & 1 deletion tests/ui/associated-inherent-types/normalization-overflow.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//@ revisions: current next
//@[next] compile-flags: -Znext-solver
//@ ignore-compare-mode-next-solver (explicit revisions)
#![feature(inherent_associated_types)]
#![allow(incomplete_features)]

Expand All @@ -6,7 +9,9 @@
struct T;

impl T {
type This = Self::This; //~ ERROR overflow evaluating associated type `T::This`
type This = Self::This;
//[current]~^ ERROR overflow evaluating associated type `T::This`
//[next]~^^ ERROR type mismatch resolving `T::This normalizes-to _`
}

fn main() {}
10 changes: 9 additions & 1 deletion tests/ui/auto-traits/assoc-ty.next.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,15 @@ LL | let _: <() as Trait>::Output = ();
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

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

error: aborting due to 5 previous errors

Some errors have detailed explanations: E0271, E0380, E0658.
For more information about an error, try `rustc --explain E0271`.
1 change: 1 addition & 0 deletions tests/ui/auto-traits/assoc-ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ fn main() {
//[current]~^ ERROR mismatched types
//[next]~^^ ERROR type mismatch resolving `<() as Trait>::Output normalizes-to _`
//[next]~| ERROR type mismatch resolving `<() as Trait>::Output normalizes-to _`
//[next]~| ERROR type mismatch resolving `<() as Trait>::Output normalizes-to _`
}
5 changes: 0 additions & 5 deletions tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ help: this trait has no implementations, consider adding one
|
LL | trait Foo {}
| ^^^^^^^^^
note: required by a bound in `A`
--> $DIR/alias-bounds-when-not-wf.rs:8:11
|
LL | type A<T: Foo> = T;
| ^^^ required by this bound in `A`

error[E0277]: the trait bound `usize: Foo` is not satisfied
--> $DIR/alias-bounds-when-not-wf.rs:16:10
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ LL | fn build2<T>(x: T) -> impl Sized {
| ^^^^^^^^^^

error[E0720]: cannot resolve opaque type
--> $DIR/recursive-in-exhaustiveness.rs:39:23
--> $DIR/recursive-in-exhaustiveness.rs:40:23
|
LL | fn build3<T>(x: T) -> impl Sized {
| ^^^^^^^^^^
Expand Down
30 changes: 23 additions & 7 deletions tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
LL | (build2(x),)
| ^^^^^^^^^ types differ

error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
--> $DIR/recursive-in-exhaustiveness.rs:30:6
|
LL | (build2(x),)
| ^^^^^^^^^ types differ
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
--> $DIR/recursive-in-exhaustiveness.rs:30:5
|
Expand All @@ -26,13 +34,21 @@ LL | (build2(x),)
= note: tuples must have a statically known size to be initialized

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

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

error[E0277]: the size for values of type `(impl Sized,)` cannot be known at compilation time
--> $DIR/recursive-in-exhaustiveness.rs:41:16
--> $DIR/recursive-in-exhaustiveness.rs:42:16
|
LL | let (x,) = (build3((x,)),);
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
Expand All @@ -41,7 +57,7 @@ LL | let (x,) = (build3((x,)),);
= note: tuples must have a statically known size to be initialized

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

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

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

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

error: aborting due to 10 previous errors
error: aborting due to 12 previous errors

Some errors have detailed explanations: E0271, E0277, E0284, E0308.
For more information about an error, try `rustc --explain E0271`.
2 changes: 2 additions & 0 deletions tests/ui/impl-trait/recursive-in-exhaustiveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ fn build2<T>(x: T) -> impl Sized {
//[next]~^ ERROR type mismatch resolving
//[next]~| ERROR type mismatch resolving
//[next]~| ERROR the size for values of type
//[next]~| ERROR type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
}

// Opaque<T> = Opaque<(T,)>
Expand All @@ -43,6 +44,7 @@ fn build3<T>(x: T) -> impl Sized {
//[next]~| ERROR type mismatch resolving
//[next]~| ERROR type mismatch resolving
//[next]~| ERROR type mismatch resolving
//[next]~| ERROR type mismatch resolving
//[next]~| ERROR the size for values of type
//[next]~| ERROR mismatched types
build3(x)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
error[E0275]: overflow normalizing the type alias `X2`
--> $DIR/infinite-type-alias-mutual-recursion.rs:9:11
|
LL | type X1 = X2;
| ^^
|
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead

error[E0275]: overflow normalizing the type alias `X3`
--> $DIR/infinite-type-alias-mutual-recursion.rs:14:11
|
LL | type X2 = X3;
| ^^
|
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead

error[E0275]: overflow normalizing the type alias `X1`
--> $DIR/infinite-type-alias-mutual-recursion.rs:18:11
|
LL | type X3 = X1;
| ^^
|
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0275`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
error[E0391]: cycle detected when expanding type alias `X1`
--> $DIR/infinite-type-alias-mutual-recursion.rs:9:11
|
LL | type X1 = X2;
| ^^
|
note: ...which requires expanding type alias `X2`...
--> $DIR/infinite-type-alias-mutual-recursion.rs:14:11
|
LL | type X2 = X3;
| ^^
note: ...which requires expanding type alias `X3`...
--> $DIR/infinite-type-alias-mutual-recursion.rs:18:11
|
LL | type X3 = X1;
| ^^
= note: ...which again requires expanding type alias `X1`, completing the cycle
= note: type aliases cannot be recursive
= help: consider using a struct, enum, or union instead to break the cycle
= help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
note: cycle used when checking that `X1` is well-formed
--> $DIR/infinite-type-alias-mutual-recursion.rs:9:1
|
LL | type X1 = X2;
| ^^^^^^^
= 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

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0391`.
Loading
Loading