The following code:
enum MyEnum {
A,
B,
}
impl ToString for MyEnum {
fn to_string(&self) -> String {
match *self {
Self::A => format!("A"),
Self::B => format!("B"),
}
}
}
pub fn foo<I: ToString>(item: I) {
println!("item: {}", item.to_string());
}
pub fn bar<I: ToString>(iter: impl Iterator<Item = I>) {
iter.for_each(|item| println!("item: {}", item.to_string()))
}
fn main() {
foo(MyEnum::A);
bar([MyEnum::A, MyEnum::B].iter());
}
Produces the following compilation error:
error[E0277]: `MyEnum` doesn't implement `std::fmt::Display`
--> src\bin\main6.rs:25:2
|
25 | bar([MyEnum::A, MyEnum::B].iter());
| ^^^ `MyEnum` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `MyEnum`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
= note: required because of the requirements on the impl of `std::fmt::Display` for `&MyEnum`
= note: required because of the requirements on the impl of `ToString` for `&MyEnum`
note: required by a bound in `bar`
--> src\bin\main6.rs:19:15
|
19 | pub fn bar<I: ToString>(iter: impl Iterator<Item = I>) {
| ^^^^^^^^ required by this bound in `bar`
For more information about this error, try `rustc --explain E0277`.
bar accepts iterators whose items implement ToString. MyEnum implements ToString, so [MyEnum::A, MyEnum::B].iter() is in fact an iterator of items that implement ToString.
foo and bar are very similar, in both the generic type I is replaced with MyEnum, so why is the trait bound Display required in bar but not in foo?
[MyEnum::A, MyEnum::B].iter()creates an iterator whose item is&MyEnum.&MyEnumdoes not implementToString, onlyMyEnumdoes. This works:Playground
And if you want to accept any
&Isuch thatI: Display: