@@ -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,53 @@ 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
127
+ ` Trait ` is existentially quantified, so is in effect also the ` Assoc ` .
128
+ Semantically speaking, ` 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 can likewise be seen as:
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
+
103
152
# Drawbacks
104
153
[ drawbacks ] : #drawbacks
105
154
@@ -111,16 +160,79 @@ different. However, we believe that the parallel to the use of bounds elsewhere
111
160
makes this new syntax immediately recognizable and understandable.
112
161
113
162
# Rationale and alternatives
114
- [ alternatives ] : #alternatives
163
+ [ alternatives ] : #rationale-and- alternatives
115
164
116
165
As with any new surface syntax, one alternative is simply not introducing
117
166
the syntax at all. That would still leave developers with the
118
167
` MyTrait<AssociatedType = impl Bounds> ` form. However, allowing the more
119
168
direct bounds syntax provides a better parallel to the use of bounds elsewhere.
120
169
The introduced form in this RFC is comparatively both shorter and clearer.
121
170
171
+ ### An alternative desugaring of bounds on associated types
172
+
173
+ [ RFC 2089 ] : https://github.com/rust-lang/rfcs/blob/master/text/2089-implied-bounds.md
174
+
175
+ An alternative desugaring of the following definition:
176
+
177
+ ``` rust
178
+ trait TraitA {
179
+ type AssocA : TraitB <AssocB : TraitC >;
180
+ }
181
+ ```
182
+
183
+ is to add the ` where ` clause, as specified above, to the trait, desugaring to:
184
+
185
+ ``` rust
186
+ trait TraitA
187
+ where
188
+ <Self :: AssocA as TraitB >:: AssocB : TraitC ,
189
+ {
190
+ type AssocA : TraitB ;
191
+ }
192
+ ```
193
+
194
+ However, at the time of this writing, a Rust compiler will treat this
195
+ differently than the desugaring proposed in the reference.
196
+ The following snippet illustrates the difference:
197
+
198
+ ``` rust
199
+ trait Foo where <Self :: Bar as Iterator >:: Item : Copy {
200
+ type Bar : Iterator ;
201
+ }
202
+
203
+ trait Foo2 {
204
+ type Bar : Iterator <Item = Self :: BarItem >;
205
+ type BarItem : Copy ;
206
+ }
207
+
208
+ fn use_foo <X : Foo >(arg : X )
209
+ where <X :: Bar as Iterator >:: Item : Copy
210
+ // ^-- Remove this line and it will error with:
211
+ // error[E0277]: `<<X as Foo>::Bar as std::iter::Iterator>::Item` doesn't implement `Copy`
212
+ {
213
+ let item : <X :: Bar as Iterator >:: Item ;
214
+ }
215
+
216
+ fn use_foo2 <X : Foo2 >(arg : X ) {
217
+ let item : <X :: Bar as Iterator >:: Item ;
218
+ }
219
+ ```
220
+
221
+ The desugaring with a ` where ` therefore becomes problematic from a perspective
222
+ of usability.
223
+
224
+ However, [ RFC 2089, Implied Bounds] [ RFC 2089 ] specifies that desugaring to the
225
+ ` where ` clause in the trait will permit the ` use_foo ` function to omit its
226
+ ` where ` clause. This entails that both desugarings become equivalent from the
227
+ point of view of a user. The desugaring with ` where ` therefore becomes viable
228
+ in the presence of [ RFC 2089] .
229
+
122
230
# Unresolved questions
123
231
[ unresolved ] : #unresolved-questions
124
232
125
- - Does allowing this for ` dyn ` trait objects introduce any unforseen issues?
126
- This can be resolved during stabilization.
233
+ - Does allowing this for ` dyn ` trait objects introduce any unforeseen issues?
234
+ This can be resolved during stabilization.
235
+
236
+ - The exact desugaring in the context of putting bounds on an associated type
237
+ of a trait is left unresolved. The semantics should however be preserved.
238
+ This is also the case with other desugarings in this RFC.
0 commit comments