[Rust] 射影 (projection) について

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](https://rustc-dev-guide.rust-lang.org/appendix/glossary.html#projection)」

ちなみに (おそらく) 公式の 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](https://rustc-dev-guide.rust-lang.org/mir/index.html#mir-data-types)」

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

- 物体: `_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](https://github.com/rust-lang/rust/blob/1.63.0/compiler/rustc_middle/src/mir/interpret/error.rs#L231)」
参考「[L932-L933 - rust/sugg.rs at 1.63.0 · rust-lang/rust](https://github.com/rust-lang/rust/blob/1.63.0/src/tools/clippy/clippy_utils/src/sugg.rs#L932-L933)」
参考「[L978 - rust/sugg.rs at 1.63.0 · rust-lang/rust](https://github.com/rust-lang/rust/blob/1.63.0/src/tools/clippy/clippy_utils/src/sugg.rs#L978)」
参考「[L26 - rust/const_let_eq.rs at 1.63.0 · rust-lang/rust](https://github.com/rust-lang/rust/blob/1.63.0/src/test/ui/consts/const_let_eq.rs#L26)」

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

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

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

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

```rust
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](https://rust-analyzer.github.io/manual.html#generate_enum_as_method)」
参考「[Projections and Structural Pinning - std::pin - Rust](https://doc.rust-lang.org/stable/std/pin/index.html#projections-and-structural-pinning)」

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

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

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

- `P1..Pm` は型またはライフタイム `P` の集合 (空集合の場合もあり)
- `P0` 型は `TraitName<P1..Pn>` トレイトを実装している型
- `AssocItem` は `TraitName<P1..Pn>` トレイトで宣言されている関連要素

```
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](https://rustc-dev-guide.rust-lang.org/traits/goals-and-clauses.html#domain-goals)」

参考「[Associated Items - The Rust Reference](https://doc.rust-lang.org/reference/items/associated-items.html)」

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

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

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

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

参考「[Index in std::ops - Rust](https://doc.rust-lang.org/std/ops/trait.Index.html)」
参考「[Iterator in core::iter - Rust](https://doc.rust-lang.org/core/iter/trait.Iterator.html)」
参考「[IntoIterator in std::iter - Rust](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html)」