考虑以下简单示例:
use std::cell::RefCell;
// Compiles fine
fn good(t: RefCell<String>) -> bool {
t.borrow().len() == 12
}
// error[E0597]: `t` does not live long enough
fn bad(t: RefCell<String>) -> bool {
let t = t;
t.borrow().len() == 12
}
该bad
函数无法编译并出现以下错误:
error[E0597]: `t` does not live long enough
--> src/lib.rs:9:5
|
8 | let t = t;
| - binding `t` declared here
9 | t.borrow().len() == 12
| ^---------
| |
| borrowed value does not live long enough
| a temporary with access to the borrow is created here ...
10 | }
| -
| |
| `t` dropped here while still borrowed
| ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Ref<'_, String>`
|
= note: the temporary is part of an expression at the end of a block;
consider forcing this temporary to be dropped sooner, before the block's local variables are dropped
help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block
|
9 | let x = t.borrow().len() == 12; x
| +++++++ +++
这对我来说看起来非常奇怪。仅将函数参数重新分配给局部变量会导致编译失败。你能解释一下为什么吗?
参考文献中提到了这一点:
我不确定这对于语言的运行是否是必要的,是否使语言更方便,或者仅仅是编译器最初的实现方式,但现在更改将是向后不兼容的。如果有人知道更多,请评论或编辑此答案。
我已经意识到这一点,并且在理解下降顺序时有时会出现这种情况。对我来说新奇的是,函数参数显然甚至在更晚的时候就被删除了。这里几乎提到了这一点,但不完全是。因此,下降顺序必须是:
这是一个演示这一点的程序。
它打印以下内容:
在您的代码中,最终表达式创建一个临时
std::cell::Ref<'_, String>
. 由于Ref
具有Drop
行为(具体来说,生命周期包含在实现的类型中)Drop
,因此它要求生命周期在发生 drop 时有效,这与普通的共享引用不同&
。由于它借用了RefCell<String>
,因此Ref
必须在RefCell
删除 之前删除 。并且根据上面的规则,当RefCell
is 绑定在函数内部时,this 是不满足的。错误消息中的解决方法应该足够了。