任何人都可以通过以下代码告诉问题是什么?编译器抱怨生命周期,但错误消息绝对没有意义 . 我已经尝试了我能想到的一切,但似乎没有任何帮助 .
use std::borrow::BorrowMut;
trait Trait<'a> {
fn accept(&mut self, &'a u8);
}
struct Impl<'a>{
myref: Option<&'a u8>,
}
impl<'a> Trait<'a> for Impl<'a> {
fn accept(&mut self, inp: &'a u8) { self.myref = Some(inp); }
}
fn new<'a>() -> Box<Trait<'a> + 'a> {
Box::new(Impl{myref: None})
}
fn user<'a>(obj: &mut Trait<'a>) {}
fn parent<'a>(x: &'a u8) {
let mut pool = new();
user(pool.borrow_mut());
}
编译器错误是
error: `pool` does not live long enough
--> src/wtf.rs:22:10
|
22 | user(pool.borrow_mut());
| ^^^^ does not live long enough
23 | }
| - borrowed value dropped before borrower
|
= note: values in a scope are dropped in the opposite order they are created
这绝对没有意义 . 借款人的生活如何?我甚至没有使用借来的 Value !
3 回答
好吧,这确实有意义,但它是明确写出所有生命周期的代码,并且无关紧要的细节被剔除:
现在,从
parent
的最后一行的角度来看,我们可以通过读取user
的定义并替换parent
中的生命周期来计算出以下等价:'a
='x
'b
='i
'b
='x
此外,这让我们得出结论:
'x
='i
这就是问题 . 由于你定义
user
的方式,你已经把自己置于这样一种情况:pool_ref
借用的生命周期(等于你借来的pool
存储位置的生命周期)必须与生命周期相同'x
用于存储在pool
中的东西 .它有点像
Box
能够在它存在之前有一个指向它自己的指针,这没有任何意义 .无论哪种方式,修复都很简单 . 更改
user
实际上具有正确的类型:这与
new
生成的类型匹配 . 或者,只是不要使用borrow_mut
:这是有效的,因为它是"re-borrowing" . 调用
borrow_mut
或多或少地直接转换生命周期,但重新借用允许编译器将借用缩小到更短的生命周期 . 换句话说,显式调用borrow_mut
不允许编译器有足够的自由度来使它们全部排成一行,重新借用 .暂时不谈:
无关紧要 . Rust完全在本地进行类型和生命周期检查 . 它永远不会查看另一个函数的主体,看看它在另一个函数中做了什么 .
请注意,错误消息还有更多内容:
我们来看
user
:这表示它将接受一个使用生命周期
'a
参数化的特征对象的可变引用(具有未命名的生命周期) .转到
new
,我会说这个方法是 highly 可疑的:这表示它将返回一个盒装特征对象,其中包含调用者指定的任何生命周期 . That basically never makes sense .
所有这一切,我不清楚为什么代码选择使用
borrow_mut
. 我会写得更直接:这取消引用
Box<Trait>
得到Trait
,然后获取一个可变引用,产生&mut Trait
,它编译 .我目前无法解释为什么
BorrowMut
的行为不同 .我不确定为什么会发生这种错误,但我可以给出解决方案!
首先,似乎使用borrow_mut会不必要地限制返回引用的生命周期 . 使用运算符创建引用可以解决错误 .
但是,如果我们不这样做,我们可以通过在
user
的obj
参数中添加Trait
对象的生命周期来解决错误 .