Rust闭包中重分配output切片触发E0597生命周期错误求助
Rust闭包中修改外部可变切片引发生命周期错误的原因?
我理解通常借用数据无法逃逸闭包的原因,但这次场景里,我只是把外部的可变切片output重新分配为它自身的子切片,没尝试把它赋值给闭包内部变量(这才会导致逃逸),却触发了生命周期错误。相关代码及报错如下:
struct A { a: u8 } impl A { pub fn fill_and_write( &self, values: &[u8], mut output: &mut [u8], ) -> Result<usize, ()>{ let len = output.len(); values.iter().try_for_each(|v| { let written = 3; // write something and return how many was written output = &mut output[written..]; Ok::<(),()>(()) }); Ok(len - output.len()) } }
报错信息:
--> src/lib.rs:14:13 | 9 | mut output: &mut [u8], | ---------- `output` declared here, outside of the closure body ... 14 | output = &mut output[written..]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0597]: `output` does not live long enough
这是因为Rust闭包捕获可变引用时,会生成嵌套的可变借用作用域,导致闭包内对output的重新赋值触发了生命周期冲突:
- 闭包捕获外部
output的可变引用后,内部的output会被视为指向原切片的临时可变借用。 - 当你执行
output = &mut output[written..]时,新生成的子切片引用的生命周期仅限于闭包内部的单次迭代,但外部的output需要的生命周期是整个fill_and_write函数的作用域。 - Rust借用检查器判定:这个子切片引用无法存活到闭包外部,后续函数对
output的使用会出现生命周期不匹配,因此抛出错误。
解决方法
- 手动遍历替代闭包:把逻辑移出闭包,直接用
for循环就不会有捕获问题:
struct A { a: u8 } impl A { pub fn fill_and_write( &self, values: &[u8], mut output: &mut [u8], ) -> Result<usize, ()>{ let len = output.len(); for _ in values { let written = 3; output = &mut output[written..]; } Ok(len - output.len()) } }
- 用容器包装切片引用:如果坚持用
try_for_each,可以把output包装在双层可变引用里,让闭包捕获容器的可变引用而非直接捕获切片:
struct A { a: u8 } impl A { pub fn fill_and_write( &self, values: &[u8], mut output: &mut [u8], ) -> Result<usize, ()>{ let len = output.len(); let mut output_ref = &mut output; values.iter().try_for_each(|_| { let written = 3; *output_ref = &mut output_ref[written..]; Ok(()) })?; Ok(len - output.len()) } }
内容的提问来源于stack exchange,提问作者Poperton
相关产品推荐
相关产品推荐

