Skip to content

Commit

Permalink
Auto merge of rust-lang#117542 - compiler-errors:only-normalize-predi…
Browse files Browse the repository at this point in the history
…cate, 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 rust-lang#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.
  • Loading branch information
bors committed Nov 8, 2023
2 parents 750c2ec + 97c9d8f commit fab1054
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 9 deletions.
10 changes: 8 additions & 2 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// check-pass
// known-bug: #117606

#![feature(associated_type_defaults)]

Expand Down
Original file line number Diff line number Diff line change
@@ -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`.
Original file line number Diff line number Diff line change
@@ -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() {}
2 changes: 1 addition & 1 deletion tests/ui/traits/new-solver/specialization-transmute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 9 additions & 2 deletions tests/ui/traits/new-solver/specialization-transmute.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`

error: aborting due to 2 previous errors; 1 warning emitted

For more information about this error, try `rustc --explain E0284`.
Some errors have detailed explanations: E0282, E0284.
For more information about an error, try `rustc --explain E0282`.
2 changes: 1 addition & 1 deletion tests/ui/traits/new-solver/specialization-unconstrained.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>() {}
Expand Down
11 changes: 9 additions & 2 deletions tests/ui/traits/new-solver/specialization-unconstrained.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`

error: aborting due to 2 previous errors; 1 warning emitted

For more information about this error, try `rustc --explain E0284`.
Some errors have detailed explanations: E0282, E0284.
For more information about an error, try `rustc --explain E0282`.

0 comments on commit fab1054

Please sign in to comment.