impl Trait

トレイト境界と同様に、impl Trait 構文は関数の引数や戻り値で使用できます。

// 著作権 2022 Google LLC
// SPDX-License-Identifier: Apache-2.0

// 次の糖衣構文:
//   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);
    dbg!(many);
    let many_more = add_42_millions(10_000_000);
    dbg!(many_more);
    let debuggable = pair_of(27);
    dbg!(debuggable);
}

impl Trait を使うと、名前を付けられない型を扱えます。impl Trait の意味は、使われる位置によって少し異なります。

  • パラメータでは、impl Trait はトレイト境界付きの匿名ジェネリックパラメータのようなものです。

  • 戻り値の型では、それはそのトレイトを実装する何らかの具体的な型を、型名を挙げずに意味します。これは、公開 API で具体的な型を公開したくない場合に便利です。

    戻り値位置では型推論は難しくなります。impl Foo を返す関数は、ソース中にそれを書かなくても、返す具体的な型を自ら決定します。collect<B>() -> B のようにジェネリックな型を返す関数は、B を満たす任意の型を返すことができ、呼び出し側が let x: Vec<_> = foo.collect() のように、あるいはターボフィッシュ foo.collect::<Vec<_>>() を使って、そのうちの 1 つを選ぶ必要がある場合があります。

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