Trait and lifetime bounds
Syntax
TypeParamBounds :
TypeParamBound (+
TypeParamBound )*+
?TypeParamBound :
Lifetime | TraitBound | UseBoundTraitBound :
(?
| ForLifetimes )? TypePath
|(
(?
| ForLifetimes )? TypePath)
LifetimeBounds :
( Lifetime+
)* Lifetime?Lifetime :
LIFETIME_OR_LABEL
|'static
|'_
UseBound :
use
UseBoundGenericArgsUseBoundGenericArgs :
<
>
|<
( UseBoundGenericArg,
)*
UseBoundGenericArg,
?
>
UseBoundGenericArg :
Lifetime
| IDENTIFIER
|Self
Trait and lifetime bounds provide a way for generic items to restrict which types and lifetimes are used as their parameters. Bounds can be provided on any type in a where clause. There are also shorter forms for certain common cases:
- Bounds written after declaring a generic parameter:
fn f<A: Copy>() {}
is the same asfn f<A>() where A: Copy {}
. - In trait declarations as supertraits:
trait Circle : Shape {}
is equivalent totrait Circle where Self : Shape {}
. - In trait declarations as bounds on associated types:
trait A { type B: Copy; }
is equivalent totrait A where Self::B: Copy { type B; }
.
Bounds on an item must be satisfied when using the item. When type checking and
borrow checking a generic item, the bounds can be used to determine that a
trait is implemented for a type. For example, given Ty: Trait
- In the body of a generic function, methods from
Trait
can be called onTy
values. Likewise associated constants on theTrait
can be used. - Associated types from
Trait
can be used. - Generic functions and types with a
T: Trait
bounds can be used withTy
being used forT
.
Bounds that don’t use the item’s parameters or higher-ranked lifetimes are checked when the item is defined. It is an error for such a bound to be false.
Copy
, Clone
, and Sized
bounds are also checked for certain generic types when using the item, even if the use does not provide a concrete type.
It is an error to have Copy
or Clone
as a bound on a mutable reference, trait object, or slice.
It is an error to have Sized
as a bound on a trait object or slice.
Trait and lifetime bounds are also used to name trait objects.
?Sized
?
is only used to relax the implicit Sized
trait bound for type parameters or associated types.
?Sized
may not be used as a bound for other types.
Lifetime bounds
Lifetime bounds can be applied to types or to other lifetimes.
The bound 'a: 'b
is usually read as 'a
outlives 'b
.
'a: 'b
means that 'a
lasts at least as long as 'b
, so a reference &'a ()
is valid whenever &'b ()
is valid.
T: 'a
means that all lifetime parameters of T
outlive 'a
.
For example, if 'a
is an unconstrained lifetime parameter, then i32: 'static
and &'static str: 'a
are satisfied, but Vec<&'a ()>: 'static
is not.
Higher-ranked trait bounds
ForLifetimes :
for
GenericParams
Trait bounds may be higher ranked over lifetimes. These bounds specify a bound
that is true for all lifetimes. For example, a bound such as for<'a> &'a T: PartialEq<i32>
would require an implementation like
and could then be used to compare a &'a T
with any lifetime to an i32
.
Only a higher-ranked bound can be used here, because the lifetime of the reference is shorter than any possible lifetime parameter on the function:
Higher-ranked lifetimes may also be specified just before the trait: the only difference is the scope of the lifetime parameter, which extends only to the end of the following trait instead of the whole bound. This function is equivalent to the last one.
Implied bounds
Lifetime bounds required for types to be well-formed are sometimes inferred.
The type parameter T
is required to outlive 'a
for the type &'a T
to be well-formed.
This is inferred because the function signature contains the type &'a T
which is
only valid if T: 'a
holds.
Implied bounds are added for all parameters and outputs of functions. Inside of requires_t_outlives_a
you can assume T: 'a
to hold even if you don’t explicitly specify this:
Only lifetime bounds are implied, trait bounds still have to be explicitly added. The following example therefore causes an error:
Lifetime bounds are also inferred for type definitions and impl blocks for any type:
Use bounds
Certain bounds lists may include a use<..>
bound to control which generic parameters are captured by the impl Trait
abstract return type. See precise capturing for more details.