14-泛型参数
5 分钟阅读
译文 · 基于 The Rust Reference
原文链接: https://doc.rust-lang.org/reference/items/generics.html
r[items.generics]
泛型参数
r[items.generics.syntax]
GenericParams -> `<` ( GenericParam (`,` GenericParam)* `,`? )? `>`
GenericParam -> OuterAttribute* ( LifetimeParam | TypeParam | ConstParam )
LifetimeParam -> Lifetime ( `:` LifetimeBounds? )?
TypeParam -> IDENTIFIER ( `:` Bounds? )? ( `=` Type )?
ConstParam ->
`const` IDENTIFIER `:` Type
( `=` ( BlockExpression | IDENTIFIER | `-`?LiteralExpression ) )?
r[items.generics.syntax.intro]
函数、类型别名、结构体、枚举、联合体、trait 和实现都可以由类型、常量和生命周期参数化。这些参数列在尖括号(<...>)中,通常紧跟在项名之后、定义之前。对于没有名称的实现,它们直接出现在 impl 之后。
r[items.generics.syntax.decl-order] 泛型参数的顺序被限制为先是生命周期参数,然后类型参数和常量参数可以混排。
r[items.generics.syntax.duplicate-params] 同一参数名不得在 [GenericParams] 列表中声明超过一次。
带有类型、常量和生命周期参数的项的一些例子:
| |
r[items.generics.syntax.scope] 泛型参数在声明它们的项定义内处于作用域中。它们不在函数体内声明的项的作用域中,如项声明所述。更多细节参见泛型参数作用域。
r[items.generics.builtin-generic-types] 引用、原始指针、数组、切片、元组和函数指针也具有生命周期或类型参数,但并不用路径语法来指称。
r[items.generics.invalid-lifetimes]
'_ 和 'static 不是合法的生命周期参数名。
r[items.generics.const]
常量泛型
r[items.generics.const.intro] 常量泛型参数允许项在常量值上是泛型的。
r[items.generics.const.namespace] 该 const 标识符在值命名空间中为该常量参数引入一个名称,并且该项的所有实例都必须用给定类型的值来实例化。
r[items.generics.const.allowed-types]
常量参数唯一允许的类型是 u8、u16、u32、u64、u128、usize、i8、i16、i32、i64、i128、isize、char 和 bool。
r[items.generics.const.use] 常量参数可以在常量项可以使用的任何地方使用,例外是当用在类型或数组重复表达式中时,它必须是独立的(如下所述)。也就是说,它们允许出现在下列位置:
- 作为应用于构成该项签名一部分的任何类型的常量。
- 作为用于定义关联常量的常量表达式的一部分,或作为关联类型的参数。
- 作为该项中任何函数体内任何运行时表达式中的值。
- 作为该项中任何函数体内所用任何类型的参数。
- 作为该项中任何字段的类型的一部分。
| |
| |
r[items.generics.const.standalone]
进一步的限制是,常量参数在类型或数组重复表达式中只能作为独立实参出现。在那些上下文中,它们只能用作单段路径表达式,可能位于块内(例如 N 或 {N})。也就是说,它们不能与其他表达式组合。
| |
r[items.generics.const.argument] 路径中的常量实参指定该项要使用的常量值。
r[items.generics.const.argument.const-expr]
该实参必须要么是推断常量,要么是赋予该常量参数的类型的常量表达式。除非它是单路径段(一个 [IDENTIFIER])或字面量(可能带有前导 - token),否则该常量表达式必须是块表达式(用花括号包围)。
注意 这一语法限制是必要的,以避免在解析类型内部的表达式时需要无限向前看。
| |
注意 在泛型实参列表中,推断常量被解析为[推断类型][InferredType],但随后在语义上被当作一种单独的常量泛型实参。
r[items.generics.const.inferred]
在期望常量实参的地方,可以使用 _(可选地被任意数量的匹配圆括号包围),称为推断常量([路径规则][paths.expr.complex-const-params]、[数组表达式规则][expr.array.length-restriction])。这会请求编译器在可能的情况下根据周围信息推断该常量实参。
| |
注意 推断常量在语义上不是[表达式][Expression],因此不被花括号内接受。
1 2 3fn f<const N: usize>() -> [u8; N] { [0; _] } let _: [_; 1] = f::<{ _ }>(); // ^ 错误:这里不允许 `_`
r[items.generics.const.inferred.constraint] 推断常量不能用在项签名中。
| |
r[items.generics.const.type-ambiguity] 当泛型实参既可以解析为类型实参也可以解析为常量实参而产生歧义时,它总是被解析为类型。把该实参放在块表达式中可以强制将其解释为常量实参。
| |
r[items.generics.const.variance] 与类型参数和生命周期参数不同,常量参数可以声明而不在参数化项内部使用,泛型实现中所述的实现除外:
| |
r[items.generics.const.exhaustiveness]
在解析 trait 约束义务时,确定该约束是否满足时不考虑常量参数的所有实现是否穷尽。例如,在下列代码中,即使 bool 类型的所有可能常量值都已实现,trait 约束仍未满足,因而仍是错误:
| |
r[items.generics.where]
Where 子句
r[items.generics.where.syntax]
WhereClause -> `where` ( WhereClauseItem `,` )* WhereClauseItem?
WhereClauseItem ->
LifetimeWhereClauseItem
| TypeBoundWhereClauseItem
LifetimeWhereClauseItem -> Lifetime `:` LifetimeBounds?
TypeBoundWhereClauseItem -> ForLifetimes? Type `:` Bounds?
r[items.generics.where.intro] Where 子句提供另一种在类型和生命周期参数上指定约束的方式,以及在并非类型参数的类型上指定约束的方式。
r[items.generics.where.higher-ranked-lifetimes]
for 关键字可用于引入高阶生命周期。它只允许 [LifetimeParam] 参数。
| |
r[items.generics.attributes]
属性
泛型生命周期参数和类型参数允许带属性。没有内置属性会在此位置做任何事,不过自定义 derive 属性可能赋予其含义。
此例展示使用自定义 derive 属性来修改泛型参数的含义。
| |