# \#\[derive(Debug)\] by default

**URL:** <https://internals.rust-lang.org/t/derive-debug-by-default/11734>\
**Category:** language design\
**Created:** [January 31, 2020, 2:36am UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734 "2020-01-31T02:36:10Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![alfie](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/alfie/32/6496_2.png) [@alfie](https://internals.rust-lang.org/u/alfie)\
**Post date:** [January 31, 2020, 2:36am UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/1 "2020-01-31T02:36:10Z")

</div>

I'm just curious as to what would be the downside of having `#[derive(Debug)]` enabled by default for ALL structs etc when building the debug target, rather than having to sprinkle it on a handful of datatypes manually during development?

---

<div class="post-metadata">

**Author:** ![notriddle](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/notriddle/32/14082_2.png) [@notriddle](https://internals.rust-lang.org/u/notriddle)\
**Post date:** [January 31, 2020, 2:56am UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/2 "2020-01-31T02:56:36Z")

</div>

There'd need to be a way to turn it off for things like encryption keys and structs that you want to manually implement Debug for, it would require making Debug special in a way that other traits aren't, it would open the floodgates for people asking for additional traits to be made special in the same way, and since Debug doesn't exist without libstd, it would need to handle the discontinuity between no\_std and std crates.

None of these are unsolvable problems, of course. And I actually like the sound of that, too. But it involves making a trait special when right now it's just an ordinary trait with an ordinary derive macro, and a lot of people don't like adding special-cases like that.

---

<div class="post-metadata">

**Author:** ![alfie](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/alfie/32/6496_2.png) [@alfie](https://internals.rust-lang.org/u/alfie)\
**Post date:** [January 31, 2020, 3:05am UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/3 "2020-01-31T03:05:19Z")

</div>

Ok, that's an awesome answer. Totally agree.

As we can't just enable it by default because of those issues, how about solving this another way? What would people think of a command line flag e.g:

```
cargo build --derive-debug-all

```

... or something like that? To me, I think that would be handy

---

<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:** [January 31, 2020, 3:13am UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/4 "2020-01-31T03:13:47Z")

</div>

That wouldn't be useful at all. Since the code wouldn't compile without it (unless it did but then the flag would have no effect).

---

<div class="post-metadata">

**Author:** ![alfie](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/alfie/32/6496_2.png) [@alfie](https://internals.rust-lang.org/u/alfie)\
**Post date:** [January 31, 2020, 3:28am UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/5 "2020-01-31T03:28:01Z")

</div>

hmm... yeah, you're right.

Any thoughts on how something like this could work then?

---

<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:** [January 31, 2020, 4:52am UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/6 "2020-01-31T04:52:47Z")

</div>

I've found `#![warn(missing_debug_implementations)]` to be "enough," personally, as it reminds you when you forget to derive `Debug`, and I'm used to just accepting every struct requiring some amount of attributes to tell how it should behave.

The "perfect" "magic `Debug`" to me would be the functional equivalent of providing a blanket `default impl` for all types with the implementation of `#[derive(Debug)]`. Thus, you'd be able to override it immediately by providing your own `impl Debug` which is more specific than `for<T>` (i.e. any impl that you could write anyway). It'd also have to always apply; silently turning off if some member doesn't impl `Debug` (either because it didn't opt in to magic `Debug` impls or through some explicit opt-out of the magic impl (`impl !Debug`? Could that be generally applicable to `default impl`?), because otherwise it's a huge semver hazard to accidentally make a struct not impl `Debug` anymore by introducing a new private member.

We _could_ potentially add a magic `default` automatic `Debug` derive for _all_ types (even those where it'd be a compile error, for the reason above) on an edition boundary (probably one that has stable specialization, though), but I think the problems with it outweigh the potential benefits. However, `missing_debug_implementations` is a good candidate for raising up to warn-by-default (at least when running lints via `cargo clippy` rather than `cargo check`} I think, especially if it can be/is limited to only `pub` types (I don't recall if it is off the top of my head).

---

<div class="post-metadata">

**Author:** ![alfie](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/alfie/32/6496_2.png) [@alfie](https://internals.rust-lang.org/u/alfie)\
**Post date:** [January 31, 2020, 10:35am UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/7 "2020-01-31T10:35:25Z")

</div>

The problem with `missing_debug_implementation` is that you have to manually add it (or let you editor do it etc), which is what I have issue with - IMHO lots of `derive(Debug)` sprinkled clutters code too.

Alternatively, which is what I'm opposed to, would be to add an option to `cargo fmt` which adds the `derive` everywhere!

... I started this thread hating the cluttering, but now think auto-sprinkling may be the best of all worlds!

---

<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:** [January 31, 2020, 3:07pm UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/8 "2020-01-31T15:07:51Z")

</div>

> [@alfie](#):
>
> Alternatively, which is what I'm opposed to, would be to add an option to `cargo fmt` which adds the `derive` everywhere!

If the lint is marked as machine applicable, then `cargo fix` will be able to apply it for you. (`cargo fmt` afterwards would then `merge_derives` for you.)

And I'm in favor of making `missing_derive_implementations` warn-by-default (for `pub` types) so that you don't have to opt into it.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [January 31, 2020, 3:11pm UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/9 "2020-01-31T15:11:57Z")

</div>

I haven't measured, but I expect it'd affect compilation times and executable sizes. There would be more macros to expand and compile, and I don't know if the linker can be trusted to remove unused `Debug` implementations.

---

<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:** [January 31, 2020, 4:41pm UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/10 "2020-01-31T16:41:08Z")

</div>

We actually have a case study here with syn: they've made derive impls opt-in specifically because they both negatively impact compile time for their huge number of AST structs and are rarely used in practice.

A "magic default impl" might have more freedom to only generate when requested and/or be more efficient than a syntactical derive (which tbh I don't think `#[derive__Default]` even is anyway?), but ultimately, yes, always applying a `Debug` derive will have some performance impact.

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [January 31, 2020, 11:29pm UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/11 "2020-01-31T23:29:24Z")

</div>

> [@alfie](#):
>
> IMHO lots of `derive(Debug)` sprinkled clutters code too

Personally I haven't been too annoyed with that, since it's usually `#[derive(Debug, Clone)]` or more, so just removing the `Debug, ` doesn't feel like it's make all that much of a difference.

Which is, of course, additional evidence for notriddle's point about floodgates and wanting the same feature for more traits. I suppose that "auto-derived" traits _would_ combo well with [expanded negative impls](https://internals.rust-lang.org/t/explicit-negative-impls-to-fix-pin-soundness-hole/11587), though...

---

<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:** [February 1, 2020, 6:33pm UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/12 "2020-02-01T18:33:08Z")

</div>

What's wrong with just writing `#[derive(Debug)]`? Seriously, I don't see a _problem_ to be solved here.

---

<div class="post-metadata">

**Author:** ![mbrubeck](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mbrubeck/32/174_2.png) [@mbrubeck](https://internals.rust-lang.org/u/mbrubeck)\
**Post date:** [February 1, 2020, 6:38pm UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/13 "2020-02-01T18:38:37Z")

</div>

One problem is when your type contains types from a library, and the library author neglected to write `#[derive(Debug)]` on all _their_ types.

The [API guidelines](https://rust-lang.github.io/api-guidelines/interoperability.html) recommend preemptively implementing `Debug` for all types, but there's not great tooling to help authors do this consistently.

---

<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:** [February 1, 2020, 6:49pm UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/14 "2020-02-01T18:49:10Z")

</div>

[`#![deny(missing_debug_implementations)]`](https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#missing-debug-implementations)

---

<div class="post-metadata">

**Author:** ![jjpe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jjpe/32/9779_2.png) [@jjpe](https://internals.rust-lang.org/u/jjpe)\
**Post date:** [February 1, 2020, 11:08pm UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/15 "2020-02-01T23:08:30Z")

</div>

> [@H2CO3](#):
>
> `#![deny(missing_debug_implementations)]`

This is a nice tool, didn't know this existed.

> [@H2CO3](#):
>
> What's wrong with just writing `#[derive(Debug)]` ? Seriously, I don't see a _problem_ to be solved here.

If a problem exists at all here, I would say it is that both the `missing_debug_implementations` lint and the `#[derive(Debug)]` attribute actively require an action to be taken on the part of the programmer, and since programmers tend to be lazy, I expect most people want a "zero-action" solution. In other words, they want the generation of `Debug` impls automated away completely.

Such a solution would have to play nice with extant manual `Debug` impls though, because those usually exist because the author deemed the derivable `Debug` impl insufficient.

---

<div class="post-metadata">

**Author:** ![Tom-Phinney](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tom-phinney/32/3299_2.png) [@Tom-Phinney](https://internals.rust-lang.org/u/Tom-Phinney)\
**Post date:** [February 1, 2020, 11:17pm UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/16 "2020-02-01T23:17:06Z")

</div>

> [@jjpe](#):
>
> Such a solution would have to play nice with extant manual `Debug` impls though, because those usually exist because the author deemed the derivable `Debug` impl insufficient.

That's been my experience when I've deliberately created a manual debug `Impl` for a struct: to better convey the data in an application-related 2D form.

---

<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:** [February 2, 2020, 7:11pm UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/17 "2020-02-02T19:11:42Z")

</div>

In this case, I just have to disagree that "zero-action" is desirable here. It's basically magic with downsides stemming from reasons similar to what you mentioned. Furthermore, adding the one crate attribute _literally once per project_ shouldn't be deemed too much effort.

Edit: while thinking about it, an obvious solution to "I didn't know about/I don't want to type `missing_debug_implementations`" is to make the lint warn-by default (or higher, up to discussion). However I'm not sure if that can be done without a breaking change. I'd actually welcome more warnings enabled by default, both in rustc and in Clippy.

---

<div class="post-metadata">

**Author:** ![tspiteri](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tspiteri/32/7283_2.png) [@tspiteri](https://internals.rust-lang.org/u/tspiteri)\
**Post date:** [February 3, 2020, 4:05pm UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/18 "2020-02-03T16:05:11Z")

</div>

I agree with making it an enabled-by-default clippy lint, but disagree with enabling the lint by default on rustc, as there are legitimate reasons not to derive `Debug`. (Compilation performance is to me such a legitimate reason.)

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [February 4, 2020, 4:32am UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/19 "2020-02-04T04:32:18Z")

</div>

> [@tspiteri](#):
>
> as there are legitimate reasons not to

Note that that's a reason it shouldn't be _deny_-by-default (or worse, a hard error), but not that it shouldn't be warn-by-default. If you have one of those legitimate reasons, you can disable it -- globally or just for the one type. (Like many of our other warn-by-default lints, such as naming conventions.)

---

<div class="post-metadata">

**Author:** ![dhm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhm/32/4879_2.png) [@dhm](https://internals.rust-lang.org/u/dhm)\
**Post date:** [February 6, 2020, 10:11am UTC](https://internals.rust-lang.org/t/derive-debug-by-default/11734/20 "2020-02-06T10:11:01Z")

</div>

Since nobody has mentioned this:

> making a struct automagically `derive(Debug)` when possible makes it so that adding a non `Debug` field to a `pub` type becomes a breaking change.

The solution, as said by @CAD97, would require specialization:

```rust
#![feature(specialization)]

impl<T : ?Sized> Debug for T {
    default
    fn fmt (...) -> _
    {
        ..."<no Debug representation available>"
    }
}

```

This way _everything_ would be guaranteed to have a `Debug` impl, for which changing in a future edition `derive(Debug)` to be opt-out1 rather than opt-in would then just be a matter of measuring the impact in compilation times.

1 Ideally with an attribute applicable on a type definition (_à la_ `#[derive...]`) but also applicable to a module (like the other attributes): the latter case would allow people concerned about compile times to keep functioning as it does now.

* * *

All this having been said, I am with @H2CO3 in that this is not really an actual concern, provided `missing_debug_implementations` becomes a `warn-by-default` lint:

> What is greater, the laziness of programmers, or the itching of a warning?

[Next page](https://internals.rust-lang.org/t/derive-debug-by-default/11734.md?page=2)
