Синтаксис impl
Как и ограничения трейтов, синтаксис impl Trait можно использовать в аргументах функций и в возвращаемых значениях:
// Copyright 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()или с помощью turbofish:foo.collect::<Vec<_>>().
Какой тип у debuggable? Попробуйте let debuggable: () = .., чтобы посмотреть, что покажет сообщение об ошибке.