# Deriving \`Error\`

**URL:** <https://internals.rust-lang.org/t/deriving-error/11894>\
**Category:** language design\
**Created:** [February 24, 2020, 3:31pm UTC](https://internals.rust-lang.org/t/deriving-error/11894 "2020-02-24T15:31:08Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)\
**Post date:** [February 24, 2020, 3:31pm UTC](https://internals.rust-lang.org/t/deriving-error/11894/1 "2020-02-24T15:31:08Z")

</div>

Originally, a type implementing `Error` had to implement `fn description(&self) -> &str`. This is no longer the case, and as of Rust 1.41, that method is actually deprecated. This is because `Error` requires `Debug + Display`, so the built-in solution is to just use `.to_string()`.

Given this combination of factors, I believe it makes sense to add a `#[derive(Error)]` to the compiler. This would behave in a similar manner to `#[derive(Copy)]`, throwing a compiler error if `Display` is not implemented. If a `Display` impl is present, the code could expand by adding `impl std::error::Error for Foo {}`.

* * *

Example error:

Current status with deriving `Copy` without a `Clone` impl:

```rust
#[derive(Copy)]
struct Foo;

```

```nohighlight
error[E0277]: the trait bound `Foo: std::clone::Clone` is not satisfied
 --> src/lib.rs:1:10
  |
1 | #[derive(Copy)]
  | ^^^^ the trait `std::clone::Clone` is not implemented for `Foo`

error: aborting due to previous error

```

A similar error could be thrown when deriving `Error` without a `Display` impl:

```rust
#[derive(Error)]
struct Foo;

```

```nohighlight
error[E0277]: the trait bound `Foo: std::fmt::Display` is not satisfied
 --> src/lib.rs:1:10
  |
1 | #[derive(Error)]
  | ^^^^^ the trait `std::fmt::Display` is not implemented for `Foo`

error: aborting due to previous error

```

* * *

Thoughts?

NB: A `Debug` impl would also be required, per `Error`'s definition, giving similar errors.

---

<div class="post-metadata">

**Author:** ![Nokel81](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nokel81/32/3966_2.png) [@Nokel81](https://internals.rust-lang.org/u/Nokel81)\
**Post date:** [February 24, 2020, 4:15pm UTC](https://internals.rust-lang.org/t/deriving-error/11894/2 "2020-02-24T16:15:13Z")

</div>

Have you taken a look at [`thiserror`](https://docs.rs/thiserror/1.0.11/thiserror/)?

---

<div class="post-metadata">

**Author:** ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)\
**Post date:** [February 24, 2020, 4:16pm UTC](https://internals.rust-lang.org/t/deriving-error/11894/3 "2020-02-24T16:16:40Z")

</div>

I'm aware of that crate. What I'm suggesting is a derive for something that _already has_ a `Display` impl, not something to generate it alongside deriving `Error`.

I think this would be a good fit for the compiler, given its similarities to existing derives.

---

<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:** [February 24, 2020, 4:23pm UTC](https://internals.rust-lang.org/t/deriving-error/11894/4 "2020-02-24T16:23:11Z")

</div>

From a language complexity perspective it seems reasonable for `#[derive(Error)]` to simply expand to `impl Error for MyType {}`, especially since we can reuse most of the compiler code.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [February 24, 2020, 4:25pm UTC](https://internals.rust-lang.org/t/deriving-error/11894/5 "2020-02-24T16:25:55Z")

</div>

The `Error` trait also has `source()` and `backtrace()` methods. They're optional, but is there any reasonable way we can support them?

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [February 24, 2020, 4:34pm UTC](https://internals.rust-lang.org/t/deriving-error/11894/6 "2020-02-24T16:34:32Z")

</div>

This would be great to have, but it presents these design challenges and someone has to drive the consensus process:

1. Error has a non-deriveable supertrait. Currently this is not true of any built-in deriveable traits; are we okay with this change to the consistency of the std derives?
2. Error has several optional methods which users _do_ care about - backtrace & source as Josh said. Can we generate these in the derive?
3. If the solution to #2 requires attributes (as it does in many ecosystem derives), error would be the first std derive to have attributes. Again, are we okay with using this feature in std derives?

Obviously we shouldn't let theoretical purity around the std derives stop us from providing useful features to users, but we should also have a clear sense - if we are going to start introducing these complexities to the std derives - what the limitations on std derives will be. Probably we don't want this to start a slippery slope to providing derives that are complex DSLs with dozens of attribute features and so on.

---

<div class="post-metadata">

**Author:** ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)\
**Post date:** [February 24, 2020, 4:42pm UTC](https://internals.rust-lang.org/t/deriving-error/11894/7 "2020-02-24T16:42:53Z")

</div>

(1) is a point that is obviously a matter of opinion; I think it's fine.

(2) has _some_ analog, in the sense that `Hash::has_slice` and `Clone::clone_from` are optional methods. I have no idea if anyone actually uses those in practice, though, whereas the methods on `Error` are certainly used by some.

(3) is an interesting point. Would introducing a derive that has no options make sense? It would be forward compatible with adding attributes if that were ever desired.

I think having the trivial case handled would be worthwhile, while still allowing custom implementations that provide a source/backtrace. Though that raises the question: If there is a derive, would that lead people away from providing that info?

---

<div class="post-metadata">

**Author:** ![burntsushi](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/burntsushi/32/279_2.png) [@burntsushi](https://internals.rust-lang.org/u/burntsushi)\
**Post date:** [February 24, 2020, 4:43pm UTC](https://internals.rust-lang.org/t/deriving-error/11894/8 "2020-02-24T16:43:41Z")

</div>

See also: [thiserror](https://docs.rs/thiserror/1.0.11/thiserror/)

It goes a bit beyond `derive(Error)` in that it also acts as `derive(Display)`. It also handles `source` and `backtrace`.

Personally, I like it. Personally, I'd also be potentially in favor of moving something like this to std, but I'd really like to see `thiserror` succeed first. (Wow, looking at its reverse dependencies, it already appears to be doing quite well.)

EDIT: Derp, I see `thiserror` was mentioned above. Ah well. So I guess if I'm to add something here, I'd say this: is it worth having a `derive(Error)` that doesn't handle `Display`?

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [February 24, 2020, 6:48pm UTC](https://internals.rust-lang.org/t/deriving-error/11894/9 "2020-02-24T18:48:27Z")

</div>

I'd love to have a built-in `derive(Display)`, too.

---

<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:** [February 24, 2020, 6:55pm UTC](https://internals.rust-lang.org/t/deriving-error/11894/10 "2020-02-24T18:55:02Z")

</div>

> [@withoutboats](#):
>
> Error has a non-deriveable supertrait. Currently this is not true of any built-in deriveable traits; are we okay with this change to the consistency of the std derives?

This is a good point, especially in lieu of [https://github.com/rust-lang/rfcs/pull/2385](https://github.com/rust-lang/rfcs/pull/2385), since it sorta implies we would never do that RFC, and perhaps we shouldn't.

> [@withoutboats](#):
>
> If the solution to #2 requires attributes (as it does in many ecosystem derives), error would be the first std derive to have attributes. Again, are we okay with using this feature in std derives?

I would personally like to see e.g. `#[default]` on `enum` variants used to make `#[derive(Default)]` work on `enum`s. That seems quite useful to me.

> [@josh](#):
>
> I'd love to have a built-in `derive(Display)` , too.

What would it print?

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [February 24, 2020, 7:29pm UTC](https://internals.rust-lang.org/t/deriving-error/11894/11 "2020-02-24T19:29:59Z")

</div>

> [@Centril](#):
>
> This is a good point, especially in lieu of [https://github.com/rust-lang/rfcs/pull/2385](https://github.com/rust-lang/rfcs/pull/2385), since it sorta implies we would never do that RFC, and perhaps we shouldn't.

I don't think we should have _implied_ supertraits; rather, I think it makes sense to have aliases for sets of traits.

> [@Centril](#):
>
> I would personally like to see e.g. `#[default]` on `enum` variants used to make `#[derive(Default)]` work on `enum` s. That seems quite useful to me.

I'd love to have a mechanism to `derive(Default)` using `#[default]`.

> [@Centril](#):
>
> > [@josh](#):
> >
> > I'd love to have a built-in `derive(Display)` , too.
> 
> What would it print?

I'd want something very similar to `thiserror`, with a `#[display]` attribute. See [Please support `#[display("...")]` as a synonym for `#[error("...")]` · Issue #65 · dtolnay/thiserror · GitHub](https://github.com/dtolnay/thiserror/issues/65)

---

<div class="post-metadata">

**Author:** ![dtolnay](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dtolnay/32/1447_2.png) [@dtolnay](https://internals.rust-lang.org/u/dtolnay)\
**Post date:** [February 24, 2020, 7:41pm UTC](https://internals.rust-lang.org/t/deriving-error/11894/12 "2020-02-24T19:41:05Z")

</div>

> [@jhpratt](#):
>
> I'm aware of that crate. What I'm suggesting is a derive for something that _already has_ a `Display` impl, not something to generate it alongside deriving `Error`.

Thiserror can derive for something that already has a Display impl. Just omit the error("...") attributes.

---

<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:** [February 24, 2020, 7:42pm UTC](https://internals.rust-lang.org/t/deriving-error/11894/13 "2020-02-24T19:42:53Z")

</div>

> [@josh](#):
>
> I'd love to have a mechanism to `derive(Default)` using `#[default]` .

(It's part of my "default field values" draft as a holistic set of improvements re. defaults, [https://github.com/Centril/rfcs/pull/19](https://github.com/Centril/rfcs/pull/19), but I haven't had the time to finish the RFC and I'm not sure we should burden the overburdened compiler team with that right now, albeit it would be a nice feature.)

---

<div class="post-metadata">

**Author:** ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)\
**Post date:** [February 24, 2020, 7:49pm UTC](https://internals.rust-lang.org/t/deriving-error/11894/14 "2020-02-24T19:49:00Z")

</div>

Didn't realize that. Prior art, then! And given how popular the crate is, I think it's worth discussing at least.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [February 24, 2020, 9:00pm UTC](https://internals.rust-lang.org/t/deriving-error/11894/15 "2020-02-24T21:00:59Z")

</div>

I think there's value in finishing and reviewing that RFC, and it can sit on the queue to be prioritized based on value and available implementer time.

---

<div class="post-metadata">

**Author:** ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)\
**Post date:** [February 27, 2020, 2:11am UTC](https://internals.rust-lang.org/t/deriving-error/11894/16 "2020-02-27T02:11:44Z")

</div>

What would be the way forward on this? It seems like most of the people here seem to agree that _in principle_ something along this line could exist, and the prior art via `thiserror` indicates that it could be quite common. There are a number of points that need to be worked out, of course.

I presume an RFC would be necessary at some point?

---

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [February 27, 2020, 2:35am UTC](https://internals.rust-lang.org/t/deriving-error/11894/17 "2020-02-27T02:35:26Z")

</div>

> [@withoutboats](#):
>
> Error has a non-deriveable supertrait. Currently this is not true of any built-in deriveable traits; are we okay with this change to the consistency of the std derives?

This is something of a tangent, but: talking with some people the other day, there was an interesting observation about `thiserror` and its current `Error` derive. Really the main value of `thiserror` is its `Display` derive,. If you want to write a crate with optional `no_std` support with `thiserror`, you don't actually want to derive `Error`, but you still want the `Display` derive. There's an [open PR to add a `std` feature to `thiserror`](https://github.com/dtolnay/thiserror/pull/64) so when you `derive(Error)` without that feature enabled, you don't... actually derive `Error`, you just derive `Display`, which seems weird.

For crates like this, it seems like the better way to go is instead a crate like [`displaydoc`](https://crates.io/crates/displaydoc) to do the `Display` derive, and then something like this:

```rust
#[cfg(feature = "std")]
impl std::error::Error for MyError {}

```

It'd sure be nice if that were instead:

```rust
#[cfg_attr(std, derive(Error))]
struct MyError { ... }

```

> Error has several optional methods which users _do_ care about - backtrace & source as Josh said. Can we generate these in the derive?

I think if I were using a custom derive, it'd be for the above trivial case that just treats `std::error::Error` like a marker trait. Anything fancier than that and I'd probably just handwrite it, personally.

> [@withoutboats](#):
>
> If the solution to #2 requires attributes (as it does in many ecosystem derives), error would be the first std derive to have attributes. Again, are we okay with using this feature in std derives?

I don't know what the implementation details are, but I'd sure love if more of the built-in custom derives supported attributes for various things, especially `Default`. I know there are plenty of additional crates to provide "power user derives", but for something like "I want to `derive(Default)`, but change the default for one field", it's usually easy enough to handwrite the `Default` impl.

It sure would be nice to do things like:

```rust
#[derive(Default)]
struct MyStruct {
   foo: bool,
   bar: usize,
   #[default(myfunc)]
   baz: MyType,
} 

fn myfunc() -> MyType {
    ...
}

```

...or...

```rust
#[derive(Default)
enum X {
   #[default]
   A,
   B,
   C,
}

```

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [February 27, 2020, 4:42am UTC](https://internals.rust-lang.org/t/deriving-error/11894/18 "2020-02-27T04:42:59Z")

</div>

> [@bascule](#):
>
> I think if I were using a custom derive, it'd be for the above trivial case that just treats `std::error::Error` like a marker trait. Anything fancier than that and I'd probably just handwrite it, personally.

I'll have to disagree here.

Errors that are a wrapper around upstream errors are typically still considered good (when implemented correctly), and are not uncommon. Implementing `Error` correctly means hooking up `cause`, etc. to the wrapped error.

Forwarding these methods is simple but very boilerplatey, and it just compounds for libraries taking the more-errors (as opposed to god-error) approach.

---

<div class="post-metadata">

**Author:** ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)\
**Post date:** [February 27, 2020, 4:57am UTC](https://internals.rust-lang.org/t/deriving-error/11894/19 "2020-02-27T04:57:37Z")

</div>

As others have mentioned with regard to `Default` and a possible `#[default]` attribute on enums, I think having a `#[source]` attribute to indicate what should be returned from the `source()` method would also make sense. From my (admittedly limited) proc macro experience, it wouldn't be too difficult to implement, either.

---

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [February 28, 2020, 3:42am UTC](https://internals.rust-lang.org/t/deriving-error/11894/20 "2020-02-28T03:42:24Z")

</div>

> [@CAD97](#):
>
> Errors that are a wrapper around upstream errors are typically still considered good (when implemented correctly), and are not uncommon.

[I strongly agree.](https://crates.io/crates/anomaly)

> [@](#):
>
> Implementing `Error` correctly means hooking up `cause` , etc. to the wrapped error.

You'll want to use [`Error::source`](https://doc.rust-lang.org/std/error/trait.Error.html#method.source) these days, but yes, I also agree with that.

> [@](#):
>
> Forwarding these methods is simple but very boilerplatey, and it just compounds for libraries taking the more-errors (as opposed to god-error) approach.

To me that's gravy, and can be added in the future. I don't think that problem is big enough to block making some incremental progress on a `std::err::Error` derive which handles the "marker trait" use case, nor do I see how adding that derive now would negatively impact future work on such a feature.

The attribute DSL for doing that sounds like it'd need a lot of design work / consideration / bikeshedding, whereas a "marker trait" derive is a relatively simple, self-contained thing. As @withoutboats noted earlier, if you wanted to add an attribute DSL for this, it would be the first std derive to have attributes, which I think might make it even more controversial.

That said:

> [@jhpratt](#):
>
> I think having a `#[source]` attribute to indicate what should be returned from the `source()` method would also make sense. From my (admittedly limited) proc macro experience, it wouldn't be too difficult to implement, either.

If that's all it is, it might be ok. Seems like it would only work for `struct`s?

[Next page](https://internals.rust-lang.org/t/deriving-error/11894.md?page=2)
