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) {}

#[derive(Debug)]
struct SomeTTT;

// impl SomeT for SomeTT {}

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


fn main() {
    let ss = SomeTTT;
    some_t(ss);
}

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

error[E0277]: the trait bound `SomeTTT: SomeT` is not satisfied
  --> src/main.rs:17:12
   |
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/main.rs:12:24
   |
12 | impl<T: Debug + Clone> SomeT for T {}
   |                        ^^^^^     ^
note: required by a bound in `some_t`
  --> src/main.rs:5:14
   |
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.

2 Likes

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).

2 Likes

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.