impl Trait

與特徵界限類似,impl Trait 語法可用於 函式引數和回傳值中:

// Syntactic sugar for:
//   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 就像是具有特徵界限的匿名泛型參數。

  • 對回傳型別來說,impl Trait 代表回傳型別就是實作特徵的 某些具體型別,因而不必指名特定型別。如果您不想在公用 API 中公開具體型別, 這就非常有用。

    在回傳位置進行推論並不容易。回傳 impl Foo 的函式 會挑選自身回傳的具體型別,而不必在來源中寫出此資訊。回傳泛型型別 (例如 collect<B>() -> B) 的函式則可回傳 符合 B 的任何型別 ,而呼叫端可能需要選擇一個型別,例如使用 let x: Vec<_> = foo.collect() 或 Turbofish:foo.collect::<Vec<_>>()

思考一下,debuggable 的型別為何?您可以嘗試使用 let debuggable: () = .. 查看錯誤訊息顯示的內容。