error[E0521]: borrowed data escapes outside of function
error[E0521]: borrowed data escapes outside of method
error[E0521]: borrowed data escapes outside of closure
メッセージには関数版、メソッド版、そしてクロージャ版がある。
どれも似た内容のため、ここでは主に関数版について説明する。
(クロージャ版には後述の特殊事情あり。)
このエラーは参照型の引数の扱いを間違えると発生する。
参照型の引数は、ライフタイム注釈に 'static を指定されない限り、関数のライフタイムを包む程度のライフタイムしか保証されない。これを、関数の外でも通用する、より広いライフタイムを持つ参照として処理すると、このエラーが発生する。
以下では、匿名のライフタイムを持つ参照 arg を、それよりも広い 'static ライフタイムを持つ参照として扱おうとしている。
fn f(arg: &i32) {
use_static(arg);
}
fn use_static(target: &'static i32) {
_ = target;
}
error[E0521]: borrowed data escapes outside of function
--> src\main.rs:2:5
|
1 | fn f(arg: &i32) {
| --- - let's call the lifetime of this reference `'1`
| |
| `arg` is a reference that is only valid in the function body
2 | use_static(arg);
| ^^^^^^^^^^^^^^^
| |
| `arg` escapes the function body here
| argument requires that `'1` must outlive `'static`
前のパターンとほぼ同じだが、より間接的なため気付きにくくなる。
fn f(arg: &Box<i32>) {
use_static(arg.as_ref());
}
fn use_static(target: &'static i32) {
_ = target;
}
error[E0521]: borrowed data escapes outside of function
--> src\main.rs:2:5
|
1 | fn f(arg: &Box<i32>) {
| --- - let's call the lifetime of this reference `'1`
| |
| `arg` is a reference that is only valid in the function body
2 | use_static(arg.as_ref());
| ^^^^^^^^^^^^^^^^^^^^^^^^
| |
| `arg` escapes the function body here
| argument requires that `'1` must outlive `'static`
以下では、匿名のライフタイムを持つ参照 arg を、Any トレイトを持つものとして扱おうとしている。しかし、Any トレイトは 'static ライフタイム境界を持つため、それまたはその内部により狭いライフタイムを持つ参照があってはならない。
use std::any::Any;
fn f(arg: &i32) {
use_any(arg);
}
fn use_any<T: Any>(any: T) {
_ = any;
}
error[E0521]: borrowed data escapes outside of function
--> src\main.rs:4:5
|
3 | fn f(arg: &i32) {
| --- - let's call the lifetime of this reference `'1`
| |
| `arg` is a reference that is only valid in the function body
4 | use_any(arg);
| ^^^^^^^^^^^^
| |
| `arg` escapes the function body here
| argument requires that `'1` must outlive `'static`
クロージャが関係するパターン。
以下のように、クロージャでも関数と同様のエラーが発生する。
ただし、以下ではクロージャの引数の型を明示している点に注意。
fn main() {
let mut vec = Vec::<&i32>::new();
let _closure = |item: &i32| {
vec.push(item);
};
}
error[E0521]: borrowed data escapes outside of closure
--> src\main.rs:4:9
|
2 | let mut vec = Vec::<&i32>::new();
| ------- `vec` declared here, outside of the closure body
3 | let _closure = |item: &i32| {
| ---- `item` is a reference that is only valid in the closure body
4 | vec.push(item);
| ^^^^^^^^^^^^^^ `item` escapes the closure body here
クロージャでは引数 (実引数) の型情報からパラメタ (仮引数) の型推論ができる。そのため、関数の場合とは微妙に状況が異なる。そして、これにより問題のエラーを解消できる場合がある。
なぜなら、型を明示した場合、引数のライフタイムはクロージャのライフタイムを包む程度にしか保証されないが、型を省略した場合、引数のライフタイムは実引数のものと同じとなり、それはクロージャの外でも通用するためである。
サブタイプが関連。詳しくは『参照引数の流出 × サブタイプ』を参照。