Why we need to repeat trait bounds that were specified in trait definitions?

Viewed 52

I have a function like this:

pub fn foo<T: FromStr<Err = impl Display>>() -> T {
    T::from_str("123").map_err(|e| println!("{e}")).unwrap()
}

It has a trait bound on T and a trait bound on that trait's associated type Err. I want to create an "alias" for these bounds. Here is my first trial:

pub trait AliasTrait: FromStr
where
    <Self as FromStr>::Err: Display,
{
}

impl<T: FromStr<Err = impl Display>> AliasTrait for T {}

pub fn foo<T: AliasTrait>() -> T {
    T::from_str("123").map_err(|e| println!("{e}")).unwrap()
}

However rustc complains that

error[E0277]: `<T as FromStr>::Err` doesn't implement `std::fmt::Display`
  --> src/main.rs:19:15
   |
19 | pub fn foo<T: AliasTrait>() -> T {
   |               ^^^^^^^^^^ `<T as FromStr>::Err` cannot be formatted with the default formatter
   |
   = help: the trait `std::fmt::Display` is not implemented for `<T as FromStr>::Err`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `AliasTrait`
  --> src/main.rs:13:29
   |
11 | pub trait AliasTrait: FromStr
   |           ---------- required by a bound in this
12 | where
13 |     <Self as FromStr>::Err: Display,
   |                             ^^^^^^^ required by this bound in `AliasTrait`
help: consider further restricting the associated type
   |
19 | pub fn foo<T: AliasTrait>() -> T where <T as FromStr>::Err: std::fmt::Display {
   |                                  ++++++++++++++++++++++++++++++++++++++++++++

For more information about this error, try `rustc --explain E0277`.

But when I change the AliasTrait to

pub trait AliasTrait: FromStr<Err = <Self as AliasTrait>::Err> {
    type Err: Display;
}

impl<T: FromStr<Err = impl Display>> AliasTrait for T {
    type Err = T::Err;
}

Then it works.

Rust Playground

I do not quite understand why the first AliasTrait implementation needs to repeat the trait bounds specified in its definition. Because all types that implement AliasTrait should have satisfied these bounds. This is totally redundant.

1 Answers
Related