For now, this reference is a best-effort document. We strive for validity and completeness, but are not yet there. In the future, the docs and lang teams will work together to figure out how best to do this. Until then, this is a best-effort attempt. If you find something wrong or missing, file an issue or send in a pull request.

Type and Lifetime Parameters

Syntax
Generics :
   < GenericParams >

GenericParams :
      LifetimeParams
   | ( LifetimeParam , )\* TypeParams

LifetimeParams :
   ( LifetimeParam , )\* LifetimeParam?

LifetimeParam :
   OuterAttribute? LIFETIME_OR_LABEL ( : LifetimeBounds )?

TypeParams:
   ( TypeParam , )\* TypeParam?

TypeParam :
   OuterAttribute? IDENTIFIER ( : TypeParamBounds? )? ( = Type )?

Functions, type aliases, structs, enumerations, unions, traits, and implementations may be parameterized by types and lifetimes. These parameters are listed in angle brackets (<...>), usually immediately after the name of the item and before its definition. For implementations, which don't have a name, they come directly after impl. Lifetime parameters must be declared before type parameters. Some examples of items with type and lifetime parameters:


# #![allow(unused_variables)]
#fn main() {
fn foo<'a, T>() {}
trait A<U> {}
struct Ref<'a, T> where T: 'a { r: &'a T }
#}

References, raw pointers, arrays, slices, tuples, and function pointers have lifetime or type parameters as well, but are not referred to with path syntax.

Where clauses

Syntax
WhereClause :
   where ( WhereClauseItem , )\* WhereClauseItem ?

WhereClauseItem :
      LifetimeWhereClauseItem
   | TypeBoundWhereClauseItem

LifetimeWhereClauseItem :
   Lifetime : LifetimeBounds

TypeBoundWhereClauseItem :
   ForLifetimes? Type : TypeParamBounds?

ForLifetimes :
   for < LifetimeParams >

Where clauses provide another way to specify bounds on type and lifetime parameters as well as a way to specify bounds on types that aren't type parameters.

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 defining the item. It is an error to have Copy or Cloneas a bound on a mutable reference, trait object or slice or Sized as a bound on a trait object or slice.

struct A<T>
where
    T: Iterator,            // Could use A<T: Iterator> instead
    T::Item: Copy,
    String: PartialEq<T>,
    i32: Default,           // Allowed, but not useful
    i32: Iterator,          // Error: the trait bound is not satisfied
    [T]: Copy,              // Error: the trait bound is not satisfied
{
    f: T,
}

Attributes

Generic lifetime and type parameters allow attributes on them. There are no built-in attributes that do anything in this position, although custom derive attributes may give meaning to it.

This example shows using a custom derive attribute to modify the meaning of a generic parameter.

// Assume that the derive for MyFlexibleClone declared `my_flexible_clone` as
// an attribute it understands.
#[derive(MyFlexibleClone)] struct Foo<#[my_flexible_clone(unbounded)] H> {
    a: *const H
}