Rust のリファレンス等で “projection” という言葉が使われることがありますが、Rust における “projection” の説明を見つけることがむずかしかったため、記事として残します。

1. Rust における用語「射影 (projection)」の説明

「射影 (projection)」はいわゆる「相対パス」の総称です。

例えば、x.f は「フィールド射影 (field projection)」、T::Item は「関連型射影 (associated type projection)」(または「射影型 (projection type)」) です。

参考「projection – Appendix B: Glossary – Guide to Rustc Development」

ちなみに (おそらく) 公式の Rust では使用されていませんが、「関連型射影 (associated type projection)」でなく「フィールド射影 (field projection)」の型を「射影の型 (projection type)」と表記する場合もあります。

文脈によって解釈してください。

2. メモリ上の場所に関する「射影 (projection)」の例

2.1. 中水準中間表現 MIR での「フィールド射影 (field projection)」の例

(本記事では「中水準中間表現 MIR」に関しては触れません。)

「射影 (projection)」は、基となる (メモリ上の) 場所から「突き出された (project out)」フィールド等です。

例えば、ローカル変数 _1 を基となるパスとし、f を「射影要素 (projection element)」として、(メモリ上の) 場所 _1.f は「射影 (projection)」です。

(ローカル変数 _1 も射影 _1.f も「(メモリ上の) 場所」に含まれます。)

参照外し *_1 も「射影 (projection)」の例です。

参考「MIR data types – The MIR (Mid-level IR) – Guide to Rustc Development」

物体の影に例えると以下のようになります:

    • 物体: _1 (のメモリ上の場所)

 

    • スクリーンおよび光の当て方: 物体の f の要素を取得する

 

    影: _1.f (のメモリ上の場所)

2.2. 配列やスライスの「インデックス射影 (index projection)」

配列やスライスに関して、特定のインデックスの場所を表現した (array[i] のような) ものも「射影 (projection)」で、「インデックス射影 (index projection)」と呼ばれます。

配列のインデックス射影 (array index projection) を単に「配列射影 (array projection)」と呼ぶこともあります。

(おそらく) 公式ドキュメントにしっかり書かれていませんが、Rust のコード中等で使用されている名称です。

参考「L231 – rust/error.rs at 1.63.0 · rust-lang/rust」
参考「L932-L933 – rust/sugg.rs at 1.63.0 · rust-lang/rust」
参考「L978 – rust/sugg.rs at 1.63.0 · rust-lang/rust」
参考「L26 – rust/const_let_eq.rs at 1.63.0 · rust-lang/rust」

2.3. 「射影メソッド (projection method)」によって得られる参照等の「フィールド射影 (field projection)」

ゲッターメソッドによって参照等の「フィールド射影 (field projection)」を得ることもできます。

このとき、そのゲッターメソッドを「射影メソッド (projection method)」と呼びます。

(※これは「メソッド射影 (method projection)」ではありません。)

struct Something {
    data: i32,
}

impl Something {
    // data メソッドは射影メソッド
    fn data(&self) -> &i32 {
        &self.data
    }

    // data_mut メソッドは射影メソッド
    fn data_mut(&mut self) -> &mut i32 {
        &mut self.data
    }
}

fn main() {
    let mut foo = Something { data: 23 };

    let bar = foo.data(); // foo.data() はフィールド射影
    println!("{}", *bar);

    let baz = foo.data_mut(); // foo.data_mut() はフィールド射影
    *baz = 42;
    println!("{}", *baz);
}

ある Field 型のフィールドに対して、参照型 &Field や &mut Field だけでなく、(固定された) Pin<&Field> や Pin<&mut Field> 型等も「フィールド射影 (field projection)」になります。

(Pin に関しては本記事では不説明。)

参考「generate_enum_as_method – User Manual」
参考「Projections and Structural Pinning – std::pin – Rust」

3. 「関連型射影 (associated type projection)」の例

3.1. トレイトを解決するときの「関連型射影 (associated type projection)」の例

関連要素 (associated item) における「射影 (projection)」は以下のように表されます:

P1..Pm は型またはライフタイム P の集合 (空集合の場合もあり)

P0 型は TraitName トレイトを実装している型

AssocItem は TraitName トレイトで宣言されている関連要素

Projection = <P0 as TraitName<P1..Pn>>::AssocItem<Pn+1..Pm>

関連要素 (associated item) が関連型 (associated type) の場合は「関連型射影 (associated type projection)」(または「射影型 (projection type)」) と呼ばれます。

参考「Domain goals – Goals and clauses – Guide to Rustc Development」

参考「Associated Items – The Rust Reference」

3.2. 標準ライブラリでの「関連型射影 (associated type projection)」の例

関連型 (associated type) を参照する構文 Self::Foo や ::Bar 等は全て「関連型射影 (associated type projection)」(または「射影型 (projection type)」) になります。

例えば、コレクション型等で以下のような射影があります:

<T as Index<I>>::Output;
<T as Iterator>::Item;
<T as IntoIterator>::Item;

参考「Index in std::ops – Rust」
参考「Iterator in core::iter – Rust」
参考「IntoIterator in std::iter – Rust」

广告
将在 10 秒后关闭
bannerAds