Осмысливаем области видимости (Thinking in scopes) Rust

В туториале сказано:

Вот код:

let mut x = 5;
let y = &mut x;

*y += 1;

println!("{}", x);

Этот код выдает нам такую ошибку:

error: cannot borrow `x` as immutable because it is also borrowed as mutable
    println!("{}", x);
                   ^

Это потому, что мы нарушили правила: у нас есть изменяемая ссылка &mut T, указывающая на x, и поэтому мы не можем создать какую-либо &T. Одно из двух. Примечание подсказывает как следует рассматривать эту проблему:

note: previous borrow ends here
fn main() {

}
^

Вопрос

Почему мой код прекрасно компилируется и исполняется?

Мой код:

#![allow(unused_variables)]
fn main() {
    let mut x = 5;
    let y = &mut x;
    *y += 1;
    println!("{}", x);
}

Выход:

D:\Source\RUST\playground> cargo build
   Compiling playground v0.1.0 (D:\Source\RUST\playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.36s
D:\Source\RUST\playground> cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target\debug\playground.exe`
6

Ответы (1 шт):

Автор решения: Fat-Zer

Эта версия RPL достаточно сильно устарела, актуальную можно найти здесь.


Сейчас в Rust область видимости ссылки (reference’s scope) начинается её объявлением и заканчивается её последним использованием. Поэтому в примере всё и в порядке, к моменту println! y уже вышла из области видимости и владение (ownership) вернулось к x.

Если в println!, например, попробовать распечатать y:

println!("{} {}", x, y);

то увидишь ту же самую ошибку:

error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
 --> src/main.rs:5:23
  |
3 |     let y = &mut x;
  |             ------ mutable borrow occurs here
4 |     *y += 1; //
5 |     println!("{} {}", x, y);
  |                       ^  - mutable borrow later used here
  |                       |
  |                       immutable borrow occurs here
→ Ссылка