error[E0373]: closure may outlive the current function, but it borrows `val`, which is owned by the current function
クロージャのキャプチャ変数のライフタイムが、クロージャの境界を順守できないほど短い。
問題のクロージャが関数の戻り値になっているパターン。
以下では、関数 get_lambda の戻り値がクロージャであり、それが変数 val をキャプチャしている。しかし、val はローカル変数のため、関数の呼出後は有効でなくなっている。
fn get_lambda() -> impl Fn() {
let val = 42;
|| { dbg!(val); }
}
error[E0373]: closure may outlive the current function, but it borrows `val`, which is owned by the current function
--> src\lib.rs:3:5
|
3 | || { dbg!(val); }
| ^^ --- `val` is borrowed here
| |
| may outlive borrowed value `val`
|
note: closure is returned here
--> src\lib.rs:3:5
|
3 | || { dbg!(val); }
| ^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `val` (and any other referenced variables), use the `move` keyword
|
3 | move || { dbg!(val); }
| ++++
問題のクロージャが関数の引数になっているパターン。
以下では、関数 call_lambda の引数がクロージャであり、それが変数 val をキャプチャしている。しかし、val はローカル変数のため、'static つきの引数型からは参照できない。
fn test() {
let val = 42;
call_lambda(|| { dbg!(val); });
}
fn call_lambda(_f: impl Fn() + 'static) {}
error[E0373]: closure may outlive the current function, but it borrows `val`, which is owned by the current function
--> src\lib.rs:3:17
|
3 | call_lambda(|| { dbg!(val); });
| ^^ --- `val` is borrowed here
| |
| may outlive borrowed value `val`
|
note: function requires argument type to outlive `'static`
--> src\lib.rs:3:5
|
3 | call_lambda(|| { dbg!(val); });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `val` (and any other referenced variables), use the `move` keyword
|
3 | call_lambda(move || { dbg!(val); });
| ++++
エラーメッセージの help
にある通り、クロージャに move を指定する。
すると、クロージャはキャプチャ変数を参照する代わりに、クロージャ自身にキャプチャ変数を移動してその内容を使うようになる。これにより、クロージャとキャプチャ変数のライフタイムは必ず一致するようになる。