防锈功能没有静态寿命?

时间:2016-06-26 21:08:26

标签: rust lifetime

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

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

fn main() {
    let cb: &'static (Fn(u8) -> u8) = &dox;
}

但它失败了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

免费功能怎么可能没有静态生命周期?这段代码怎么可能不安全?

2 个答案:

答案 0 :(得分:8)

&dox的类型不是&Fn(u8) -> u8(甚至是&fn(u8) -> u8),它只是可强制 &Fn(u8) -> u8。因此,您实际上是在取一个临时的地址。即使他们原则上可以'static,临时工也不会晋升到'static。例如,此代码无效:

fn main() {
    let a: &'static i32 = &5;
}

这有一些解决方法。通常,人们可以明确地创建一个static变量并引用它:

fn main() {
    static FIVE: i32 = 5;
    let a: &'static i32 = &FIVE;
}

在您不具备直接作用的特定情况下,因为Fn(u8) -> u8是未归类的类型(特别是特征),因此您无法将其放在static中。你可以这样做:

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

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

答案 1 :(得分:2)

从Rust 1.21开始,将自动执行“静态升级”,并且原始代码将按原样编译。

此代码也可以编译:

class Test {
    static public function func($value, $validation) {
        $validation->error('field','Some error desc');
        return false;
    }
}

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

fn main() {
    let a: &'static i32 = &5;
}