Rust E0277错误:FnMut闭包签名不匹配如何正确传handler
问题描述
我为多个结构体实现了Processor trait以复用相似逻辑,该trait提供collect_responses函数,接收handler向量并返回各handler生成的响应向量。当前代码无法编译,抛出如下错误:
error[E0277]: expected a `FnMut<(HandlerInput<'_>,)>` closure, found `dyn for<'r, 's> FnMut(&'r mut HandlerInput<'s>) -> Result<HandlerOutput, std::io::Error>` --> src/lib.rs:146:18 | 146 | self.process(handler, vec![]); | ^^^^^^^ expected an `FnMut<(HandlerInput<'_>,)>` closure, found `dyn for<'r, 's> FnMut(&'r mut HandlerInput<'s>) -> Result<HandlerOutput, std::io::Error>` | = help: the trait `FnMut<(HandlerInput<'_>,)>` is not implemented for `dyn for<'r, 's> FnMut(&'r mut HandlerInput<'s>) -> Result<HandlerOutput, std::io::Error>` = note: expected a closure with arguments `(&mut HandlerInput<'_>,)` found a closure with arguments `(HandlerInput<'_>,)` = note: required because of the requirement
沙箱示例可查看完整上下文。
涉及的trait代码如下:
pub trait Processor { fn process_input(input: HandlerInput) -> Result<Vec<HandlerOutput>, Error>; fn collect_responses( handlers: Vec<Box<dyn FnMut(&mut HandlerInput) -> Result<HandlerOutput, Error>>>, input: HandlerInput ) -> Result<Vec<HandlerOutput>, Error> { let responses = handlers .iter() .map(|func| func(&mut input)) .filter(|r| match r { Ok(_) => true, _ => false, }) .map(|r| r.unwrap()) .collect::<Vec<HandlerOutput>>(); return if responses.is_empty() { Err( Error::new( ErrorKind::Other, "No successful response" ) ) } else { Ok(responses) } } }
报错位置的方法代码如下:
fn process<F>(&mut self, handler: F, data: Vec<u8>) where F: FnMut(HandlerInput) -> Result<HandlerOutput, Error> { let response: Result<HandlerOutput, Error> = handler(HandlerInput { session: &mut self.session, data: Some(data), }); match response.unwrap() { HandlerOutput::Data(result) => { self.handle_write(result).unwrap(); }, HandlerOutput::ConnectionRequest(host, port) => { self.connect(&host[..], port); }, HandlerOutput::Void => {}, } }
更新: 调用process方法的代码如下:
let handlers = AuthProcessor::init(); for handler in handlers { self.process(handler, vec![]); }
请问如何才能正确向self.process传入handler参数?
错误原因
核心问题是闭包参数签名不匹配:
- 你存入
Vec的handler类型是Box<dyn FnMut(&mut HandlerInput) -> Result<HandlerOutput, Error>>,要求接收&mut HandlerInput可变引用作为参数 - 但
process方法的泛型约束要求F: FnMut(HandlerInput) -> Result<HandlerOutput, Error>,要求接收HandlerInput所有权作为参数
两者是完全独立的FnMut实现,编译器无法自动转换,因此直接传参会报类型不匹配错误。
修复方案
统一两处的参数签名即可,二选一:
方案1(最小改动):修改process方法约束,匹配现有handler签名
和collect_responses的调用逻辑保持一致,将process的泛型约束改为接收可变引用,调整内部调用逻辑:
fn process<F>(&mut self, mut handler: F, data: Vec<u8>) where F: FnMut(&mut HandlerInput) -> Result<HandlerOutput, Error> { let mut input = HandlerInput { session: &mut self.session, data: Some(data), }; let response: Result<HandlerOutput, Error> = handler(&mut input); match response.unwrap() { HandlerOutput::Data(result) => { self.handle_write(result).unwrap(); }, HandlerOutput::ConnectionRequest(host, port) => { self.connect(&host[..], port); }, HandlerOutput::Void => {}, } }
方案2:修改handler集合类型,匹配现有process签名
如果你确实需要handler获取HandlerInput的所有权,就把collect_responses的参数类型、AuthProcessor::init返回的Vec元素类型统一改成Box<dyn FnMut(HandlerInput) -> Result<HandlerOutput, Error>>。注意这种写法下调用多个handler时,需要为每个handler单独构造新的HandlerInput实例,否则第一个handler拿走所有权后后续变量无法使用。
内容的提问来源于stack exchange,提问作者Sergio Ivanuzzo
相关产品推荐
相关产品推荐

