首页 > 解决方案 > 实现 IntoIterator 以迭代内部集合时的生命周期冲突

问题描述

我有以下结构:

pub struct Data<T, IDX: From<usize>> {
    inner: Vec<T>,
    _idx_marker: std::marker::PhantomData<IDX>,
    // other data...
}

我想实现IntoIteratorfor &Dataand &mut Data,它迭代一些内部集合。此外,迭代器不仅返回当前条目,还返回一个额外的 generic IDX
&Data一切正常的情况下。但是在实现IntoIterator&mut Data我遇到了以下问题:

// impl<'a, T, IDX: From<usize>> IntoIterator for &'a Data<T, IDX> ...

// pub struct DataIntoIterator<'a, T, IDX: From<usize>> ...

// impl<'a, T, IDX: From<usize>> Iterator for DataIntoIterator<'a, T, IDX> ...

impl<'a, T, IDX: From<usize>> IntoIterator for &'a mut Data<T, IDX> {
    type Item = (IDX, &'a mut T);
    type IntoIter = DataIntoIteratorMut<'a, T, IDX>;

    fn into_iter(self) -> Self::IntoIter {
        DataIntoIteratorMut {
            inner: &mut self.inner,
            index: 0,
            __: std::marker::PhantomData,
        }
    }
}

pub struct DataIntoIteratorMut<'a, T, IDX: From<usize>> {
    pub inner: &'a mut Vec<T>,
    pub index: usize,
    __: std::marker::PhantomData<IDX>,
}

impl<'a, T, IDX: From<usize>> Iterator for DataIntoIteratorMut<'a, T, IDX> {
    type Item = (IDX, &'a mut T);
    
    fn next(&mut self) -> Option<Self::Item> {
        if let Some(value) = self.inner.get_mut(self.index) // ERROR!
        {
            let ret = Some( (IDX::from(self.index), value) );
            self.index += 1;
            ret
        } else {
            None
        }
    }
}

编译器给出以下令人困惑的错误消息:

cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements

note: ...so that reference does not outlive borrowed content
note: expected `std::iter::Iterator`
         found `std::iter::Iterator`rustc(E0495)

此错误消息对我来说毫无意义。我可以使用不安全的代码获取我想要的数据:

impl<'a, T, IDX: From<usize>> Iterator for DataIntoIteratorMut<'a, T, IDX> {
    type Item = (IDX, &'a mut T);
    
    fn next(&mut self) -> Option<Self::Item> {
        if self.index < self.inner.len() {
            let ptr = self.inner.as_mut_ptr();
            unsafe { // is this dangerous?
                let value: &'a mut T = &mut *ptr.add(self.index);
                let ret = Some( (IDX::from(self.index), value) );
                self.index += 1;
                ret
            }
        } else {
            None
        }
    }
}

这可以编译,但我想避免这样的不安全黑客攻击。这个问题有安全的解决方案吗?

标签: rustiteratorunsafe

解决方案


推荐阅读