custom_error
custom_error copied to clipboard
Compile error for using bincode::Error on 1.7.1
After upgrading to 1.7.1, the compiler complained that error[E0277]: the trait bound 'std::boxed::Box<bincode::ErrorKind>: std::borrow::Borrow<dyn std::error::Error>' is not satisfied
I'm sure that it didn't occurred on 1.6.0 and 1.7.0. But this version breaks my codes...
Note: The bincode::ErrorKind enum DO implement std::error::Error.
Details:
error[E0277]: the trait bound `std::boxed::Box<bincode::ErrorKind>: std::borrow::Borrow<dyn std::error::Error>` is not satisfied
custom_error! {pub SimpleError
Binary { source: bincode::Error } = "Binary Serialize/Deserialize Error",
}
= help: the following implementations were found:
<std::boxed::Box<T> as std::borrow::Borrow<T>>
= note: required by `std::borrow::Borrow::borrow`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
This must have been introduced by https://github.com/lovasoa/custom_error/commit/d55faa97ae200255002a610f0da246dc110f50ae ...
Can you please provide a failing example ?
OK, here is the failing example:
use bincode;
use custom_error::custom_error;
custom_error! {pub SimpleError
Binary { source: bincode::Error } = "Binary Serialize/Deserialize Error",
}
I would say the problem comes from bincode, who do not implement std::error::Error on their Error type.
After some investigation, this indeed comes from d55faa9. This would be fixable with specialization for handling Box<dyn Error> in a particular way, but I don't see how it could be done in today's rust.
std::boxed::Boxdo implementstd::borrow::Borrowbincode::ErrorKinddo implementstd::error::Error
This would fail to compile:
let a: &dyn std::error::Error = std::borrow::Borrow::borrow(&e);
39 | let a: &dyn std::error::Error = std::borrow::Borrow::borrow(&e);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::borrow::Borrow<dyn std::error::Error>` is not implemented for `std::boxed::Box<bincode::ErrorKind>`
But this is ok:
let a: &bincode::ErrorKind = std::borrow::Borrow::borrow(&e);
let b: &dyn std::error::Error = a;
:frowning:
yes. But the thing is: the macro cannot generate the second code, because it does not have access to the underlying type (bincode::ErrorKind).
If this is in fact possible and you have an idea of how to implement the conversion that works for both Box<dyn Error> and Box<ConcreteErrorType>, let me know!
This is the most possible solution I could find... I don't know if this can be generated by macro.
let a: &dyn std::error::Error = std::borrow::Borrow::borrow(&*e);
I am sorry that I may not provide more help because I am not familiar with macro...
The problem is that &*e doesn't work for non-boxed errors.
Is there a known workaround for this problem? Should we file a bug report at bincode?
The workaround is to manually implement From<bincode::Error> for your error, and to name the field something other than source...
You can open a bug report at bincode, as it is indeed unconventional not to implement std::error::Error on your main error type, but since it essentially just works in every other case, I'm not sure they'll be willing to do something...
Thanks! I'll file a bug report tomorrow.
I guess https://github.com/servo/bincode/issues/227 is related — would it be good enough for custom_error?
Yes, it's exactly what we would need!
Hi, maintainer of bincode here. Error should be implemented for all Box<T> where T: Error by a blanket impl in std. I'm not sure what bincode could do to fix this.
An error type has to implement std::borrow::Borrow<dyn std::error::Error> for it to work with custom_error. This allows the library to implement source for both types that implement Error directly and Box<dyn Error>. Unfortunately, this does not work for other boxed error types.
I'm having similar issue:
error: the trait bound tree_sitter::LanguageError: StdError is not satisfied required for the cast to the object type dyn StdError
LanguageError definition:
/// An error that occurred when trying to assign an incompatible `Language` to a `Parser`.
#[derive(Debug, PartialEq, Eq)]
pub struct LanguageError {
version: usize,
}
My definition:
custom_error! {
pub Error
ParseError = "Unable to create tree_sitter tree.",
Io{source: io::Error} = "unable to read from the file",
LangError{source: LanguageError} = "Unable to load language tree_sitter v{source}"
}
Thanks
cc @Leo1003
tree_sitter::LanguageError does not implement the standard Error trait. You should open an issue on their side.