Stabilize associated type bounds (RFC 2289) by compiler-errors · Pull Request #122055 · rust-lang/rust (original) (raw)
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 towhere 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 Should associated type bounds on supertraits be implied? #112573/Make associated type bounds in supertrait position implied #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 isCopy
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: Collect relevant item bounds from trait clauses for nested rigid projections #120752 (comment). - 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--
- Implementation of RFC 2289 (associated_type_bounds) #57428
- Ban associated type bounds in bad positions #108063
- Fix elaboration with associated type bounds #110512
- Make associated type bounds in supertrait position implied #112629
- Remove support for associated_type_bound nested in dyn types #120719
- For a rigid projection, recursively look at the self type's item bounds to fix the associated_type_bounds feature #120584
Closes #52662