12. Generics¶
12.1. Generic Parameters¶
Syntax
GenericParameterList
::= < (GenericParameter
(,GenericParameter
)* ,?)? >GenericParameter
::=OuterAttributeOrDoc
* (ConstantParameter
|LifetimeParameter
|TypeParameter
)ConstantParameter
::= constName
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:23 As a binding argument in the trait bounds of a type that contains another generic parameter that constrains the implementation, or
12.1:24 The implemented trait, or
12.1:25 The implementing type.
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:30 As a constant argument in the signature and fields of an item.
12.1:31 In the constant initializer of an associated constant.
12.1:32 As a constant argument of an associated type's
InitializationType
.12.1:33 As a constant argument of any type used within a function body.
12.1:34 As a value of any expression within a function body.
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:37 If the type parameter is used in a reference type, then the type parameter has an implicit lifetime bound for the lifetime of the reference type,
12.1:38 If the type parameter is used as a generic argument of an abstract data type, the type parameter inherits all the lifetime bounds from the corresponding generic parameter of the generic argument.
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:40 If the type parameter is used in a reference type, then the type parameter has an implicit lifetime bound for the lifetime of the reference type,
12.1:41 If the type parameter is used as a generic argument of an abstract data type, the type parameter inherits all the lifetime bounds from the corresponding generic parameter of the generic argument.
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
::= whereWhereClausePredicateList
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
|BindingBoundArgument
|ConstantArgument
|LifetimeArgument
|TypeArgument
BindingArgument
::=Identifier
=TypeSpecification
BindingBoundArgument
::=Identifier
:TypeBoundList
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 binding bound argument is a generic argument that further imposes bounds on an associated trait type.
12.3:6 A binding bound argument shall only be used within the confines of a type bound predicate‘s bounds, impl trait type‘s bounds, associated type‘s bounds or trait‘s supertraits.
12.3:7 A constant argument is a generic argument that supplies the value of a constant parameter.
12.3:8 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:9 A lifetime argument is a generic argument that supplies the lifetime of a lifetime parameter.
12.3:10 A type argument is a generic argument that supplies the type of a type parameter.
12.3:11 Generic arguments are subject to generic conformance.
Examples
trait Trait {
type Assoc;
}
12.3:12 The following is a generic function with a binding argument.
fn func<'lifetime, T, const C: usize>() where T: Trait<Assoc = usize> {}
12.3:13
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:7 The generic arguments consist only of conformant binding arguments, conformant constant arguments, conformant lifetime arguments, and conformant type arguments, and
12.4:8 Any remaining generic parameters without corresponding conformant generic arguments are constant parameters with constant parameter initializers, lifetime parameters with either inferred lifetime arguments or elided lifetimes, type parameters with type parameter initializers or inferred type arguments, and
12.4:9 All lifetime arguments come first, followed by constant arguments and type arguments in the order defined by the generic parameters, followed by binding arguments, and
12.4:10 All constant arguments, lifetime arguments, and type arguments have a corresponding generic parameter.
12.4:11 Generic arguments shall be conformant.
12.4:12 The value of a constant parameter is determined as follows:
12.4:13 If the constant parameter has a conformant constant argument, then the value is that of the constant argument.
12.4:14 Otherwise, if the constant parameter has a constant parameter initializer, then the value is that of the constant parameter initializer.
12.4:15 Otherwise this is a static error.