Right.
With just look at the type of function foo, you can conclude:
- The return type must have the same type of its operator.
- The function body cannot assume anything on top of the fact that the parameter is
Display.
- Because
Display contains only one method, namely fmt, and it takes self by reference, you can conclude this is functionaly equivalent to
fn foo<T: Display>(x: &T){...}
except that in the usage site it is slightly different.
On the other hand the signature of foo2 tells the same thing of its parameter, but for the return type, it only tells you it is also a Display but you have no idea what it is. So it can return you any value that Display and just use the input parameter in a println! macro or similar.
Examples. You can write
fn foo2(x: impl Display) -> impl Display {
println!("{}",x);
100
}
but the closest thing you can do for foo is something like
fn foo<T: Display>(x: T) -> T {
println!("{}", x);
x
}
in other words, you are not able to return anything other than x (unless unsafely, of cause). More interestingly, although you can say fn foo<T:Display>(mut x: T) -> T {...}, you will not be able to mutate x as Display does not contain any mutable method.