custom_error icon indicating copy to clipboard operation
custom_error copied to clipboard

Compile error for using bincode::Error on 1.7.1

Open Leo1003 opened this issue 6 years ago • 18 comments

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)

Leo1003 avatar Sep 12 '19 11:09 Leo1003

This must have been introduced by https://github.com/lovasoa/custom_error/commit/d55faa97ae200255002a610f0da246dc110f50ae ...

lovasoa avatar Sep 12 '19 13:09 lovasoa

Can you please provide a failing example ?

lovasoa avatar Sep 12 '19 13:09 lovasoa

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.

lovasoa avatar Sep 12 '19 13:09 lovasoa

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.

lovasoa avatar Sep 12 '19 15:09 lovasoa

  • std::boxed::Box do implement std::borrow::Borrow
  • bincode::ErrorKind do implement std::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:

Leo1003 avatar Sep 13 '19 08:09 Leo1003

yes. But the thing is: the macro cannot generate the second code, because it does not have access to the underlying type (bincode::ErrorKind).

lovasoa avatar Sep 13 '19 10:09 lovasoa

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!

lovasoa avatar Sep 13 '19 10:09 lovasoa

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...

Leo1003 avatar Sep 13 '19 15:09 Leo1003

The problem is that &*e doesn't work for non-boxed errors.

lovasoa avatar Sep 13 '19 16:09 lovasoa

Is there a known workaround for this problem? Should we file a bug report at bincode?

glehmann avatar Nov 13 '19 20:11 glehmann

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...

lovasoa avatar Nov 13 '19 22:11 lovasoa

Thanks! I'll file a bug report tomorrow.

glehmann avatar Nov 14 '19 00:11 glehmann

I guess https://github.com/servo/bincode/issues/227 is related — would it be good enough for custom_error?

glehmann avatar Nov 14 '19 07:11 glehmann

Yes, it's exactly what we would need!

lovasoa avatar Nov 14 '19 09:11 lovasoa

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.

ZoeyR avatar Apr 01 '20 04:04 ZoeyR

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.

lovasoa avatar Apr 01 '20 08:04 lovasoa

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

kkharji avatar Apr 24 '21 17:04 kkharji

tree_sitter::LanguageError does not implement the standard Error trait. You should open an issue on their side.

lovasoa avatar Apr 27 '21 19:04 lovasoa