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
}