我构建了一个无法工作的闭包示例,也找不到它不工作的任何原因。为什么最后一次关闭时编译失败?
struct S {}
fn filter<P>(predicate: P)
where
P: Fn(&S) -> bool,
{
predicate(&S {});
}
fn main() {
// this works
filter(|_s| true);
// this also works
fn cb1(_s: &S) -> bool {
true
}
filter(cb1);
// but this doesn't work
let cb2 = |_s| true;
filter(cb2);
}
输出:
error[E0631]: type mismatch in closure arguments
--> /tmp/closure.rs:19:5
|
18 | let cb2 = |_s| true;
| --------- found signature of `fn(_) -> _`
19 | filter(cb2);
| ^^^^^^ expected signature of `for<'r> fn(&'r S) -> _`
|
note: required by `filter`
--> /tmp/closure.rs:3:1
|
3 | fn filter<P>(predicate: P) where P: Fn(&S) -> bool,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0271]: type mismatch resolving `for<'r> <[closure@/tmp/closure.rs:18:15: 18:24] as std::ops::FnOnce<(&'r S,)>>::Output == bool`
--> /tmp/closure.rs:19:5
|
19 | filter(cb2);
| ^^^^^^ expected bound lifetime parameter, found concrete lifetime
|
note: required by `filter`
--> /tmp/closure.rs:3:1
|
3 | fn filter<P>(predicate: P) where P: Fn(&S) -> bool,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
最佳答案
来自以下Type mismatches resolving a closure that takes arguments by reference和 How to declare a lifetime for a closure argument?看来解决方案是改变:
fn filter<P>(predicate: P)
where
P: Fn(&S) -> bool,
{
predicate(&S {});
}
至
fn filter<'a, P>(predicate: P)
where
P: Fn(&'a S) -> bool,
{
predicate(&S {});
}
虽然我不知道为什么。当闭包被内联指定与存储在变量中并稍后使用时,它似乎与推断的生命周期相关。但当 &S
不是返回的结果时,尚不清楚为什么 &S
需要 'a
生命周期。如果您明白这一点,请在评论中解释。
尽管这个问题已“解决”,但最初发布的精简失败案例实际上并不能帮助我解决真正的问题,因为我无法编辑遇到问题的代码源 https://docs.rs/walkdir/2.2.9/walkdir/struct.IntoIter.html#method.filter_entry
当我尝试将存储的回调传递到 filter_entry
方法时,问题就出现了。解决方案是在 filter_entry
签名中放入显式生命周期,如本文前面所述,但只有在您想要编辑第三方代码时才可以这样做。我认为不幸的是,这个特定问题的答案是“你不能使用带有 filter_entry
的存储闭包”
关于rust - 为什么这个简单的闭包会失败,而其他两个函数会成功?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58773989/