Derive Default minor mystery

A long time ago I ran into a situation where I needed to derive Default on a struct that contained an Option of something that wasn't Default. I don't remember the exact details, but I was left with a lasting impression that this didn't work (In particular I remember being very surprised by it). Ever since then I've been manually implementing Default in such cases to get around the apparent deficiency in #[derive(Default)].

I just had a sudden burst of curiosity and tested this:

struct Bar;

#[derive(Default)]
struct Foo {
  bar: Option<Bar>
}

fn main() {
  let _foo = Foo::default();
}

... and it works just fine! I feel like an idiot. All those manual impl Default for .. just to work around a non-existing limitation. Is there any face-saving for me here? Is there a situation where an Option<T> won't shield the absence of T: Default? Or is this something that actually didn't work a few years back?

Absence any other explanation I'm going to speculate that I mistyped Default as Debug. :grimacing:

Probably that. Default has been implemented for Option<T> since pre 1.0 regardless of whether T implements Default itself, which is not necessary when defaulting to the None variant.

1 Like

You might be remembering the generic case:

#[derive(Default)]
struct Foo<T> {
  bar: Option<T>
}

Here, the derived default impl will automatically apply a T: Default bound, even if it's not necessary. This breaks for <Foo<Bar>>::default().

13 Likes

yes, when the type is generic, and this is a known limitation. see this blog post about "perfect derive" for more information:

https://smallcultfollowing.com/babysteps/blog/2022/04/12/implied-bounds-and-perfect-derive/

5 Likes