【发布时间】:2015-02-22 00:03:13
【问题描述】:
use std::io::BufReader;
struct Foo {
buf: [u8, ..10]
}
trait Bar<'a> {
fn test(&self, arg: BufReader<'a>) {}
}
impl<'a, T: Bar<'a>> Foo {
fn bar(&'a mut self, t: T) {
t.test(BufReader::new(&self.buf));
let b = &mut self.buf;
}
fn baz(&self, t: T) {
t.test(BufReader::new(&self.buf));
}
}
fn main() {}
上面的代码编译失败,报错:
lifetimes.rs:17:31: 17:40 error: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
lifetimes.rs:17 t.test(BufReader::new(&self.buf));
^~~~~~~~~
lifetimes.rs:16:5: 18:6 help: consider using an explicit lifetime parameter as shown: fn baz(&'a self, t: T)
lifetimes.rs:16 fn baz(&self, t: T) {
lifetimes.rs:17 t.test(BufReader::new(&self.buf));
lifetimes.rs:18 }
error: aborting due to previous error
但是,如果我添加命名的生命周期参数,则在调用test 后,我不能可变借用buf 字段,如fn bar 所示。注释掉fn baz 并尝试编译结果:
lifetimes.rs:13:22: 13:30 error: cannot borrow `self.buf` as mutable because it is also borrowed as immutable
lifetimes.rs:13 let b = &mut self.buf;
^~~~~~~~
lifetimes.rs:12:32: 12:40 note: previous borrow of `self.buf` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `self.buf` until the borrow ends
lifetimes.rs:12 t.test(BufReader::new(&self.buf));
^~~~~~~~
lifetimes.rs:14:6: 14:6 note: previous borrow ends here
lifetimes.rs:11 fn bar(&'a mut self, t: T) {
lifetimes.rs:12 t.test(BufReader::new(&self.buf));
lifetimes.rs:13 let b = &mut self.buf;
lifetimes.rs:14 }
^
error: aborting due to previous error
我对此的理解是,通过在&'a mut self参数中加上命名生命周期'a,只要self引用有效,BufReader所取的引用就有生命周期,一直到最后的功能。这与后行 self.buf 的可变借用相冲突。
但是,我不确定为什么需要 self 上的命名生命周期参数。在我看来,BufReader 引用应该只能在 t.test 方法调用的生命周期内存在。编译器是否在抱怨,因为必须确保 self.buf 借用只与 &self 借用一样长?在方法调用的整个生命周期内仍然只借用它的情况下,我将如何去做呢?
任何帮助解决这个问题和理解这里的语义将不胜感激!
更新
所以我仍在研究这个问题,我发现this test case 和this issue 基本上显示了我正在尝试做的事情。我非常想了解为什么测试用例链接指向的错误是错误。
我可以在问题 rustc 输出中看到试图指出错误是什么,但我无法理解它到底想表达什么。
【问题讨论】:
-
您能否详细解释一下为什么您想要
trait Bar<'a>以及您的目标是什么?就我而言,我认为这是将<'a>放在特征中的每个方法上的简写,但我错了。我目前的理解是,当 implementer 需要参与生命周期时(可能是因为它正在存储具有该生命周期的引用),您可以为 trait 添加生命周期。 -
上面的例子有效,但是当我尝试在类似上面的函数中对
self进行另一个可变引用时,就会出现问题。它错误地说我必须等待前一个可变借用完成,这是在函数的末尾。 -
“当我尝试使用另一个可变引用时” - 如果我理解你,那就是你的问题:你 simply aren't allowed to have two mutable references to the same thing at the same time。这是一个非常不同的问题/问题。
-
是的,这就是编译器失败的原因。如果查看我上面的示例代码,特别是
fn bar及其相关的 rustc 错误(第二个),您会看到正在发生的事情。我的想法是&'a self引用使BufReader在fn bar的长度内保持活动状态,但我想做的只是在调用test的时间段内让那个借用保持活动状态。