error-chain
error-chain copied to clipboard
Error links cause conflicting From implementations when used cross-crate
I have this minimal repository that reproduces the issue: https://github.com/dflemstr/error-chain-test
Running cargo build
in the b
directory yields:
$ cargo build
Compiling b v0.1.0 (file:///home/dflemstr/github.com/dflemstr/error-chain-test/b)
error[E0119]: conflicting implementations of trait `std::convert::From<ErrorKind>` for type `ErrorKind`:
--> src/lib.rs:5:1
|
5 | error_chain! {
| ^
|
= note: conflicting implementation in crate `core`
= note: this error originates in a macro outside of the current crate
error: aborting due to previous error
error: Could not compile `b`.
To learn more, run the command again with --verbose.
I hate conflicting implementations of From
XD
Does anyone knows how we can see WHICH implementation conflicts?
Here's the output of cargo expand
: https://gist.github.com/dflemstr/1b1a4ae1465fa72b42c4866c8a82d86a
EDIT: Accidentally uploaded the wrong gist, fixed now
I'm totally new to this and am just passing through, but doesn't the example code say to put the error_chain!{}
invocation inside of a mod errors{}
to avoid conflicts...? Looking through your gist, it seems that
impl From<<a::Error as ::error_chain::ChainedError>::ErrorKind> for ErrorKind
is resolving to the exact ErrorKind that's being implemented, thus the conflicting implementation in the 'core' crate is actually
impl From<T> for T
which is just "Things can be converted to themselves" implementation provided for all types.
For <a::Error as ::error_chain::ChainedError>::ErrorKind
to resolve, first you have to look at a::Error's impl of ::error_chain::ChainedError. In the macro expansion, the trait is implemented with type ErrorKind = ErrorKind
. This would be in the A crate, so the fully qualified version would be type ErrorKind = a::ErrorKind
. Therefore it all finally resolves to:
impl From<a::ErrorKind> for b::ErrorKind
But, because the error_chain! macro isn't in a submodule, its methods are marked pub, which means they're part of the crate's public interface. Which means that the compiler could convert a::ErrorKind to a::Error through From<ErrorKind> for Error
in the A crate, then through From<a::Error> for Error
in the B crate, and then through From<Error> for ErrorKind
in the B crate, thus resulting in:
impl From <ErrorKind> for ErrorKind
in the B crate. Which is conflicting with imple From <T> for T
.
I honestly don't know if the rust compiler checks and/or cares about long conversion chains. I also don't know if it'll use From trait definitions in a crate that has no "use" statements. However, It does seem odd to have these things part of the crate interface. The recommended way of encapsulating the macro in a mod error {}
submodule and then use error::*
would not make these conversion operators public, from what I understand about rust. You'd need a pub use
to do that. It would make sense then why the link{} section is so important, if those definitions aren't public.
I'm still a noob in some areas of rust and an expert in others, so I don't know what I don't know. I might be totally wrong. But this is what my intuition tells me, and it's a great time to learn a little part of the language.
Edit: Also note that I do not (currently) have access to a working rust installation, so I cannot test my hypothesis.
The issue still happens with the error chains in different modules though.
As I've found out from https://www.reddit.com/r/rust/comments/5fv9ar/details_of_implicit_coercion/ , most of what I thought I knew is hogwash. Just go ahead and ignore me, sorry!
Fixed by https://github.com/brson/error-chain/pull/75, could you try master?