# Allow constructing non\_exhaustive structs using ..Default::default()

**URL:** <https://internals.rust-lang.org/t/allow-constructing-non-exhaustive-structs-using-default-default/13868>\
**Category:** language design\
**Created:** [January 19, 2021, 4:15pm UTC](https://internals.rust-lang.org/t/allow-constructing-non-exhaustive-structs-using-default-default/13868 "2021-01-19T16:15:36Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![LoganDark](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/logandark/32/7266_2.png) [@LoganDark](https://internals.rust-lang.org/u/LoganDark)\
**Post date:** [January 19, 2021, 4:15pm UTC](https://internals.rust-lang.org/t/allow-constructing-non-exhaustive-structs-using-default-default/13868/1 "2021-01-19T16:15:37Z")

</div>

Let's say there is a config struct that decides some behavior in some library:

```rust
struct Config {
    pub use_foo: bool,
    pub far_enabled: bool,
    pub title: String,
}

```

Right now, adding any new configuration options is a breaking change. This is undesirable because I may want to expand the library's functionality in the future.

At first, I considered using `#[non_exhaustive]`, because that's supposed to signal to the user (and the compiler) that more fields may be added in the future. If my `Config` implemented `Default`, I assumed that meant that downstream users could just use this syntax:

```rust
let config = Config {
    use_foo: false,
    ..Default::default()
}

```

That way, any new fields that are added will be given their default values. Seems perfectly reasonable, right? Well, that's forbidden by the compiler:

```rust
error[E0639]: cannot create non-exhaustive struct using struct expression

```

Looking up that error code, it looks like `#[non_exhaustive]` is _only_ meant to signal that more fields may be added in the future - the exact behavior to enforce that does not seem exactly defined.

Why am I not allowed to construct using an existing instance which already has all the fields? That would allow users to specify the config options they want to change while new fields will simply be set to their defaults.

I think `#[non_exhaustive]` should allow you to use struct expressions if you also use `..<some_instance_of_the_struct>`. That way, the compiler can guarantee that you will have all the fields, because any fields you miss in your expression can be filled in by the fields of that `<some_instance_of_the_struct>`. `Default::default()` fills this role perfectly and would be useful for configuration.

Thoughts?

Please note that the next best alternative is the BuilderBuilderBuilder pattern and I don't want to force that on my users for any reason.

```rust
let config_builder_builder: ConfigBuilderBuilder<BuilderVersionOne> = ConfigBuilderBuilderBuilder::new()
    .use_builder_builder_pattern_version(BuilderBuilderPatternVersion::One)
    .builder_builder();

let config_builder = config_builder_builder
    .add_support_for_option(ConfigOption::InvertY) // ConfigOption is non_exhaustive
    .builder();

let config = config_builder
    .set_config_option(ConfigOption::InvertY) // not specifying the option panics
    // specifying unsupported options panics
    .build_config();

// now you have a config

```

---

<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 19, 2021, 5:29pm UTC](https://internals.rust-lang.org/t/allow-constructing-non-exhaustive-structs-using-default-default/13868/2 "2021-01-19T17:29:58Z")

</div>

You'll probably be interested in this thread, and upcoming RFC, from ekuber:

> [@Pre-pre-RFC: syntactic sugar for \`Default::default()\`](https://internals.rust-lang.org/t/pre-pre-rfc-syntactic-sugar-for-default-default/13234):
>
> Edit: the intent behind this thread was to flesh out enough of the scope to be able to write an RFC, and to that end it was wildly successful. I will be opening an RFC soon. This first post is now slightly divorced from my current thinking (the intent is the same, but the details have changed quite a bit), but I have [left a comment further down-thread with a summary of my intentions for the RFC](https://internals.rust-lang.org/t/pre-pre-rfc-syntactic-sugar-for-default-default/13234/75). I have interacted with some verbose types that are designed to leverage a Default implementation he…

---

<div class="post-metadata">

**Author:** ![LoganDark](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/logandark/32/7266_2.png) [@LoganDark](https://internals.rust-lang.org/u/LoganDark)\
**Post date:** [January 19, 2021, 5:46pm UTC](https://internals.rust-lang.org/t/allow-constructing-non-exhaustive-structs-using-default-default/13868/3 "2021-01-19T17:46:27Z")

</div>

I think that's cool 😃 I hope that it can work with `#[non_exhaustive]` like `Default::default()` does in my example.

---

<div class="post-metadata">

**Author:** ![ekuber](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ekuber/32/1646_2.png) [@ekuber](https://internals.rust-lang.org/u/ekuber)\
**Post date:** [January 19, 2021, 5:50pm UTC](https://internals.rust-lang.org/t/allow-constructing-non-exhaustive-structs-using-default-default/13868/4 "2021-01-19T17:50:36Z")

</div>

RFC coming shortly!

_This_ is _not_ an edge I had thought about too much. It feels like it could be an independent (smaller) RFC for which I see no backwards compat issues _as long as the usage of `non_exhaustive` in the wild conforms to its spirit_. I would be for this change (and shouldn't be too hard to do), but needs to be approved by [T-lang].

---

<div class="post-metadata">

**Author:** ![LoganDark](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/logandark/32/7266_2.png) [@LoganDark](https://internals.rust-lang.org/u/LoganDark)\
**Post date:** [January 19, 2021, 5:52pm UTC](https://internals.rust-lang.org/t/allow-constructing-non-exhaustive-structs-using-default-default/13868/5 "2021-01-19T17:52:28Z")

</div>

> [@ekuber](#):
>
> as long as the usage of `non_exhaustive` in the wild conforms to its spirit

I've seen it advertised as a quick hack to force people to go through your constructor function, even if all fields are public. I don't think they would provide a Default impl in that case, though.

---

<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 19, 2021, 6:22pm UTC](https://internals.rust-lang.org/t/allow-constructing-non-exhaustive-structs-using-default-default/13868/6 "2021-01-19T18:22:53Z")

</div>

> [@LoganDark](#):
>
> Why am I not allowed to construct using an existing instance which already has all the fields?

Because of the way FRU desugars it can't access private fields, and `non_exhaustive` doesn't say that you'll only add public fields in the future.

Some past history: [Pre-RFC: Relaxed #[non\_exhaustive] structs - #15 by scottmcm](https://internals.rust-lang.org/t/pre-rfc-relaxed-non-exhaustive-structs/11977/15)

---

<div class="post-metadata">

**Author:** ![LoganDark](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/logandark/32/7266_2.png) [@LoganDark](https://internals.rust-lang.org/u/LoganDark)\
**Post date:** [January 19, 2021, 6:24pm UTC](https://internals.rust-lang.org/t/allow-constructing-non-exhaustive-structs-using-default-default/13868/7 "2021-01-19T18:24:37Z")

</div>

Ah, yes. I have encountered this before.

I was going to link to the post, but it turns out it's the same post you just linked.

---

<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:** [April 19, 2021, 6:24pm UTC](https://internals.rust-lang.org/t/allow-constructing-non-exhaustive-structs-using-default-default/13868/8 "2021-04-19T18:24:56Z")

</div>

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