Auto merge of #117542 - compiler-errors:only-normalize-predicate, r=lcnr

Only use `normalize_param_env` when normalizing predicate in `check_item_bounds`

Only use the `normalize_param_env` when normalizing the item bound predicate in `check_item_bounds`, instead of using it when processing this obligation as well. This causes <BUG> to reoccur, but hopefully with better caching in the future, we can fix this would having such bad effects on perf.

This PR also fixes #117598. It turns out that the GAT predicate that we install is actually wrong -- given code like:

```
impl<'r> HasValueRef<'r> for Any {
    type Database = Any;
}
```

We currently generate a predicate that looks like `<Any as HasValueRef<'r>>::Database = Any`, where `'r` is an early-bound variable. Really this GAT assumption should be universally quantified over the impl's args, i.e. `for<'r> <Any as HasValueRef<'r>>::Database = Any`, but then we'd need the binder to also include all the WC of the impl as well, which we don't support yet, lol.
This commit is contained in:
bors 2023-11-08 10:08:44 +00:00
commit fab1054e17
8 changed files with 73 additions and 9 deletions

View file

@ -2162,7 +2162,7 @@ pub(super) fn check_type_bounds<'tcx>(
impl_ty: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
let param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref);
let param_env = tcx.param_env(impl_ty.def_id);
debug!(?param_env);
let container_id = impl_ty.container_id(tcx);
@ -2217,8 +2217,14 @@ pub(super) fn check_type_bounds<'tcx>(
.collect();
debug!("check_type_bounds: item_bounds={:?}", obligations);
// Normalize predicates with the assumption that the GAT may always normalize
// to its definition type. This should be the param-env we use to *prove* the
// predicate too, but we don't do that because of performance issues.
// See <https://github.com/rust-lang/rust/pull/117542#issue-1976337685>.
let normalize_param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref);
for mut obligation in util::elaborate(tcx, obligations) {
let normalized_predicate = ocx.normalize(&normalize_cause, param_env, obligation.predicate);
let normalized_predicate =
ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate);
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
obligation.predicate = normalized_predicate;

View file

@ -1,4 +1,4 @@
// check-pass
// known-bug: #117606
#![feature(associated_type_defaults)]

View file

@ -0,0 +1,24 @@
error[E0277]: the trait bound `<Self as Foo>::Bar<()>: Eq<i32>` is not satisfied
--> $DIR/assume-gat-normalization-for-nested-goals.rs:6:30
|
LL | type Bar<T>: Baz<Self> = i32;
| ^^^ the trait `Eq<i32>` is not implemented for `<Self as Foo>::Bar<()>`
|
note: required for `i32` to implement `Baz<Self>`
--> $DIR/assume-gat-normalization-for-nested-goals.rs:13:23
|
LL | impl<T: Foo + ?Sized> Baz<T> for i32 where T::Bar<()>: Eq<i32> {}
| ^^^^^^ ^^^ ------- unsatisfied trait bound introduced here
note: required by a bound in `Foo::Bar`
--> $DIR/assume-gat-normalization-for-nested-goals.rs:6:18
|
LL | type Bar<T>: Baz<Self> = i32;
| ^^^^^^^^^ required by this bound in `Foo::Bar`
help: consider further restricting the associated type
|
LL | trait Foo where <Self as Foo>::Bar<()>: Eq<i32> {
| +++++++++++++++++++++++++++++++++++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,20 @@
// check-pass
trait Database: for<'r> HasValueRef<'r, Database = Self> {}
trait HasValueRef<'r> {
type Database: Database;
}
struct Any;
impl Database for Any {}
impl<'r> HasValueRef<'r> for Any {
// Make sure we don't have issues when the GAT assumption
// `<Any as HasValue<'r>>::Database = Any` isn't universally
// parameterized over `'r`.
type Database = Any;
}
fn main() {}

View file

@ -10,7 +10,7 @@ trait Default {
}
impl<T> Default for T {
default type Id = T;
default type Id = T; //~ ERROR type annotations needed
// This will be fixed by #111994
fn intu(&self) -> &Self::Id { //~ ERROR type annotations needed
self

View file

@ -16,6 +16,13 @@ LL | fn intu(&self) -> &Self::Id {
|
= note: cannot satisfy `<T as Default>::Id == _`
error: aborting due to previous error; 1 warning emitted
error[E0282]: type annotations needed
--> $DIR/specialization-transmute.rs:13:23
|
LL | default type Id = T;
| ^ cannot infer type for associated type `<T as Default>::Id`
For more information about this error, try `rustc --explain E0284`.
error: aborting due to 2 previous errors; 1 warning emitted
Some errors have detailed explanations: E0282, E0284.
For more information about an error, try `rustc --explain E0282`.

View file

@ -11,7 +11,7 @@ trait Default {
}
impl<T> Default for T {
default type Id = T;
default type Id = T; //~ ERROR type annotations needed
}
fn test<T: Default<Id = U>, U>() {}

View file

@ -20,6 +20,13 @@ note: required by a bound in `test`
LL | fn test<T: Default<Id = U>, U>() {}
| ^^^^^^ required by this bound in `test`
error: aborting due to previous error; 1 warning emitted
error[E0282]: type annotations needed
--> $DIR/specialization-unconstrained.rs:14:22
|
LL | default type Id = T;
| ^ cannot infer type for associated type `<T as Default>::Id`
For more information about this error, try `rustc --explain E0284`.
error: aborting due to 2 previous errors; 1 warning emitted
Some errors have detailed explanations: E0282, E0284.
For more information about an error, try `rustc --explain E0282`.