2016-06-26 10 views
8

私はこの単純なコードをコンパイルしようとしています:錆機能には静的寿命がありませんか?

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

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

をしかし、それは錆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 

それは自由な関数は、静的な寿命を持っていない可能性がありどのように?どのようにこのコードは安全ではないでしょうか?

答えて

9

&doxのタイプは&Fn(u8) -> u8(あるいは&fn(u8) -> u8)ではない、それは&Fn(u8) -> u8単に強制可能です。したがって、あなたは実際に一時的なアドレスを取っています。たとえ原則として'staticであっても、一時的な人生は'staticに昇格されません。たとえば、次のコードはどちらも動作しません。

これにはいくつかの回避策があります。 Fn(u8) -> u8は無サイズタイプ(特に形質)であるので、あなたがすることはできませんので、直接動作しません、あなたの特定のケースで

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

:通常1だけ明示的static変数を作成し、そのへの参照を取ることができますそれを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タイプを使用し、生涯のビジネスを回避することもできます。

関連する問題