The errors that result from having multiple versions of a crate can be quite inscrutable.
A nice one I got today:
29 | ReadBincode::new(new_inner(channel))
| ^^^^^^^^^^^^^^^^ the trait `std::convert::From<std::boxed::Box<bincode::ErrorKind>>` is not implemented for `my_module::Error`
|
= help: the following implementations were found:
<my_module::Error as std::convert::From<std::io::Error>>
<my_module::Error as std::convert::From<std::boxed::Box<bincode::ErrorKind>>>
= note: required by `<tokio_serde_bincode::ReadBincode<T, U>>::new`
Edit: in fact, that’s part of a more general complaint about namespacing: namespacing in errors is done on a rather blanket basis, which can be a bit unhelpful.
On the one hand if you have only one Result (or OsStringExt) in scope it can make errors unreadable to refer to it as std::result::Result (resp. std::os::ext::ffi::OsStringExt) once the types get big — often to understand an error message I have to paste it into a new emacs buffer and manually remove a lot of the namespacing and format the types across multiple lines so I can see what’s actually going on.
On the other hand, in cases like the above where there are multiple things with the same name being referred to, it would be nice to have the types and traits prefixed by their crate and version — if the error read, for example,
29 | ReadBincode::new(new_inner(channel))
| ^^^^^^^^^^^^^^^^ the trait `From<Box<bincode[0.8]::ErrorKind>>` is not implemented for `Error`
|
= help: the following implementations were found:
<Error as From<io::Error>>
<Error as From<Box<bincode[0.9]::ErrorKind>>>
= note: required by `ReadBincode<T, U>::new`
(using the shorthand module names that are in scope where possible) the cause of the error becomes immediately clear.