Don't check GAT bounds in normalization by aliemjay · Pull Request #117682 · rust-lang/rust (original) (raw)

This should fix most of GAT bugs related to where Self: 'a. See the ui tests for examples.

The core idea is that we don't check associated type bounds when normalizing them, but rather rely on the them being well-formed. This is similar to how we deal with other rigid types. This should, for example, eliminate the strange inconsistent behavior in this snippet:

trait Trait { type Gat<'a> where Self: 'a; } impl Trait for T { type Gat<'a> = &'a T where Self: 'a; }

type Raw<'a, T> = &'a T; // requires T: 'a type Gat<'a, T> = ::Gat::<'a>; // requires T: 'a as well

fn test<T, U: Trait>() { let _: fn(Raw<'_, T>); // Ok let _: fn(Gat<'_, T>); // Error now; Ok with this PR let _: fn(Gat<'_, U>); // Ok (normalized to a rigid projection) }

The main problem with this approach is that we currently don't check the well-formedness of projection types before normalizing them. See #100041 and #104764. This causes us to accept the following invalid code (from tests/ui/generic-associated-types/unsatisfied-{body,item}-lifetime-bound.rs)

trait Trait { type Gat<'a> where Self: 'a; } impl Trait for T { type Gat<'a> = () where Self: 'a; }

struct MyTy { f: ::Gat::<'static>, // error now (as expected); passes with this PR! g: T, }

but I believe both issues are relatively straightforward to fix given the previous attempts in #100046 and #104746.

Another problem is that of tests/ui/generic-associated-types/projection-bound-cycle{,-generic}.rs, but that's hopefully fixable in some kind of analysis. (I can see it in compare_predicate_entailement).

So, my question to @rust-lang/types is that, assuming that we have a satisfactory solution to both problems above, do you have other concerns about this approach?

r? @ghost