| r[items.associated] |
| # Associated Items |
| |
| r[items.associated.syntax] |
| > **<sup>Syntax</sup>**\ |
| > _AssociatedItem_ :\ |
| > [_OuterAttribute_]<sup>\*</sup> (\ |
| > [_MacroInvocationSemi_]\ |
| > | ( [_Visibility_]<sup>?</sup> ( [_TypeAlias_] | [_ConstantItem_] | [_Function_] ) )\ |
| > ) |
| |
| r[items.associated.intro] |
| *Associated Items* are the items declared in [traits] or defined in |
| [implementations]. They are called this because they are defined on an associate |
| type — the type in the implementation. |
| |
| r[items.associated.kinds] |
| They are a subset of the kinds of items you can declare in a module. |
| Specifically, there are [associated functions] (including methods), [associated types], and [associated constants]. |
| |
| [associated functions]: #associated-functions-and-methods |
| [associated types]: #associated-types |
| [associated constants]: #associated-constants |
| |
| r[items.associated.related] |
| Associated items are useful when the associated item logically is related to the |
| associating item. For example, the `is_some` method on `Option` is intrinsically |
| related to Options, so should be associated. |
| |
| r[items.associated.decl-def] |
| Every associated item kind comes in two varieties: definitions that contain the |
| actual implementation and declarations that declare signatures for |
| definitions. |
| |
| r[items.associated.trait-items] |
| It is the declarations that make up the contract of traits and what is available |
| on generic types. |
| |
| r[items.associated.fn] |
| ## Associated functions and methods |
| |
| r[items.associated.fn.intro] |
| *Associated functions* are [functions] associated with a type. |
| |
| r[items.associated.fn.decl] |
| An *associated function declaration* declares a signature for an associated |
| function definition. It is written as a function item, except the |
| function body is replaced with a `;`. |
| |
| r[items.associated.name] |
| The identifier is the name of the function. |
| |
| r[items.associated.same-signature] |
| The generics, parameter list, return type, and where clause of the associated function must be the same as the |
| associated function declarations's. |
| |
| r[items.associated.fn.def] |
| An *associated function definition* defines a function associated with another |
| type. It is written the same as a [function item]. |
| |
| An example of a common associated function is a `new` function that returns |
| a value of the type the associated function is associated with. |
| |
| ```rust |
| struct Struct { |
| field: i32 |
| } |
| |
| impl Struct { |
| fn new() -> Struct { |
| Struct { |
| field: 0i32 |
| } |
| } |
| } |
| |
| fn main () { |
| let _struct = Struct::new(); |
| } |
| ``` |
| |
| r[items.associated.fn.qualified-self] |
| When the associated function is declared on a trait, the function can also be |
| called with a [path] that is a path to the trait appended by the name of the |
| trait. When this happens, it is substituted for `<_ as Trait>::function_name`. |
| |
| ```rust |
| trait Num { |
| fn from_i32(n: i32) -> Self; |
| } |
| |
| impl Num for f64 { |
| fn from_i32(n: i32) -> f64 { n as f64 } |
| } |
| |
| // These 4 are all equivalent in this case. |
| let _: f64 = Num::from_i32(42); |
| let _: f64 = <_ as Num>::from_i32(42); |
| let _: f64 = <f64 as Num>::from_i32(42); |
| let _: f64 = f64::from_i32(42); |
| ``` |
| |
| r[items.associated.fn.method] |
| ### Methods |
| |
| r[items.associated.fn.method.intro] |
| Associated functions whose first parameter is named `self` are called *methods* |
| and may be invoked using the [method call operator], for example, `x.foo()`, as |
| well as the usual function call notation. |
| |
| r[items.associated.fn.method.self-ty] |
| If the type of the `self` parameter is specified, it is limited to types resolving |
| to one generated by the following grammar (where `'lt` denotes some arbitrary |
| lifetime): |
| |
| ```text |
| P = &'lt S | &'lt mut S | Box<S> | Rc<S> | Arc<S> | Pin<P> |
| S = Self | P |
| ``` |
| |
| The `Self` terminal in this grammar denotes a type resolving to the implementing type. |
| This can also include the contextual type alias `Self`, other type aliases, |
| or associated type projections resolving to the implementing type. |
| |
| ```rust |
| # use std::rc::Rc; |
| # use std::sync::Arc; |
| # use std::pin::Pin; |
| // Examples of methods implemented on struct `Example`. |
| struct Example; |
| type Alias = Example; |
| trait Trait { type Output; } |
| impl Trait for Example { type Output = Example; } |
| impl Example { |
| fn by_value(self: Self) {} |
| fn by_ref(self: &Self) {} |
| fn by_ref_mut(self: &mut Self) {} |
| fn by_box(self: Box<Self>) {} |
| fn by_rc(self: Rc<Self>) {} |
| fn by_arc(self: Arc<Self>) {} |
| fn by_pin(self: Pin<&Self>) {} |
| fn explicit_type(self: Arc<Example>) {} |
| fn with_lifetime<'a>(self: &'a Self) {} |
| fn nested<'a>(self: &mut &'a Arc<Rc<Box<Alias>>>) {} |
| fn via_projection(self: <Example as Trait>::Output) {} |
| } |
| ``` |
| |
| r[associated.fn.method.self-pat-shorthands] |
| Shorthand syntax can be used without specifying a type, which have the |
| following equivalents: |
| |
| Shorthand | Equivalent |
| ----------------------|----------- |
| `self` | `self: Self` |
| `&'lifetime self` | `self: &'lifetime Self` |
| `&'lifetime mut self` | `self: &'lifetime mut Self` |
| |
| > [!NOTE] |
| > Lifetimes can be, and usually are, elided with this shorthand. |
| |
| r[associated.fn.method.self-pat-mut] |
| If the `self` parameter is prefixed with `mut`, it becomes a mutable variable, |
| similar to regular parameters using a `mut` [identifier pattern]. For example: |
| |
| ```rust |
| trait Changer: Sized { |
| fn change(mut self) {} |
| fn modify(mut self: Box<Self>) {} |
| } |
| ``` |
| |
| As an example of methods on a trait, consider the following: |
| |
| ```rust |
| # type Surface = i32; |
| # type BoundingBox = i32; |
| trait Shape { |
| fn draw(&self, surface: Surface); |
| fn bounding_box(&self) -> BoundingBox; |
| } |
| ``` |
| |
| This defines a trait with two methods. All values that have [implementations] |
| of this trait while the trait is in scope can have their `draw` and |
| `bounding_box` methods called. |
| |
| ```rust |
| # type Surface = i32; |
| # type BoundingBox = i32; |
| # trait Shape { |
| # fn draw(&self, surface: Surface); |
| # fn bounding_box(&self) -> BoundingBox; |
| # } |
| # |
| struct Circle { |
| // ... |
| } |
| |
| impl Shape for Circle { |
| // ... |
| # fn draw(&self, _: Surface) {} |
| # fn bounding_box(&self) -> BoundingBox { 0i32 } |
| } |
| |
| # impl Circle { |
| # fn new() -> Circle { Circle{} } |
| # } |
| # |
| let circle_shape = Circle::new(); |
| let bounding_box = circle_shape.bounding_box(); |
| ``` |
| |
| r[items.associated.fn.params.edition2015] |
| > **Edition differences**: In the 2015 edition, it is possible to declare trait |
| > methods with anonymous parameters (e.g. `fn foo(u8)`). This is deprecated and |
| > an error as of the 2018 edition. All parameters must have an argument name. |
| |
| r[items.associated.fn.param-attributes] |
| #### Attributes on method parameters |
| |
| Attributes on method parameters follow the same rules and restrictions as |
| [regular function parameters]. |
| |
| r[items.associated.type] |
| ## Associated Types |
| |
| r[items.associated.type.intro] |
| *Associated types* are [type aliases] associated with another type. |
| |
| r[items.associated.type.restrictions] |
| Associated types cannot be defined in [inherent implementations] nor can they be given a |
| default implementation in traits. |
| |
| r[items.associated.type.decl] |
| An *associated type declaration* declares a signature for associated type |
| definitions. It is written in one of the following forms, where `Assoc` is the |
| name of the associated type, `Params` is a comma-separated list of type, |
| lifetime or const parameters, `Bounds` is a plus-separated list of trait bounds |
| that the associated type must meet, and `WhereBounds` is a comma-separated list |
| of bounds that the parameters must meet: |
| |
| <!-- ignore: illustrative example forms --> |
| ```rust,ignore |
| type Assoc; |
| type Assoc: Bounds; |
| type Assoc<Params>; |
| type Assoc<Params>: Bounds; |
| type Assoc<Params> where WhereBounds; |
| type Assoc<Params>: Bounds where WhereBounds; |
| ``` |
| |
| r[items.associated.type.name] |
| The identifier is the name of the declared type alias. |
| |
| r[items.associated.type.impl-fulfillment] |
| The optional trait bounds must be fulfilled by the implementations of the type alias. |
| |
| r[items.associated.type.sized] |
| There is an implicit [`Sized`] bound on associated types that can be relaxed using the special `?Sized` bound. |
| |
| r[items.associated.type.def] |
| An *associated type definition* defines a type alias for the implementation |
| of a trait on a type |
| |
| r[items.associated.type.def.restriction] |
| They are written similarly to an *associated type declaration*, but cannot contain `Bounds`, but instead must contain a `Type`: |
| |
| <!-- ignore: illustrative example forms --> |
| ```rust,ignore |
| type Assoc = Type; |
| type Assoc<Params> = Type; // the type `Type` here may reference `Params` |
| type Assoc<Params> = Type where WhereBounds; |
| type Assoc<Params> where WhereBounds = Type; // deprecated, prefer the form above |
| ``` |
| |
| r[items.associated.type.alias] |
| If a type `Item` has an associated type `Assoc` from a trait `Trait`, then |
| `<Item as Trait>::Assoc` is a type that is an alias of the type specified in the |
| associated type definition |
| |
| r[items.associated.type.param] |
| Furthermore, if `Item` is a type parameter, then `Item::Assoc` can be used in type parameters. |
| |
| r[items.associated.type.generic] |
| Associated types may include [generic parameters] and [where clauses]; these are |
| often referred to as *generic associated types*, or *GATs*. If the type `Thing` |
| has an associated type `Item` from a trait `Trait` with the generics `<'a>` , the |
| type can be named like `<Thing as Trait>::Item<'x>`, where `'x` is some lifetime |
| in scope. In this case, `'x` will be used wherever `'a` appears in the associated |
| type definitions on impls. |
| |
| ```rust |
| trait AssociatedType { |
| // Associated type declaration |
| type Assoc; |
| } |
| |
| struct Struct; |
| |
| struct OtherStruct; |
| |
| impl AssociatedType for Struct { |
| // Associated type definition |
| type Assoc = OtherStruct; |
| } |
| |
| impl OtherStruct { |
| fn new() -> OtherStruct { |
| OtherStruct |
| } |
| } |
| |
| fn main() { |
| // Usage of the associated type to refer to OtherStruct as <Struct as AssociatedType>::Assoc |
| let _other_struct: OtherStruct = <Struct as AssociatedType>::Assoc::new(); |
| } |
| ``` |
| |
| An example of associated types with generics and where clauses: |
| |
| ```rust |
| struct ArrayLender<'a, T>(&'a mut [T; 16]); |
| |
| trait Lend { |
| // Generic associated type declaration |
| type Lender<'a> where Self: 'a; |
| fn lend<'a>(&'a mut self) -> Self::Lender<'a>; |
| } |
| |
| impl<T> Lend for [T; 16] { |
| // Generic associated type definition |
| type Lender<'a> = ArrayLender<'a, T> where Self: 'a; |
| |
| fn lend<'a>(&'a mut self) -> Self::Lender<'a> { |
| ArrayLender(self) |
| } |
| } |
| |
| fn borrow<'a, T: Lend>(array: &'a mut T) -> <T as Lend>::Lender<'a> { |
| array.lend() |
| } |
| |
| fn main() { |
| let mut array = [0usize; 16]; |
| let lender = borrow(&mut array); |
| } |
| ``` |
| |
| ### Associated Types Container Example |
| |
| Consider the following example of a `Container` trait. Notice that the type is |
| available for use in the method signatures: |
| |
| ```rust |
| trait Container { |
| type E; |
| fn empty() -> Self; |
| fn insert(&mut self, elem: Self::E); |
| } |
| ``` |
| |
| In order for a type to implement this trait, it must not only provide |
| implementations for every method, but it must specify the type `E`. Here's an |
| implementation of `Container` for the standard library type `Vec`: |
| |
| ```rust |
| # trait Container { |
| # type E; |
| # fn empty() -> Self; |
| # fn insert(&mut self, elem: Self::E); |
| # } |
| impl<T> Container for Vec<T> { |
| type E = T; |
| fn empty() -> Vec<T> { Vec::new() } |
| fn insert(&mut self, x: T) { self.push(x); } |
| } |
| ``` |
| |
| ### Relationship between `Bounds` and `WhereBounds` |
| |
| In this example: |
| |
| ```rust |
| # use std::fmt::Debug; |
| trait Example { |
| type Output<T>: Ord where T: Debug; |
| } |
| ``` |
| |
| 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`. |
| |
| r[items.associated.type.generic-where-clause] |
| ### Required where clauses on generic associated types |
| |
| r[items.associated.type.generic-where-clause.intro] |
| Generic associated type declarations on traits currently may require a list of |
| where clauses, dependent on functions in the trait and how the GAT is used. These |
| rules may be loosened in the future; updates can be found [on the generic |
| associated types initiative repository](https://rust-lang.github.io/generic-associated-types-initiative/explainer/required_bounds.html). |
| |
| r[items.associated.type.generic-where-clause.valid-fn] |
| In a few words, these where clauses are required in order to maximize the allowed |
| definitions of the associated type in impls. To do this, any clauses that *can be |
| proven to hold* on functions (using the parameters of the function or trait) |
| where a GAT appears as an input or output must also be written on the GAT itself. |
| |
| ```rust |
| trait LendingIterator { |
| type Item<'x> where Self: 'x; |
| fn next<'a>(&'a mut self) -> Self::Item<'a>; |
| } |
| ``` |
| |
| In the above, on the `next` function, we can prove that `Self: 'a`, because of |
| the implied bounds from `&'a mut self`; therefore, we must write the equivalent |
| bound on the GAT itself: `where Self: 'x`. |
| |
| r[items.associated.type.generic-where-clause.intersection] |
| When there are multiple functions in a trait that use the GAT, then the |
| *intersection* of the bounds from the different functions are used, rather than |
| the union. |
| |
| ```rust |
| trait Check<T> { |
| type Checker<'x>; |
| fn create_checker<'a>(item: &'a T) -> Self::Checker<'a>; |
| fn do_check(checker: Self::Checker<'_>); |
| } |
| ``` |
| |
| In this example, no bounds are required on the `type Checker<'a>;`. While we |
| know that `T: 'a` on `create_checker`, we do not know that on `do_check`. However, |
| if `do_check` was commented out, then the `where T: 'x` bound would be required |
| on `Checker`. |
| |
| r[items.associated.type.generic-where-clause.forward] |
| The bounds on associated types also propagate required where clauses. |
| |
| ```rust |
| trait Iterable { |
| type Item<'a> where Self: 'a; |
| type Iterator<'a>: Iterator<Item = Self::Item<'a>> where Self: 'a; |
| fn iter<'a>(&'a self) -> Self::Iterator<'a>; |
| } |
| ``` |
| |
| Here, `where Self: 'a` is required on `Item` because of `iter`. However, `Item` |
| is used in the bounds of `Iterator`, the `where Self: 'a` clause is also required |
| there. |
| |
| r[items.associated.type.generic-where-clause.static] |
| Finally, any explicit uses of `'static` on GATs in the trait do not count towards |
| the required bounds. |
| |
| ```rust |
| trait StaticReturn { |
| type Y<'a>; |
| fn foo(&self) -> Self::Y<'static>; |
| } |
| ``` |
| |
| r[items.associated.const] |
| ## Associated Constants |
| |
| r[items.associated.const.intro] |
| *Associated constants* are [constants] associated with a type. |
| |
| r[items.associated.const.decl] |
| An *associated constant declaration* declares a signature for associated |
| constant definitions. It is written as `const`, then an identifier, |
| then `:`, then a type, finished by a `;`. |
| |
| r[items.associated.const.name] |
| The identifier is the name of the constant used in the path. The type is the |
| type that the definition has to implement. |
| |
| r[items.associated.const.def] |
| An *associated constant definition* defines a constant associated with a |
| type. It is written the same as a [constant item]. |
| |
| r[items.associated.const.eval] |
| Associated constant definitions undergo [constant evaluation] only when |
| referenced. Further, definitions that include [generic parameters] are |
| evaluated after monomorphization. |
| |
| ```rust,compile_fail |
| struct Struct; |
| struct GenericStruct<const ID: i32>; |
| |
| impl Struct { |
| // Definition not immediately evaluated |
| const PANIC: () = panic!("compile-time panic"); |
| } |
| |
| impl<const ID: i32> GenericStruct<ID> { |
| // Definition not immediately evaluated |
| const NON_ZERO: () = if ID == 0 { |
| panic!("contradiction") |
| }; |
| } |
| |
| fn main() { |
| // Referencing Struct::PANIC causes compilation error |
| let _ = Struct::PANIC; |
| |
| // Fine, ID is not 0 |
| let _ = GenericStruct::<1>::NON_ZERO; |
| |
| // Compilation error from evaluating NON_ZERO with ID=0 |
| let _ = GenericStruct::<0>::NON_ZERO; |
| } |
| ``` |
| |
| ### Associated Constants Examples |
| |
| A basic example: |
| |
| ```rust |
| trait ConstantId { |
| const ID: i32; |
| } |
| |
| struct Struct; |
| |
| impl ConstantId for Struct { |
| const ID: i32 = 1; |
| } |
| |
| fn main() { |
| assert_eq!(1, Struct::ID); |
| } |
| ``` |
| |
| Using default values: |
| |
| ```rust |
| trait ConstantIdDefault { |
| const ID: i32 = 1; |
| } |
| |
| struct Struct; |
| struct OtherStruct; |
| |
| impl ConstantIdDefault for Struct {} |
| |
| impl ConstantIdDefault for OtherStruct { |
| const ID: i32 = 5; |
| } |
| |
| fn main() { |
| assert_eq!(1, Struct::ID); |
| assert_eq!(5, OtherStruct::ID); |
| } |
| ``` |
| |
| [_ConstantItem_]: constant-items.md |
| [_Function_]: functions.md |
| [_MacroInvocationSemi_]: ../macros.md#macro-invocation |
| [_OuterAttribute_]: ../attributes.md |
| [_TypeAlias_]: type-aliases.md |
| [_Visibility_]: ../visibility-and-privacy.md |
| [`Arc<Self>`]: ../special-types-and-traits.md#arct |
| [`Box<Self>`]: ../special-types-and-traits.md#boxt |
| [`Pin<P>`]: ../special-types-and-traits.md#pinp |
| [`Rc<Self>`]: ../special-types-and-traits.md#rct |
| [`Sized`]: ../special-types-and-traits.md#sized |
| [traits]: traits.md |
| [type aliases]: type-aliases.md |
| [inherent implementations]: implementations.md#inherent-implementations |
| [identifier]: ../identifiers.md |
| [identifier pattern]: ../patterns.md#identifier-patterns |
| [implementations]: implementations.md |
| [type]: ../types.md#type-expressions |
| [constants]: constant-items.md |
| [constant item]: constant-items.md |
| [functions]: functions.md |
| [function item]: ../types/function-item.md |
| [method call operator]: ../expressions/method-call-expr.md |
| [path]: ../paths.md |
| [regular function parameters]: functions.md#attributes-on-function-parameters |
| [generic parameters]: generics.md |
| [where clauses]: generics.md#where-clauses |
| [constant evaluation]: ../const_eval.md |