Я пытаюсь понять, чем я обидел компилятор ржавчины, но не могу понять, что не так.
Итак, основной алгоритм:
И вот как я это закодировал
fn append_at_end(&mut self, value: i32) {
match self {
List::Empty => {
*self = List::new_node(value);
},
List::Head(head) => {
let mut itr = head;
loop {
if let Some(x) = itr {
if x.next.is_none() {
x.next = Some(Node::new_node(value));
break;
} else {
itr = &mut x.next;
}
}
}
}
}
}
Теперь компилятор ржавчины жалуется на этот блок кода.
Compiling random v0.1.0 (/Users/katharva/Personal/rust/random)
error[E0503]: cannot use `*itr` because it was mutably borrowed
--> src/main.rs:65:28
|
65 | if let Some(x) = itr {
| ^^^^^-^
| | |
| | `itr.0` is borrowed here
| use of borrowed `itr.0`
| borrow later used here
error[E0499]: cannot borrow `itr.0` as mutable more than once at a time
--> src/main.rs:65:33
|
65 | if let Some(x) = itr {
| ^ --- first borrow used here, in later iteration of loop
| |
| `itr.0` was mutably borrowed here in the previous iteration of the loop
Some errors have detailed explanations: E0499, E0503.
For more information about an error, try `rustc --explain E0499`.
error: could not compile `random` (bin "random") due to 2 previous errors
Но тот же код, написанный как
fn append_at_end_option2(&mut self, value: i32) {
match self {
List::Empty => {
*self = List::new_node(value);
},
List::Head(head) => {
let mut itr = head;
loop {
match itr {
None => {},
Some(x) => {
// A bit convoluted but shows the bug
if x.next.is_none() {
x.next = Some(Node::new_node(value));
break;
} else {
itr = &mut x.next;
}
}
}
}
}
}
}
Или
fn append_at_end_option1(&mut self, value: i32) {
match self {
List::Empty => {
*self = List::new_node(value);
},
List::Head(head) => {
let mut itr = head;
loop {
if let Some(x) = itr {
itr = &mut x.next;
continue;
}
*itr = Some(Node::new_node(value));
break;
}
}
}
}
все в порядке, компилятор этим доволен. И append_at_end_option2
, и append_at_end_option1
будут работать как положено. Насколько я понимаю, все три части кода имеют одинаковую логику. Так почему же первый не приемлем?
Добавленная вами ссылка ведет на пустую игровую площадку. Вам нужно использовать кнопку [ПОДЕЛИТЬСЯ] в правом верхнем углу, чтобы получить ссылку, которой можно поделиться. Также убедитесь, что минимальный воспроизводимый пример находится в вашем вопросе, просто ссылки на него недостаточно!
Если вы нашли решение, добавьте ответ ниже, не редактируйте свой вопрос, чтобы он содержал такие вещи, как решение или «закрыто».
Одно из различий между выражением if let и match заключается в том, что if let становится владельцем значения. и заимствование его заново привело бы к ошибке. Насколько я знаю, причина, по которой работает третий метод, заключается в используемой вами операции Deref, которая освобождает значение.
Это неправильно, match
и if let
семантически эквивалентны, оба могут стать владельцем и оба могут получить ссылку.
Судя по всему, это работает на игровой площадке ржавчины. Похоже на ошибку компилятора, которую исправили.
Возможно, это это известное ограничение средства проверки заимствований , пожалуйста, отредактируйте свой вопрос и включите минимальный воспроизводимый пример.