相关疑难解决方法(0)

为什么`std :: mem :: drop`与排名较高的特征范围中的闭包| _ |()不完全相同?

的实现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)

closures type-inference traits higher-kinded-types rust

9
推荐指数
2
解决办法
160
查看次数

Rust:为什么将闭包绑定到变量会改变类型?

我有这个(最简化的)代码:

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) 编译了完全相同的代码,得到了一个更好的错误: …

closures rust

9
推荐指数
1
解决办法
130
查看次数

如何将引用参数传递给盒装闭包?

我想存储一个回调,它可以采用不同类型的参数(拥有的值和引用),还可以修改其环境(因此是 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)

closures callback rust

2
推荐指数
1
解决办法
94
查看次数