Ваш код недействителен, потому что вы пытаетесь вернуть несколько изменяемых ссылок на один и тот же фрагмент с одним и тем же временем жизни 'a
.
Чтобы это работало, вам потребуется разное время жизни для каждого возвращаемого значения Item
, чтобы не хранить 2 изменяемые ссылки на один и тот же фрагмент. Вы не можете сделать это сейчас, потому что для этого требуются Generi c Связанные типы:
type Item<'item> = &'item mut D; // Does not work today
Одним из решений является проверка уникальности индексов и повторное связывание времени жизни ссылочного элемента с 'a
в unsafe
блок. Это безопасно, потому что все индексы уникальны, поэтому пользователь не может хранить 2 изменяемые ссылки на один и тот же элемент.
Не забудьте инкапсулировать весь код внутри модуля, чтобы структура не могла быть собрана без проверка new
:
mod my_mod {
pub struct LookupIterMut<'a, D> {
data: &'a mut [D],
indices: &'a [usize],
i: usize,
}
impl<'a, D> LookupIterMut<'a, D> {
pub fn new(data: &'a mut [D], indices: &'a [usize]) -> Result<Self, ()> {
let mut uniq = std::collections::HashSet::new();
let all_distinct = indices.iter().all(move |&x| uniq.insert(x));
if all_distinct {
Ok(LookupIterMut {
data,
indices,
i: 0,
})
} else {
Err(())
}
}
}
impl<'a, D> Iterator for LookupIterMut<'a, D> {
type Item = &'a mut D;
fn next(&mut self) -> Option<Self::Item> {
self.indices.get(self.i).map(|&index| {
self.i += 1;
unsafe { std::mem::transmute(&mut self.data[index]) }
})
}
}
}
Обратите внимание, что ваш код будет Pani c, если один индекс выходит за пределы.