fn trait_fn<T: Copy>(a: T) -> T {
// err: Display is not implemented
// println!("{}", a);
a
}
fn trait_iml(a: impl Copy) -> impl Copy {
// err: Display is not implemented
// println!("{}", a);
a
}
fn trait_where<T>(a: T) -> T
where
T: Copy,
{
// err: Display is not implemented
// println!("{}", a);
a
}
fn main() {
println!("{}", trait_fn(1));
// err: Display is not implemented
// Why would the other two be OK?
// println!("{}", trait_iml(1));
// behavior like trait_fn
println!("{}", trait_where(1));
}
They are the same only in function argument types, not in return types. Further down in the document you linked it talks about return types. Using impl Trait instead of T: Trait without changing the meaning of the signature is only possible if the T is only used once, in (a: T) -> T it is used twice.
In addtion, why does the variable 'a' could be printed in main function, but could not be printed in trait_fn function?
I think the both have the same type <T: Copy>, so they could not be printed.
fn trait_fn<T: Copy>(a: T) -> T {
// err: Display is not implemented
// println!("{}", a);
a
}
fn main() {
println!("{}", trait_fn(1));
}
Main knows that T is the type i32, which implements Display. On the other hand, as far as trait_fn is concerned, T might be any type that the caller chooses which implements Copy, so it can only do things that are valid for all types that implement Copy.
By the way, I did not say anything about why the println doesn’t work inside of the trait_… functions, my main point was to point out why there is a difference between trait_fn and trait_iml even though you read somewhere that using impl Trait is “the same” as using T: Trait. By the way, trait_where is the same as trait_fn.
The feature is not too extensively documented. If you want to read more details besides what’s in the book, maybe the (first) RFC for the feature does some more explaining. (Note that that RFC was created before impl Trait in argument position existed, so there will be no comparison/contrasting to that feature.)