Stack Overflow Error When Converting Types with `From` Trait

54 Views Asked by At

I don't know how to express the issue generally in the title but I have encountered a stack overflow error while defining an Error struct to handle third party library errors. Here is an example code snippet.

pub struct Error(ErrorKind);

impl From<FooError> for Error {
    fn from(e: FooError) -> Self {
        e.into()
    }
}

impl From<BarError> for Error {
    fn from(e: BarError) -> Self {
        e.into()
    }
}

pub enum ErrorKind {
    Foo(FooError),
    Bar(BarError),
    Baz,
}

impl From<FooError> for ErrorKind {
    fn from(e: FooError) -> Self {
        Self::Foo(e)
    }
}

impl From<BarError> for ErrorKind {
    fn from(e: BarError) -> Self {
        Self::Bar(e)
    }
}

#[derive(Debug)]
pub struct FooError;
pub struct BarError;


fn main() {
    let foo_e = FooError;
    dbg!(&foo_e);
    let _e = Error::from(foo_e);
}

When I wrote the From<T> implementation for Error type converting from a custom type e.g FooError unintentionally, I got surprised how the compiler understood the type conversion from FooError to ErrorKind then Error with a single expression e.into(). Then I moved on until I encountered a fatal error. Dived in what was the cause was and this was it. When I change the implementation to;

impl From<FooError> for Error {
    fn from(e: FooError) -> Self {
        Self(e.into())
    }
}

The error was gone. I don't think this is intentional where compiler is missing this. If this is a bug, I would like to contribute this to the language. If not what is the casue of the error and why is this allowed by the compiler.

Any professionals help would be appreciated.

Here is the playground. Try it to reproduce the error.

1

There are 1 best solutions below

0
marknikky On

Sorry for my misunderstanding. I know that the implenetation impl From<A> for B generates Into<B>. Due to this, e.into() inside the implementation is simply calling the from function recursively and that causes a stack overflow error.