属性
属性には、不活性(または組み込み)と能動的(非組み込み)の 2 種類があります。
組み込み/不活性属性
これらの属性は、コンパイラ自体の
compiler/rustc_feature/src/builtin_attrs.rs
で定義されています。
例としては、#[allow] や #[macro_use] があります。
これらの属性には、いくつかの重要な特徴があります。
- これらは常にスコープ内にあり、通常のパスベースの名前解決には参加しません。
- これらは名前を変更できません。たとえば、
use allow as fooはコンパイルされますが、#[foo]と書くと エラーが発生します。 - これらは「不活性」です。つまり、マクロ展開コードによってそのまま残されます。
その結果、何らかの動作は、コンパイラがそれらの存在を明示的に確認することによって生じます。
たとえば、lint 関連のコードは、属性自体の展開から動作が生じるのではなく、
#[allow]、#[warn]、#[deny]、および#[forbid]を明示的に確認します。
「非組み込み」/「能動的」属性
これらの属性は、クレート(標準ライブラリ、または proc-macro クレート)によって定義されます。
重要: #[derive] など、多くの非組み込み属性は、依然として
Rust のコア言語の一部と見なされます。しかし、標準ライブラリに対応する定義があるため、これらは
「組み込み属性」とは呼ばれません。
非組み込み属性の定義には、2 つの形式があります。
- proc-macro 属性。proc-macro クレート内で
#[proc_macro_attribute]が付与された関数によって定義されます。 - AST ベースの属性。標準ライブラリで定義されます。これらの属性には、
library/core/src/macros/mod.rsのような場所で定義された特別な「スタブ」 マクロがあります。
これらの定義は、マクロが通常のパスベースの名前解決に参加できるようにするために存在します。つまり、他の項目定義と同様に、
インポート、再エクスポート、名前変更ができます。しかし、定義の本体は空です。代わりに、
そのマクロには #[rustc_builtin_macro]
属性が付与されており、これは rustc_builtin_macros 内の対応する関数を実行するようコンパイラに指示します。
すべての非組み込み属性には、次の特徴があります。
- 他のすべての定義(例: 構造体)と同様に、インポートによってスコープに取り込まれなければなりません。
多くの標準ライブラリ属性はプレリュードに含まれています。これが、
#[derive]と書いても インポートなしで動作する理由です。 - これらはマクロ展開に参加します。マクロの実装は、属性の対象を変更せずに残すことも、 対象を変更することも、新しい AST ノードを生成することも、対象を完全に削除することもあります。