blob: bbecfb676395de46cab90306fcb56c439b18ac2d [file] [log] [blame] [view] [edit]
r[items.associated]
# Associated Items
r[items.associated.syntax]
> **<sup>Syntax</sup>**\
> _AssociatedItem_ :\
> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup> (\
> &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; [_MacroInvocationSemi_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | ( [_Visibility_]<sup>?</sup> ( [_TypeAlias_] | [_ConstantItem_] | [_Function_] ) )\
> &nbsp;&nbsp; )
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 &mdash; 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