我正在Rust中读取anyhow
crate 的代码。我不完全了解particular line:
{
let vtable = &ErrorVTable { ... };
construct(vtable, ...);
}
fn construct(vtable: &'static ErrorVTable, ...);
我们似乎创建了一个ErrorVTable
结构,并返回对其具有生命周期`static的引用。我希望编译器在函数堆栈上创建一个结构,并返回对其的引用,从而导致奇怪的内存问题。但是似乎编译器检测到在编译时推断出的所有可能的
E
的此变量,并以某种方式为它们创建了静态变量?这实际上如何运作?
最佳答案
考虑以下简化代码:
struct Foo {
x: i32
}
fn test(_: &'static Foo) {}
fn main() {
let f = Foo{ x: 42 };
test(&f);
}
如预期的那样,它不会与以下消息一起编译:
f
does not live long enough
但是,这种稍微的变化确实可以编译:
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的确切规则有些复杂,可能会在较新的编译器版本中进行扩展。
关于rust - 无论如何都隐式转换为静态生存期::错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63300111/