@@ -10,6 +10,8 @@ Introduce the bound form `MyTrait<AssociatedType: Bounds>`, permitted anywhere
10
10
a bound of the form ` MyTrait<AssociatedType = T> ` would be allowed. The bound
11
11
` T: Trait<AssociatedType: Bounds> ` desugars to the bounds ` T: Trait ` and
12
12
` <T as Trait>::AssociatedType: Bounds ` .
13
+ See the [ reference] [ reference-level-explanation ] and [ rationale] [ alternatives ]
14
+ for exact details.
13
15
14
16
# Motivation
15
17
[ motivation ] : #motivation
@@ -86,8 +88,8 @@ impl<I: Clone + Iterator<Item: Clone>> Clone for Peekable<I> {
86
88
# Reference-level explanation
87
89
[ reference-level-explanation ] : #reference-level-explanation
88
90
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 ` .
91
93
Rust currently allows both of those bounds anywhere a bound can currently appear;
92
94
the new syntax does not introduce any new semantics.
93
95
@@ -100,6 +102,58 @@ Meanwhile, the surface syntax `dyn Trait<AssociatedType: Bounds>` desugars into
100
102
` dyn Trait<AssociatedType = T> ` where ` T ` is a named type variable ` T ` with the
101
103
bound ` T: Bounds ` .
102
104
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
+
103
157
# Drawbacks
104
158
[ drawbacks ] : #drawbacks
105
159
@@ -111,16 +165,79 @@ different. However, we believe that the parallel to the use of bounds elsewhere
111
165
makes this new syntax immediately recognizable and understandable.
112
166
113
167
# Rationale and alternatives
114
- [ alternatives ] : #alternatives
168
+ [ alternatives ] : #rationale-and- alternatives
115
169
116
170
As with any new surface syntax, one alternative is simply not introducing
117
171
the syntax at all. That would still leave developers with the
118
172
` MyTrait<AssociatedType = impl Bounds> ` form. However, allowing the more
119
173
direct bounds syntax provides a better parallel to the use of bounds elsewhere.
120
174
The introduced form in this RFC is comparatively both shorter and clearer.
121
175
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
+
122
235
# Unresolved questions
123
236
[ unresolved ] : #unresolved-questions
124
237
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