更高级别的生命周期和泛型不能很好地发挥

iop*_*opq 1 closures traits lifetime rust

在这里的代码中

trait Foo {
    type Output;
    fn foo(self) -> Self::Output;
}

impl<'a> Foo for &'a () {
    type Output = &'a ();
    fn foo(self) -> Self::Output {
        self
    }
}

fn func<F: Foo>(f: F) -> F::Output {
    f.foo()
}

fn func2<'a>(f: &'a ()) -> &'a () {
    func::<&'a ()>(f)
}

fn has_hrl<F: Fn(&()) -> &()>(f: F) {}

fn main() {
    //has_hrl(func); // FAILS
    has_hrl(func2);
    has_hrl(|x| func(x));
}
Run Code Online (Sandbox Code Playgroud)

我们想做has_hrl(func),但Rust只接受关闭has_hrl(|x| func(x)).这是为什么?因为它适用于类似的具体类型func2,但不适用于泛型类型.

Fra*_*gné 7

在这个表达式中:

has_hrl(func)
Run Code Online (Sandbox Code Playgroud)

编译器被迫选择一个特定的实例func.func是在通用的F: Foo,并为所有'a,&'a ()实现了Foo,但是编译器只能选择一个特定的'a实例func,因为类型变量不能代表的类型众多.因此,func::<&'a ()>没有实现for<'a> Fn(&'a ()) -> &'a (),它只实现Fn(&'x ()) -> &'x ()一个特定的生命周期'x.

如果你宣称这会工作has_hrl一样fn has_hrl<'a, F: Fn(&'a ()) -> &'a ()>(_: F) {}.但是,我的功率水平不足以解释为什么生命周期需要明确.- ljedrz

这是因为原来的声明有必然隐含的排名更高的寿命(绑定相当于F: for<'a> Fn(&'a ()) -> &'a ()),这意味着F必须实现Fn(&'a ()) -> &'a ()所有寿命'a.您的版本只需要F实现Fn(&'a ()) -> &'a ()一个具体的生命周期.您还会发现,如果has_hrl尝试使用has_hrl函数本地的生命周期调用闭包,则此版本不起作用,因为调用者不可能将该生命周期作为参数传递(这就是为什么引入了更高级别的生命周期边界的原因).