impl Trait

トレイト境界と似たように、構文 impl Traitは関数の引数と返り値においてのみ利用可能です:

// 以下の糖衣構文:
//   fn add_42_millions<T: Into<i32>>(x: T) -> i32 {
fn add_42_millions(x: impl Into<i32>) -> i32 {
    x.into() + 42_000_000
}

fn pair_of(x: u32) -> impl std::fmt::Debug {
    (x + 1, x - 1)
}

fn main() {
    let many = add_42_millions(42_i8);
    println!("{many}");
    let many_more = add_42_millions(10_000_000);
    println!("{many_more}");
    let debuggable = pair_of(27);
    println!("debuggable: {debuggable:?}");
}
This slide should take about 5 minutes.

impl Trait allows you to work with types which you cannot name. The meaning of impl Trait is a bit different in the different positions.

  • パラメタに対しては、impl Traitは、トレイト境界を持つ匿名のジェネリックパラメタのようなものです。

  • 返り値の型に用いる場合は、特定のトレイトを実装する何らかの具象型を返すが、具体的な型名は明示しないということを意味します。このことは公開されるAPIに具象型を晒したくない場合に便利です。

    返り値の位置における型推論は困難です。impl Fooを返す関数は、それが返す具象型はソースコードに書かれることないまま、具象型を選びます。collect<B>() -> Bのようなジェネリック型を返す関数は、Bを満たすどのような型でも返すことがあります。 また、関数の呼び出し元はそのような型を一つを選ぶ必要があるかもしれません。 それは、 let x: Vec<_> = foo.collect()としたり、turbofishを用いてfoo.collect::<Vec<_>>()とすることで行えます。

debuggable の型は何でしょうか。let debuggable: () = .. を試して、エラー メッセージの内容を確認してください。