Ответы Ejdrien демонстрируют разницу между изменчивыми и неизменяемыми заимствованиями, однако не учитывают подзаголовок в вашем вопросе, который заключается в том, что вы выполняете заимствования как часть сопоставления с шаблоном .
Когда вы пишете
let (mut part1, mut part2) = someTuple;
, вы связываете содержимое someTuple
с изменяемыми переменными part1
и part2
с помощью , перемещая их. Если содержимое someTuple
не было в состоянии Copy
, переменные part1
и part2
становятся исключительными владельцами своих соответствующих значений. Если вы попытаетесь получить доступ к someTuple
позже, написав, например,
println!("{}", someTuple.0);
, вы получите сообщение об ошибке компиляции из средства проверки заимствования, которое напоминает
error[E0382]: borrow of moved value: `someTuple.0`
--> main.rs:6:20
|
4 | let (mut part1, mut part2) = someTuple;
| --------- value moved here
5 |
6 | println!("{}", someTuple.0);
| ^^^^^^^^^^^ value borrowed here after move
В этом конкретном контексте Есть два способа сообщить компилятору, что мы хотим заимствовать только содержимое someTuple
. Первым является метод, описанный Эйдриеном, который явно заимствует кортеж и выполняет сопоставление с шаблоном с последующей результирующей ссылкой:
// Produce two mutable references
let (part1, part2) = &mut someTuple;
// Produce two immutable references
let (part1, part2) = &someTuple;
Проблема этого подхода заключается в том, что мы вынуждены заимствовать все таким же образом. Что если нам нужна только изменчивая ссылка на someTuple.0
и мы хотим получить someTuple.1
как копию или неизменную ссылку? Для приведенного здесь примера кортежа это может показаться не слишком критичным, но для более сложных случаев сопоставления с образцом гораздо важнее иметь этот тип элемента управления.
Это дает нам два вторых решения: привязка ссылок. Вместо вышесказанного мы можем написать
// Produce two mutable references
let (ref mut part1, ref mut part2) = someTuple;
// Produce two immutable references
let (ref part1, ref part2) = someTuple;
Здесь мы явно указываем, как мы хотим связать каждую переменную в сопоставлении с образцом. Ключевым моментом здесь является то, что мы можем смешивать изменяемые и неизменяемые заимствования, поэтому следующее также полностью допустимо:
// Produce immutable reference and one mutable reference
let (ref part1, ref mut part2) = someTuple;
println!("{}", &someTuple.0); // Make a second immutable reference someTuple.0
*part2 = ... // Mutate someTuple.1
println!("{}", part1); // Continue using the immutable reference
Если мы поменяем вышеуказанное с явным изменяемым заимствованием в правой части, мы ' Я снова получу ошибки от заемщика из-за одновременных изменяемых и неизменяемых ссылок:
let (part1, part2) = &mut someTuple;
println!("{}", &someTuple.0);
*part2 = ... // Mutate someTuple.1
println!("{}", part1);
производит
error[E0502]: cannot borrow `someTuple.0` as immutable because it is also borrowed as mutable
--> main.rs:6:20
|
4 | let (part1,part2) =&mut someTuple;
| -------------- mutable borrow occurs here
5 |
6 | println!("{}", &someTuple.0);
| ^^^^^^^^^^^^ immutable borrow occurs here
...
9 | println!("{}", part1);
| ----- mutable borrow later used here
error: aborting due to previous error