12. Generics

12.1. Generic Parameters

Syntax

GenericParameterList ::=
    < (GenericParameter (, GenericParameter)* ,?)? >

GenericParameter ::=
    OuterAttributeOrDoc* (
        ConstantParameter
      | LifetimeParameter
      | TypeParameter
    )

ConstantParameter ::=
   const Name TypeAscription (= ConstantParameterInitializer)?

ConstantParameterInitializer ::=
    BlockExpression
  | Identifier
  | -? LiteralExpression

LifetimeParameter ::=
    Lifetime (: LifetimeIndicationList)?

TypeParameter ::=
    Name (: TypeBoundList?)? (= TypeParameterInitializer)?

TypeParameterInitializer ::=
    TypeSpecification

Legality Rules

12.1:1 A generic parameter is a placeholder for a constant, a lifetime, or a type, whose constant, lifetime, or type is supplied statically by a generic argument.

12.1:2 All LifetimeParameters in a GenericParameterList shall precede all ConstantParameters and TypeParameters.

12.1:3 A generic enum is an enum with generic parameters.

12.1:4 A generic function is a function with generic parameters.

12.1:5 A generic implementation is an implementation with generic parameters.

12.1:6 A generic struct is a struct with generic parameters.

12.1:7 A generic trait is a trait with generic parameters.

12.1:8 A generic type alias is a type alias with generic parameters.

12.1:9 A generic union is a union with generic parameters.

12.1:10 A constant parameter is a generic parameter for a constant.

12.1:11 A constant parameter initializer is a construct that provides the default value of its related constant parameter.

12.1:12 A constant parameter initializer shall be a constant expression.

12.1:13 It is a static error to use a generic parameter in the discriminant initializer of an enum variant.

12.1:14 A lifetime parameter is a generic parameter for a lifetime.

12.1:15 A lifetime parameter shall not be used within a constant context, except for the 'static lifetime.

12.1:16 A type parameter is a generic parameter for a type.

12.1:17 A type parameter initializer is a construct that provides the default value of its related type parameter.

12.1:18 The type of the type parameter initializer of a type parameter shall satisfy the trait bounds of the type parameter.

12.1:19 A generic enum shall use all of its type parameters and lifetime parameters at least once in at least one of its enum variants.

12.1:20 A generic struct shall use all of its type parameters and lifetime parameters at least once in at least one of its fields.

12.1:21 A generic union shall use all of its type parameters and lifetime parameters at least once in at least one of its fields.

12.1:22 A generic parameter is said to constrain an implementation if the generic parameter appears at least once in one of the following:

12.1:26 It is a static error if a constant parameter or a type parameter of an implementation does not constrain the implementation.

12.1:27 It is a static error if a lifetime parameter of an implementation is used in an associated type without constraining the implementation.

12.1:28 The type of a constant parameter shall be a scalar type.

12.1:29 A constant parameter shall be used in the following contexts:

12.1:35 A type parameter has an implicit core::marker::Sized bound, unless an opt-out trait bound for the core::marker::Sized trait is present.

12.1:36 A type parameter of an abstract data type has implicit lifetime bounds depending on its usage in the fields of the abstract data type as follows:

12.1:39 A type parameter of a function has implicit lifetime bounds depending on its usages in the function parameters and return type as follows:

12.1:42 A generic parameter with a bound of the form

<X: Bound>

12.1:43 is equivalent to the generic parameter without the bound and a where clause of the following form:

where X: Bound

Examples

struct Array<T, const N: usize>([T; N])

fn generic_function<'a, T>() {}

struct Reference<'a, T: 'a> {
    the_reference: &'a T
}

12.2. Where Clauses

Syntax

WhereClause ::=
    where WhereClausePredicateList

WhereClausePredicateList ::=
    WhereClausePredicate (, WhereClausePredicate)* ,?

WhereClausePredicate ::=
    LifetimeBoundPredicate
  | TypeBoundPredicate

LifetimeBoundPredicate ::=
   LifetimeIndication : LifetimeIndicationList?

TypeBoundPredicate ::=
   ForGenericParameterList? TypeSpecification : TypeBoundList?

Legality Rules

12.2:1 A where clause is a construct that specifies bounds on lifetime parameters and types that have to hold for the construct subject to the where clause to be valid.

12.2:2 A where clause predicate is either a lifetime bound predicate or a type bound predicate.

12.2:3 A lifetime bound predicate is a construct that specifies lifetime bounds on a lifetime parameter.

12.2:4 A type bound predicate is a construct that specifies lifetime bounds and trait bounds on a type.

12.2:5 A construct is valid when all of its where clause predicates hold true for the supplied generic arguments.

12.2:6 A trivial predicate is a where clause predicate that does not use the generic parameters or higher-ranked trait bounds of the related construct.

12.2:7 It is a static error to create a trivial predicate that does not hold.

Examples

struct Clause<T> where T: Iterator {
    field: T
}

12.3. Generic Arguments

Syntax

GenericArgumentList ::=
    < ( GenericArgument (, GenericArgument)* ,? )? >

GenericArgument ::=
    BindingArgument
  | ConstantArgument
  | LifetimeArgument
  | TypeArgument

BindingArgument ::=
    Identifier = TypeSpecification

ConstantArgument ::=
    BlockExpression
  | -? LiteralExpression
  | Identifier

LifetimeArgument ::=
    LifetimeIndication

TypeArgument ::=
    TypeSpecification

Legality Rules

12.3:1 A generic argument supplies a static input for an associated trait type or a generic parameter.

12.3:2 A BindingArgument shall follow ConstantArguments, LifetimeArguments, and TypeArguments in a GenericArgumentList.

12.3:3 A LifetimeArgument shall precede BindingArguments, ConstantArguments, and TypeArguments in a GenericArgumentList.

12.3:4 A binding argument is a generic argument that supplies the type of an associated trait type.

12.3:5 A constant argument is a generic argument that supplies the value of a constant parameter.

12.3:6 A constant argument may only appear as a single segment path expression, optionally encapsulated in a block expression, within an array repetition constructor or a type.

12.3:7 A lifetime argument is a generic argument that supplies the lifetime of a lifetime parameter.

12.3:8 A type argument is a generic argument that supplies the type of a type parameter.

12.3:9 Generic arguments are subject to generic conformance.

Examples

trait Trait {
    type Assoc;
}

12.3:10 The following is a generic function with a binding argument.

fn func<'lifetime, T, const C: usize>() where T: Trait<Assoc = usize> {}

12.3:11 The following are generic arguments for func.

func::<'static, u32, 0>();

12.4. Generic Conformance

Legality Rules

12.4:1 Generic conformance measures the compatibility between a set of generic parameters and a set of generic arguments.

12.4:2 A binding argument is conformant with an associated type when the supplied type of the binding argument fulfills the required trait bounds of the associated type.

12.4:3 A constant argument is conformant with a constant parameter when the types of the constant argument and the constant parameter are unifiable.

12.4:4 A lifetime argument is conformant with a lifetime parameter when it outlives the lifetime specified by the lifetime parameter.

12.4:5 A type argument is conformant with a type parameter when the type of the type argument fulfills the required trait bounds of the type parameter.

12.4:6 Generic arguments are conformant with generic parameters when

12.4:11 Generic arguments shall be conformant.

12.4:12 The value of a constant parameter is determined as follows: