error: captured variable cannot escape `FnMut` closure body

FnMut クロージャからキャプチャ変数が流出した。

詳細

FnMut クロージャが可変でキャプチャしている変数の参照 (不変参照か可変参照かは不問) が、クロージャの外に公開されてしまうと発生する。

これが危険な理由は、初回の呼出で流出したキャプチャ変数の参照の存在中に、クロージャの呼出がまた行われ、キャプチャ変数の更新が行われる可能性があるためである。

サンプル

以下で、use_fn_mutuse_fn_once で代替すると、エラーはなくなる。


fn main() {
    let mut counter = 1;
    use_fn_mut(|| {
        counter += 1;
        &counter
    });
}

#[allow(dead_code)]
fn use_fn_mut<'a, F>(_: F)
where
    F: FnMut() -> &'a i32 + 'a
{}

#[allow(dead_code)]
fn use_fn_once<'a, F>(_: F)
where
    F: FnOnce() -> &'a i32 + 'a
{}

error: captured variable cannot escape `FnMut` closure body
 --> src\main.rs:5:9
  |
2 |     let mut counter = 1;
  |         ----------- variable defined here
3 |     use_fn_mut(|| {
  |                 - inferred to be a `FnMut` closure
4 |         counter += 1;
  |         ------- variable captured here
5 |         &counter
  |         ^^^^^^^^ returns a reference to a captured variable which escapes the closure body
  |
  = note: `FnMut` closures only have access to their captured variables while they are executing...
  = note: ...therefore, they cannot allow references to captured variables to escape