Rust生命周期错误:无法同时多次可变借用*self问题排查
解决Rust中可变借用多次冲突的问题
问题代码
struct DrawBatch<'a> { triangles : &'a mut i32, } struct Batch<'a> { draw_batch : Vec<DrawBatch<'a>>, default_count : i32 } impl<'a> Batch<'a> { fn circle<'e: 'a>(&'e mut self) { // a circle is made up of multiple triangles (fan) self.triangle(); self.triangle(); } fn triangle<'m : 'a>(&'m mut self) { // draws a triangle let batch = self.get_last_batch(); // modify the batch, add triangles, etc *batch.triangles += 1; println!("triangle count: {}", batch.triangles); } fn get_last_batch<'r : 'a>(&'r mut self) -> &mut DrawBatch { if self.draw_batch.is_empty() { // there must always be at least one draw batch self.draw_batch.push(DrawBatch { triangles: &mut self.default_count }); } return self.draw_batch.last_mut().unwrap(); } } fn main() { let de = 0; let mut b = Batch{ draw_batch: Vec::new(), default_count : de }; b.circle(); }
错误信息
error[E0499]: cannot borrow
*selfas mutable more than once at a time
--> src/main.rs:13:9
|
9 | impl<'a> Batch<'a> {
| -- lifetime'adefined here
...
self.triangle(); first mutable borrow occurs here argument requires that *selfis borrowed for'aself.triangle(); ^^^^^^^^^^^^^^^ second mutable borrow occurs here
问题根源
你给triangle和get_last_batch方法添加的'm: 'a、'r: 'a生命周期约束是核心问题。该约束强制方法对self的可变借用生命周期'm/'r必须长于或等于Batch的生命周期'a,这意味着第一次调用self.triangle()时,self的可变借用会被锁定到整个Batch实例的生命周期,后续无法再次进行可变借用。
实际上这些约束完全多余:DrawBatch的'a已经绑定了default_count的生命周期,方法的借用生命周期只需要满足单次调用的范围即可,不需要和'a强行绑定。
修复后的代码
struct DrawBatch<'a> { triangles: &'a mut i32, } struct Batch<'a> { draw_batch: Vec<DrawBatch<'a>>, default_count: i32, } impl<'a> Batch<'a> { fn circle(&mut self) { // a circle is made up of multiple triangles (fan) self.triangle(); self.triangle(); } fn triangle(&mut self) { // draws a triangle let batch = self.get_last_batch(); // modify the batch, add triangles, etc *batch.triangles += 1; println!("triangle count: {}", batch.triangles); } fn get_last_batch(&mut self) -> &mut DrawBatch<'a> { if self.draw_batch.is_empty() { // there must always be at least one draw batch self.draw_batch.push(DrawBatch { triangles: &mut self.default_count, }); } self.draw_batch.last_mut().unwrap() } } fn main() { let mut de = 0; // 需要改为mut,因为要被可变借用 let mut b = Batch { draw_batch: Vec::new(), default_count: de, }; b.circle(); }
修复说明
- 移除多余生命周期约束:删除
circle、triangle、get_last_batch方法上自定义的生命周期参数和约束,让Rust的自动生命周期推导处理方法的借用周期。 - 明确返回类型生命周期:将
get_last_batch的返回类型改为&mut DrawBatch<'a>,让编译器明确返回的引用生命周期和Batch的'a一致,而非方法的临时借用周期。 - 修正可变变量:
main中的de改为mut,因为DrawBatch需要持有它的可变引用,否则会触发新的编译错误。
修改后,每次triangle调用对self的可变借用仅在调用期间有效,调用结束后借用自动释放,两次调用之间不会存在借用冲突,代码可以正常编译运行。
内容的提问来源于stack exchange,提问作者frankelot
相关产品推荐
相关产品推荐

