For a rigid projection, recursively look at the self type's item bounds to fix the associated_type_bounds feature#120584
Merged
bors merged 4 commits intorust-lang:masterfrom Feb 10, 2024
Merged
Conversation
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Given a deeply nested rigid projection like
<<<T as Trait1>::Assoc1 as Trait2>::Assoc2 as Trait3>::Assoc3, this PR adjusts both trait solvers to look at the item bounds for all ofAssoc3,Assoc2, andAssoc1in order to satisfy a goal. We do this because the item bounds for projections may contain relevant bounds for other nested projections when theassociated_type_bounds(ATB) feature is enabled. For example:This has been a long-standing place of brokenness for ATBs, and is also part of the reason why ATBs currently desugar so differently in various positions (i.e. sometimes desugaring to param-env bounds, sometimes desugaring to RPITs, etc). For example, in RPIT and TAIT position,
impl Foo<Bar: Baz>currently desugars toimpl Foo<Bar = impl Baz>because we do not currently take advantage of these nested item bounds if we desugared them into a single set of item bounds on the opaque. This is obviously both strange and unnecessary if we just take advantage of these bounds as we should.Approach
This PR repeatedly peels off each projection of a given goal's self type and tries to match its item bounds against a goal, repeating with the self type of the projection. This is pretty straightforward to implement in the new solver, only requiring us to loop on the self type of a rigid projection to discover inner rigid projections, and we also need to introduce an extra probe so we can normalize them.
In the old solver, we can do essentially the same thing, however we rely on the fact that projections should be normalized already. This is obviously not always the case -- however, in the case that they are not fully normalized, such as a projection which has both infer vars and, we bail out with ambiguity if we hit an infer var for the self type.
Caveats
for<'a> <?0 as Tr<'a>>: Tr2. Because we stall them, they no longer are eagerly treated as error -- this cause some existingknown-bugtests to go from fail -> pass.I'm pretty unconvinced that this is a problem since we make code that we expect to pass in the new solver also pass in the old solver, though this obviously doesn't solve the full problem.
And then also...
We also adjust the desugaring of ATB to always desugar to a regular associated bound, rather than sometimes to an impl Trait except for when the ATB is present in a
dyn Trait. We need to lowerdyn Trait<Assoc: Bar>todyn Trait<Assoc = impl Bar>because object types need all of their associated types specified.I would also be in favor of splitting out the ATB feature and/or removing support for object types in order to stabilize just the set of positions for which the ATB feature is consistent (i.e. always elaborates to a bound).