使用async块与ServiceFn实现tower::Layer遇类型推导错误求助
解决Tower layer_fn中async块的类型推导错误
方案一:使用泛型约束明确Service类型
将layer_fn的闭包参数改为泛型类型并添加Service约束,让编译器能明确追踪请求、响应和错误类型:
use std::convert::Infallible; use tower::Service; tower::ServiceBuilder::new() .layer_fn(|mut service: S| { tower::service_fn(move |request: String| { async move { let response: Result<String, Infallible> = service.call(request).await; // 这里可以添加需要await的业务逻辑 response } }) }) .service_fn(|request: String| { async move { Ok::<_, Infallible>(request) } });
原理:通过泛型约束S: Service<String, Response = String, Error = Infallible>,直接明确了下游Service的请求类型、响应类型和错误类型,编译器可以在async块中准确推导service.call(request)返回的Future类型,解决类型推断失败的问题。
方案二:用Turbofish明确call方法的类型参数
如果需要保留ServiceFn<_>的标注,可以通过Turbofish语法直接指定call方法的类型参数:
use std::convert::Infallible; use tower::util::ServiceFn; tower::ServiceBuilder::new() .layer_fn(|mut service: ServiceFn<_>| { tower::service_fn(move |request| { async move { // 用Turbofish指定请求类型为String,帮助编译器推导返回类型 let response = service.call::<String, _, _>(request).await; // 业务逻辑处理 response } }) }) .service_fn(|request: String| { async move { Ok::<_, Infallible>(request) } });
原理:Service::call是一个带多个类型参数的方法,在async块中编译器无法自动推导这些参数,通过turbofish语法明确指定请求类型为String,可以让编译器反向推导出返回的Future和结果类型。
错误原因分析
原代码中直接将参数标注为ServiceFn<_>,占位符类型_在async块中无法被编译器正确解析——因为await会引入Future类型,而编译器需要明确的类型信息来构建这个Future。通过上述两种方式给编译器提供足够的类型线索,就能解决E0698类型推断错误。
内容的提问来源于stack exchange,提问作者linuskmr
相关产品推荐
相关产品推荐

