Rust使用可变引用指针循环时出现E0499可变借用错误问题
Rust链表可变遍历借用冲突问题原因解析
错误根本原因
这个报错是当前稳定版Rust默认借用检查器的生命周期推导限制导致的,具体逻辑如下:
- 你在
match &mut p.next这一步对*p产生了一个可变借用,这个借用的产物n是下一个节点的可变引用 - 当你在
Some分支执行p = n时,相当于把p这个可变指针的生命周期和刚才的&mut p.next借用的生命周期绑定到了一起:编译器会认为只要p还在被使用,最初的那个可变借用就不能结束,否则p指向的引用就会失效 - 借用检查器目前不会对分支的互斥性做精细化的生命周期分析:哪怕你走的是根本不会产生
n的None分支,或者循环结束后才调用grow,编译器依然判定最初的可变借用仍在生效,此时你再调用p.grow()(需要再次可变借用*p)就会触发二次可变借用冲突 - 你去掉
p = n后编译正常,正是因为此时&mut p.next的借用仅在match表达式内部生效,match结束后借用自动释放,不会和后续p的使用产生冲突。
可行的修复方案
你可以换一种遍历写法避开这个生命周期推导限制,比如先判断尾节点再取引用:
struct A { next: Option<Box<A>>, } impl A { fn grow(&mut self) { self.next = Some(Box::new(A { next: None })); } } fn main() { let mut a = A{ next: Some(Box::new(A { next: None }))}; let mut p = &mut a; loop { match p.next { Some(_) => p = p.next.as_mut().unwrap(), None => { p.grow(); break; } } } }
也可以开启nightly版本的Polonius借用检查器,你的原始代码可以直接正常编译。
内容的提问来源于stack exchange,提问作者Determinant
相关产品推荐
相关产品推荐

