首页 > 解决方案 > 具有多个生命周期参数的迭代器的 impl Iterator 失败

问题描述

我的代码看起来(有点)像这样:

struct OutputIterator<'r, 'i: 'r> {
    input_handler: &'r mut InputHandler<'i>
}

impl<'r, 'i> Iterator for OutputIterator<'r, 'i> {
    type Item = i32;

    fn next(&mut self) -> Option<Self::Item> {
        self.input_handler.inputs.next().map(|x| x * 2)
    }
}

struct InputHandler<'a> {
    inputs: Box<dyn Iterator<Item = i32> + 'a>
}

impl<'a> InputHandler<'a> {
    fn outputs<'b>(&'b mut self) -> OutputIterator<'b, 'a> {
        OutputIterator { input_handler: self }
    }
}

fn main() {
    let mut input_handler = InputHandler {
        inputs: Box::new(vec![1,2,3,4,5].into_iter())
    };
    for output in input_handler.outputs() {
        println!("{}", output);
    }
}

基本上,用户可以提供一个输入迭代器,然后获得一个输出迭代器(在我的真实代码中,输入和输出之间的连接要复杂得多,涉及到一堆内部状态。多个输入可能指向一个输出,或者相反 -反之亦然)。

这行得通,但我想改变它,impl Iterator既可以隐藏OutputIterator类型,又可以在使用假的测试时更轻松地换出返回类型。我最好的尝试改变 InputHandler impl,如下所示:

impl<'a> InputHandler<'a> {
    fn outputs<'b>(&'b mut self) -> impl Iterator<Item = i32> + 'b {
        OutputIterator { input_handler: self }
    }
}

不幸的是,这让我:error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds

有没有办法使这项工作?对于采用具有一定生命周期的迭代器的接口而言,这很重要InputHandler,并且显然必须以OutputIterator某种方式传递给它,但我真的很想从调用者那里抽象出这些细节。原则上,调用者应该只需要担心输入Iterator和寿命InputHandler超过OutputIterator所以我认为这里的逻辑生命周期OutputIterator是这两者中的较小者?任何关于为什么会发生此错误或如何修复它的清晰度都会很棒!

如果有帮助,这里有一个生锈的游乐场,里面有代码。

标签: rustiteratorlifetime

解决方案


通过https://stackoverflow.com/a/50548538/1757964使用https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999的解决方法:

trait Captures<'a> {}
impl<'a, T: ?Sized> Captures<'a> for T {}

impl<'a> InputHandler<'a> {
    fn outputs<'b>(&'b mut self) -> impl Iterator<Item = i32> + Captures<'a> + 'b {
        OutputIterator { input_handler: self }
    }
}

推荐阅读