Ответ 1
Итак, если я просто комментирую
b
, введите: no movea
вb
, но вместо этого "re" -borrow*a
?Что мне не хватает?
Абсолютно ничего, поскольку в этом случае эти две операции семантически очень похожи (и эквивалентны, если a
и b
принадлежат к одной и той же области).
- Либо вы перемещаете ссылку
a
вb
, делаяa
перемещенное значение и больше не доступно. - Либо вы перебросите
*a
вb
, сделавa
непригодным для использования, покаb
находится в области.
Второй случай менее определен, чем первый, вы можете показать это, поместив строку, определяющую b
в под-область.
Этот пример не будет компилироваться, потому что a
перемещается:
fn main() {
let a: &mut i32 = &mut 0;
{ let b = a; }
let c = a;
}
Но это будет, потому что когда b
выходит за рамки a
, разблокируется:
fn main() {
let a: &mut i32 = &mut 0;
{ let b = &mut *a; }
let c = a;
}
Теперь, на вопрос "Почему аннотирование типа b
меняет поведение?", я предполагал бы следующее:
- Когда нет аннотации типа, операция представляет собой простой и простой ход. Ничего не нужно проверять.
- Когда есть аннотация типа, может потребоваться преобразование (перевод
&mut _
в&_
или преобразование простой ссылки в ссылку на объект-объект). Поэтому компилятор выбирает повторное заимствование значения, а не движение.
Например, этот код является правдоподобным:
fn main() {
let a: &mut i32 = &mut 0;
let b: &i32 = a;
}
и здесь перемещение a
в b
не имеет никакого смысла, поскольку они имеют разный тип. Тем не менее этот код компилируется: b
просто забирает *a
, и значение не будет доступно с возможностью изменения через a
, пока b
находится в области.