对于具有多个生命周期参数的迭代器,impl Iterator 失败
impl Iterator failing for iterator with multiple lifetime parameters
我的代码看起来(有点)像这样:
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
类型并允许在测试中更容易地换出 return 类型伪造的。我最好的尝试是像这样改变 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
的逻辑生命周期是这两个中较小的那个?任何关于为什么会发生此错误或如何修复它的澄清都会很棒!
如果有帮助,这里是 rust playground,里面有代码。
使用 https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999, via 中的解决方法:
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 }
}
}
我的代码看起来(有点)像这样:
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
类型并允许在测试中更容易地换出 return 类型伪造的。我最好的尝试是像这样改变 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
的逻辑生命周期是这两个中较小的那个?任何关于为什么会发生此错误或如何修复它的澄清都会很棒!
如果有帮助,这里是 rust playground,里面有代码。
使用 https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999, via
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 }
}
}