泛型参数
语法
GenericParams :
<
>
|<
(GenericParam,
)* GenericParam,
?>
GenericParam :
OuterAttribute* ( LifetimeParam | TypeParam | ConstParam )LifetimeParam :
Lifetime (:
LifetimeBounds )?TypeParam :
IDENTIFIER (:
TypeParamBounds? )? (=
Type )?ConstParam:
const
IDENTIFIER:
Type (=
Block | IDENTIFIER | -?LITERAL )?
函数、类型别名、结构体、枚举、联合体、trait 和 实现 可以通过类型、常量和生命周期进行参数化。这些参数列在尖括号 (<...>
) 中,通常紧跟在项的名称之后,并在其定义之前。对于没有名称的实现,它们直接出现在 impl
之后。
泛型参数的顺序被限制为先是生命周期参数,然后是类型和常量参数混合排列。
在 GenericParams 列表中,同一个参数名称不能声明多次。
带有类型、常量和生命周期参数的项的一些示例
泛型参数在其声明的项定义范围内有效。它们在函数体中声明的项的范围内无效,如 项声明 中所述。有关更多详细信息,请参阅 泛型参数作用域。
引用、裸指针、数组、切片、元组 和 函数指针 也具有生命周期或类型参数,但不是用路径语法引用的。
'_
和 '_static
不是有效的生命周期参数。
常量泛型
常量泛型参数 允许项在常量值上是泛型的。
const
标识符在 值命名空间 中为常量参数引入一个名称,并且项的所有实例都必须使用给定类型的值实例化。
常量参数唯一允许的类型是 u8
、u16
、u32
、u64
、u128
、usize
、i8
、i16
、i32
、i64
、i128
、isize
、char
和 bool
。
常量参数可以用于任何可以使用 常量项 的地方,但当在 类型 或 数组重复表达式 中使用时,它必须是独立的(如下所述)。也就是说,它们允许在以下位置使用:
- 作为应用于构成问题项签名一部分的任何类型的常量。
- 作为用于定义 关联常量 的常量表达式的一部分,或作为 关联类型 的参数。
- 作为项中任何函数体中任何运行时表达式中的值。
- 作为项中任何函数体中使用的任何类型的参数。
- 作为项中任何字段类型的一部分。
作为进一步的限制,常量参数可能仅作为 类型 或 数组重复表达式 内的独立参数出现。在这些上下文中,它们可能仅用作单个段 路径表达式,可能在 代码块 内(例如 N
或 {N}
)。也就是说,它们不能与其他表达式组合使用。
路径 中的常量参数指定要用于该项的常量值。
参数必须是分配给常量参数类型的 常量表达式。常量表达式必须是 代码块表达式(用大括号括起来),除非它是单个路径段(IDENTIFIER)或 字面量(可能带有前导 -
标记)。
注意:此语法限制是必要的,以避免在解析类型内部的表达式时需要无限前瞻。
当泛型参数可以解析为类型参数或常量参数时存在歧义时,它始终解析为类型。将参数放在代码块表达式中可以强制将其解释为常量参数。
与类型和生命周期参数不同,常量参数可以声明为不用于参数化项内部,但 泛型实现 中描述的实现除外。
在解析 trait bound 义务时,在确定 bound 是否满足时,不考虑常量参数的所有实现的穷尽性。例如,在以下示例中,即使实现了 bool
类型的所有可能的常量值,trait bound 仍然不满足,因此仍然会报错
Where 子句
语法
WhereClause :
where
( WhereClauseItem,
)* WhereClauseItem ?WhereClauseItem :
LifetimeWhereClauseItem
| TypeBoundWhereClauseItemLifetimeWhereClauseItem :
Lifetime:
LifetimeBoundsTypeBoundWhereClauseItem :
ForLifetimes? Type:
TypeParamBounds?
Where 子句 提供了另一种指定类型和生命周期参数的 bound 的方法,以及指定非类型参数类型的 bound 的方法。
for
关键字可用于引入 高阶生命周期。它只允许 LifetimeParam 参数。
属性
泛型生命周期和类型参数允许在其上添加 属性。在此位置没有任何内置属性执行任何操作,尽管自定义派生属性可能会赋予其含义。
此示例显示了使用自定义派生属性来修改泛型参数的含义。
// 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
}