安定性属性
このセクションでは、rustc の標準ライブラリで、安定した API が内部的に不安定な API を使用できるようにする安定性属性と仕組みについて説明します。
NOTE: このセクションは ライブラリ 機能についてのものであり、言語 機能についてのものではありません。 言語機能を安定化する手順については、Stabilizing Features を参照してください。
unstable
#[unstable(feature = "foo", issue = "1234", reason = "lorem ipsum")]
属性は、アイテムを不安定であると明示的にマークします。
“unstable” としてマークされたアイテムは、nightly コンパイラであっても、そのクレートに対応する #![feature] 属性がなければ使用できません。
この制限はクレート境界を越える場合にのみ適用され、不安定なアイテムはそれを定義しているクレート内では使用できます。
issue フィールドは、関連する GitHub の issue number を指定します。
このフィールドは必須であり、すべての不安定機能には関連する追跡 issue があるべきです。
適切な値がないまれなケースでは、issue = "none" が使用されます。
unstable 属性はすべてのサブアイテムに波及し、その属性を再適用する必要はありません。
したがって、これをモジュールに適用すると、そのモジュール内のすべてのアイテムが不安定になります。
機能名を変更する場合は、有用なエラーメッセージを生成するために old_name = "old_name" を追加できます。
特定のサブアイテムを安定にするには、それらに #[stable] 属性を使用します。
安定性の仕組みは、pub の動作と似ています。
非公開モジュールの公開関数を持つことができるのと同様に、不安定なモジュール内に安定した関数を持つことも、その逆も可能です。
以前は、rustc bug により、不安定なモジュール内の安定したアイテムが、その場所では安定版コードから利用可能でした。
2024年9月時点で、[accidentally stabilized paths] を持つアイテムには、それらのパスに依存するコードが壊れるのを防ぐため、`#[rustc_allowed_through_unstable_modules]` 属性が付けられています。破壊的変更を避けるために必要な場合を除き、この属性をこれ以上のアイテムに追加してはいけません。
unstable 属性には soft 値を持たせることもでき、これによりハードエラーではなく、デフォルトで deny となる将来非互換 lint になります。
これは、過去に誤って受け入れられていた bench 属性で使用されています。
これにより、Cargo の lint capping を利用して依存関係を壊すことを防ぎます。
stable
#[stable(feature = "foo", since = "1.420.69")] 属性は、アイテムが安定化済みであることを明示的にマークします。
安定した関数は、その本体内で不安定なものを使用できることに注意してください。
rustc_const_unstable
#[rustc_const_unstable(feature = "foo", issue = "1234", reason = "lorem ipsum")] は、unstable 属性と同じインターフェイスを持ちます。
これは、const fn の const 性が不安定であることをマークするために使用されます。
これはまれなケースでのみ必要です。
const fnが不安定な言語機能または intrinsic を使用している場合。 (これに該当する場合、コンパイラがこの属性を追加するよう指示します。)const fnが#[stable]であるが、まだ const-stable にすることが意図されていない場合。- const-unstable な intrinsic を呼び出すために必要な feature gate を変更する場合。
const 安定性は通常の安定性とは異なり、再帰的です。#[rustc_const_unstable(...)] 関数は、安定版コードから間接的に呼び出すことすらできません。
これは、不安定なコンパイラ実装の成果物が誤って安定版コードに漏れ出したり、不完全な実装の偶発的な癖に縛られたりすることを避けるためです。
このチェックを細かく調整する方法については、下記の rustc_const_stable_indirect 属性と rustc_allow_const_fn_unstable 属性を参照してください。
rustc_const_stable
#[rustc_const_stable(feature = "foo", since = "1.420.69")] 属性は、const fn の const 性が stable であることを明示的にマークします。
rustc_const_stable_indirect
#[rustc_const_stable_indirect] 属性は、#[rustc_const_unstable(...)] 関数に追加することで、#[rustc_const_stable(...)] 関数から呼び出せるようにできます。
これは、その関数が実装の観点では安定版に対応する準備ができていること(つまり、不安定なコンパイラ機能を使用していないこと)を示します。その関数がまだ const-stable でない唯一の理由は API 上の懸念です。
これは、コンパイラ内で const 呼び出しが合成される lang item にも追加するべきです。これにより、それらの呼び出しが再帰的な const 安定性ルールを回避しないようにします。
rustc_intrinsic_const_stable_indirect
intrinsic において、この属性はその intrinsic を「公開された安定関数によって使用される準備ができている」とマークします。
その intrinsic に rustc_const_unstable 属性がある場合は、削除するべきです。
intrinsic にこの属性を追加するには、t-lang と wg-const-eval の承認が必要です!
rustc_default_body_unstable
#[rustc_default_body_unstable(feature = "foo", issue = "1234", reason = "lorem ipsum")] 属性は、unstable 属性と同じインターフェイスを持ちます。
これは、trait 内のアイテムのデフォルト実装を不安定としてマークするために使用されます。
default-body-unstable なアイテムを持つ trait は、そのようなアイテムに明示的な本体を提供することで安定的に実装できます。または、対応する #![feature] を有効にすることでデフォルト本体を使用できます。
ライブラリ機能の安定化
機能を安定化するには、次の手順に従います。
- @T-libs-api メンバーに、追跡 issue で FCP を開始するよう依頼し、FCP が完了するまで待ちます(
disposition-mergeを伴う)。 #[unstable(...)]を#[stable(since = "CURRENT_RUSTC_VERSION")]に変更します。- この API のテストまたは doc-test から
#![feature(...)]を削除します。 その機能がコンパイラまたはツールで使用されている場合は、そこからも削除します。 - これが
const fnの場合は、#[rustc_const_stable(since = "CURRENT_RUSTC_VERSION")]を追加します。 あるいは、これをまだ const 安定化する想定ではない場合は、新しい feature gate(新しい追跡 issue を伴う)用に#[rustc_const_unstable(...)]を追加します。 rust-lang/rustに対して PR を開きます。- 適切なラベルを追加します:
@rustbot modify labels: +T-libs-api。 - 追跡 issue にリンクし、“Closes #XXXXX” と記載します。
- 適切なラベルを追加します:
機能を安定化する例としては、tracking issue #81656 with FCP と、関連する implementation PR #84642 を参照できます。
allow_internal_unstable
マクロとコンパイラの糖衣構文展開は、その本体を呼び出し元に公開します。
標準ライブラリのマクロ内で不安定なものを使用できない問題を回避するために、指定された機能を安定したマクロ内で使用できるようにする #[allow_internal_unstable(feature1, feature2)] 属性があります。
マクロが const コンテキストで使用され、#[rustc_const_unstable(...)] 関数への呼び出しを生成する場合、allow_internal_unstable があっても、それは依然として拒否されることに注意してください。
そのマクロが再帰的な const 安定性チェックを誤って回避できないようにするため、関数に #[rustc_const_stable_indirect] を追加してください。
rustc_allow_const_fn_unstable
上で説明したように、安定した const fn の内部では、不安定な const 機能は間接的であっても許可されません。
しかし、ときには、ある機能が安定化されることは分かっているが、それがいつなのかは分からない、あるいは安定した(ただし、たとえば実行時には遅い)回避策があるため、不安定機能を破棄した場合でも常に何らかの安定版にフォールバックできる、という場合があります。
そのような場合、[rustc_allow_const_fn_unstable(feature1, feature2)] 属性を使用して、安定した(または間接的に安定した)const fn の本体内で一部の不安定機能を許可できます。
また、const fn には、実行時に呼び出した場合とコンパイル時に呼び出した場合で同じように振る舞う必要があるという不変条件があり、それを維持するよう注意する必要があります(こちらのブログ記事も参照)。
これは、たとえばメモリアドレスを整数に変換するような const fn を作成してはならないことを意味します。
なぜなら、もののアドレスは非決定的であり、コンパイル時には不明であることが多いからです。
いずれかの const fn に rustc_allow_const_fn_unstable 属性を追加する場合は、必ず @rust-lang/wg-const-eval に通知してください。
staged_api
stable または unstable 属性を使用するクレートは、そのクレートに
#![feature(staged_api)] 属性を含めなければなりません。
deprecated
標準ライブラリにおける非推奨化は、ユーザーコードにおける非推奨化とほぼ同じです。
項目に #[deprecated] を使用する場合は、stable
または unstable 属性も付与されていなければなりません。
deprecated は次の形式です。
#[deprecated(
since = "1.38.0",
note = "explanation for deprecation",
suggestion = "other_function"
)]
suggestion フィールドは任意です。
指定する場合は、警告を修正するための機械的に適用可能な提案として使用できる文字列であるべきです。
これは通常、識別子の名前が変更されたものの、その他の大きな変更が不要な場合に使用されます。
suggestion フィールドを使用する場合は、クレートルートに
#![feature(deprecated_suggestion)] が必要です。
ユーザーコードとのもう 1 つの違いは、since フィールドが実際に現在の rustc のバージョンに対してチェックされることです。
since が将来のバージョンである場合、deprecated_in_future lint がトリガーされます。これはデフォルトでは allow ですが、標準ライブラリの大部分では
#![warn(deprecated_in_future)] によって警告に引き上げています。
unstable_feature_bound
#[unstable_feature_bound(foo)] 属性は、#[unstable] 属性と併用して、安定した型および安定したトレイトの impl を不安定としてマークするために使用できます。
std/core では、#[unstable_feature_bound(foo)] が注釈された項目は、同じく #[unstable_feature_bound(foo)] が注釈された別の項目からのみ使用できます。
std/core の外部では、#[unstable_feature_bound(foo)] を持つ項目を使用するには、クレートに #![feature(foo)] 属性を指定してその機能を有効化する必要があります。
現在、#[unstable_feature_bound] を注釈できる項目は次のとおりです。
impl- 自由関数
- トレイト
名前変更された機能と削除された機能
不安定機能は名前変更および削除されることがあります。
機能の名前を変更する場合は、#[unstable] 属性に old_name = "old_name" を追加できます。
機能を削除する場合は、削除された機能のユーザーに分かりやすいエラーメッセージを生成するために、#!unstable_removed(feature = "foo", reason = "brief description", link = "link", since = "1.90.0")
属性を使用するべきです。
link フィールドは、GitHub issue、コメント、PR など、その機能の削除に関する最も関連性の高い情報へリンクするために使用できます。