21d94a3d2c
Stabilize associated type bounds (RFC 2289) This PR stabilizes associated type bounds, which were laid out in [RFC 2289]. This gives us a shorthand to express nested type bounds that would otherwise need to be expressed with nested `impl Trait` or broken into several `where` clauses. ### What are we stabilizing? We're stabilizing the associated item bounds syntax, which allows us to put bounds in associated type position within other bounds, i.e. `T: Trait<Assoc: Bounds...>`. See [RFC 2289] for motivation. In all position, the associated type bound syntax expands into a set of two (or more) bounds, and never anything else (see "How does this differ[...]" section for more info). Associated type bounds are stabilized in four positions: * **`where` clauses (and APIT)** - This is equivalent to breaking up the bound into two (or more) `where` clauses. For example, `where T: Trait<Assoc: Bound>` is equivalent to `where T: Trait, <T as Trait>::Assoc: Bound`. * **Supertraits** - Similar to above, `trait CopyIterator: Iterator<Item: Copy> {}`. This is almost equivalent to breaking up the bound into two (or more) `where` clauses; however, the bound on the associated item is implied whenever the trait is used. See #112573/#112629. * **Associated type item bounds** - This allows constraining the *nested* rigid projections that are associated with a trait's associated types. e.g. `trait Trait { type Assoc: Trait2<Assoc2: Copy>; }`. * **opaque item bounds (RPIT, TAIT)** - This allows constraining associated types that are associated with the opaque without having to *name* the opaque. For example, `impl Iterator<Item: Copy>` defines an iterator whose item is `Copy` without having to actually name that item bound. The latter three are not expressible in surface Rust (though for associated type item bounds, this will change in #120752, which I don't believe should block this PR), so this does represent a slight expansion of what can be expressed in trait bounds. ### How does this differ from the RFC? Compared to the RFC, the current implementation *always* desugars associated type bounds to sets of `ty::Clause`s internally. Specifically, it does *not* introduce a position-dependent desugaring as laid out in [RFC 2289], and in particular: * It does *not* desugar to anonymous associated items in associated type item bounds. * It does *not* desugar to nested RPITs in RPIT bounds, nor nested TAITs in TAIT bounds. This position-dependent desugaring laid out in the RFC existed simply to side-step limitations of the trait solver, which have mostly been fixed in #120584. The desugaring laid out in the RFC also added unnecessary complication to the design of the feature, and introduces its own limitations to, for example: * Conditionally lowering to nested `impl Trait` in certain positions such as RPIT and TAIT means that we inherit the limitations of RPIT/TAIT, namely lack of support for higher-ranked opaque inference. See this code example: https://github.com/rust-lang/rust/pull/120752#issuecomment-1979412531. * Introducing anonymous associated types makes traits no longer object safe, since anonymous associated types are not nameable, and all associated types must be named in `dyn` types. This last point motivates why this PR is *not* stabilizing support for associated type bounds in `dyn` types, e.g, `dyn Assoc<Item: Bound>`. Why? Because `dyn` types need to have *concrete* types for all associated items, this would necessitate a distinct lowering for associated type bounds, which seems both complicated and unnecessary compared to just requiring the user to write `impl Trait` themselves. See #120719. ### Implementation history: Limited to the significant behavioral changes and fixes and relevant PRs, ping me if I left something out-- * #57428 * #108063 * #110512 * #112629 * #120719 * #120584 Closes #52662 [RFC 2289]: https://rust-lang.github.io/rfcs/2289-associated-type-bounds.html |
||
---|---|---|
.. | ||
auxiliary | ||
alias-bounds-when-not-wf.rs | ||
alias-bounds-when-not-wf.stderr | ||
anonymize-binders-for-refine.rs | ||
assumed-wf-bounds-in-impl.rs | ||
async-and-ret-ref.rs | ||
async-and-ret-ref.stderr | ||
bad-item-bound-within-rpitit-2.rs | ||
bad-item-bound-within-rpitit-2.stderr | ||
bad-item-bound-within-rpitit.rs | ||
bad-item-bound-within-rpitit.stderr | ||
box-coerce-span-in-default.rs | ||
check-wf-on-non-defaulted-rpitit.rs | ||
check-wf-on-non-defaulted-rpitit.stderr | ||
cycle-effective-visibilities-during-object-safety.rs | ||
cycle-effective-visibilities-during-object-safety.stderr | ||
deep-match-works.rs | ||
deep-match.rs | ||
deep-match.stderr | ||
default-body-type-err-2.rs | ||
default-body-type-err-2.stderr | ||
default-body-type-err.rs | ||
default-body-type-err.stderr | ||
default-body-with-rpit.rs | ||
default-body.rs | ||
default-method-binder-shifting.rs | ||
default-method-constraint.rs | ||
doesnt-satisfy.rs | ||
doesnt-satisfy.stderr | ||
dont-project-to-rpitit-with-no-value.rs | ||
dont-project-to-rpitit-with-no-value.stderr | ||
early.rs | ||
encode.rs | ||
ensure-rpitits-are-created-before-freezing.rs | ||
ensure-rpitits-are-created-before-freezing.stderr | ||
foreign-dyn-error.rs | ||
foreign-dyn-error.stderr | ||
foreign.rs | ||
foreign.stderr | ||
gat-outlives.rs | ||
gat-outlives.stderr | ||
generics-mismatch.rs | ||
generics-mismatch.stderr | ||
issue-102140.rs | ||
issue-102140.stderr | ||
issue-102301.rs | ||
issue-102571.rs | ||
issue-102571.stderr | ||
lifetime-in-associated-trait-bound.rs | ||
method-signature-matches.lt.stderr | ||
method-signature-matches.mismatch_async.stderr | ||
method-signature-matches.mismatch.stderr | ||
method-signature-matches.rs | ||
method-signature-matches.too_few.stderr | ||
method-signature-matches.too_many.stderr | ||
missing-lt-outlives-in-rpitit-114274.rs | ||
missing-lt-outlives-in-rpitit-114274.stderr | ||
missing-static-bound-from-impl.rs | ||
missing-static-bound-from-impl.stderr | ||
nested-rpitit-bounds.rs | ||
nested-rpitit.rs | ||
object-safety-sized.rs | ||
object-safety.rs | ||
object-safety.stderr | ||
opaque-and-lifetime-mismatch.rs | ||
opaque-and-lifetime-mismatch.stderr | ||
opaque-in-impl-is-opaque.rs | ||
opaque-in-impl-is-opaque.stderr | ||
opaque-in-impl.rs | ||
opaque-variances.rs | ||
outlives-in-nested-rpit.rs | ||
placeholder-implied-bounds.rs | ||
refine-normalize.rs | ||
refine.rs | ||
refine.stderr | ||
return-dont-satisfy-bounds.rs | ||
return-dont-satisfy-bounds.stderr | ||
reveal.rs | ||
rpitit-cycle-in-generics-of.rs | ||
rpitit-hidden-types-self-implied-wf-via-param.rs | ||
rpitit-hidden-types-self-implied-wf-via-param.stderr | ||
rpitit-hidden-types-self-implied-wf.rs | ||
rpitit-hidden-types-self-implied-wf.stderr | ||
rpitit-shadowed-by-missing-adt.rs | ||
rpitit-shadowed-by-missing-adt.stderr | ||
sibling-function-constraint.rs | ||
sibling-function-constraint.stderr | ||
signature-mismatch.failure.stderr | ||
signature-mismatch.rs | ||
span-bug-issue-121457.rs | ||
span-bug-issue-121457.stderr | ||
specialization-broken.rs | ||
specialization-broken.stderr | ||
specialization-substs-remap.rs | ||
success.rs | ||
suggest-missing-item.fixed | ||
suggest-missing-item.rs | ||
suggest-missing-item.stderr | ||
trait-more-generics-than-impl.rs | ||
trait-more-generics-than-impl.stderr | ||
unconstrained-lt.rs | ||
unconstrained-lt.stderr | ||
variance.rs | ||
variance.stderr | ||
variances-of-gat.rs | ||
wf-bounds.rs | ||
wf-bounds.stderr | ||
where-clause.rs |