Reputation: 892
I'm having trouble with the borrow checker not "releasing" a mutable borrow.
I have:
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<_>>();
And it's complaining:
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
I can understand the problem if I was handing onto a reference related to the mutable call, but that doesn't appear to be the case.
Rust Playground with full code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=de4143ddf57cc8a97e7a884bbe13dfa4
Upvotes: 3
Views: 127
Reputation: 10474
The problem here is in the lifetime annotations. You're using the same lifetime 'd
throughout, so the mutable borrow in c.iter_rows_mut
has to last the entire lifetime of c
.
To fix this, use a different lifetime in iter_rows
and iter_rows_mut
. It'll be implicitly bound to be no longer than 'd
, but it'll allow more flexibility.
The fully explicit signatures should be
fn iter_rows<'a>(&'a self, vertical_range: Range<usize>) -> impl Iterator<Item=(usize, &'a [T])> + 'a
and
fn iter_rows_mut<'a>(&'a mut self, vertical_range: Range<usize>) -> impl Iterator<Item=(usize, &'a mut [T])> + 'a {
Thanks to lifetime elision, though, we don't need any of those lifetimes. All the lifetimes in the output type will be implicitly the same as the lifetime on &self
(or &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])>
P.S. The into_iter
calls in each of these functions aren't necessary: chunks_exact
already produces an iterator. Clippy warns about this.
Upvotes: 5