rust-lang / trait-system-refactor-initiative

The Rustc Trait System Refactor Initiative
21 stars 0 forks source link

generalization is incomplete for aliases #8

Open lcnr opened 1 year ago

lcnr commented 1 year ago

when generalizing a projection we have to be careful. We're using ?ident.universe for inference variables in a given universe.

given that this is already an issue in on stable we could add a test for this and stabilize even with this incompleteness.

1. ?x sub <() as Trait<?y>>::Assoc

must not generalize ?x to <() as Trait<?y>>::Assoc as ?x may get inferred to a subtype of the normalized projection. Otherwise this would be incomplete. Should emit AliasRelate in this case instead. example

2. ?x eq <?x as Trait>::Assoc :heavy_check_mark:

this must not result in a universe error as the alias may be normalized to ?x. https://github.com/rust-lang/rust/issues/105787

3. ?x eq <<T as Id<?x>>::Id as Unnormalizable>::Assoc

This may hold, as ?x can be constrained to <T as Unnormalizable>::Assoc: example. We cannot simply emit a NormalizesTo goal if equating fails the occurs check, as we could also normalize a nested projection instead.

4. ?x.0 eq <() as Trait<?y.1>>::Assoc

This must not generalize ?x.0 to <() as Trait<?z.1>>::Assoc because that should result in a universe error but it must also not relate it to <() as Trait<?z.0>>::Assoc because the projection may not actually normalize to a type mentioning z so if we then equate the substs in AliasRelate we end up pulling down the universe of ?y to 0 as well which would be incomplete. Should instead emit AliasRelate(?x.0, <() as Trait<?y.1>>::Assoc, Equate).

5. <?x.1 as Trait>::Assoc eq ?y.0

Roughly the same setup as the previous issue but with a different potential unsoundness.

If we generalize ?y.0 to <?z.0 as Trait<'a>>::Assoc (the self ty ending up in a lower universe than ?x.1) this is potentially incomplete if we have a param env candidate such as !T.1: Trait and no other candidates for proving Trait as we would consider ourselves unable to normalize <?z.0 as Trait>::Assoc as ?z.0 eq !T.1 would give a universe error and we would return NoSolution. This is wrong if the assoc type does not actually mention the placeholder as we would be able to instantiate ?y.0 with the assoc type's normalized form.

This could likely only occur with non_lifetime_binders that support where clauses and it would also likely have to be slighltly more complex of a reproduction to workaround the fact that ?0: Trait are always ambiguous.

6. for<'a> fn(<<?x as OtherTrait>::Assoc as Trait<'a>>::Assoc) eq ?x

TODO: explain why this is an issue

7. for<'a> fn(<?0.0 as Trait<'a, ?2.1>>::Assoc) eq ?1.0

Solutions:


There have been various large comments on PRs about soundness of generalization: one, two