rust - 为什么在闭包中调用函数与在 Rust 中直接调用函数时生命周期不同?
问题描述
在以下代码示例中:
fn default_values() -> &'static [u32] {
static VALUES: [u32; 3] = [1, 2, 3];
&VALUES
}
fn main() {
let values: [u32; 3] = [4, 5, 6];
let optional_values: Option<&[u32]> = Some(&values);
// this compiles and runs fine
let _v = optional_values.unwrap_or_else(|| default_values());
// this fails to compile
let _v = optional_values.unwrap_or_else(default_values);
}
最后一条语句无法编译:
error[E0597]: `values` does not live long enough
--> src/main.rs:8:49
|
8 | let optional_values: Option<&[u32]> = Some(&values);
| ^^^^^^ borrowed value does not live long enough
...
12 | }
| - borrowed value only lives until here
|
= note: borrowed value must be valid for the static lifetime...
我在想:
- 发生了什么导致最后两个语句之间的行为差异
- 第一种是否
unwrap_or_else(|| default_values())
是正确的处理方式,或者是否有更好的模式
解决方案
发生这种情况是因为default_values
实施Fn() -> &'static [u32]
,但不是for<'a> Fn() -> &'a [u32]
。特征是不变的,因此您不能将“实现Fn() -> &'static [u32]
的东西”强制为“实现的东西Fn() -> &'a [u32]
”(对于一些'a
小于'static
),即使从逻辑上讲,default_values
可以同时满足两者。
在闭包中调用它时,default_values()
返回 a &'static [u32]
,但可以立即将其强制转换为 a &'a u32
,从而使闭包本身能够实现Fn() -> &'a [u32]
(其中&'a
由编译器确定)。
至于为什么添加as fn() -> &'static [u32]
有效,我假设编译器可以识别函数指针类型fn() -> &'static [u32]
能够实现Fn() -> &'a [u32]
任何'a
. 我不确定为什么它对普通函数和闭包也不这样做;也许未来的编译器版本可能足够智能以允许原始代码。
另一种解决方案是制作default_values
可以实现所需Fn
特征的类型:
fn default_values<'a>() -> &'a [u32] {
static VALUES: [u32; 3] = [1, 2, 3];
&VALUES
}
这里的签名不是说“这是一个返回'static
引用的函数”,而是说“这是一个可以返回任何生命周期的引用的函数”。我们知道“任何生命周期的引用”必须是'static
引用,但编译器认为签名是不同的,因为它具有额外的自由度。此更改足以使您的原始示例编译。
推荐阅读
- electron - 如何在 Electron 中制作一个透明的加载 GIF 窗口?
- android - 是否可以编写脚本将 PWA 应用程序添加到主屏幕?
- python - Python断言列表中的所有元素不是无
- html - 如何使用图像替换 Navbar.brand?
- python - 使用 scons 0.98.1 和 python2.7 无法使用旧版本构建 gem5(stt/sdo/invisispec)
- javascript - TypeError:无法读取未定义的属性(读取“地图”)ReactJs从文件中获取数据
- c# - 比赛开始创建房间后,Photon Unity中所有人离开后房间会消失吗?
- asp.net-core - 为使用 HotChocolate 框架和 ASP.NetCore 5.0 构建的 GraphQL 端点设置 Windows 身份验证
- vue.js - Vue/Nuxt.js 图片幻灯片
- javascript - 如何使用 socket.io 检索客户端