Conflicting implementations of trait `std::convert::From<ErrorDesc>` for type `ErrorDesc`

I am trying to create a Result type where error type is always a string:

#[derive(PartialEq, Debug)]
struct ErrorDesc(String);
type Result<T> = std::result::Result<T, ErrorDesc>;

In the book, it was suggested that we implement the From trait. So I tried something like this:

impl<T: std::fmt::Debug> From<T> for ErrorDesc {
   fn from(value: T) -> Self {
      ErrorDesc(/*print value in a string...*/);
    }
};

But I got this error:

error[E0119]: conflicting implementations of trait `std::convert::From<ErrorDesc>` for type `ErrorDesc`
 --> sensors/src/lib.rs:7:1
  |
7 | impl<T: std::fmt::Debug> From<T> for ErrorDesc {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: conflicting implementation in crate `core`:
          - impl<T> From<T> for T;

This my first code in Rust, and I am pretty sure I am just missing something... What are workarounds? Can anyone please help?

The conflicting implementation only exists because ErrorDesc itself implements Debug, too, so removing the Debug from the derive would work to avoid the error.


In case you want help understanding the problem in the first place, I find the compiler message gives all information necessary, so instead of repeating or rephrasing it all, I would need you to explain in more detail what aspects of the error or error message you did and didn't understand.

Thank you! Removing derive Debug has helped.


Regarding this question:

This is how I read the error message:

  1. ErrorDesc has two implementations of the From trait (which is not allowed).
  2. One of them is mine (=> this is expected).
  3. The other somehow comes from crate core (which I do not have control over).

After you mentioned derive Debug I guess the other implementation of the trait was generated by the macros? But even in this case, it is unclear how the implementation can be in the core crate...

From the point of view of clarity of error message, clang/C++ for example, would provide exact "logical path/chain" from my code in my file to the code in other parts. It would look something like this:

After expansion of macros XXX in file XXX line XXX
in substitution of template XXX with parameters XXX in file XXX line XXX
in instantiation of class  XXX with parameters XXX in file XXX line XXX
...
<error description occurred in "remote" file>

In the case of my error message, it just does not provide information how I ended up with the second implementation, instead it just states that

note: conflicting implementation in crate `core`:
          - impl<T> From<T> for T;

This is referring to this blanket impl in the core library (part of the standard library; where the From trait itself is defined). It is also mentioned here in the docs.

To read the impl<T> From<T> for T: it means that for all types T, the trait implementation From<T> for T is given. This includes all types, i.e. also your type ErrorDesc, which gives From<ErrorDesc> for ErrorDesc as a specific instance of the generic implementation.

On the other hand your impl<T: Debug> From<T> for ErrorDesc is another generic implementation. This implementation will, if ErrorDesc implements Debug, give rise to a second (and thus conflicting) From<ErrorDesc> for ErrorDesc implementation.

The derive(Debug) gives rise to a Debug for ErrorDesc implementation, so that ErrorDesc: Debug is fulfilled and your T: Debug-constrained From<…> implementation will apply. The derive does not do anything beyond that, it doesn’t directly interfere with the From trait, but due to your generic From-impl, the Debug for ErrorDesc implementation will indirectly lead to the conflict, as described above.


Note how the error message did kindly point out that the conflicting / overlapping case is precisely the From<ErrorDesc> for ErrorDesc instance

conflicting implementations of trait `std::convert::From<ErrorDesc>` for type `ErrorDesc`

And it also points out both generic implementations involved that cause the conflict

7 | impl<T: std::fmt::Debug> From<T> for ErrorDesc {

          - impl<T> From<T> for T;

Admitted, the error message leaves the necessary deduction of figuring out why either of these generic impls can be instantiated as From<ErrorDesc> for ErrorDesc to the reader. I.e. in both cases by instantiating T with ErrorDesc, and in the former case by also checking that ErrorDesc: Debug applies.

3 Likes

Wait, but how would you then actually implement Debug for ErrorDesc? It seems reasonable to me that an ErrorDesc can both be Debug and created from something that also is.

I guess it is still possible to add an associated function directly to the struct like this (Rust Playground), but this still doesn't satisfy the trait bound From<T> for any T.