Type and Lifetime Parameters
类型参数和生存期参数
generics.md
commit: aeda9bc3f65dfce916b1c1e4f1cab5fcddd8cd40
本章译文最后维护日期:2024-06-15
句法
GenericParams :
<
>
|<
(GenericParam,
)* GenericParam,
?>
GenericParam :
OuterAttribute* ( LifetimeParam | TypeParam | ConstParam )LifetimeParam :
LIFETIME_OR_LABEL (:
LifetimeBounds )?TypeParam :
IDENTIFIER (:
TypeParamBounds? )? (=
Type )?ConstParam:
const
IDENTIFIER:
Type (=
Block | IDENTIFIER | -?LITERAL )?
函数、类型别名、结构体、枚举、联合体、trait 和实现可以通过类型参数、常量参数和生存期参数达到参数化配置的的效果。这些参数在尖括号(<...>
)中列出,通常都是紧跟在程序项名称之后和程序项的定义之前。对于实现,因为它没有名称,那它们就直接位于关键字 impl
之后。
泛型参数的顺序被严格限定为生存期参数必须在前,然后是类型参数和常量参数混合。
同一参数名不能在 GenericParams 列表中声明多次。
下面给出一些带类型参数、常量参数和生存期参数的程序项的示例:
泛型参数在声明它们的程序项定义的范围内有效。它们不是函数体中声明的程序项,这个在程序项声明中有讲述。 更多细节请参阅[范型参数的作用域][generic parameter scopes]。
引用、裸指针、数组、切片、元组和函数指针也有生存期参数或类型参数,但这些程序项不能使用路径句法去引用。
Const generics
常量泛型
常量泛型参数允许程序项在常量值上泛型化。const标识符为常量参数引入了一个名称,并且该程序项的所有实例必须用给定类型的值去实例化该参数。
常量参数类型值允许为:u8
, u16
, u32
, u64
, u128
, usize
, i8
, i16
, i32
, i64
, i128
, isize
, char
和 bool
这些类型。
常量参数可以在任何可以使用常量项的地方使用,但在类型或数组定义中的重复表达式中使用时,必须如下所述是独立的。也就是说,它们可以在以下地方上允许:
- 可以用于类型内部,用它来构成所涉及的程序项签名的一部分。
- 作为常量表达式的一部分,用于定义关联常量项,或作为关联类型的形参。
- 作为程序项里的任何函数体中的任何运行时表达式中的值。
- 作为程序项中任何函数体中使用到的任何类型的参数。
- 作为程序项中任何字段类型的一部分使用。
作为进一步的限制,常量只能作为类型或数组定义中的重复表达式中的独立实参出现。在这种上下文限制下,它们只能以单段路径表达式的形式使用(例如 N
或以块{N}
的形式出现)。也就是说,它们不能与其他表达式结合使用。
路径中的常量实参指定了该程序项使用的常量值。实参必须是常量形参所属类型的常量表达式。常量表达式必须是块表达式(用花括号括起来),除非它是单独路径段(一个标识符)或一个字面量(此字面量可以是以 -
打头的 token)。
注意:这种句法限制是必要的,用以避免在解析类型内部的表达式时可能会导致无限递归(infinite lookahead)。
当存在歧义时,如果泛型参数可以同时被解析为类型或常量参数,那么它总是被解析为类型。在块表达式中放置实参可以强制将其解释为常量实参。
与类型参数和生存期参数不同,常量参数可以声明而不必在被它参数化的程序项中使用,但和泛型实现关联的实现例外:
当处理 trait约束时,在确定是否满足相关约束时,不会考虑常量参数的所有实现的穷尽性。例如,在下面的例子中,即使实现了 bool
类型的所有可能的常量值,仍会报错提示 trait约束不满足。
Where clauses
where子句
句法
WhereClause :
where
( WhereClauseItem,
)* WhereClauseItem ?WhereClauseItem :
LifetimeWhereClauseItem
| TypeBoundWhereClauseItemLifetimeWhereClauseItem :
Lifetime:
LifetimeBoundsTypeBoundWhereClauseItem :
ForLifetimes? Type:
TypeParamBounds?
where子句提供了另一种方法来为类型参数和生存期参数指定约束(bound),甚至可以为非类型参数的类型指定约束。
关键字for
可以用来引入高阶生存期参数。它只允许在 LifetimeParam 参数上使用。
Attributes
属性
泛型生存期参数和泛型类型参数允许属性,但在目前这个位置还没有任何任何有意义的内置属性,但用户可能可以通过自定义的派生属性来设置一些有意义的属性。
下面示例演示如何使用自定义派生属性修改泛型参数的含义。
// 假设 MyFlexibleClone 的派生项将 `my_flexible_clone` 声明为它可以理解的属性。
#[derive(MyFlexibleClone)]
struct Foo<#[my_flexible_clone(unbounded)] H> {
a: *const H
}