user3690467
user3690467

Reputation: 3377

Is it possible to exclude a type from generic trait implementation?

I am trying to create an error type with a blanket From implementation for any Error, however since this type is itself an Error I am getting conflicts:

pub struct ApiError(pub i64, pub String);

impl<T: Error> From<T> for ApiError {
    fn from(err: T) -> Self {
        Self(500, err.to_string())
    }
}

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

I assume it is because of the cycle I have created by implementing Error on ApiError. Is it possible to say something like T: Error & not ApiError and exclude my particular type from this blanket implementation for From?

If this is not possible I am curious how anyhow seems to do something similar?

Upvotes: 6

Views: 1069

Answers (1)

Michael Anderson
Michael Anderson

Reputation: 73450

You can not do this in rust, but there is a work around.

Looking at the docs, anyhow::Error doesn't implement Error, instead it implemented Deref<Error> (and similar traits). This allows anyhow::Error to be silently converted to &Error.

This means it can now implement From<T:Error> without running into the conflict you mention.

Upvotes: 6

Related Questions