防锈功能没有静态寿命?

Phi*_*ppe 8 lifetime rust

我正在尝试使这个简单的代码编译:

fn dox(x: u8) -> u8 { x*2 }

fn main() {
    let cb: &'static (Fn(u8) -> u8) = &dox;
}
Run Code Online (Sandbox Code Playgroud)

但它失败了Rust 1.9:

x.rs:4:40: 4:43 error: borrowed value does not live long enough
x.rs:4     let cb: &'static (Fn(u8) -> u8) = &dox;
                                              ^~~
note: reference must be valid for the static lifetime...
x.rs:4:44: 5:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 4:43
x.rs:4     let cb: &'static (Fn(u8) -> u8) = &dox;
x.rs:5 }
error: aborting due to previous error
Run Code Online (Sandbox Code Playgroud)

自由函数如何没有静态生命周期?这段代码怎么会不安全?

小智 8

类型&dox不是&Fn(u8) -> u8(或甚至&fn(u8) -> u8),它只是强制性的 &Fn(u8) -> u8.因此,你实际上是在拿一个临时的地址.'static即使他们原则上可以将临时工作提升到终身'static.例如,此代码也不起作用:

fn main() {
    let a: &'static i32 = &5;
}
Run Code Online (Sandbox Code Playgroud)

有一些解决方法.通常,可以只显式创建一个static变量并引用它:

fn main() {
    static FIVE: i32 = 5;
    let a: &'static i32 = &FIVE;
}
Run Code Online (Sandbox Code Playgroud)

在你的特定情况下,不能直接工作,因为Fn(u8) -> u8是一个未经过类型化的特性(特别是一个特征)所以你不能把它放在一个static.你可以这样做:

fn main() {
    static DOX: fn(u8) -> u8 = dox; // note: fn, not Fn
    let a: &'static Fn(u8) -> u8 = &DOX;
}
Run Code Online (Sandbox Code Playgroud)

但是,对Fn*特征对象的静态引用是一件相当愚蠢的事情.可以作为'static参考的闭包非常罕见,因此您也可以使用普通fn(u8) -> u8类型并避开整个终身业务.


She*_*ter 4

从 Rust 1.21 开始,“静态提升”会自动执行,原始代码会按原样编译。

此代码也可以编译:

fn main() {
    let a: &'static i32 = &5;
}
Run Code Online (Sandbox Code Playgroud)

此外,不从环境中捕获任何内容的闭包可以自动转换为函数指针,因此您也不需要创建单独的函数:

fn main() {
    let cb: fn(u8) -> u8 = |x| x * 2;
}
Run Code Online (Sandbox Code Playgroud)