@@ -205,22 +205,49 @@ types cannot be defined in [inherent implementations] nor can they be given a
205
205
default implementation in traits.
206
206
207
207
An * associated type declaration* declares a signature for associated type
208
- definitions. It is written as ` type ` , then an [ identifier] , and
209
- finally an optional list of trait bounds.
208
+ definitions. It is written in one of the following forms, where ` Assoc ` is the
209
+ name of the associated type, ` Params ` is a comma-separated list of type,
210
+ lifetime or const parameters, ` Bounds ` is a plus-separated list of trait bounds
211
+ that the associated type must meet, and ` WhereBounds ` is a comma-separated list
212
+ of bounds that the parameters must meet:
213
+
214
+ <!-- ignore: illustrative example forms -->
215
+ ``` rust,ignore
216
+ type Assoc;
217
+ type Assoc: Bounds;
218
+ type Assoc<Params>;
219
+ type Assoc<Params>: Bounds;
220
+ type Assoc<Params> where WhereBounds;
221
+ type Assoc<Params>: Bounds where WhereBounds;
222
+ ```
210
223
211
224
The identifier is the name of the declared type alias. The optional trait bounds
212
225
must be fulfilled by the implementations of the type alias.
213
226
There is an implicit [ ` Sized ` ] bound on associated types that can be relaxed using the special ` ?Sized ` bound.
214
227
215
- An * associated type definition* defines a type alias on another type. It is
216
- written as ` type ` , then an [ identifier] , then an ` = ` , and finally a [ type] .
228
+ An * associated type definition* defines a type alias for the implementation
229
+ of a trait on a type. They are written similarly to an * associated type declaration* ,
230
+ but cannot contain ` Bounds ` , but instead must contain a ` Type ` :
231
+
232
+ <!-- ignore: illustrative example forms -->
233
+ ``` rust,ignore
234
+ type Assoc = Type;
235
+ type Assoc<Params> = Type; // the type `Type` here may reference `Params`
236
+ type Assoc<Params> = Type where WhereBounds;
237
+ type Assoc<Params> where WhereBounds = Type; // deprecated, prefer the form above
238
+ ```
217
239
218
240
If a type ` Item ` has an associated type ` Assoc ` from a trait ` Trait ` , then
219
241
` <Item as Trait>::Assoc ` is a type that is an alias of the type specified in the
220
242
associated type definition. Furthermore, if ` Item ` is a type parameter, then
221
243
` Item::Assoc ` can be used in type parameters.
222
244
223
- Associated types must not include [ generic parameters] or [ where clauses] .
245
+ Associated types may include [ generic parameters] and [ where clauses] ; these are
246
+ often referred to as * generic associated types* , or * GATs* . If the type ` Thing `
247
+ has an associated type ` Item ` from a trait ` Trait ` with the generics ` <'a> ` , the
248
+ type can be named like ` <Thing as Trait>::Item<'x> ` , where ` 'x ` is some lifetime
249
+ in scope. In this case, ` 'x ` will be used wherever ` 'a ` appears in the associated
250
+ type definitions on impls.
224
251
225
252
``` rust
226
253
trait AssociatedType {
@@ -249,6 +276,37 @@ fn main() {
249
276
}
250
277
```
251
278
279
+ An example of associated types with generics and where clauses:
280
+
281
+ ``` rust
282
+ struct ArrayLender <'a , T >(& 'a mut [T ; 16 ]);
283
+
284
+ trait Lend {
285
+ // Generic associated type declaration
286
+ type Lender <'a > where Self : 'a ;
287
+ fn lend <'a >(& 'a mut self ) -> Self :: Lender <'a >;
288
+ }
289
+
290
+ impl <T > Lend for [T ; 16 ] {
291
+ // Generic associated type definition
292
+ type Lender <'a > = ArrayLender <'a , T > where Self : 'a ;
293
+
294
+ fn lend <'a >(& 'a mut self ) -> Self :: Lender <'a > {
295
+ ArrayLender (self )
296
+ }
297
+ }
298
+
299
+ fn borrow <'a , T : Lend >(array : & 'a mut T ) -> <T as Lend >:: Lender <'a > {
300
+ array . lend ()
301
+ }
302
+
303
+
304
+ fn main () {
305
+ let mut array = [0usize ; 16 ];
306
+ let lender = borrow (& mut array );
307
+ }
308
+ ```
309
+
252
310
### Associated Types Container Example
253
311
254
312
Consider the following example of a ` Container ` trait. Notice that the type is
@@ -279,6 +337,83 @@ impl<T> Container for Vec<T> {
279
337
}
280
338
```
281
339
340
+ ### Relationship between ` Bounds ` and ` WhereBounds `
341
+
342
+ In this example:
343
+
344
+ ``` rust
345
+ # use std :: fmt :: Debug ;
346
+ trait Example {
347
+ type Output <T >: Ord where T : Debug ;
348
+ }
349
+ ```
350
+
351
+ Given a reference to the associated type like ` <X as Example>::Output<Y> ` , the associated type itself must be ` Ord ` , and the type ` Y ` must be ` Debug ` .
352
+
353
+ ### Required where clauses on generic associated types
354
+
355
+ Generic associated type declarations on traits currently may require a list of
356
+ where clauses, dependent on functions in the trait and how the GAT is used. These
357
+ rules may be loosened in the future; updates can be found [ on the generic
358
+ associated types initiative repository] ( https://rust-lang.github.io/generic-associated-types-initiative/explainer/required_bounds.html ) .
359
+
360
+ In a few words, these where clauses are required in order to maximize the allowed
361
+ definitions of the associated type in impls. To do this, any clauses that * can be
362
+ proven to hold* on functions (using the parameters of the function or trait)
363
+ where a GAT appears as an input or output must also be written on the GAT itself.
364
+
365
+ ``` rust
366
+ trait LendingIterator {
367
+ type Item <'x > where Self : 'x ;
368
+ fn next <'a >(& 'a mut self ) -> Self :: Item <'a >;
369
+ }
370
+ ```
371
+
372
+ In the above, on the ` next ` function, we can prove that ` Self: 'a ` , because of
373
+ the implied bounds from ` &'a mut self ` ; therefore, we must write the equivalent
374
+ bound on the GAT itself: ` where Self: 'x ` .
375
+
376
+ When there are multiple functions in a trait that use the GAT, then the
377
+ * intersection* of the bounds from the different functions are used, rather than
378
+ the union.
379
+
380
+ ``` rust
381
+ trait Check <T > {
382
+ type Checker <'x >;
383
+ fn create_checker <'a >(item : & 'a T ) -> Self :: Checker <'a >;
384
+ fn do_check (checker : Self :: Checker <'_ >);
385
+ }
386
+ ```
387
+
388
+ In this example, no bounds are required on the ` type Checker<'a>; ` . While we
389
+ know that ` T: 'a ` on ` create_checker ` , we do not know that on ` do_check ` . However,
390
+ if ` do_check ` was commented out, then the ` where T: 'x ` bound would be required
391
+ on ` Checker ` .
392
+
393
+ The bounds on associated types also propagate required where clauses.
394
+
395
+ ``` rust
396
+ trait Iterable {
397
+ type Item <'a > where Self : 'a ;
398
+ type Iterator <'a >: Iterator <Item = Self :: Item <'a >> where Self : 'a ;
399
+ fn iter <'a >(& 'a self ) -> Self :: Iterator <'a >;
400
+ }
401
+ ```
402
+
403
+ Here, ` where Self: 'a ` is required on ` Item ` because of ` iter ` . However, ` Item `
404
+ is used in the bounds of ` Iterator ` , the ` where Self: 'a ` clause is also required
405
+ there.
406
+
407
+ Finally, any explicit uses of ` 'static ` on GATs in the trait do not count towards
408
+ the required bounds.
409
+
410
+ ``` rust
411
+ trait StaticReturn {
412
+ type Y <'a >;
413
+ fn foo (& self ) -> Self :: Y <'static >;
414
+ }
415
+ ```
416
+
282
417
## Associated Constants
283
418
284
419
* Associated constants* are [ constants] associated with a type.
0 commit comments