Why Box<dyn Error> is not SIzed?

I am trying to build this snippet, and facing with an compilation error, but cannot understand why:

use thiserror::Error;

#[derive(Debug, Error)]
pub enum Error<E: std::error::Error> {
    #[error("")]
    Other(E),
}

pub enum ResultKind<E: std::error::Error> {
    Boxed(Error<Box<dyn std::error::Error>>),
    Typed(Error<E>)
}

here is the error:

error[E0277]: the size for values of type `(dyn std::error::Error + 'static)` cannot be known at compilation time
  --> src/lib.rs:10:11
   |
4  | pub enum Error<E: std::error::Error> {
   |                   ----------------- required by this bound in `Error`
...
10 |     Boxed(Error<Box<dyn std::error::Error>>),
   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
   |
   = help: the trait `Sized` is not implemented for `(dyn std::error::Error + 'static)`
   = note: required because of the requirements on the impl of `std::error::Error` for `Box<(dyn std::error::Error + 'static)>`

You misunderstand the error, but I agree that it is a bit cryptic. The type Box<dyn Error> is actually sized — the error is complaining that dyn Error without the Box is not sized.

The reason behind this error is that Box<T> only implements Error if T is both Sized and implements Error. However, dyn Error is not Sized, so Box<dyn Error> does not implement error.

I would probably remove the E: Error bound on both enums.

1 Like

As an aside, I wonder why that is. There's nothing I could find in the definition of the Error trait that would require that Self: Sized; in fact, there's a blanket impl Error for &T where T: ?Sized + Error. In what regard is Box different?

It's because otherwise impl From<T> for T and impl<E: Error> From<E> for Box<dyn Error> overlaps when E = Box<dyn Error>.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.