4

我有以下代码

use std::future::Future;
fn main() {
    handle(Test::my_func);
}

fn handle<Fut>(fun: for<'r> fn(&'r mut Test) -> Fut) -> bool
where
    Fut: Future<Output = ()>,
{
    true
}

struct Test {}

impl Test {
    pub async fn my_func<'r>(&'r mut self) -> () {
        ()
    }
}

此外,您可以在Rust Playground上在线运行它。

出现以下错误:

error[E0308]: mismatched types
  --> src/main.rs:4:12
   |
4  |     handle(Test::my_func);
   |            ^^^^^^^^^^^^^ one type is more general than the other
...
17 |     pub async fn my_func<'r>(&'r mut self) -> () {
   |                                               -- checked the `Output` of this `async fn`, found opaque type
   |
   = note: while checking the return type of the `async fn`
   = note: expected fn pointer `for<'r> fn(&'r mut Test) -> impl Future`
              found fn pointer `for<'r> fn(&'r mut Test) -> impl Future`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground`

To learn more, run the command again with --verbose.

现在,这真的很奇怪,因为它清楚地表明它正在得到它所期望的。我不明白哪种类型比哪种更通用。我对生命周期的了解不足以调试此代码。有人可以对此有更多的了解吗?

4

1 回答 1

6

有时你可以从 nightly 编译器中得到更好的错误:

16 |     pub async fn my_func<'r>(&'r mut self) -> () {
   |                                               ^^ checked the `Output` of this `async fn`, found opaque type
   = note: expected fn pointer `for<'r> fn(&'r mut Test) -> impl Future`
              found fn pointer `for<'r> fn(&'r mut Test) -> impl for<'r> Future`

简单来说,这意味着您希望fun成为一个函数,该函数返回一个实现该Future特征的结构,但具有隐式+ 'static绑定,这意味着该结构不能具有仅在'r.

但是,Test::my_func确实想参考&mut 'r self,因此该程序被编译器拒绝。

您可以想象类似的东西for<'r> fn(&'r mut Test) -> (impl Future + 'r),但这目前不被rustc接受,并且AFAIK没有任何方法可以做到这一点(没有不安全或拳击一切)。

根据您的用例,您可能能够摆脱:

fn handle<'a, Fut>(fun: impl Fn(&'a mut Test) -> Fut) -> bool
where
    Fut: Future<Output = ()> + 'a,
{
    true
}

这是有效的,因为我们需要一个生命周期 ( 'a),我们可以为Fut: Future<Output = ()> + 'a边界命名,而不是任何生命周期 ( for<'r> ..),我们无法在该边界中命名,但这更具限制性。

于 2021-08-09T07:18:28.833 回答