如何调用以自身结构体为参数、且被结构体持有的Rust闭包?
解决Rust中结构体闭包成员调用自身的E0499错误
错误原因
这段代码触发E0499的核心问题是:在(self.f)(self)这一行,Rust会同时产生两次对*self的可变借用:
- 访问
self.f时,需要可变借用整个self来获取闭包成员; - 把
self作为参数传给闭包时,又需要一次可变借用。
Rust的借用检查器禁止同一时间存在多个对同一对象的可变借用,因此抛出错误。
解决方案
通过临时转移闭包的所有权,避免同时借用整个结构体。用std::mem::take或std::mem::replace先取出闭包(用默认值占位),调用闭包后再放回结构体。
修改后的完整代码:
use std::mem; type Thunk = Box<dyn FnMut(&mut Config) + Send + 'static>; struct Config { s: String, f: Thunk, } impl Config { fn run(&mut self) { // 取出闭包,用默认空闭包占位 let mut f = mem::take(&mut self.f); // 调用闭包,此时self的闭包成员已被替换,不会产生借用冲突 f(self); // 将原闭包放回结构体 self.f = f; } } fn main() { let mut cfg = Config { s: String::from("hello"), f: Box::new(|c| { println!("{}", c.s); // 测试修改结构体成员 c.s = String::from("modified"); }), }; cfg.run(); println!("{}", cfg.s); // 输出 modified }
代码说明
mem::take(&mut self.f)会把self.f替换为该类型的默认值(这里是一个空闭包),同时返回原来的闭包;- 调用
f(self)时,self的闭包成员已经被替换,此时借用的self和闭包不再存在重叠的可变借用; - 调用完成后把原闭包放回
self.f,恢复结构体的完整状态。
你也可以用mem::replace手动指定占位闭包,效果完全一致:
let mut f = mem::replace(&mut self.f, Box::new(|_| {}));
内容的提问来源于stack exchange,提问作者misterx527
相关产品推荐
相关产品推荐

