Этот код не справляется с ужасной системой проверки чеков (игровая площадка):
struct Data {
a: i32,
b: i32,
c: i32,
}
impl Data {
fn reference_to_a(&mut self) -> &i32 {
self.c = 1;
&self.a
}
fn get_b(&self) -> i32 {
self.b
}
}
fn main() {
let mut dat = Data{ a: 1, b: 2, c: 3 };
let aref = dat.reference_to_a();
println!("{}", dat.get_b());
}
Ошибка:
error[E0502]: cannot borrow `dat` as immutable because it is also borrowed as mutable
--> <anon>:19:20
|
18 | let aref = dat.reference_to_a();
| --- mutable borrow occurs here
19 | println!("{}", dat.get_b());
| ^^^ immutable borrow occurs here
20 | }
| - mutable borrow ends here
Может кто-нибудь объяснить, почему именно? Я бы подумал, что изменчивый заимствование dat преобразуется в неизменяемое, когда возвращается reference_to_a(), потому что эта функция возвращает неизменяемую ссылку. Является ли проверка чека еще недостаточно умной? Планируется ли это? Есть ли способ обойти это?
Время жизни отличается от того, является ли ссылка изменчивой или нет. Работа через код:
fn reference_to_a(&mut self) -> &i32
Несмотря на то, что время жизни было отменено, это эквивалентно:
fn reference_to_a<'a>(&'a mut self) -> &'a i32
i.e. время входа и выхода одинаково. Это единственный способ назначить времена жизни такой функции (если она не вернула ссылку &'static на глобальные данные), так как вы не можете создать выходное время жизни из ничего.
Это означает, что если вы сохраняете возвращаемое значение, сохраняя его в переменной, вы также сохраняете &mut self.
Другой способ думать об этом заключается в том, что &i32 является подзаголовком &mut self, поэтому действует только до истечения этого срока.
Как указывает @aSpex, это описано в nomicon.