缺少顶级功能的实现

Missing implementation for top level functions

我正在尝试使一个特征可用于 Rust 中的顶级函数。

trait FnTrait {
    fn call(self);
}

impl FnTrait for fn() {
    fn call(self) {
        self()
    }
}

fn foo() {
    println!("Hello, World!")
}

fn main() {
    FnTrait::call(foo)
}

但是下面的代码无法通过 (Playground Link)

编译
error[E0277]: the trait bound `fn() {foo}: FnTrait` is not satisfied
  --> <anon>:16:5
   |
16 |     FnTrait::call(foo)
   |     ^^^^^^^^^^^^^ the trait `FnTrait` is not implemented for `fn() {foo}`
   |
   = help: the following implementations were found:
             <fn() as FnTrait>
   = note: required by `FnTrait::call`

我发现我可以通过强制转换 foo 来欺骗它编译

FnTrait::call(foo as fn())

但这很烦人,我程序中的某些函数比 foo 更复杂。有什么办法避免演员表?我的性格有什么问题吗?

Rust 中的每个函数都有自己的类型。如您所见,foo 不是 fn(),而是 fn() {foo};遗憾的是,这不是您可以在源代码中编写的实际类型,这只是编译器消息。存在这种区别是为了让编译器更容易让您将函数作为值传递,同时仍然能够内联调用。

结果是命名函数指针不能在没有转换或类型提示的情况下变成通用函数指针。例如,这有效:

fn foo() {
    println!("Hello, World!")
}

fn bar(f: fn()) {
    f()
}

fn main() {
    bar(foo)
}

但是,我不知道有什么方法可以利用它来使特性发挥作用。

前进的唯一方法是停止尝试为 函数指针 实现特征,而是为所有可调用的东西实现它:

trait FnTrait {
    fn call(self);
}

impl<F> FnTrait for F where F: FnOnce() {
    fn call(self) {
        self()
    }
}

fn foo() {
    println!("Hello, World!")
}

fn main() {
    foo.call();
}

(关于 的半相关回答。)

这将适用于任何可使用该签名调用的东西,包括函数和闭包。缺点是你只能有 one 这样的实现。您不能为任何其他签名实现此特征。

一个通用实现,或许多特定实现和大量手动转换。选择你的毒药。


顺便说一句:在 Rust 中没有 "top level function" 这样的东西,至少不是与其他类型的函数不同的东西。函数就是函数,不管它们出现在哪里。实例函数 a.k.a. 方法仍然是常规函数,只是它们的第一个参数被称为 "self".