I'm trying to implement an array where items can occupy multiple slots (details not relevant to question). I have created a method that allows me to iterate over a range of items:
pub fn get(&self, index: I) -> Option<&T>;
pub fn iter_range(&self, index: I, size: usize) -> impl Iterator<Item = &T> {
std::iter::successors(Some(index), |i| i.get_next())
.take(size)
.filter_map(|i| self.get(i))
}
Note here that the index is a generic and the only way to get the "next" index in the range is to call the get_next method returning an Option<I>.
I use std::iter::successors to generate the indices which is then used to get the items.
Next, I try to make a mutable version of this method:
pub fn get_mut(&mut self, index: I) -> Option<&mut T>;
pub fn iter_range_mut(&mut self, index: I, size: usize) -> impl Iterator<Item = &mut T> {
std::iter::successors(Some(index), |i| i.get_next())
.take(size)
.filter_map(|i| self.get_mut(i))
}
But I get this compiler error:
error: captured variable cannot escape `FnMut` closure body
--> foo\bar.rs:306:29
|
303 | pub fn iter_range_mut(&mut self, index: I, size: usize) -> impl Iterator<Item = &mut T)> {
| --------- variable defined here
...
306 | .filter_map(|i| self.get_mut(i))
| - ----^^^^^^^^^^^
| | |
| | returns a reference to a captured variable which escapes the closure body
| | variable captured here
| inferred to be a `FnMut` closure
|
= note: `FnMut` closures only have access to their captured variables while they are executing...
= note: ...therefore, they cannot allow references to captured variables to escape
I understand why I get this error, but not how to circumvent it.
I am making a mutable iterator so I expect having to write unsafe code, but how do I do so here?
Preferably I wouldn't have to create a custom iterator type.
Iteratorfor mutable references in other ways. See How can I create my own data structure with an iterator that returns mutable references? If you do have exclusivity guarantees, the solution is often to use a bit ofunsafeto adjust the lifetime (via transmute or raw pointer deref or whatever).