@@ -10,6 +10,8 @@ Introduce the bound form `MyTrait<AssociatedType: Bounds>`, permitted anywhere
1010a bound of the form ` MyTrait<AssociatedType = T> ` would be allowed. The bound
1111` T: Trait<AssociatedType: Bounds> ` desugars to the bounds ` T: Trait ` and
1212` <T as Trait>::AssociatedType: Bounds ` .
13+ See the [ reference] [ reference-level-explanation ] and [ rationale] [ alternatives ]
14+ for exact details.
1315
1416# Motivation
1517[ motivation ] : #motivation
@@ -86,8 +88,8 @@ impl<I: Clone + Iterator<Item: Clone>> Clone for Peekable<I> {
8688# Reference-level explanation
8789[ reference-level-explanation ] : #reference-level-explanation
8890
89- The surface syntax ` T: Trait<AssociatedType: Bounds> ` should always desugar
90- to a pair of bounds: ` T: Trait ` and ` <T as Trait>::AssociatedType: Bounds ` .
91+ The surface syntax ` T: Trait<AssociatedType: Bounds> ` should desugar to a pair
92+ of bounds: ` T: Trait ` and ` <T as Trait>::AssociatedType: Bounds ` .
9193Rust currently allows both of those bounds anywhere a bound can currently appear;
9294the new syntax does not introduce any new semantics.
9395
@@ -100,6 +102,58 @@ Meanwhile, the surface syntax `dyn Trait<AssociatedType: Bounds>` desugars into
100102` dyn Trait<AssociatedType = T> ` where ` T ` is a named type variable ` T ` with the
101103bound ` T: Bounds ` .
102104
105+ ## The desugaring for associated types
106+
107+ In the case of an associated type having a bound of the form:
108+
109+ ``` rust
110+ trait TraitA {
111+ type AssocA : TraitB <AssocB : TraitC >;
112+ }
113+ ```
114+
115+ we desugar to an anonymous associated type for ` AssocB ` , which corresponds to:
116+
117+ ``` rust
118+ trait TraitA {
119+ type AssocA : TraitB <AssocB = Self :: AssocA_0 >;
120+ type AssocA_0 : TraitC ; // Associated type is Unnamed!
121+ }
122+ ```
123+
124+ ## Notes on the meaning of ` impl Trait<Assoc: Bound> `
125+
126+ Note that in the context ` -> impl Trait<Assoc: Bound> ` , since the Trait is
127+ existentially quantified, the ` Assoc ` is as well. Semantically speaking,
128+ ` fn printables.. ` is equivalent to:
129+
130+ ``` rust
131+ fn printables () -> impl Iterator <Item = impl Display > { .. }
132+ ```
133+
134+ For ` arg: impl Trait<Assoc: Bound> ` , it is semantically equivalent to:
135+ ` arg: impl Trait<Assoc = impl Bound> ` .
136+
137+ ## Meaning of ` existential type Foo: Trait<Assoc: Bound> `
138+
139+ Given:
140+
141+ ```
142+ existential type Foo: Trait<Assoc: Bound>;
143+ ```
144+
145+ it can be seen as the same as:
146+
147+ ``` rust
148+ existential type Foo : Trait <Assoc = _0 >;
149+ existential type _0 : Bound ;
150+ ```
151+
152+ [ RFC 2071 ] : https://github.com/rust-lang/rfcs/blob/master/text/2071-impl-trait-type-alias.md
153+
154+ This syntax is specified in [ RFC 2071] . As in that RFC, this documentation
155+ uses the non-final syntax for existential type aliases.
156+
103157# Drawbacks
104158[ drawbacks ] : #drawbacks
105159
@@ -111,16 +165,79 @@ different. However, we believe that the parallel to the use of bounds elsewhere
111165makes this new syntax immediately recognizable and understandable.
112166
113167# Rationale and alternatives
114- [ alternatives ] : #alternatives
168+ [ alternatives ] : #rationale-and- alternatives
115169
116170As with any new surface syntax, one alternative is simply not introducing
117171the syntax at all. That would still leave developers with the
118172` MyTrait<AssociatedType = impl Bounds> ` form. However, allowing the more
119173direct bounds syntax provides a better parallel to the use of bounds elsewhere.
120174The introduced form in this RFC is comparatively both shorter and clearer.
121175
176+ ### An alternative desugaring of bounds on associated types
177+
178+ [ RFC 2089 ] : https://github.com/rust-lang/rfcs/blob/master/text/2089-implied-bounds.md
179+
180+ An alternative desugaring of the following definition:
181+
182+ ``` rust
183+ trait TraitA {
184+ type AssocA : TraitB <AssocB : TraitC >;
185+ }
186+ ```
187+
188+ is to add the ` where ` clause, as specified above, to the trait, desugaring to:
189+
190+ ``` rust
191+ trait TraitA
192+ where
193+ <Self :: AssocA as TraitB >:: AssocB : TraitC ,
194+ {
195+ type AssocA : TraitB ;
196+ }
197+ ```
198+
199+ However, at the time of this writing, a Rust compiler will treat this
200+ differently than the desugaring proposed in the reference.
201+ The following snippet illustrates the difference:
202+
203+ ``` rust
204+ trait Foo where <Self :: Bar as Iterator >:: Item : Copy {
205+ type Bar : Iterator ;
206+ }
207+
208+ trait Foo2 {
209+ type Bar : Iterator <Item = Self :: BarItem >;
210+ type BarItem : Copy ;
211+ }
212+
213+ fn use_foo <X : Foo >(arg : X )
214+ where <X :: Bar as Iterator >:: Item : Copy
215+ // ^-- Remove this line and it will error with:
216+ // error[E0277]: `<<X as Foo>::Bar as std::iter::Iterator>::Item` doesn't implement `Copy`
217+ {
218+ let item : <X :: Bar as Iterator >:: Item ;
219+ }
220+
221+ fn use_foo2 <X : Foo2 >(arg : X ) {
222+ let item : <X :: Bar as Iterator >:: Item ;
223+ }
224+ ```
225+
226+ The desugaring with a ` where ` therefore becomes problematic from a perspective
227+ of usability.
228+
229+ However, [ RFC 2089, Implied Bounds] [ RFC 2089 ] specifies that desugaring to the
230+ ` where ` clause in the trait will permit the ` use_foo ` function to omit its
231+ ` where ` clause. This entails that both desugarings become equivalent from the
232+ point of view of a user. The desugaring with ` where ` therefore becomes viable
233+ in the presence of [ RFC 2089] .
234+
122235# Unresolved questions
123236[ unresolved ] : #unresolved-questions
124237
125- - Does allowing this for ` dyn ` trait objects introduce any unforseen issues?
126- This can be resolved during stabilization.
238+ - Does allowing this for ` dyn ` trait objects introduce any unforeseen issues?
239+ This can be resolved during stabilization.
240+
241+ - The exact desugaring in the context of putting bounds on an associated type
242+ of a trait is left unresolved. The semantics should however be preserved.
243+ This is also the case with other desugarings in this RFC.
0 commit comments