Quem pegou emprestada uma variável?
Estou brigando com o verificador de empréstimos. Eu tenho duas partes de código semelhantes, uma funcionando como eu esperava e a outra não.
Aquele que funciona como eu esperava:
mod case1 {
struct Foo {}
struct Bar1 {
x: Foo,
}
impl Bar1 {
fn f<'a>(&'a mut self) -> &'a Foo {
&self.x
}
}
// only for example
fn f1() {
let mut bar = Bar1 { x: Foo {} };
let y = bar.f(); // (1) 'bar' is borrowed by 'y'
let z = bar.f(); // error (as expected) : cannot borrow `bar` as mutable more
// than once at a time [E0499]
}
fn f2() {
let mut bar = Bar1 { x: Foo {} };
bar.f(); // (2) 'bar' is not borrowed after the call
let z = bar.f(); // ok (as expected)
}
}
Aquele que não:
mod case2 {
struct Foo {}
struct Bar2<'b> {
x: &'b Foo,
}
impl<'b> Bar2<'b> {
fn f(&'b mut self) -> &'b Foo {
self.x
}
}
fn f4() {
let foo = Foo {};
let mut bar2 = Bar2 { x: &foo };
bar2.f(); // (3) 'bar2' is borrowed as mutable, but who borrowed it?
let z = bar2.f(); // error: cannot borrow `bar2` as mutable more than once at a time [E0499]
}
}
Eu esperava poder ligarBar2::f
duas vezes sem irritar o compilador, como no caso 1.
A questão está no comentário (3): quem pediu emprestadobar2
, considerando que não há afetação?
Aqui está o que eu entendo:
No caso 1,f2
chamada: o parâmetro da vida'a
é aquele do receptor&Foo
valor, portanto, essa vida útil fica vazia quando não há afetação ebar
não é emprestado após oBar1::f
ligar;
No caso 2,bar2
emprestafoo
(como imutável), portanto, o parâmetro de duração'b
noBar2
struct é ofoo
vida útil de referência, que termina no final def4
corpo. ChamandoBar2::f
emprestabar2
para essa vida, ou seja, até o final def4
.
Mas a questão ainda é: quem pediu emprestadobar2
? Poderia serBar2::f
? ComoBar2::f
manteria a propriedade emprestada após a ligação? O que estou perdendo aqui?
Estou usando o Rust 1.14.0-nightly (86affcdf6 2016-09-28) em x86_64-pc-windows-msvc.