Sized error with Box<Error>

I have the following code

fn run(opts: Opts) -> Result<(), impl std::error::Error/*( aka Error )*/> {
    if false {
        let e = <Box<dyn Error> as From<&'static str>>::from("test");
        return Err(e);
    }
    Ok(())
}

which doesn't compile because Box<dyn Error> doesn't implement Error (because its contents don't implement Sized). Is there a way to make this code work. It's just a placeholder so it doesn't really matter, but I feel it would help me to understand trait object better.

I never noticed that there's no impl Error for Box<dyn Error>. I suppose you want to return impl Error, rather than Box<dyn Error>, to hide the return type? If so, you can probably define an adapter struct (e.g. struct Adapter(Box<dyn Error>), impl Error for it, and return that.

The issue is that this implementation is missing the T: ?Sized bound to support trait objects. That should be backwards compatible to add, but I'm surprised that it hasn't been noticed before if it is really that trivial to fix...

3 Likes

I'll stick a PR in and see what feedback it gets.

Update: I added ?Sized to the bound and got the following error

error[E0119]: conflicting implementations of trait `core::convert::From<alloc_crate::boxed::Box<dyn error::Error>>` for type `alloc_crate::boxed::Box<dyn error::Error>`:
   --> src/libstd/error.rs:219:1
    |
219 | impl<'a, E: Error + ?Sized + 'a> From<E> for Box<dyn Error + 'a> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: conflicting implementation in crate `core`:
            - impl<T> core::convert::From<T> for T;

error[E0119]: conflicting implementations of trait `core::convert::From<alloc_crate::boxed::Box<dyn error::Error + core::marker::Send + core::marker::Sync>>` for type `alloc_crate::boxed::Box<dyn error::Error + core::marker::Send + core::marker::Sync>`:
   --> src/libstd/error.rs:255:1
    |
255 | impl<'a, E: Error + Send + Sync + ?Sized + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: conflicting implementation in crate `core`:
            - impl<T> core::convert::From<T> for T;

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0119`.
error: Could not compile `std`.

I think those conversions are unnecessary now since they are covered by the blanket impl. I will try removing them and see if I get errors.

Update 2: This causes failure so the conflict must be between 2 things that are not the same. Is this a rustc bug?

Update 3: I asked about the issue on irlo, but I don't fully understand the response. Does it mean that the conflicting impls above are redundant? It doesn't seem so since removing them causes errors elsewhere.