Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parametrized error types causes type evaluation overflows when recursive #317

Open
zannabianca1997 opened this issue Sep 3, 2024 · 0 comments

Comments

@zannabianca1997
Copy link

zannabianca1997 commented Sep 3, 2024

thiserror works well with recursive error types, and this snippet compiles with no error:

use std::error::Error;

use thiserror::Error; // 1.0.63

#[derive(Debug, Error)]
pub enum MyError {
    #[error("Recurse")]
    Recurse(#[source] Box<MyError>),
    #[error("Payload")]
    Payload(&'static str),
}


fn main() {
    let _: &dyn Error = &MyError::Payload("Hello");
}

But when one uses an error that is parametrized over his content, it causes an overflow in type evaluation:

use std::error::Error;

use thiserror::Error; // 1.0.63

#[derive(Debug, Error)]
pub enum MyError<Payload> {
    #[error("Recurse")]
    Recurse(#[source] Box<MyError<Payload>>),
    #[error("Payload")]
    Payload(Payload),
}


fn main() {
    let _: &dyn Error = &MyError::Payload("Hello");
}
   Compiling playground v0.0.1 (/playground)
error[E0275]: overflow evaluating the requirement `Box<MyError<&str>>: std::error::Error`
  --> src/main.rs:15:25
   |
15 |     let _: &dyn Error = &MyError::Payload("Hello");
   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: required for `MyError<&str>` to implement `std::error::Error`
  --> src/main.rs:5:17
   |
5  | #[derive(Debug, Error)]
   |                 ^^^^^ unsatisfied trait bound introduced in this `derive` macro
6  | enum MyError<Payload> {
   |      ^^^^^^^^^^^^^^^^
   = note: required for the cast from `&MyError<&str>` to `&dyn std::error::Error`
   = note: this error originates in the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0275`.
error: could not compile `playground` (bin "playground") due to 1 previous error

I can easily implement by myself, but often this is not possible due to too many variants

use std::error::Error;
use std::fmt::{Display, Debug};

#[derive(Debug)]
pub enum MyError<Payload> {
    Recurse(Box<MyError<Payload>>),
    Payload(Payload),
}

impl<Payload> Display for MyError<Payload> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>)->std::fmt::Result {
        match self {
            Self::Recurse(_) => write!(f, "Recurse"),
            Self::Payload(_) => write!(f, "Payload"),
        }
    }
}

impl<Payload> Error for MyError<Payload>
where 
    MyError<Payload>: Debug + 'static,
{
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            Self::Recurse(source) => Some(source),
            Self::Payload(_) => None,
        }
    }
}

fn main() {
    let _: &dyn Error = &MyError::Payload("Hello");
}

Is this an hard limitation?

zannabianca1997 added a commit to zannabianca1997/dices that referenced this issue Sep 5, 2024
…rsive parametrized errors.

This whole ordeal can be removed when [issue 317](dtolnay/thiserror#317) on `thiserror` will be resolved.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant