error[E0521]: borrowed data escapes outside of function

error[E0521]: borrowed data escapes outside of method

error[E0521]: borrowed data escapes outside of closure

E0521 - 参照引数の流出』にサブタイプが関連する派生パターン。

原因

可変参照には被参照型のサブタイプが波及しない。そのため、クロージャのライフタイム制約 (キャプチャ変数のライフタイム) が他のクロージャのそれと包含関係にあっても、それらの可変参照型どうしは互いに互換性がない。

サンプル

以下では、inc の型は &'v mut FnMut() + 'v である。
しかし、関数 callback には &'v mut FnMuyt + 'static などが必要になる。


fn main() {
    exec(&mut 0);
}

fn exec<'v>(val: &'v mut i32) {
    let mut inc = || *val += 1;
    callback(&mut inc);
}

fn callback(f: &mut (dyn FnMut() + 'static)) {
    f();
}

error[E0521]: borrowed data escapes outside of function
 --> src\main.rs:7:5
  |
5 | fn exec<'v>(val: &'v mut i32) {
  |         --  --- `val` is a reference that is only valid in the function body
  |         |
  |         lifetime `'v` defined here
6 |     let mut inc = || *val += 1;
7 |     callback(&mut inc);
  |     ^^^^^^^^^^^^^^^^^^
  |     |
  |     `val` escapes the function body here
  |     argument requires that `'v` must outlive `'static`
  |
  = note: requirement occurs because of a mutable reference to `(dyn FnMut() + 'static)`
  = note: mutable references are invariant over their type parameter
  = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

補足

'static ライフタイムの省略

省略された 'static がエラーに関係するパターンもある。

以下では、type Action = dyn FnMut();type Action = dyn FnMut() + 'static; と等価になるため、前のコードと同様のコンパイルエラーになる。


fn main() {
    exec(&mut 0);
}

fn exec<'v>(val: &'v mut i32) {
    let mut inc = || *val += 1;
    callback(&mut inc);
}

fn callback(f: &mut Action) {
    f();
}

type Action = dyn FnMut();

error[E0521]: borrowed data escapes outside of function
 --> src\main.rs:7:5
  |
5 | fn exec<'v>(val: &'v mut i32) {
  |         --  --- `val` is a reference that is only valid in the function body
  |         |
  |         lifetime `'v` defined here
6 |     let mut inc = || *val += 1;
7 |     callback(&mut inc);
  |     ^^^^^^^^^^^^^^^^^^
  |     |
  |     `val` escapes the function body here
  |     argument requires that `'v` must outlive `'static`
  |
  = note: requirement occurs because of a mutable reference to `(dyn FnMut() + 'static)`
  = note: mutable references are invariant over their type parameter
  = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance