【问题标题】:Implicit conversion to static lifetime in anyhow::Error无论如何隐式转换为静态生命周期::Error
【发布时间】:2020-08-07 10:38:57
【问题描述】:

我正在阅读 Rust 中 anyhow crate 的代码。有一个particular line我没完全掌握:

{
 let vtable = &ErrorVTable { ... };
 construct(vtable, ...);
}

fn construct(vtable: &'static ErrorVTable, ...);

我们似乎创建了一个ErrorVTable 结构,并返回一个对它的引用,该引用具有生命周期`static。我希望编译器在函数堆栈上创建一个结构,并返回对它的引用,从而导致奇怪的内存问题。

但似乎编译器检测到这个变量对于所有可能的E 在编译时推断并以某种方式为它们创建静态变量?这实际上是如何工作的?

【问题讨论】:

标签: rust reference


【解决方案1】:

考虑这个简化的代码:

struct Foo {
    x: i32
}

fn test(_: &'static Foo) {}

fn main() {
    let f = Foo{ x: 42 };
    test(&f);
}

正如预期的那样,它没有编译,带有消息:

f 活得不够长

然而,这种轻微的变化确实可以编译:

fn main() {
    let f = &Foo{ x: 42 };
    test(f);
}

不同的是,前者的Foo对象是本地的,有本地生命周期,所以不能建立'static的引用。但在后者中,实际对象是一个静态常量,因此它具有静态生命周期,f 只是对它的引用。

为了帮助查看差异,请考虑以下其他等效代码:

const F: Foo = Foo{ x: 42 };
fn main() {
    test(&F);
}

或者如果你使用一个实际的常量字面量:

fn test_2(_: &'static i32) {}
fn main() {
    let i = &42;
    test_2(&i);
}

当然,这仅在 Foo 构造的所有参数都为常量时才有效。如果任何值不是常量,那么编译器将静默切换到本地临时而不是静态常量,您将失去 'static 生命周期。

这个 constant promotion 的精确规则(有时被称为)有点复杂,可能会在更新的编译器版本中扩展。

【讨论】:

    猜你喜欢
    • 2021-01-03
    • 1970-01-01
    • 1970-01-01
    • 2011-09-12
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多