Do not emit alias-eq when instantiating a type var from a canonical response in the new solver by compiler-errors · Pull Request #109037 · rust-lang/rust (original) (raw)
I think the approach this PR takes is not correct. This ended up kind of a huge comment, sorry for giant wall of TEXT :<
I think generalizer right now is wrong for projections. The case of ?0 <: <?1 as Trait>::Assoc
will result in generalizing the projection to <?1 as Trait>::Assoc
(assuming universes are OK) and then instantiate ?0
to <?1 as Trait>::Assoc
and relate <?1 as Trait>::Assoc <: <?1 as Trait>::Assoc
which will trivially succeed.
If we imagine ?1
getting inferred to Foo<?2>
and an impl such as:impl<T> Trait for Foo<T> { type Assoc = T; }
Then ideally what would happen here is that post-normalization we end up with Foo<?2> <: Foo<?3>
instead of Foo<?1> <: Foo<?1>
. With lazy norm this probably will likely get worse and introduce backwards compatibility problems where we will end up having projections instead of their normalized form.
Fixing this will be incompatible with the way that this PR currently has sub
/sup
relate the substs of projections. I suspect that in the future we will want to change AliasEq
to AliasRelate
that stores a variance (for whether to do eq/sub/sup). Generalization would then turn projections into infer vars and then emit AliasRelate
so that the previous case of:?0 <: <?1 as Trait>::Assoc
will result in us generalizing <?1 as Trait>::Assoc
to ?2
, instantiating ?0
to ?2
and then emitting AliasRelate(?2, sub, <?1 as Trait>::Assoc)
. (Although the exact way that we solve this problem may not be this but I think its almost guaranteed that relating substs like this PR does, will be incompatible with a solution)
This could probably be fixed by just Not setting eager_relate_projections_via_substs
for sub
/sup
and only doing it for eq
.
Instantiation relating the substs of projections when doing eq
is less obviously incorrect but still wrong I think.
Generalizer has a special case to avoid creating new infer vars for invariant positions except for the situation where the var being instantiated is in a lower universe than the variable being generalized. So we can actually end up in a situation where generalizing a projection results in a type that is not ==
to the version before generalizing:
?0.0 instantiated-to <?1.1 as Trait>::Assoc
- generalize
<?1.1 as Trait>::Assoc
to<?2.0 as Trait>::Assoc
- instantiate
?0.0
as<?2.0 as Trait>::Assoc
<?2.0 as Trait>::Assoc eq <?1.1 as Trait>::Assoc
If we were to relate the substs of these two projections ?1.1
would get inferred to have the universe of ?2.0
as it is lower. This could then go on to cause universe errors when relating ?1.1
with a placeholder in universe 0 as the infer var has now been resolved to ?2.0
which cannot name the placeholder.
This is likely unsound during coherence as it would cause NoSolution
when the aliases being equal could have held through other means that the substs being equal. For example it's possible that ?2.0
and ?1.1
would each get inferred to completely different types allowing normalization to succeed with the normalized types ending up equal.
I suspect that you could get the same issue with sub
/sup
however since those are not used for coherence it would probably be "fine" for those to be incorrect.
This could probably be fixed by only setting eager_relate_projections_via_substs
when we are not in intercrate mode. Right now new solver's behaviour for alias equality does not change between coherence and type checking and I think that is desirable to maintain unless completely necessary to give up (which I do not think this issue requires)
I am not entirely sure what lcnr's plan for the FIXME in unify_query_var_values
is. Eventually we do need to handle it some way for occurs check on projections so that ?0 eq <?0 as Trait>::Assoc
does not give us NoSolution
instead of ambiguity during coherence (afaik the current plan is to emit PredicateKind::Ambig
when this occurs). Handling this would only require downgrading the QueryResult
to ambiguous if there are any goals.
If we wanted to handle AliasEq
here though we would have to actually evaluate the nested goals afaict because under lazy norm we may end up with these AliasEq
goals actually being able to succeed via normalized tys being equal.
I haven't talked about the somewhat more subjective complaints about this PR (generally the solution having a "hacky" vibe that is probably a soundness footgun as relating substs is generally Very Wrong) since I think the more objective problems (this PR being unsound as is) are more important.