Компилятор продолжает считать заимствование как изменчивое, когда оно фактически является неизменным [dубликат]

Этот код не справляется с ужасной системой проверки чеков (игровая площадка):

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(), потому что эта функция возвращает неизменяемую ссылку. Является ли проверка чека еще недостаточно умной? Планируется ли это? Есть ли способ обойти это?

9
задан 17 December 2016 в 00:06

1 ответ

Время жизни отличается от того, является ли ссылка изменчивой или нет. Работа через код:

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.

3
ответ дан 15 August 2018 в 16:38
  • 1
    Спасибо, так есть решение или обходное решение? Будут ли исправлять нелегические времена жизни? – Timmmm 17 December 2016 в 13:51
  • 2
    Я не думаю, что есть обходное решение, кроме разделения мутации на отдельный вызов метода. Это не лексическая жизнь; &i32 заимствован из &mut self, поэтому они фундаментально связаны друг с другом. – Chris Emerson 17 December 2016 в 14:17
  • 3
    @Timmmm пример OP работает как есть с включенным NLL. – mcarton 14 August 2018 в 01:17

Другие вопросы по тегам:

Похожие вопросы: