Фон
Я знаю, что программа проверки заимствований запрещает более одного изменяемого заимствования. Например, приведенный ниже код недействителен:
fn main() {
let mut x = 42;
let a = &mut x;
let b = &mut x;
println!("{} {}", a, b);
}
Однако, если первое заимствование отбрасывается из-за выхода за рамки, второе заимствование является действительным:
fn main() {
let mut x = 1;
{
let a = &mut x;
println!("{}", a);
}
let b = &mut x;
println!("{}", b);
}
Из-за нелексическое время жизни (NLL) , первое заимствование даже не должно выходить за рамки - программа проверки заимствования только требует, чтобы он больше не использовался. Итак, приведенный ниже код действителен в Rust 2018:
fn main() {
let mut x = 1;
let a = &mut x;
println!("{}", a);
let b = &mut x;
println!("{}", b);
}
Проблема
Но я не понимаю, почему приведенный ниже код недействителен:
use std::str::Chars;
fn main() {
let s = "ab".to_owned();
let mut char_iter = s.chars();
let mut i = next(&mut char_iter);
dbg!(i.next());
let mut j = next(&mut char_iter);
dbg!(j.next());
}
fn next<'a>(char_iter: &'a mut Chars<'a>) -> impl Iterator<Item = char> + 'a {
char_iter.take_while(|&ch| ch != ' ')
}
Сообщение об ошибке компиляции:
error[E0499]: cannot borrow `char_iter` as mutable more than once at a time
--> src/main.rs:10:22
|
7 | let mut i = next(&mut char_iter);
| -------------- first mutable borrow occurs here
...
10 | let mut j = next(&mut char_iter);
| ^^^^^^^^^^^^^^ second mutable borrow occurs here
11 | dbg!(j.next());
12 | }
| - first borrow might be used here, when `i` is dropped and runs the destructor for type `impl std::iter::Iterator`
Из сообщения об ошибке Я подумал, что, может быть, NLL еще не поддерживает этот случай. Итак, я сбросил i
раньше:
use std::str::Chars;
fn main() {
let s = "ab".to_owned();
let mut char_iter = s.chars();
{
let mut i = next(&mut char_iter);
dbg!(i.next());
}
let mut j = next(&mut char_iter);
dbg!(j.next());
}
fn next<'a>(char_iter: &'a mut Chars<'a>) -> impl Iterator<Item = char> + 'a {
char_iter.take_while(|&ch| ch != ' ')
}
( Rust Playground )
Но я получил более запутанное сообщение об ошибке:
error[E0499]: cannot borrow `char_iter` as mutable more than once at a time
--> src/main.rs:12:22
|
8 | let mut i = next(&mut char_iter);
| -------------- first mutable borrow occurs here
...
12 | let mut j = next(&mut char_iter);
| ^^^^^^^^^^^^^^
| |
| second mutable borrow occurs here
| first borrow later used here
Почему написано first borrow later used here
, даже если i
уже пропущено и выходит за рамки ранее?
Альтернативный подход
Код будет скомпилирован, если я изменю подпись функции next
на это:
fn next(char_iter: impl Iterator<Item = char>) -> impl Iterator<Item = char> {
char_iter.take_while(|&ch| ch != ' ')
}
Но все же я хочу понять, почему исходный next
функция не работает.