error: lifetime may not live long enough
『error - ライフタイムの不足』のクロージャについての派生パターン。
クロージャは関数と異なり、その代入先や実引数の型情報も型推論に利用できる。これを利用して、クロージャは引数のライフタイムについて、省略ルールではなく、そうした周辺情報から推論する戦略を取っている。
この戦略はだいたいうまくいくが、複数のライフタイムについての関係性 (等しいや含む) を示したい場合、『解決策』で紹介する方法が必要で、こちらは少し面倒である。
以下では、単純なライフタイムの推測ができずエラーになっている。
fn main() {
let _closure = |x: &i32| -> &i32 { x };
}
error: lifetime may not live long enough --> src\main.rs:2:40 | 2 | let _closure = |x: &i32| -> &i32 { x }; | - - ^ returning this value requires that `'1` must outlive `'2` | | | | | let's call the lifetime of this reference `'2` | let's call the lifetime of this reference `'1`
解決策はいくつかある。
※ 高階関数は万能だが少し面倒…。
不安定な機能 closure_lifetime_binder を使う。
欠点: 、ナイトリー版でしか使えない。
#![feature(closure_lifetime_binder)]
fn main() {
let _closure = for<'a> |x: &'a i32| -> &'a i32 { x };
}
クロージャ専用の機能を使っていなければ、関数として型指定すればよい。
欠点: クロージャによる変数のキャプチャができない。
fn main() {
let _closure = (|x| { x }) as fn(&i32) -> &i32;
}
クロージャの代わりに関数を使えば、同じ構成でも問題にならない。
欠点: クロージャによる変数のキャプチャができない。
fn main() {
let _closure = function;
}
fn function(x: &i32) -> &i32 {
x
}
クロージャを生成する関数を利用すれば、関数のライフタイム規則を利用できる。
利点: クロージャによる変数のキャプチャを再現するには、関数にその変数を渡せばよい。
fn main() {
let _closure = make_closure();
}
fn make_closure() -> impl Fn(&i32) -> &i32 {
|x| x
}