Considere o seguinte exemplo simples:
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
}
A bad
função falha ao compilar com o seguinte erro:
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
| +++++++ +++
Isso parece extremamente estranho para mim. Apenas reatribuir o parâmetro de função a variáveis locais falha na compilação. Você poderia explicar por quê?
Isso é mencionado na Referência :
Não tenho certeza se isso é necessário para o funcionamento da linguagem, torna-a mais conveniente ou é simplesmente como o compilador foi originalmente implementado, mas seria incompatível com versões anteriores mudar agora. Se alguém souber mais, comente ou edite esta resposta.
Estou ciente disso e às vezes surge ao entender a ordem de entrega. O que há de novo para mim é que os argumentos da função, aparentemente, são eliminados ainda mais tarde . Isso é quase mencionado aqui , mas não exatamente. A ordem de queda, portanto, deve ser:
Aqui está um programa que demonstra isso.
Ele imprime o seguinte:
No seu código, a expressão final cria um arquivo
std::cell::Ref<'_, String>
. ComoRef
temDrop
comportamento - especificamente, o tempo de vida está contido em um tipo que o implementaDrop
- ele exige que o tempo de vida seja válido quando ocorre a queda, ao contrário de uma referência compartilhada normal&
. Como ele toma emprestado doRefCell<String>
, oRef
deve ser eliminado antes que oRefCell
seja eliminado. E de acordo com as regras acima, isso não é satisfeito quandoRefCell
está vinculado à função.A solução alternativa na mensagem de erro sempre deve ser suficiente.