2016-06-26 12 views
8

mi sto cercando di fare questo semplice compilare il codice:La funzione ruggine non ha una durata statica?

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

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

ma non riesce a 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 

Come è possibile che una funzione libera non ha vita statica? In che modo questo codice potrebbe non essere sicuro?

risposta

9

Il tipo di &dox non è &Fn(u8) -> u8 (o anche &fn(u8) -> u8), esso è semplicemente Coercible a&Fn(u8) -> u8. Pertanto, stai effettivamente prendendo l'indirizzo di un temporaneo. I temporanei non vengono promossi alla durata di 'static anche se, in linea di principio, potrebbero essere 'static. Ad esempio questo codice non funziona neanche:

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

Esistono alcuni accorgimenti per questo. Normalmente si può solo creare esplicitamente una variabile static e prendere il riferimento a tale:

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

Nel vostro caso specifico che non funziona direttamente a causa Fn(u8) -> u8 è un tipo non calibrati (un tratto, in particolare) così non si può mettilo in un static. È possibile farlo:

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

Tuttavia, un riferimento statico a un oggetto tratto Fn* è una cosa piuttosto sciocca. Le chiusure che possono essere referenze da 'static sono estremamente rare, quindi potresti anche usare un semplice tipo fn(u8) -> u8 e scavalcare l'intera azienda per tutta la vita.

Problemi correlati