Help me learn blanket trait implementation

I have been trying to write some code to wrap my head around blanket trait implementations. Here is my code --

use std::fmt::Debug;

trait SomeT {}

fn some_t<F: SomeT>(f: F) {}

struct SomeTTT;

// impl SomeT for SomeTT {}

impl<T: Debug + Clone> SomeT for T {}

fn main() {
    let ss = SomeTTT;

If I pass owned ss to some_t() it throws an error --

error[E0277]: the trait bound `SomeTTT: SomeT` is not satisfied
  --> src/
17 |     some_t(ss);
   |     ------ ^^ the trait `SomeT` is not implemented for `SomeTTT`
   |     |
   |     required by a bound introduced by this call
note: required for `SomeTTT` to implement `SomeT`
  --> src/
12 | impl<T: Debug + Clone> SomeT for T {}
   |                        ^^^^^     ^
note: required by a bound in `some_t`
  --> src/
5  | fn some_t<F: SomeT>(f: F) {}
   |              ^^^^^ required by this bound in `some_t`
help: consider borrowing here
17 |     some_t(&ss);
   |            +

so when I pass shared ss i.e &ss that the compiler wants me to pass. Even if the struct SomeTTT does not implement the Clone trait, and the blanket implement has a trait bound of Debug + Clone. In this case the code compiles. Can somebody explain why this compiles?

&T always implements Clone thanks to the blanket implementation impl<T> Clone for &T. This means that the impl you wrote applies to &SomeTT, which is the type of &ss.


Also, &SomeTTT is a distinct type from SomeTTT.

Also, in case you didn't know, impl<T> ... for T includes every &U (where &U meets the bounds).


Thank you for the explanation

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.