error[E0119]: conflicting implementations of trait `std::convert::From<cache::Error<_>>` for type `cache::Error<_>`
--> src/cache.rs:30:1
|
30 | impl<B: Backend> From<B::Error> for Error<B> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `core`:
- impl<T> std::convert::From<T> for T;
This would be really nice to be able to do ? on it, which I am doing a lot, this is for a library by the way and also, B::Error is probably not the user's own type (usually the backend library's type i.e sqlx::Error)
So how would you do this idiomatically?
There's not a way to do it generically, and any feature that would allow it is a long way out.
On the practical front, this means that you have to have concrete implementations, unfortunately, which have to be in your crate or B::Error's crate (or the standard library).
As in, you can't use generics (even if they have a trait bound), you have to use concrete types like sqlx::Error. (I think this is what you mean by "do it for traits".)
Adding a bound for some new second trait on the associated type doesn't help as
You don't want to do that anyway, as again, only you or B::Error's crate could implement it
Coherence doesn't consider where clause constraints like that to boot, so even if it was viable, it doesn't gain you anything
I played around with some experimental features that expand coherence some, and couldn't get it to work with those even.
Compile error is because Backend and Backend::Error are allowed to be same type but switching to a unlinked trait allows From; just you may miss out elsewhere.
I don't understand how impl<B> From<B> for Error<B> { works, B could be anything right? Including Error itself, which would conflict so how come this works?
Oh! I see it now, this is much simpler! What's weird is thiserror isn't even demanding a Display implementation on now, is this an error with thiserror? Rust Playground
Of course I'd use it like this but it's weird that this impl isn't required Rust Playground
Ah, I see. In this case, Display is implemented wherever the generic type parameter is Display itself; if it isn't, thiserror's derive is simply not applicable - playground with a simple proof.
If we do cargo expand on this code, we'll see this explicitly:
impl<BackendError> std::fmt::Display for CacheError<BackendError> where
BackendError: std::fmt::Display {
// skipped
}