我想为特定类型的闭包实现一个trait。下面是一个最小的示例(playground):
trait Foo {
fn foo(&self, x: &u32);
}
impl<F> Foo for F
where F: Fn(&u32)
{
fn foo(&self, x: &u32) {
self(x)
}
}
fn main() {
let _: &FnOnce(&u32) = &|x| {}; // works
let _: &Foo = &|x| {}; // doesn't work
}
结果如下:
error: type mismatch resolving `for<'r> <[closure@<anon>:16:29: 16:35] as std::ops::FnOnce<(&'r u32,)>>::Output == ()`:
expected bound lifetime parameter ,
found concrete lifetime [--explain E0271]
--> <anon>:16:28
|>
16 |> let _: &Foo = &|x| {};
|> ^^^^^^^
note: required because of the requirements on the impl of `Foo` for `[closure@<anon>:16:29: 16:35]`
note: required for the cast to the object type `Foo`
error: type mismatch: the type `[closure@<anon>:16:29: 16:35]` implements the trait `std::ops::Fn<(_,)>`, but the trait `for<'r> std::ops::Fn<(&'r u32,)>` is required (expected concrete lifetime, found bound lifetime parameter ) [--explain E0281]
--> <anon>:16:28
|>
16 |> let _: &Foo = &|x| {};
|> ^^^^^^^
note: required because of the requirements on the impl of `Foo` for `[closure@<anon>:16:29: 16:35]`
note: required for the cast to the object type `Foo`
我已经尝试像这样显式地将HRTB添加到where
子句中:
where F: for<'a> Fn(&'a u32)
但它没有帮助。我还在impl
块上声明了生命周期,如下所示:
impl<'a, F> Foo for F
where F: Fn(&'a u32) { ... }
但是这会导致impl
块内的生存期错误。我认为这些错误是正确的,生命周期参数不能在impl
块上声明。
我如何修复这个例子?
查看这部分错误:
[…]实现了
std::ops::Fn<(_,)>
特性,但for<'r> std::ops::Fn<(&'r u32,)>
特性是必需的
我认为基本上没有足够的代码来允许正确推断类型。添加显式类型注释允许编译示例:
let _: &Foo = &|x: &u32| {};
这里有一个部分答案,从一个有趣的实验开始:
trait Foo {
fn foo(&self, x: &u32);
}
impl<F> Foo for F
where F: Fn(&u32)
{
fn foo(&self, x: &u32) {
self(x)
}
}
fn main() {
let f1: &Fn(&u32) = &|_x| {};
let f2: &Foo = &f1;
// but this fails:
// let f3: &Foo = &|_x| {};
f2.foo(&3);
}
(游乐场)我所做的就是将FnOnce
更改为Fn
以保持与trait的一致性,并将您的第一个闭包分配给&Foo
类型的绑定-并且这一个工作。
这告诉我trait本身是好的——在创建trait对象时推断闭包的类型是有问题的。回到错误,我们被告知闭包实现了std::ops::Fn<(_,)>
,但for<'r> std::ops::Fn<(&'r u32,)>
是必需的。这意味着您尝试的第一件事(将for<'r>...
添加到性状)没有任何效果,因为性状已经需要这样做。
在这一点上,我被困住了——我认为我没有足够详细地理解闭包的推理规则,以了解为什么有区别,或者如何使其工作。我希望有人能来把它填上!
免责声明:我不知道我在做什么。
以下作品:
trait Foo<'a> {
fn foo(&self, x: &'a u32);
}
impl<'a, F> Foo<'a> for F where F: Fn(&'a u32) {
fn foo(&self, x: &'a u32) {
self(x)
}
}