| r[items.associated] | |
| # Associated items | |
| r[items.associated.syntax] | |
| ```grammar,items | |
| AssociatedItem -> | |
| OuterAttribute* ( | |
| MacroInvocationSemi | |
| | ( Visibility? ( 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 is logically 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]. | |
| > [!NOTE] | |
| > A common example is an associated function named `new` that returns a value of the type with which it is associated. | |
| ```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.edition2018] | |
| > [!EDITION-2018] | |
| > 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); | |
| } | |
| ``` | |
| [`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 |