lambda - 为什么这个闭包需要内联或 `dyn` ? `dyn` 在这里做什么?

标签 lambda rust closures lifetime borrow-checker

我对下面的生命周期发生了什么感到困惑:

struct Foo{}
impl Foo {
    fn foo(&self, _s: &str) {}
}

fn main() {
    let foo = &Foo{};
    let closure = |s| foo.foo(s);

    // Part 1: error message about wrong lifetime in FnOnce
    take_closure(closure); 

    // Part 2: no error when inlined
    take_closure(|s| foo.foo(s));

    // Part 3: no error when `dyn`d and given explicit signature
    let closure: &dyn Fn(&str) -> _ = &|s| foo.foo(s);
    take_closure(closure);
}

fn take_closure(f: impl Fn(&str) -> ()) {
    let s = get_string();
    f(&s)
}

fn get_string() -> String {
    "".to_string()
}

playground

  1. 为什么第 1 部分会出错?
  2. 为什么第 2 部分没有错误?
  3. 为什么第 3 部分没有错误以及第 3 部分中实际发生了什么? Rust 会创建 vtable 吗? LLVM 输出在 2 和 3 之间不同
  4. 有更好的方法吗?内联很丑陋,dyn 也很丑陋,让我想知道它到底做了什么。

最佳答案

Why does Part 1 error?

当闭包的声明与其使用位置分开时,Rust 的类型推断不能很好地决定闭包应该具有什么类型。当闭包接受引用时,编译器通常假设将涉及一些特定生命周期,而不是此处实际要求的“调用者关心提供的任何生命周期”。

事实上,有 an active Rust RFC to improve this通过添加另一种方法来指定闭包的生命周期参数。 (RFC 还包含一个示例,其中做出相反的生命周期假设是行不通的。)

what actually happens in part 3? Does Rust make a vtable?

是的,每当您使用dyn 时都会涉及到一个vtable。这与这里的根本原因并不特别相关。只是 dyn Fn(&str) 中省略的生命周期以您需要的方式得到解决,而不是您不需要的方式。

Is there a better way? Inlining is ugly and dyn is both ugly and makes me wonder about what it actually does.

将闭包直接放在使用它的函数调用表达式中是 非常 常见的 Rust 风格,我建议您尽可能坚持使用它,因为它也是与类型推断一起使用的良好方式。

在需要多次使用闭包的情况下,作为一种解决方法,您可以通过一个限制其类型的函数传递闭包:

fn string_acceptor<F: Fn(&str) -> ()>(f: F) -> F {
    f
}

...

    let foo = &Foo{};
    let closure = string_acceptor(|s| foo.foo(s));

关于lambda - 为什么这个闭包需要内联或 `dyn` ? `dyn` 在这里做什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71087386/

相关文章:

c++ - for_each 用 vector<bool> 的 lambda 就地修改

c++ - 使用 lambda 调用的 move 构造函数

调试失败!在图书馆

Swift:未初始化返回闭包的惰性变量

rust - 将 Struct <'a>::method as a ` 传递给 <'a> Fn(&Foo<' a>)` 以在闭包中使用

c# - 如何获取 T 函数中使用的属性名称字符串

java - 坚持使用 java8 lambda 表达式

javascript - 如何在javascript闭包调用中生成动态字符串

concurrency - 线程生命周期错误

rust - 如何将创建包含具有生命周期的 Cell 的结构的函数传递给另一个函数?