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
. &MyEnum
does not implement ToString
, only MyEnum
does. This works:
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].into_iter());
}
And if you want to accept any &I
such that I: Display
:
pub fn bar<'a, I: 'a>(iter: impl Iterator<Item = &'a I>) where I: ToString {
iter.for_each(|item| println!("item: {}", item.to_string()))
}