更高等级的生命周期和泛型表现不佳
Higher rank lifetimes and generics not playing nicely
在此处的代码中
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
中的具体类型,但不适用于泛型类型。
在这个表达式中:
has_hrl(func)
编译器被迫选择 func
的一个特定实例。 func
在 F: Foo
上是通用的,对于所有 'a
、&'a ()
实现 Foo
,但编译器只能选择一个特定的 'a
来实例化func
,因为一个类型变量不能表示多种类型。因此,func::<&'a ()>
不会实现 for<'a> Fn(&'a ()) -> &'a ()
,它只会在一个特定的生命周期 'x
.
内实现 Fn(&'x ()) -> &'x ()
This would work if you declared has_hrl
like fn has_hrl<'a, F: Fn(&'a ()) -> &'a ()>(_: F) {}
. My power level is insufficient to explain why the lifetime needs to be explicit, though. – ljedrz
那是因为原始声明有一个隐含的更高级别的生命周期边界(该边界等同于 F: for<'a> Fn(&'a ()) -> &'a ()
),这意味着 F
必须为 [=40 实现 Fn(&'a ()) -> &'a ()
=]全部 生命周期'a
。您的版本只需要 F
来实现 Fn(&'a ()) -> &'a ()
一个具体的生命周期。您还会发现,如果 has_hrl
尝试使用 has_hrl
函数的本地生命周期调用闭包,则此版本不起作用,因为调用者不可能将该生命周期作为参数传递(这就是引入更高级别生命周期界限的原因。
在此处的代码中
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
中的具体类型,但不适用于泛型类型。
在这个表达式中:
has_hrl(func)
编译器被迫选择 func
的一个特定实例。 func
在 F: Foo
上是通用的,对于所有 'a
、&'a ()
实现 Foo
,但编译器只能选择一个特定的 'a
来实例化func
,因为一个类型变量不能表示多种类型。因此,func::<&'a ()>
不会实现 for<'a> Fn(&'a ()) -> &'a ()
,它只会在一个特定的生命周期 'x
.
Fn(&'x ()) -> &'x ()
This would work if you declared
has_hrl
likefn has_hrl<'a, F: Fn(&'a ()) -> &'a ()>(_: F) {}
. My power level is insufficient to explain why the lifetime needs to be explicit, though. – ljedrz
那是因为原始声明有一个隐含的更高级别的生命周期边界(该边界等同于 F: for<'a> Fn(&'a ()) -> &'a ()
),这意味着 F
必须为 [=40 实现 Fn(&'a ()) -> &'a ()
=]全部 生命周期'a
。您的版本只需要 F
来实现 Fn(&'a ()) -> &'a ()
一个具体的生命周期。您还会发现,如果 has_hrl
尝试使用 has_hrl
函数的本地生命周期调用闭包,则此版本不起作用,因为调用者不可能将该生命周期作为参数传递(这就是引入更高级别生命周期界限的原因。