スタティックライフタイム
Rustにはいくつかの予約されたライフタイム名があります。その1つがstatic
で、2つの状況で使用することがあります。
// A reference with 'static lifetime: let s: &'static str = "hello world"; // 'static as part of a trait bound: fn generic<T>(x: T) where T: 'static {}
2つの状況におけるstatic
は微妙に異なる意味を持っており、Rustを学ぶときの混乱の元になっています。
いくつかの例とともにそれぞれの使い方を見てみましょう。
参照のライフタイム
参照のライフタイムが'static
であることは、参照が指し示す値がプログラムの実行中に渡って生き続けることを示します。
また、より短いライフタイムに圧縮することも可能です。
'static
ライフタイムを持つ変数を作るには下記の2つ方法があります。
どちらの場合も、値は読み取り専用のメモリ領域に格納されます。
static
宣言とともに定数を作成する。- 文字列リテラルで
&'static str
型を持つ変数を作成する。
では、それぞれの方法の例を見ていきましょう。
// Make a constant with `'static` lifetime. // `'static`ライフタイムを持つ定数を作成 static NUM: i32 = 18; // Returns a reference to `NUM` where its `'static` // lifetime is coerced to that of the input argument. // `NUM`への参照を返す。ライフタイムは`'static`から引数の // ライフタイムへと圧縮されている。 fn coerce_static<'a>(_: &'a i32) -> &'a i32 { &NUM } fn main() { { // Make a `string` literal and print it: // 文字列リテラルを用いて変数を作成し、プリントする let static_string = "I'm in read-only memory"; println!("static_string: {}", static_string); // When `static_string` goes out of scope, the reference // can no longer be used, but the data remains in the binary. // `static_string`がスコープから抜けると、参照は使用することが // できなくなるが、データはバイナリ中に残る。 } { // Make an integer to use for `coerce_static`: // `coerce_static`関数を呼び出すために、整数を作成 let lifetime_num = 9; // Coerce `NUM` to lifetime of `lifetime_num`: // `NUM`を`lifetime_num`のライフタイムへと圧縮 let coerced_static = coerce_static(&lifetime_num); println!("coerced_static: {}", coerced_static); } println!("NUM: {} stays accessible!", NUM); }
トレイト境界
トレイト境界としての'static
は型が非静的な参照を含まないことを意味します。
言い換えると、レシーバはその型をいくらでも長く保持することができ、意図的にドロップするまでは決して無効になることはないということです。
次のポイントを押さえておきましょう。所有権のある値が'static
ライフタイム境界をパスするとしても、その値への参照が'static
ライフタイム境界をパスするとは限りません。
use std::fmt::Debug; fn print_it( input: impl Debug + 'static ) { println!( "'static value passed in is: {:?}", input ); } fn main() { // i is owned and contains no references, thus it's 'static: // i は所有されていて、かつ参照を含まないので 'static let i = 5; print_it(i); // oops, &i only has the lifetime defined by the scope of // main(), so it's not 'static: // おっと、&i は main() で定義されたライフタイムしかもたないため 'static ではない print_it(&i); }
コンパイラのメッセージはこのようになります、
error[E0597]: `i` does not live long enough
エラー[E0597]: `i`は十分なライフタイムを持っていません
--> src/lib.rs:15:15
|
15 | print_it(&i);
| ---------^^--
| | |
| | borrowed value does not live long enough
| | 借用した値のライフタイムが不足
| argument requires that `i` is borrowed for `'static`
| 引数は`i`が`'static`として借用されることを要求する
16 | }
| - `i` dropped here while still borrowed
| `i`は借用されたままここでドロップされる