@@ -205,22 +205,49 @@ types cannot be defined in [inherent implementations] nor can they be given a
205205default implementation in traits.
206206
207207An * 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+ ```
210223
211224The identifier is the name of the declared type alias. The optional trait bounds
212225must be fulfilled by the implementations of the type alias.
213226There is an implicit [ ` Sized ` ] bound on associated types that can be relaxed using the special ` ?Sized ` bound.
214227
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+ ```
217239
218240If a type ` Item ` has an associated type ` Assoc ` from a trait ` Trait ` , then
219241` <Item as Trait>::Assoc ` is a type that is an alias of the type specified in the
220242associated type definition. Furthermore, if ` Item ` is a type parameter, then
221243` Item::Assoc ` can be used in type parameters.
222244
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.
224251
225252``` rust
226253trait AssociatedType {
@@ -249,6 +276,37 @@ fn main() {
249276}
250277```
251278
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+
252310### Associated Types Container Example
253311
254312Consider the following example of a ` Container ` trait. Notice that the type is
@@ -279,6 +337,83 @@ impl<T> Container for Vec<T> {
279337}
280338```
281339
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+
282417## Associated Constants
283418
284419* Associated constants* are [ constants] associated with a type.
0 commit comments