指向方法错误的全局函数指针“类型不匹配”

eli*_*ang 5 rust

我想创建一个指向类方法的全局函数指针,所以我做了类似以下最小可重现示例的操作:

struct Foo<'a> {
    data: &'a str,
}

impl<'a> Foo<'a> {
    pub fn foo(&self) {
        println!("{}", self.data);
    }
}

type FooFn = fn(&Foo);

const FUNC: FooFn = Foo::foo;

fn main() {
    let data = String::from("hello");
    let foo = Foo { data: &data };
    FUNC(&foo);
}
Run Code Online (Sandbox Code Playgroud)

铁锈游乐场

rustc给了我这个错误:

$ rustc test.rs
error[E0308]: mismatched types
  --> test.rs:13:21
   |
13 | const FUNC: FooFn = Foo::foo;
   |                     ^^^^^^^^ one type is more general than the other
   |
   = note: expected fn pointer `for<'r, 's> fn(&'r Foo<'s>)`
              found fn pointer `for<'r> fn(&'r Foo<'_>)`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
Run Code Online (Sandbox Code Playgroud)

这个错误想表达什么?我该如何修复它?

Sve*_*ach 5

Rust 中的函数指针可以具有早期绑定晚期绑定的生命周期参数。需要在创建函数指针时指定早期绑定生命周期参数。后期绑定生命周期参数仅在调用指针指向的函数时指定并且每次调用该函数时该参数都可以不同。

函数指针类型FooFn有两个后期绑定生命周期参数。正如错误消息中所述,它的定义相当于

let FooFn = for<'r, 's> fn(&'r Foo<'s>);
Run Code Online (Sandbox Code Playgroud)

但类型Foo::foo不同。只有在完全指定关联函数的类型后,才能查找关联函数。换句话说,self 类型的所有生命周期参数都需要提前绑定。这意味着Foo::foo具有一个早期绑定和一个后期绑定生命周期参数。的生命周期参数Foo在创建函数指针时固定,并且只能在该特定生命周期内调用该函数指针。'_编译器在错误消息中表示了这个尚未确定的生命周期。(在这种情况下,稍后'_被推断为'static,因为它是唯一在这里有意义的固定生命周期,但这与这个问题并不真正相关。)

有几种方法可以解决这个问题。一种方法是创建foo()一个自由函数:

fn foo(foo: &Foo) {
    println!("{}", foo.data);
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是封装Foo::foo一个简单的闭包:

const FUNC: FooFn = |f| Foo::foo(f);
Run Code Online (Sandbox Code Playgroud)

这样,我们引用的函数就不再是关联函数,并且所有生命周期参数都可以进行后期绑定。