Неявное преобразование из типа T
в dyn Trait
для Trait
, реализованное T
, представляет собой так называемое нестандартное принуждение , особый вид принуждения.Хотя Rust несколько неохотно работает с неявными преобразованиями типов, приведения действительно происходят неявно в узлах приведения , но не в других местах.
Аргументы вызова функций являются узлами приведения.Это объясняет, почему ваша функция show_item()
работает так, как вам нужно.
Все принуждения также можно выполнять явно, используя оператор as
.По этой причине версия, использующая map()
, работает нормально.
Ваше определение show_items()
,
fn show_items<'a>(items: impl Iterator<Item = &'a Display>)
, с другой стороны, является совершенно другой историей.Синтаксис impl
, используемый здесь, является сокращением для
fn show_items<'a, I>(items: I)
where
I: Iterator<Item = &'a dyn Display>,
Функция является универсальной для типа итератора, и компилятор проверяет, что тип, который вы фактически передаете, реализует эту чертусвязаны Iterator<Item = &'a dyn Display>
.Типа std::slice::Iter<'_, u32>
из вашего примера кода просто нет, отсюда и ошибка.Нет принуждения, которое преобразует аргумент в другой тип, чтобы заставить его реализовать некоторую границу черты, требуемую универсальной функцией.Также совершенно неясно, к какому типу конвертировать std::slice::Iter<'_, u32>
, чтобы превратить его в итератор для &dyn Display
.
Обратите внимание, что ваша версия определения функции неоправданно ограничена, поскольку требует наличия итератора для объектов признаков.Было бы гораздо более естественным и более производительным просто потребовать, чтобы элементы итератора реализовали Display
вместо:
fn show_items<I>(items: I)
where
I: IntoIterator,
I::Item: Display,
(я также изменил Iterator
на IntoIterator
, поскольку это более общее и болееудобный.)