Borrow Checker: невозможно заимствовать как неизменяемый, потому что он также заимствован как изменяемый - PullRequest
2 голосов
/ 21 марта 2020

У меня проблемы с тем, что контролер заимствований не "выпускает" изменяемый заем.

У меня есть:

let mut data = (1..=100).collect::<Vec<_>>();
let mut c = Canvas::new(10, 10, &mut data);


c.iter_rows_mut(4..7);
c.iter_rows(4..7).collect::<Vec<_>>();

И он жалуется:

error[E0502]: cannot borrow `c` as immutable because it is also borrowed as mutable
  --> src/lib.rs:59:9
   |
57 |         c.iter_rows_mut(4..7);
   |         - mutable borrow occurs here
58 | 
59 |         c.iter_rows(4..7).collect::<Vec<_>>();
   |         ^
   |         |
   |         immutable borrow occurs here
   |         mutable borrow later used here

error: aborting due to previous error

Я могу понять проблему, если бы передавал ссылку, связанную с изменяемым вызовом, но это не так.

Rust Playground с полным кодом: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=de4143ddf57cc8a97e7a884bbe13dfa4

1 Ответ

4 голосов
/ 21 марта 2020

Проблема здесь в аннотациях времени жизни. Вы используете одно и то же время жизни 'd, поэтому изменяемый заем в c.iter_rows_mut должен длиться все время жизни c.

. Чтобы исправить это, используйте другое время жизни в iter_rows и iter_rows_mut. Это будет неявно связано не более чем 'd, но это даст большую гибкость.

Полностью явные подписи должны быть

fn iter_rows<'a>(&'a self, vertical_range: Range<usize>) -> impl Iterator<Item=(usize, &'a [T])> + 'a

и

fn iter_rows_mut<'a>(&'a mut self, vertical_range: Range<usize>) -> impl Iterator<Item=(usize, &'a mut [T])> + 'a {

Благодаря жизненному выбору нам не нужно никаких из этих жизней. Все времена жизни в типе вывода будут неявно такими же, как и у &self (или &mut self).

fn iter_rows(&self, vertical_range: Range<usize>) -> impl Iterator<Item=(usize, &[T])>
fn iter_rows_mut(&mut self, vertical_range: Range<usize>) -> impl Iterator<Item=(usize, &mut [T])>

(детская площадка)

PS Вызовы into_iter в каждой из этих функций не нужны: chunks_exact уже создает итератор. Клиппи предупреждает об этом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...