如果在 Rust < 1.31 中未使用生命周期,为什么在引用类型上实现特征时需要生命周期?
Why is a lifetime needed when implementing a trait on a reference type if the lifetime is otherwise unused, in Rust < 1.31?
我正在使用早于 1.31 的 Rust 实现引用类型的特征。 当我告诉 Rust 我正在为哪种引用类型实现特征时,为什么 Rust 想要一个明确的生命周期?
这是一个简单的例子。一个结构 Inches
,一个实现
Add
&Inches
的特征,以及使用该实现的函数。
初始示例
use std::ops::Add;
struct Inches(i32);
// this would work: impl<'b> Add for &'b Inches
impl Add for &Inches {
type Output = Inches;
fn add(self, other: &Inches) -> Inches {
let &Inches(x) = self;
let &Inches(y) = other;
Inches(x + y)
}
}
// lifetime specifier needed here because otherwise
// `total = hilt + blade` doesn't know whether `total` should live
// as long as `hilt`, or as long as `blade`.
fn add_inches<'a>(hilt: &'a Inches, blade: &'a Inches) {
let total = hilt + blade;
let Inches(t) = total;
println!("length {}", t);
}
fn main() {
let hilt = Inches(10);
let blade = Inches(20);
add_inches(&hilt, &blade);
}
编译失败,出现以下错误:
error: missing lifetime specifier [E0106]
impl Add for &Inches {
^~~~~~~
我添加了缺少的生命周期说明符(仍然无法编译)
// was: impl Add for &Inches {
impl Add for &'b Inches {
...
}
编译错误:
error: use of undeclared lifetime name `'b` [E0261]
impl Add for &'b Inches {
我在 impl
上声明生命周期(现在可以编译)
// was: impl Add for &'b Inches {
impl<'b> Add for &'b Inches {
...
}
这最终编译正确。
我的问题
Why is &Inches
in impl Add for &Inches
considered to lack a
lifetime specifier? What problem is solved by telling the compiler
that this Add method is for &Inches
with some unspecified non-static
lifetime 'b
, and then never referring to that lifetime anywhere
else?
Rust 1.31 及更高版本
原因很简单:直到 Rust 1.31 才实现。
现在,初始示例编译,您可以编写 impl Add for &Inches
而不是 impl<'b> Add for &'b Inches
。这是因为 1.31.0 stabilized new lifetime elision rules.
Rust 1.31 之前
如果您查看 RFC for lifetime elision,您会发现应该涵盖您的用例:
impl Reader for BufReader { ... } // elided
impl<'a> Reader for BufReader<'a> { .. } // expanded
不过,我在游乐场试了一下,it doesn't work. The reason is that it's not implemented yet。
我为这种情况搜索了 Rust 的源代码,但出乎意料的是它们很少。我只能在本机类型上找到 Add
的这一系列实现:
impl Add<u8> for u8
impl<'a> Add<u8> for &'a u8
impl<'a> Add<&'a u8> for u8
impl<'a, 'b> Add<&'a u8> for &'b u8
如您所见,这里的生命周期都是明确的;没有省略发生。
对于您的具体问题,我相信您必须坚持明确的生命周期,直到 RFC 实现完成!
我正在使用早于 1.31 的 Rust 实现引用类型的特征。 当我告诉 Rust 我正在为哪种引用类型实现特征时,为什么 Rust 想要一个明确的生命周期?
这是一个简单的例子。一个结构 Inches
,一个实现
Add
&Inches
的特征,以及使用该实现的函数。
初始示例
use std::ops::Add;
struct Inches(i32);
// this would work: impl<'b> Add for &'b Inches
impl Add for &Inches {
type Output = Inches;
fn add(self, other: &Inches) -> Inches {
let &Inches(x) = self;
let &Inches(y) = other;
Inches(x + y)
}
}
// lifetime specifier needed here because otherwise
// `total = hilt + blade` doesn't know whether `total` should live
// as long as `hilt`, or as long as `blade`.
fn add_inches<'a>(hilt: &'a Inches, blade: &'a Inches) {
let total = hilt + blade;
let Inches(t) = total;
println!("length {}", t);
}
fn main() {
let hilt = Inches(10);
let blade = Inches(20);
add_inches(&hilt, &blade);
}
编译失败,出现以下错误:
error: missing lifetime specifier [E0106]
impl Add for &Inches {
^~~~~~~
我添加了缺少的生命周期说明符(仍然无法编译)
// was: impl Add for &Inches {
impl Add for &'b Inches {
...
}
编译错误:
error: use of undeclared lifetime name `'b` [E0261]
impl Add for &'b Inches {
我在 impl
上声明生命周期(现在可以编译)
// was: impl Add for &'b Inches {
impl<'b> Add for &'b Inches {
...
}
这最终编译正确。
我的问题
Why is
&Inches
inimpl Add for &Inches
considered to lack a lifetime specifier? What problem is solved by telling the compiler that this Add method is for&Inches
with some unspecified non-static lifetime'b
, and then never referring to that lifetime anywhere else?
Rust 1.31 及更高版本
原因很简单:直到 Rust 1.31 才实现。
现在,初始示例编译,您可以编写 impl Add for &Inches
而不是 impl<'b> Add for &'b Inches
。这是因为 1.31.0 stabilized new lifetime elision rules.
Rust 1.31 之前
如果您查看 RFC for lifetime elision,您会发现应该涵盖您的用例:
impl Reader for BufReader { ... } // elided
impl<'a> Reader for BufReader<'a> { .. } // expanded
不过,我在游乐场试了一下,it doesn't work. The reason is that it's not implemented yet。
我为这种情况搜索了 Rust 的源代码,但出乎意料的是它们很少。我只能在本机类型上找到 Add
的这一系列实现:
impl Add<u8> for u8
impl<'a> Add<u8> for &'a u8
impl<'a> Add<&'a u8> for u8
impl<'a, 'b> Add<&'a u8> for &'b u8
如您所见,这里的生命周期都是明确的;没有省略发生。
对于您的具体问题,我相信您必须坚持明确的生命周期,直到 RFC 实现完成!