的实现std::mem::drop记录如下:
pub fn drop<T>(_x: T) { }
Run Code Online (Sandbox Code Playgroud)
因此,我希望该封盖|_| ()(俗称马桶封盖)drop在两个方向上都可以按1:1的比例替换。但是,下面的代码显示drop与该函数的参数上绑定的较高特级特征不兼容,而抽水马桶则兼容。
fn foo<F, T>(f: F, x: T)
where
for<'a> F: FnOnce(&'a T),
{
dbg!(f(&x));
}
fn main() {
foo(|_| (), "toilet closure"); // this compiles
foo(drop, "drop"); // this does not!
}
Run Code Online (Sandbox Code Playgroud)
编译器的错误信息:
error[E0631]: type mismatch in function arguments
--> src/main.rs:10:5
|
1 | fn foo<F, T>(f: F, x: T)
| ---
2 | where
3 | for<'a> F: FnOnce(&'a T),
| …Run Code Online (Sandbox Code Playgroud) 我有这个(最简化的)代码:
fn returns_closure() -> Box<dyn Fn(&u64)> {
let closure = |_| ();
Box::new(closure)
}
Run Code Online (Sandbox Code Playgroud)
这不会编译并带有相当无用的错误消息:
error[E0308]: mismatched types
--> src/main.rs:3:5
|
3 | Box::new(closure)
| ^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected type `FnOnce<(&u64,)>`
found type `FnOnce<(&u64,)>`
Run Code Online (Sandbox Code Playgroud)
但是,当我不先将闭包绑定到变量,而是直接在 Box 的构造函数中创建它时,它确实会编译:
error[E0308]: mismatched types
--> src/main.rs:3:5
|
3 | Box::new(closure)
| ^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected type `FnOnce<(&u64,)>`
found type `FnOnce<(&u64,)>`
Run Code Online (Sandbox Code Playgroud)
为什么第一个编译失败,两者有什么区别?
编辑:埃蒙斯的回答似乎是正确的。我用 nightly 工具链 (1.52.0) 编译了完全相同的代码,得到了一个更好的错误: …
我想存储一个回调,它可以采用不同类型的参数(拥有的值和引用),还可以修改其环境(因此是 FnMut)。当使用引用调用回调时,我希望编译器强制该参数仅在闭包主体中有效。我尝试使用盒装闭包来实现这一点。
下面显示了一个最小示例:
fn main() {
let mut caller = Caller::new();
let callback = |x: &Foo| println!("{:?}", x);
caller.register(callback);
let foo = Foo{
bar: 1,
baz: 2,
};
//callback(&foo); // works
caller.invoke(&foo); // borrowed value does not live long enough
}
struct Caller<'a, T> {
callback: Box<dyn FnMut(T) + 'a>
}
impl<'a, T> Caller<'a, T> {
fn new() -> Self {
Caller {
callback: Box::new(|_| ()),
}
}
fn register(&mut self, cb: impl FnMut(T) + 'a) {
self.callback = Box::new(cb); …Run Code Online (Sandbox Code Playgroud)