06-Trait 与生命周期约束
4 分钟阅读
译文 · 基于 The Rust Reference
r[bound]
Trait 与生命周期约束
r[bound.syntax]
Bounds -> Bound ( `+` Bound )* `+`?
Bound -> Lifetime | TraitBound | UseBound
TraitBound ->
( `?` | ForLifetimes )? TypePath
| `(` ( `?` | ForLifetimes )? TypePath `)`
LifetimeBounds -> ( Lifetime `+` )* Lifetime?
Lifetime ->
LIFETIME_OR_LABEL
| `'static`
| `'_`
UseBound -> `use` UseBoundGenericArgs
UseBoundGenericArgs ->
`<` `>`
| `<` ( UseBoundGenericArg `,`)* UseBoundGenericArg `,`? `>`
UseBoundGenericArg ->
Lifetime
| IDENTIFIER
| `Self`
r[bound.intro] Trait 与生命周期约束为泛型项提供了一种限制哪些类型和生命周期可用作其参数的方式。约束可以在 where 子句中施加于任何类型。对于某些常见情形还有更短的形式:
- 写在声明泛型参数之后的约束:
fn f<A: Copy>() {}与fn f<A>() where A: Copy {}相同。 - 在 trait 声明中作为超 trait:
trait Circle : Shape {}等价于trait Circle where Self : Shape {}。 - 在 trait 声明中作为关联类型上的约束:
trait A { type B: Copy; }等价于trait A where Self::B: Copy { type B; }。
r[bound.satisfaction]
使用某项时必须满足该项上的约束。在对泛型项进行类型检查和借用检查时,约束可用于确定某个类型实现了某个 trait。例如,给定 Ty: Trait
- 在泛型函数体内,可以对
Ty值调用Trait中的方法。同样可以使用Trait上的关联常量。 - 可以使用来自
Trait的关联类型。 - 带有
T: Trait约束的泛型函数和类型可以使用Ty作为T。
| |
r[bound.trivial] 不使用该项参数或高阶生命周期的约束在定义该项时检查。此类约束为假是错误。
r[bound.special]
在使用该项时,即使该使用并未提供具体类型,也会对某些泛型类型检查 [Copy]、[Clone] 和 [Sized] 约束。将 Copy 或 Clone 作为可变引用、trait 对象或切片上的约束是错误。将 Sized 作为 trait 对象或切片上的约束是错误。
| |
r[bound.trait-object] Trait 与生命周期约束也用于命名 trait 对象。
r[bound.sized]
?Sized
? 仅用于放宽类型参数或关联类型上隐式的 [Sized] trait 约束。?Sized 不得用作其他类型的约束。
r[bound.lifetime]
生命周期约束
r[bound.lifetime.intro] 生命周期约束可以施加于类型或其他生命周期。
r[bound.lifetime.outlive-lifetime]
约束 'a: 'b 通常读作 'a 长于 'b。'a: 'b 意味着 'a 至少与 'b 一样长,因此只要 &'b () 有效,引用 &'a () 就有效。
| |
r[bound.lifetime.outlive-type]
T: 'a 意味着 T 的所有生命周期参数都长于 'a。例如,若 'a 是不受约束的生命周期参数,则 i32: 'static 和 &'static str: 'a 得到满足,但 Vec<&'a ()>: 'static 不满足。
r[bound.higher-ranked]
高阶 trait 约束
r[bound.higher-ranked.syntax]
ForLifetimes -> `for` GenericParams
r[bound.higher-ranked.intro]
Trait 约束可以在生命周期上是 高阶 的。这些约束指定对 所有 生命周期都成立的约束。例如,诸如 for<'a> &'a T: PartialEq<i32> 的约束会要求类似如下的实现
| |
然后就可以将任意生命周期的 &'a T 与 i32 进行比较。
此处只能使用高阶约束,因为该引用的生命周期短于函数上任何可能的生命周期参数:
| |
r[bound.higher-ranked.trait] 高阶生命周期也可以就写在 trait 之前:唯一的区别是生命周期参数的作用域,它只延伸到紧随其后的 trait 的末尾,而不是整个约束。下面的函数与上一个等价。
| |
r[bound.implied]
隐含约束
r[bound.implied.intro] 类型要合式所要求的生命周期约束有时会被推断出来。
| |
要使类型 &'a T 合式,类型参数 T 必须长于 'a。这会被推断出来,因为函数签名包含类型 &'a T,而该类型仅在 T: 'a 成立时才有效。
r[bound.implied.context]
会对函数的所有参数和输出添加隐含约束。在 requires_t_outlives_a 内部,即使你没有显式指定,也可以假定 T: 'a 成立:
| |
| |
r[bound.implied.trait] 只有生命周期约束会被隐含,trait 约束仍然必须显式添加。因此下面的例子会导致错误:
| |
r[bound.implied.def] 生命周期约束也会为类型定义以及任何类型的 impl 块推断:
| |
r[bound.use]
Use 约束
某些约束列表可以包含 use<..> 约束,以控制哪些泛型参数被 impl Trait 抽象返回类型捕获。更多细节参见精确捕获。