gpt4 book ai didi

rust - 为什么在闭包中调用函数与在 Rust 中直接调用函数时生命周期不同?

转载 作者:行者123 更新时间:2023-11-29 07:43:21 25 4
gpt4 key购买 nike

在下面的代码示例中:

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...

我在想:

  1. 导致最后两个语句行为不同的原因
  2. 第一个 unwrap_or_else(|| default_values()) 是否是处理此问题的正确方法,或者是否有更好的模式

最佳答案

发生这种情况是因为 default_values 实现了 Fn() -> &'static [u32] ,而不是 for<'a> Fn() -> &'a [u32] 。特征是 invariant ,所以你不能将“实现 Fn() -> &'static [u32] 的东西”强制为“实现 Fn() -> &'a [u32] 的东西”(对于一些小于 'a'static ),尽管从逻辑上讲, default_values 可以满足两者。

当它在闭包中被调用时,default_values() 返回一个 &'static [u32] ,但它可以立即被强制转换为 &'a u32 ,使闭包本身能够实现 Fn() -> &'a [u32] (其中 &'a 由编译器确定)。

至于为什么添加 as fn() -> &'static [u32] 有效,我假设编译器可以识别函数指针类型 fn() -> &'static [u32] 能够为任何 Fn() -> &'a [u32] 实现 'a 。我不确定为什么它不对普通函数和闭包也这样做;也许 future 的编译器版本会足够智能以允许原始代码。

另一种解决方案是使 default_values 的类型能够实现您需要的 Fn 特征:

fn default_values<'a>() -> &'a [u32] {
static VALUES: [u32; 3] = [1, 2, 3];
&VALUES
}

这里的签名不是说“这是一个返回 'static 引用的函数”,而是说“这是一个可以返回任何生命周期引用的函数”。我们知道“任何生命周期的引用”必须是 'static 引用,但编译器认为签名是不同的,因为它具有额外的自由度。 This change is sufficient to make your original example compile.

关于rust - 为什么在闭包中调用函数与在 Rust 中直接调用函数时生命周期不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53171108/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com