# Error handling

**URL:** <https://internals.rust-lang.org/t/error-handling/7437>\
**Category:** Uncategorized\
**Created:** [May 2, 2018, 3:58pm UTC](https://internals.rust-lang.org/t/error-handling/7437 "2018-05-02T15:58:51Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![derekdreery](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/derekdreery/32/2632_2.png) [@derekdreery](https://internals.rust-lang.org/u/derekdreery)\
**Post date:** [May 2, 2018, 3:58pm UTC](https://internals.rust-lang.org/t/error-handling/7437/1 "2018-05-02T15:58:51Z")

</div>

Not sure if this has been mentioned before, but I’ve currently got a lot of code like the following:

```rust
fn my_func() -> Result<Obj, MyError> {
    let file = File::open("some/path")
        .context(ErrorReadingConfig)?
        .read_to_end()
        .context(ErrorReadingConfig)?;

    let mut d = Deserializer::from_bytes(&file);
    let val = T::deserialize(&mut d)
        .context(ErrorReadingConfig)?;
    d.end()
        .context(ErrorReadingConfig)?;
    Ok(val)
}

```

Maybe it would be nice to be able to do the following:

```rust
fn my_func() -> Result<Obj, MyError> {
    try {
        let file = File::open("some/path")?
            .read_to_end()?;

        let mut d = Deserializer::from_bytes(&file);
        let val = T::deserialize(&mut d)?;
        d.end()?;
        val
    }.with_context(ErrorReadingConfig)
}

```

but I don’t know if that’s too much magic.

Was wondering what the current thinking from the powers that be is?

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [May 2, 2018, 4:19pm UTC](https://internals.rust-lang.org/t/error-handling/7437/2 "2018-05-02T16:19:23Z")

</div>

What library is adding in `Result::context`? It seems like this should be possible to handle via `do catch` relatively trivially (depending on how that `context` method works anyway):

```rust
fn my_func() -> Result<Obj, MyError> {
    let res: Result<Obj, MyError> = do catch {
        let file = File::open("some/path")?
            .read_to_end()?;

        let mut d = Deserializer::from_bytes(&file);
        let val = T::deserialize(&mut d)?;
        d.end()?;
        val
    };
    res.context(ErrorReadingConfig)
}

```

---

<div class="post-metadata">

**Author:** ![derekdreery](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/derekdreery/32/2632_2.png) [@derekdreery](https://internals.rust-lang.org/u/derekdreery)\
**Post date:** [May 2, 2018, 4:28pm UTC](https://internals.rust-lang.org/t/error-handling/7437/3 "2018-05-02T16:28:31Z")

</div>

The problem is that each error returned is a different type, but each of these different types has a ‘context’ function, which returns the same type for all the input types (basically makes it a trait object and wraps it in a new type with indirection). So this would have to be

```rust
let res: Result<Obj, TraitObjectButDontBoxMeYet> ...

```

---

<div class="post-metadata">

**Author:** ![Centril](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/centril/32/3334_2.png) [@Centril](https://internals.rust-lang.org/u/Centril)\
**Post date:** [May 2, 2018, 4:29pm UTC](https://internals.rust-lang.org/t/error-handling/7437/4 "2018-05-02T16:29:02Z")

</div>

Note: `do catch` will likely be renamed to `try { .. }`.

---

<div class="post-metadata">

**Author:** ![H2CO3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/h2co3/32/2849_2.png) [@H2CO3](https://internals.rust-lang.org/u/H2CO3)\
**Post date:** [May 2, 2018, 8:28pm UTC](https://internals.rust-lang.org/t/error-handling/7437/5 "2018-05-02T20:28:39Z")

</div>

This sounds like a job for plain old generics. I’ve encountered a similar situation before, and it’s very easily solvable by extending `Result` generically and requiring (and implementing) a trait bound on each of the error types. Note that if many types implement a method with the same signature, it should have been a trait _anyway_. If even the implementation of the `.context()` method is uniform, then it’s possible that even a default implementation suffices. Something along the lines of:

```rust
struct ErrorWithContext(Box<Error>); // or something

trait ContextualError: Error + Sized + 'static {
    fn context(self) -> ErrorWithContext {
        ErrorWithContext(Box::new(self))
    }
}

struct FooError;
impl ContextualError for FooError { … }

struct BarError;
impl ContextualError for BarError { … }

trait ContextualResult<T>: Sized {
    fn context(self) -> Result<T, ErrorWithContext>;
}

impl<T, E: ContextualError> ContextualResult<T> for Result<T, E> {
    fn context(self) -> Result<T, ErrorWithContext> {
        self.map_err(E::context)
    }
}

```

For the sake of clarity, `context` here doesn’t take arguments other than `self`, although the code is easily modified to accommodate additional arguments.

---

<div class="post-metadata">

**Author:** ![derekdreery](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/derekdreery/32/2632_2.png) [@derekdreery](https://internals.rust-lang.org/u/derekdreery)\
**Post date:** [May 2, 2018, 9:09pm UTC](https://internals.rust-lang.org/t/error-handling/7437/6 "2018-05-02T21:09:19Z")

</div>

Thanks for taking the time to show this.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:30am UTC](https://internals.rust-lang.org/t/error-handling/7437/7 "2019-03-25T08:30:09Z")

</div>

Closed on March 25, 2019, 8:30am UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
