Я пишу бинарное дерево на Rust, и проверка заимствований действительно смущает меня. Вот минимальный пример, который воспроизводит проблему .
Двоичное дерево определяется следующим образом:
struct NonEmptyNode;
pub struct BinaryTree {
root: Option<NonEmptyNode>,
}
Код, отклоненный контролером заимствований:
// Implementation #1
fn set_child_helper(&self, bt: &Self, setter: fn(&NonEmptyNode, &NonEmptyNode)) -> bool {
match (self.root, bt.root) {
(Some(ref rt), Some(ref node)) => {
setter(rt, node);
true
}
_ => false,
}
}
Сообщение об ошибке
error[E0507]: cannot move out of borrowed content
--> src/main.rs:10:16
|
10 | match (self.root, bt.root) {
| ^^^^ cannot move out of borrowed content
error[E0507]: cannot move out of borrowed content
--> src/main.rs:10:27
|
10 | match (self.root, bt.root) {
| ^^ cannot move out of borrowed content
Чтобы это работало, код должен быть изменен на:
// Implementation #2
fn set_child_helper(&self, bt: &Self, setter: fn(&NonEmptyNode, &NonEmptyNode)) -> bool {
match (&self.root, &bt.root) {
// explicit borrow
(&Some(ref rt), &Some(ref node)) => {
// explicit borrow
setter(rt, node);
true
}
_ => false,
}
}
Если я сопоставлю шаблон по одной переменной за раз без явного заимствования, средство проверки заимствования не будет жаловаться вообще:
// Implementation #3
fn set_child_helper(&self, bt: &Self, setter: fn(&NonEmptyNode, &NonEmptyNode)) -> bool {
match self.root {
Some(ref rt) => match bt.root {
// No explict borrow will be fine
Some(ref node) => {
// No explicit borrow will be fine
setter(rt, node);
true
}
_ => false,
},
_ => false,
}
}
Почему реализация № 3 не требует явного заимствования, а реализация # 1 требует?