Traits
Syntax
Trait :
unsafe
?trait
IDENTIFIER GenericParams? (:
TypeParamBounds? )? WhereClause?{
InnerAttribute*
AssociatedItem*
}
A trait describes an abstract interface that types can implement. This interface consists of associated items, which come in three varieties:
The trait declaration defines a trait in the type namespace of the module or block where it is located.
Associated items are defined as members of the trait within their respective namespaces. Associated types are defined in the type namespace. Associated constants and associated functions are defined in the value namespace.
All traits define an implicit type parameter Self
that refers to “the type
that is implementing this interface”. Traits may also contain additional type
parameters. These type parameters, including Self
, may be constrained by
other traits and so forth as usual.
Traits are implemented for specific types through separate implementations.
Trait functions may omit the function body by replacing it with a semicolon. This indicates that the implementation must define the function. If the trait function defines a body, this definition acts as a default for any implementation which does not override it. Similarly, associated constants may omit the equals sign and expression to indicate implementations must define the constant value. Associated types must never define the type, the type may only be specified in an implementation.
Trait functions are not allowed to be const
.
Trait bounds
Generic items may use traits as bounds on their type parameters.
Generic traits
Type parameters can be specified for a trait to make it generic. These appear after the trait name, using the same syntax used in generic functions.
Dyn compatibility
A dyn-compatible trait can be the base trait of a trait object. A trait is dyn compatible if it has the following qualities:
- All supertraits must also be dyn compatible.
Sized
must not be a supertrait. In other words, it must not requireSelf: Sized
.
- It must not have any associated constants.
- It must not have any associated types with generics.
- All associated functions must either be dispatchable from a trait object or be explicitly non-dispatchable:
- Dispatchable functions must:
- Not have any type parameters (although lifetime parameters are allowed).
- Be a method that does not use
Self
except in the type of the receiver. - Have a receiver with one of the following types:
- Not have an opaque return type; that is,
- Not be an
async fn
(which has a hiddenFuture
type). - Not have a return position
impl Trait
type (fn example(&self) -> impl Trait
).
- Not be an
- Not have a
where Self: Sized
bound (receiver type ofSelf
(i.e.self
) implies this).
- Explicitly non-dispatchable functions require:
- Have a
where Self: Sized
bound (receiver type ofSelf
(i.e.self
) implies this).
- Have a
- Dispatchable functions must:
- The
AsyncFn
,AsyncFnMut
, andAsyncFnOnce
traits are not dyn-compatible.
Note: This concept was formerly known as object safety.
Supertraits
Supertraits are traits that are required to be implemented for a type to implement a specific trait. Furthermore, anywhere a generic or trait object is bounded by a trait, it has access to the associated items of its supertraits.
Supertraits are declared by trait bounds on the Self
type of a trait and
transitively the supertraits of the traits declared in those trait bounds. It is
an error for a trait to be its own supertrait.
The trait with a supertrait is called a subtrait of its supertrait.
The following is an example of declaring Shape
to be a supertrait of Circle
.
And the following is the same example, except using where clauses.
This next example gives radius
a default implementation using the area
function from Shape
.
This next example calls a supertrait method on a generic parameter.
Similarly, here is an example of calling supertrait methods on trait objects.
Unsafe traits
Traits items that begin with the unsafe
keyword indicate that implementing the
trait may be unsafe. It is safe to use a correctly implemented unsafe trait.
The trait implementation must also begin with the unsafe
keyword.
Sync
and Send
are examples of unsafe traits.
Parameter patterns
Function or method declarations without a body only allow IDENTIFIER or
_
wild card patterns. mut
IDENTIFIER is currently
allowed, but it is deprecated and will become a hard error in the future.
In the 2015 edition, the pattern for a trait function or method parameter is optional:
The kinds of patterns for parameters is limited to one of the following:
- IDENTIFIER
mut
IDENTIFIER_
&
IDENTIFIER&&
IDENTIFIER
Beginning in the 2018 edition, function or method parameter patterns are no longer optional. Also, all irrefutable patterns are allowed as long as there is a body. Without a body, the limitations listed above are still in effect.
Item visibility
Trait items syntactically allow a Visibility annotation, but this is
rejected when the trait is validated. This allows items to be parsed with a
unified syntax across different contexts where they are used. As an example,
an empty vis
macro fragment specifier can be used for trait items, where the
macro rule may be used in other situations where visibility is allowed.
macro_rules! create_method {
($vis:vis $name:ident) => {
$vis fn $name(&self) {}
};
}
trait T1 {
// Empty `vis` is allowed.
create_method! { method_of_t1 }
}
struct S;
impl S {
// Visibility is allowed here.
create_method! { pub method_of_s }
}
impl T1 for S {}
fn main() {
let s = S;
s.method_of_t1();
s.method_of_s();
}