Stream: project-error-handling

Topic: separating From<E: Error> from Box<dyn Error>


view this post on Zulip Jane Lusby (Feb 27 2021 at 00:37):

so I played with your try_trait_v2 crater build toolchain @scottmcm and tested out moving the From interconversions to be a property of a Result type instead of the inner Error and using that to ? directly into a Box<dyn Error> equivalent that still implements the error trait

view this post on Zulip Jane Lusby (Feb 27 2021 at 00:37):

it worked like a charm and I'm still working through the possible implications that could have

view this post on Zulip Jane Lusby (Feb 27 2021 at 00:38):

my feeling is that this _should_ be the direction the language and error handling libraries move

view this post on Zulip Jane Lusby (Feb 27 2021 at 00:39):

eyre for example could be updated to remove the From impl on eyre::Report, change the Result from a type alias to its own independent type, and add all the necessary From logic to the Try type rather than the inner report

view this post on Zulip Jane Lusby (Feb 27 2021 at 00:39):

that would let eyre::Report interoperate much more cleanly with the rest of the ecosystem

view this post on Zulip Jane Lusby (Feb 27 2021 at 00:40):

i think there's an impl that I can't really write that I want to, which is approximately equal to this part of my test crate

view this post on Zulip Jane Lusby (Feb 27 2021 at 00:40):

impl<T> FromResidual<Result<!, BoxError>> for ResultReport<T>
{
    fn from_residual(inner: Result<!, BoxError>) -> Self {
        let inner = match inner {
            Ok(_) => unreachable!(),
            Err(BoxError(inner)) => inner,
        };

        let inner = match inner.downcast::<AnyError>() {
            Ok(inner) => Err(*inner),
            Err(inner) => {
                let inner = BoxError(inner);

                let inner = AnyError {
                    inner,
                    context: Foo,
                };

                Err(inner)
            }
        };

        ResultReport { inner }
    }
}

view this post on Zulip Jane Lusby (Feb 27 2021 at 00:41):

the specific types here are fillers to make the orphan rules happy, but basically when converting from a regular Result<!, BoxError> back into an eyre::Result it would attempt to downcast the box to an eyre::Report, and use that if it already was one, otherwise it wraps it

view this post on Zulip Jane Lusby (Feb 27 2021 at 00:41):

this won't work outside of std though, because Box<dyn Error> could impl Error in the future

view this post on Zulip Jane Lusby (Feb 27 2021 at 00:42):

so this doesn't work out perfectly

view this post on Zulip Jane Lusby (Feb 27 2021 at 00:43):

actually, can this work just fine? I might be able to do Into<Box<dyn Error>> and then immediately downcast in the main generic definition

view this post on Zulip Jane Lusby (Feb 27 2021 at 00:46):

oh yea, okay cool I think that works perfectly, so I can now remove all of this extra box stuff and just use the real Box<dyn Error> type

view this post on Zulip Jane Lusby (Feb 27 2021 at 00:48):

oh gosh, this changes a lot

view this post on Zulip Jane Lusby (Feb 27 2021 at 00:49):

very exciting

view this post on Zulip Jane Lusby (Feb 27 2021 at 00:57):

One thing I really want to see if we can figure out is some path to deprecating and finally removing From<E: Error> for Box<dyn Error>

view this post on Zulip Jane Lusby (Feb 27 2021 at 00:57):

it seems like a lot of hacks would be needed to make it work though

view this post on Zulip Jane Lusby (Feb 27 2021 at 00:57):

so thats a brainstorming session for later

view this post on Zulip scottmcm (Feb 27 2021 at 01:53):

Jane Lusby said:

it worked like a charm and I'm still working through the possible implications that could have

I don't think I follow what you tried, but I'm glad it worked well :smile:

Is this the "make a new result-like type" thing?

view this post on Zulip Jane Lusby (Feb 27 2021 at 02:20):

scottmcm said:

I don't think I follow what you tried, but I'm glad it worked well :smile:

Is this the "make a new result-like type" thing?

view this post on Zulip Jane Lusby (Feb 27 2021 at 02:20):

yess

view this post on Zulip Jane Lusby (Feb 27 2021 at 02:20):

one sec

view this post on Zulip Jane Lusby (Feb 27 2021 at 02:24):

@scottmcm https://gist.github.com/yaahc/9fe7a7631ac35df227e2061bd5d56be3

view this post on Zulip Jane Lusby (Feb 27 2021 at 02:25):

so the idea is that we'd add a Result like this to eyre, remove the From<E: Error> impl on eyre::Report, and add an Error impl to it

view this post on Zulip Jane Lusby (Feb 27 2021 at 02:37):

my mind is exploding, the possibility of all error types implementing error the way they actually should has such massive implications for the rest of the error reporting stuff we've been working on

view this post on Zulip scottmcm (Feb 27 2021 at 02:58):

Ah, because you're no longer restricted by the T: From<T>

view this post on Zulip Jane Lusby (Feb 27 2021 at 02:58):

yup

view this post on Zulip Jane Lusby (Feb 27 2021 at 02:58):

so then anyhow::Error and eyre::Report get to impl Error

view this post on Zulip Jane Lusby (Feb 27 2021 at 02:59):

and you can even have them behave like normal errors

view this post on Zulip Jane Lusby (Feb 27 2021 at 02:59):

only printing the outermost error message and returning sources like expected

view this post on Zulip Jane Lusby (Feb 27 2021 at 02:59):

so you can wrap them in other error types

view this post on Zulip Jane Lusby (Feb 27 2021 at 02:59):

and then they provide a .report() fn like display() on Path for getting a type that implements only Display, not Error

view this post on Zulip Jane Lusby (Feb 27 2021 at 03:00):

and this is what handles outputting your custom format, iterating over sources etc

view this post on Zulip Jane Lusby (Feb 27 2021 at 03:00):

then presuming we've updated the PanicInfo so it can contain dyn Errors and made it so unwrap passes through the error type as a dyn Error if it impls error

view this post on Zulip Jane Lusby (Feb 27 2021 at 03:01):

or even the custom result that you use could have an unwrap that just expects its an error

view this post on Zulip Jane Lusby (Feb 27 2021 at 03:01):

the panic handler can downcast the error back to the eyre::Report type concretely to do its custom reporting, or treat it like any other error if it doesn't recognize the static type

view this post on Zulip Jane Lusby (Feb 27 2021 at 03:01):

so now we can easily preserve additional context we tack onto errors

view this post on Zulip Jane Lusby (Feb 27 2021 at 03:02):

and the FromResidual lets us pass through std::result::Result easily without re-wrapping ourself multiple times and re-capturing the backtrace

view this post on Zulip Jane Lusby (Feb 27 2021 at 03:02):

by checking a downcast each time we create our residual from a box<dyn Error>

view this post on Zulip scottmcm (Feb 27 2021 at 03:03):

Wow, this all sounds epic. It'll be a great example to answer felix's question about why FromResidual should be generic, too -- I'll have to add it to the RFC :)

(Should I just link to this zulip thread as a reference? Is there something better?)

view this post on Zulip Jane Lusby (Feb 27 2021 at 03:04):

i say just link the zulip thread

view this post on Zulip Jane Lusby (Feb 27 2021 at 03:04):

I'm working on a blog post rn for what we're planning on doing for the ecosystem

view this post on Zulip Jane Lusby (Feb 27 2021 at 03:04):

and im basically changing everything in it to be based on these plans

view this post on Zulip Jane Lusby (Feb 27 2021 at 03:05):

so depending on how long it takes me to write that (hard recently because depressed constantly) that will probably be a good link to include

view this post on Zulip Jane Lusby (Feb 27 2021 at 03:05):

but until then yea, just the zulip thread imo


Last updated: Jan 29 2022 at 10:29 UTC