在正常函数和定义为闭包的函数之间似乎存在生命周期推断上的差异.请考虑以下最小示例:

fn foo(f: &String) -> &str {
    f
}

fn bar() {
    |f: &String| -> &str { f };
}

编译器(带有--edition=2021的Rustc 1.69.0)接受foo,但拒绝bar中的闭包(这是与foo相同的函数),并出现错误

error: lifetime may not live long enough
 --> clos.rs:8:33
  |
8 |     move |f: &String| -> &str { f };
  |              -           -      ^ returning this value requires that `'1` must outlive `'2`
  |              |           |
  |              |           let's call the lifetime of this reference `'2`
  |              let's call the lifetime of this reference `'1`

foo的情况下,我的理解是编译器将其go 掉

fn foo<'a>(f: &'a String) -> &'a str { ... }

为什么它不为关闭做同样的事情呢?有没有什么方法可以让我自己手动指定生存期(特别是,我应该把<'a>放在哪里来声明生存期)?

推荐答案

我认为这是因为对于函数,从来没有任何捕获的状态,因此输入和输出的生命周期几乎总是联系在一起的.对于闭包,生命周期可能来自环境.

您可以创建一个生成闭包的函数,这允许您使用impl Fn个语法,这似乎可以正确地推断生命周期,至少在本例中是这样的.如果捕获任何状态,则需要将其作为参数传递给生成器函数.

fn generate() -> impl Fn(&String) -> &str {
    |f: &String| -> &str { f }
}

如果它在某些情况下不起作用,您可以使用for语法来显式地指定生存期.

fn generate_for() -> impl for<'a> Fn(&'a String) -> &'a str {
    |f: &String| -> &str { f }
}

这个游戏有一个夜间功能:closure_lifetime_binder.稳定后,它将允许您向闭包表达式添加for个注释,而不仅仅是向特征添加注释.

#![feature(closure_lifetime_binder)]

fn bar_nightly() {
    for<'a> |f: &'a String| -> &'a str { f };
}

Rust相关问答推荐

通用池类型xsx

为什么幻影数据不能自动推断?

什么样的 struct 可以避免使用RefCell?

将JSON密钥转换为Polars DataFrame

从特征实现调用函数的Rust惯用方法

在自身功能上实现类似移动的行为,以允许通过大小的所有者进行呼叫(&;mut;self)?

MutexGuard中的过滤载体不需要克隆

为什么Rust函数的移植速度比C++慢2倍?

你是如何在铁 rust 一侧的金牛座获得应用程序版本的?

同时从不同线程调用DLL的不同函数会出现分段错误或产生STATUS_STACK_BUFFER_OVERRUN

如何为rust trait边界指定多种可能性

如何点击()迭代器?

为什么`AlternateScreen`在读取输入键时需要按Enter键?

用于实现获取 struct 体 id 的特征规范

从 rust 函数返回 &HashMap

如何递归传递闭包作为参数?

如何获取函数中borrow 的切片的第一部分?

你能告诉我如何在 Rust 中使用定时器吗?

Rust 跨同一文件夹中文件的可见性

带有库+多个二进制文件的Cargo 项目,二进制文件由多个文件组成?