Generic struct with Display bound on type parameters, borrowed by a function

Hello my first post here!
I know the code below is not really idiomatic, but this is really for testing/understanding.

I have this simple code and with all my knowledge of Rust i thought it could compile:

use std::fmt;

struct Person<T, U>
where
    T: fmt::Display,
    U: fmt::Display,
{
    name: T,
    age: U,
}

fn greet<T, U>(person: &Person<T, U>) {
    println!("Hello {}", person.name);
}

It doesn't compile i had of course to change greet function like this:

fn greet<T, U>(person: &Person<T, U>)
where
    T: fmt::Display,
    U: fmt::Display,
{
    println!("Hello {}", person.name);
}

So my question is why do i have to bind again fmt::Display for T and U in my greet function.
My first toughts, knowing Rust, was Rust can deduce that a type Person fields have to implement Display.
I know it is not idiomatic at all and i should put greet function in an impl block.
From my researchs and Discord chan help, i have understood that it is a design choice for increasing readability. Is it right ?

1 Like

There is a plan to fix this, in the Implied Bounds RFC. It's taken a long time to implement this RFC because it depends on the new trait implementation, Chalk. However, it looks like progress is being made.

There's a bit more info in the Chalk documentation.

Thanks a lot, you put a name on what i am trying to do implied bounds.
Really helpful and thank you for the documentation!!

Iterestingly enough, implied bounds is may change what is idiomatic. Currently I would say it's "put bounds where you need them" (so in this case, on greet but not Person). After implied bounds it may be, "put bounds where you have to type the least."

1 Like

The other important thing here is that it being repeated here means that it's not a breaking change to remove a trait bound for a type.

For example, if a library had struct Color<T: Copy>(T, T, T);, it's currently not a breaking change to weaken that to T: Clone, but it would be if every method was implicitly relying on T: Copy because it mentioned Color<T> in a parameter.

For any bound that's not needed for an associated type, I'd definitely suggest bounding the implementations, not the type.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.