我正在尝试编写这个简单的代码:
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
免费功能怎么可能没有静态生命周期?这段代码怎么可能不安全?
答案 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;
}