Rust中克隆HashMap<String, Object>如何避免被移入闭包?
错误原因
你遇到的是Rust trait对象默认生命周期约束导致的编译错误:没有标注生命周期的Box<dyn Fn()> trait对象默认携带'static约束,要求闭包捕获的所有变量要么本身是'static生命周期,要么所有权被转移进闭包。
你当前代码中的闭包仅借用了栈上的hashs变量,而hashs会在所在函数执行结束后销毁,不满足'static约束,因此触发生命周期报错。
解决方案
方案1:转移克隆后的HashMap所有权进闭包(无需修改错误工具函数)
你可以在闭包外提前克隆hashs,再通过move关键字将克隆后的实例所有权转移进闭包,满足'static约束:
// 提前克隆HashMap,后续将所有权转移到闭包内 let hashs_clone = hashs.clone(); ErrorGenerator::error( "UnknownIdentifier", &format!("unknown identifier: `{}`, this identifier could not be found", tokenc.repr()), tokenc.line, tokenc.col, tokenc.file, Box::new(move || { let mut hashc: Vec<String> = hashs_clone.into_keys().collect(); hashc.sort(); // 后续实现最接近匹配提示逻辑 }), );
该方案改动最小,仅需要调整调用侧代码即可。
方案2:修改错误函数的生命周期约束(避免非必要克隆)
由于error函数执行完after_f后会立刻调用exit(1)终止程序,闭包不需要持有很长的生命周期,你可以修改error函数的定义,为闭包添加非'static的生命周期约束:
#[allow(non_snake_case)] mod ErrorGenerator { // 为闭包添加生命周期'a,取消默认的'static约束 pub fn error<'a>(name: &str, explanation: &str, line: usize, col: usize, file: String, after_f: Box<dyn Fn() + 'a>) -> ! { eprintln!("\n[ERROR] {}, Line {:?}, Column {:?}", file, line, col); eprintln!(" {}: {}", name, explanation); after_f(); std::process::exit(1); } }
修改后你原来的调用代码不需要做任何改动,闭包可以直接借用外部的hashs变量,甚至不需要克隆就能直接读取键列表,性能更好。
内容的提问来源于stack exchange,提问作者kaiserthe13th
相关产品推荐
相关产品推荐

