Rust中重新借用`impl Read`为何能避免值移动错误?
Rust中ZlibDecoder使用时的移动与重新借用问题
原始代码
fn read_data(reader: &mut (impl Read + Seek), is_compressed: bool) -> Result<f64> { let start_pos = reader.stream_position()?; let mut zlib_decoder; let mut compressed_reader: &mut dyn Read = if !is_compressed { reader } else { zlib_decoder = ZlibDecoder::new(reader); &mut zlib_decoder }; let data = compressed_reader.read_f64()?; // 跳转到下一段数据 reader.seek(SeekFrom::Start(start_pos + 100))?; Ok(data) }
编译错误信息
error[E0382]: borrow of moved value: `reader` | 604 | fn read_data(reader: &mut (impl Read + Seek), is_compressed: bool) -> Result<f64> { | ------ move occurs because `reader` has type `&mut impl Read + Seek`, which does not implement the `Copy` trait ... 621 | zlib_decoder = ZlibDecoder::new(reader); | ------ value moved here ... 653 | reader.seek(SeekFrom::Start(start_pos + 100))?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
问题原因
reader的类型是&mut impl Read + Seek,这是一个未实现Copy trait的可变引用抽象类型。当直接将reader传入ZlibDecoder::new时,相当于把这个可变引用的所有权完全转移给了ZlibDecoder,原变量reader因此失效,后续调用reader.seek自然会触发“使用已移动值”的错误。
解决方法的原理
将ZlibDecoder::new(reader)改为ZlibDecoder::new(&mut *reader)后,代码能正常运行,核心在于**重新借用(reborrow)**机制:
*reader是对可变引用的解引用操作,得到被引用的底层对象(类型为impl Read + Seek);&mut *reader基于这个底层对象创建了一个新的、生命周期更短的可变引用;- 这个新引用被传递给
ZlibDecoder时,只是临时借出使用权,并不会转移原有reader引用的所有权; - 当
compressed_reader的生命周期结束(即ZlibDecoder使用完毕),新引用的借用关系解除,原有reader的可变引用恢复可用,后续的reader.seek调用就不会再触发错误。
内容的提问来源于stack exchange,提问作者Timmmm
相关产品推荐
相关产品推荐

