Code:
extern crate failure;
use failure::{Error, Fail};
use std::fmt;
#[derive(Debug)]
struct ContextError {
msg: String,
inner: Error,
}
trait ResultContextExt<T> {
fn wrap_err<S: Into<String>>(self, msg: S) -> Result<T, ContextError>;
}
impl ContextError {
fn new(msg: String, inner: Error) -> ContextError {
ContextError { msg, inner }
}
}
impl Fail for ContextError {
fn cause(&self) -> Option<&Fail> {
Some(self.inner.as_fail())
}
}
impl fmt::Display for ContextError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.msg)
}
}
impl<T, E: Fail> ResultContextExt<T> for Result<T, E> {
fn wrap_err<S: Into<String>>(self, msg: S) -> Result<T, ContextError> {
self.map_err(move |err| ContextError::new(msg.into(), Error::from(err)))
}
}
impl<T> ResultContextExt<T> for Result<T, Error> {
fn wrap_err<S: Into<String>>(self, msg: S) -> Result<T, ContextError> {
self.map_err(move |err| ContextError::new(msg.into(), err))
}
}
fn main() {
}
Error:
error[E0119]: conflicting implementations of trait `ResultContextExt<_>` for type `std::result::Result<_, failure::Error>`:
--> src/main.rs:40:1
|
34 | impl<T, E: Fail> ResultContextExt<T> for Result<T, E> {
| ----------------------------------------------------- first implementation here
...
40 | impl<T> ResultContextExt<T> for Result<T, Error> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `std::result::Result<_, failure::Error>`
|
= note: upstream crates may add new impl of trait `std::error::Error` for type `failure::Error` in future versions
I am completely puzzled by this error. The first impl trait should only target types which implement Fail
, and Error
does not implement Fail
, so how can the second impl be a conflicting implementation? Am I missing here something?
My current workaround for this is to duplicate the trait with a different name and use that for the second impl trait. Well, this works quite good, but this seems rather hacky and is probably not idiomatic rust code.