Can't print right after init a generic struct

Rookie here.

Why printing on line 12 gives the error:

         println!("x: {}, y: {}", mixed.x, mixed.y);
                                  ^^^^^^^ `T` cannot be formatted with the default formatter

But the same println works in main?

struct Point<T, U> {
    x: T,
    y: U
}

impl<T, U> Point<T, U> {
    fn mixup<V, W>(self, p2: Point<V, W>) -> Point<T,  W> {
        let mixed = Point {
            x: self.x,
            y: p2.y
        };
        println!("x: {}, y: {}", mixed.x, mixed.y); // this is not ok
        mixed
    }
}

fn main() {
    let p1 = Point {x: 1, y: 2.0};
    let p2 = Point {x: 2.0, y: "wtf"};
    let mixed = p1.mixup(p2);
    println!("x: {}, y: {}", mixed.x, mixed.y); // but this is ok
}

(Playground)

Thanks for your help :wink:

You cannot apply the "{}", thing formatting on any thing, only on those whose type implements the Display trait:

use ::core::fmt::Display;

fn print_fail<T> (x: T)
{
    println!("{}", x);  // Error, x: T and we don't know if `T : Display`
}

fn print_ok<T> (x: T)
where
    T : Display         // Set up added bounds / constraints on the generics
{
    println!("{}", x);  // Ok, since `T : Display` we can display `x`
}
// or equivalently
fn print_ok<T : Display> (x: T)
{
    println!("{}", x);  // Ok, since `T : Display` we can display `x`
}

This is because when defining a function generic over, let's say, <T>, the caller may then feed any type T to that function, even types that are not Display, and in that case Rust would be unable to compile the "{}", x formatting line (operation would not be definedà
By adding the T : Display bound, callers are no longer allowed to use a type that would not implement that trait, thus effectively guaranteeing that any used type implements Display and that "{}", x will thus always be well-defined, no matter the type T (of x).


In your example, the mixup() function needs to have a

where
    T : Display, // type of mixed.x
    W : Display, // type of mixed.y

bound.

Thanks for your thorough explanation. I understand now!

Simply speaking, inside the mixup method, the println macro can't be certain that for each call the x and y implement the Display trait, but in main, for this specific p1 and p2 the compiler knows the result implement the Display trait so the compiler won't complain. Am I right?

2 Likes

Exactly :slight_smile: