如何声明返回迭代器的方法边界?该迭代器需使用属性可变方法生成值
Rust中返回捕获可变引用迭代器的生命周期错误分析与解决
我想要实现一个返回迭代器的方法,该迭代器会调用结构体属性的可变方法生成值,而该属性持有对另一个对象的引用。编写代码时遭遇如下编译器错误:
hidden type for
impl Iterator<Item = i32> + '_captures lifetime that does not appear in bounds
原始代码如下:
fn main() { let mut n = 0; let mut a = A(&mut n); let mut b = B(&mut a); b.run_a().for_each(|x| println!("{}", x)); b.run_a().for_each(|x| println!("{}", x)); } struct A<'a>(&'a mut i32); impl A<'_> { fn get_item(&mut self, index: usize) -> i32 { 1 } } struct B<'a, 'b: 'a>(&'a mut A<'b>); impl B<'_, '_> { fn run_a(&mut self) -> impl Iterator<Item = i32> + '_ { (0..1).map(|_| self.0.get_item(0)) } }
观察到的现象
- 若
run_a不是可变方法,或者结构体A不持有引用,代码可正常编译运行。 - 修改
run_a让其返回与&mut self生命周期绑定的迭代器,编译器会接受,但迭代器会捕获self.0,导致方法只能被调用一次:
impl<'a, 'b: 'a> B<'a, 'b> { fn run_a(&'b mut self) -> impl Iterator<Item = i32> + 'b { (0..1).map(|_| self.0.get_item(0)) } }
- 尝试声明返回的迭代器生命周期短于
&mut self,仍会触发相同错误:
impl<'a, 'b: 'a> B<'a, 'b> { fn run_a<'c>(&'b mut self) -> impl Iterator<Item = i32> + 'c where A<'a>: 'b, 'b: 'c, { (0..1).map(|_| self.0.get_item(0)) } }
问题根源
报错的核心是:map闭包捕获了&mut self.0(即&mut A<'b>),该引用包含'b生命周期,但返回类型impl Iterator + '_仅标注了与&mut self相关的生命周期,未明确包含'b,导致编译器无法确认所有被捕获的生命周期都被正确约束。
当A不持有引用时,'b生命周期不存在,自然无此问题;当run_a为不可变方法时,闭包捕获的是&A<'b>,编译器可自动推导生命周期约束,不会报错。
解决方案
需要明确标注返回的迭代器捕获了'b生命周期,同时保证方法可被多次调用(即迭代器不独占self的整个生命周期)。可以通过显式声明生命周期参数,并在返回类型中绑定'b来解决:
struct B<'a, 'b: 'a>(&'a mut A<'b>); impl<'a, 'b> B<'a, 'b> { fn run_a(&mut self) -> impl Iterator<Item = i32> + '_ + 'b { (0..1).map(|_| self.0.get_item(0)) } }
或者更清晰地显式标注所有相关生命周期:
impl<'a, 'b> B<'a, 'b> { fn run_a<'c>(&'c mut self) -> impl Iterator<Item = i32> + 'c + 'b { (0..1).map(|_| self.0.get_item(0)) } }
这样编译器能明确迭代器同时依赖于&mut self的临时生命周期'c和A中的'b生命周期,既解决了生命周期捕获的报错,又保证run_a可被多次调用。
内容的提问来源于stack exchange,提问作者Alan Alves de Oliveira
相关产品推荐
相关产品推荐

