在这里的代码中
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));
}
我们想做has_hrl(func)
,但Rust只接受闭包has_hrl(|x| func(x))
。这是为什么?因为它适用于func2
中的具体类型,但不适用于泛型类型。
答案 0 :(得分:7)
在这个表达式中:
has_hrl(func)
编译器被迫选择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
必须为<{1}}实现<{1}} em>所有生命期Fn(&'a ()) -> &'a ()
。您的版本只需要'a
来实现F
一个具体的生命周期。您还会发现,如果Fn(&'a ()) -> &'a ()
尝试使用has_hrl
函数本地的生命周期调用闭包,则此版本不起作用,因为调用者无法通过该生命周期作为参数(这就是为什么引入了更高级别的生命周期界限)。