I am trying to make this simple code compile:
fn dox(x: u8) -> u8 { x*2 }
fn main() {
let cb: &'static (Fn(u8) -> u8) = &dox;
}
But it fails with 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
How is it possible that a free function does not have static lifetime? How could this code be unsafe?
As of Rust 1.21, "static promotion" is performed automatically and your original code compiles as-is.
This code compiles as well:
fn main() {
let a: &'static i32 = &5;
}
Additionally, closures which do not capture anything from their environment can be automatically converted to function pointers, so you don't need to create a separate function, either:
fn main() {
let cb: fn(u8) -> u8 = |x| x * 2;
}
The type of &dox
is not &Fn(u8) -> u8
(or even &fn(u8) -> u8
), it is merely coercible to &Fn(u8) -> u8
. Therefore, you're actually taking the address of a temporary. Temporaries aren't promoted to 'static
lifetime even if they could, in principle, be 'static
. For example this code doesn't work either:
fn main() {
let a: &'static i32 = &5;
}
There are some workarounds for this. Normally one can just explicitly create a static
variable and take the reference to that:
fn main() {
static FIVE: i32 = 5;
let a: &'static i32 = &FIVE;
}
In your specific case that doesn't work directly because Fn(u8) -> u8
is an unsized type (a trait, specifically) so you can't just put that in a static
. You can do this:
fn main() {
static DOX: fn(u8) -> u8 = dox; // note: fn, not Fn
let a: &'static Fn(u8) -> u8 = &DOX;
}
However, a static reference to a Fn*
trait object is a rather silly thing. Closures which can be 'static
references are extremely rare, so you might just as well use a plain fn(u8) -> u8
type and sidestep the whole lifetime business.