generated at
戻り値でのimpl Trait





rust
fn f() -> impl Iterator<Item = i32> { vec![1, 2, 3].into_iter() }
f は「 Iterator<Item = i32> を実装している何か」を返す
具体的な型( Vec<i32>::IntoIter ) は外部に漏れない
呼び出し側視点でも、 Iterator<Item = i32> しか見えないということ
rust
let iter = get_iterator(); // Iterator<Item = i32>
コンパイル時に、 iter の 型は具体的な IntoIter<i32> に決まる
impl Iterator のように見えるが、内部では型が決まっている

ちなみに、dyn Traitで書くなら
fn get_value() -> Box<dyn Iterator<Item = i32>> になり、ヒープ確保が発生する

もし、これ↑がgenericsだったら、呼び出し側は具体的な型が見えるはず
genericsは関数の呼び出し時に型を決める
rust
fn get_iterator<T: Iterator<Item = i32>>() -> T { vec![1, 2, 3].into_iter() // ❌ コンパイルエラー }







GPT-4


3. 存在型との関係
戻り値の impl Trait は 「存在型(existential type)」 に相当します。

存在型とは?
「ある T が存在するが、具体的な型は公開しない」 という型の概念
impl Trait の戻り値は 「何らかの型が存在するが、それが何かは明かさない」 という性質を持つ
「ある T があるが、それが何かは言わない」 → これは 存在型

ジェネリクス ( T: Trait ) との違い
ジェネリクス ( T ) は 「全ての T に対して成り立つ」 (∀)
「任意の T に対して動作する」
fn foo<T: Trait>(x: T) {} は どんな T でも受け付ける
impl Trait は 「ある特定の型 T があるが、それを隠す」 (∃)
「何かの T があるが、それが何かは公開しない」
fn foo() -> impl Trait は ある T を返すが、それが何かは隠す

数学的には:
ジェネリクス ( T: Trait ) → 「全称型 (∀T)」 ( forall T. )
impl Trait (戻り値) → 「存在型 (∃T)」 ( exists T. )

このため、戻り値の impl Trait は 存在型の一種 であり、ジェネリクス ( T: Trait ) とは本質的に異なるもの です。