Rust如何将Future作为函数参数传递?类型不匹配编译错误怎么解决?
报错原因
- Rust 中
Futuretrait 的poll方法要求传入Pin<&mut Self>才能执行轮询操作,不可变引用&dyn Future没有实现Futuretrait,无法直接进行await操作,这是编译报错的直接原因。 - 你对 Rust async 函数返回值的理解存在小偏差:Rust 的
async fn hello() -> Query不是直接返回Query类型,而是返回一个实现了Future<Output = Query>的匿名类型,它本身就符合参数类型要求,问题出在你额外取了不可变引用传递。
对比你熟悉的 Scala Future:Scala 的 Future 是主动执行的,句柄可以随意拷贝、引用传递;而 Rust 的 Future 是惰性执行的,轮询时需要可变访问权限来修改内部状态,因此无法通过不可变引用直接执行 await。
解决方案
方案1:静态分发(推荐,无额外性能开销)
直接用泛型接收 Future 所有权,不需要引用,也是 Rust 传递 Future 参数的最常用写法:
use std::future::Future; struct Person; struct DatabaseError; type Query = Result<Vec<Person>, DatabaseError>; // 泛型约束:接收任意实现了 Future<Output = Query> 的类型 async fn hello_future<F: Future<Output = Query>>(future: F) -> bool { future.await.is_ok() } async fn hello() -> Query { unimplemented!() } async fn example() { let f = hello(); // 直接传值,不需要取引用 hello_future(f); } fn main() {}
方案2:动态分发(适合需要统一不同 Future 类型的场景)
如果确实需要动态分发(比如要把不同类型的 Future 放到同一个集合里),可以用装箱的动态 Future:
use std::future::Future; use std::pin::Pin; struct Person; struct DatabaseError; type Query = Result<Vec<Person>, DatabaseError>; // 也可以直接用 futures 库提供的 BoxFuture 别名,本质和下面的定义一致 type DynFuture = Pin<Box<dyn Future<Output = Query>>>; async fn hello_future(future: DynFuture) -> bool { future.await.is_ok() } async fn hello() -> Query { unimplemented!() } async fn example() { let f = hello(); // 把 Future 装箱之后传递 hello_future(Box::pin(f)); } fn main() {}
内容的提问来源于stack exchange,提问作者ecoe
相关产品推荐
相关产品推荐

