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
添加到 &'a mut self
参数,只要 self
引用有效, BufReader
所采用的引用就具有生命周期,直到函数结束 . 这与之后在线上的 self.buf
的可变借用相冲突 .
但是,我不确定为什么我需要 self
上的命名生命周期参数 . 在我看来, BufReader
引用应该只能在 t.test
方法调用的生命周期中存在 . 编译器是否在抱怨,因为必须确保 self.buf
借用只要 &self
借用?我怎么会这样做而仍然只是在方法调用的生命周期中借用它?
任何有关修复此问题和了解更多有关语义的帮助将非常感谢!
更新
所以我仍在调查这个问题,我发现this test case和this issue基本上显示了我想要做的事情 . 我非常想了解为什么测试用例链接指向的错误是错误的 .
我可以在问题中看到rustc输出试图指出错误是什么,但我无法理解究竟是什么意思 .
2 回答
Edit
我要在这里复制我的评论:
我原本以为在trait / struct / enum中添加一个生命周期或泛型参数是将它放在特征中的每个方法上的简写,但我是 wrong . 我目前的理解是,当该项需要参与生命周期时,您可以为trait / struct / enum添加生命周期,这可能是因为它存储了具有该生命周期的引用 .
在这里,我们为
Keeper
添加了一个生命周期,因为它可能存储它给出的引用 . 当我们调用add_one
时,借用检查器必须假设引用存储良好,所以一旦我们调用该方法,我们就不能再改变该值 .另一方面,
add_two
创建了一个只能应用于该函数调用的新生命周期,因此借用检查器知道一旦函数返回,它就是One True Owner .结果是,如果你需要存储一个引用,那么在这个级别你无能为力 . Rust无法确保您的安全,这是需要认真对待的事情 .
但是,我打赌你不需要存储引用 . 将
<'a, T: Bar<'a>>
从impl
移动到fn
,你会很高兴 .换句话说:如果你的特质或结构没有 require ,我打赌你永远不应该
impl<A>
. 将泛型放在方法上 .Original
这编译,但我不是100%确定它符合你的意图:
I fell into this trap myself,所以我会粘贴我被告知的内容:
也许其他评论/答案可以帮助进一步详细解释 .
删除所有显式生命周期也有效 . 我发现只有当我确定需要它时才会添加生命周期(即,指定两个生命周期应该在给定点相交,编译器无法知道) .
我不确定你到底想要什么,但是这个编译(在每晚生成0.13.0秒(cc19e3380 2014-12-20 20:00:36 0000)) .