我想为特定类型的闭包实现特征。这是一个最小的例子(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
块上声明生命周期参数。
如何修复此示例?
答案 0 :(得分:5)
查看错误的这一部分:
[...]实现了特征
std::ops::Fn<(_,)>
,但特征for<'r> std::ops::Fn<(&'r u32,)>
是必需的
我认为基本上没有足够的代码来允许正确推断类型。添加显式类型注释允许编译示例:
let _: &Foo = &|x: &u32| {};
答案 1 :(得分:3)
这是一个部分答案,从一个有趣的实验开始:
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
以与特征保持一致,并将第一个闭包分配给类型为&Foo
的绑定 - 并且这一个工作。< / p>
这告诉我特征本身很好 - 在制作特征对象时推断闭包的类型是个问题。回到错误,我们被告知闭包实现std::ops::Fn<(_,)>
,但for<'r> std::ops::Fn<(&'r u32,)>
是必需的。这意味着您尝试的第一件事(将for<'r>...
添加到特征中)没有任何效果,因为特征已经需要这个。
此时我被卡住了 - 我认为我不太了解闭包的推理规则,看看为什么会有差异,或者如何让它起作用。我希望有人会来填补它!
答案 2 :(得分:0)
免责声明:我不知道我在做什么。
以下作品:
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)
}
}