Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] RFC: Default field values #19

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

Centril
Copy link
Owner

@Centril Centril commented Dec 18, 2018

Rendered

This is a draft version of an RFC for you to review, before a formal proposal is made for consideration.

cc @cramertj @nrc @alexreg

}
```

## Default fields values are [`const` context]s

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why require this? It seems like they could just be functions evaluated in the position they're used. The "constness" of a given field initializer could be inferred to determine whether a particular field's initializer is const. I can see arguments both ways, but the fact that I can immediately come up w/ examples of things I'd want defaults for that wouldn't be const-valid hints to me that we'll want to expand this.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this could prevent some of the macros given above from being able to remove their custom #[default] attributes, since many (all?) of those attributes allow non-const expressions.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idea: warn-by-default lint against non-const defaults (at definition site, not at usage)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping-- @Centril did you have a chance to think more about this?

Copy link

@alexreg alexreg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super thorough as always, Mr. Centril! I hope you'll excuse my usual pedantry... Overall, I'm a big fan of this RFC, and I'd like to see it accepted without too many changes.

One final note: it may be worth a brief evaluation of the approach of this RFC vs. the derive-builder crate (or an enhanced version of it). Especially with regards to ergonomics and expressiveness. I don't think I saw that here.

text/0000-default-field-values.md Outdated Show resolved Hide resolved
text/0000-default-field-values.md Outdated Show resolved Hide resolved
text/0000-default-field-values.md Outdated Show resolved Hide resolved
text/0000-default-field-values.md Show resolved Hide resolved
text/0000-default-field-values.md Outdated Show resolved Hide resolved
text/0000-default-field-values.md Outdated Show resolved Hide resolved
text/0000-default-field-values.md Outdated Show resolved Hide resolved
text/0000-default-field-values.md Show resolved Hide resolved
text/0000-default-field-values.md Show resolved Hide resolved
text/0000-default-field-values.md Outdated Show resolved Hide resolved
Copy link

@nrc nrc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

thereby allowing enums to work with `#[derive(Default)]`.

```rust
#[derive(Default)]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we use #[derive(Default = Field)] instead of the extra attribute? It has the advantages of not letting the programmer annotate multiple variants and fewer attribute, but does require typing the variant name twice.

Note that while `#[default]` makes field defaults more useful and is useful
on its own, it is technically orthogonal in that it can be extracted out of
this RFC if need be. However, since it completes the picture, it is proposed
together with field defaults.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default is pretty underused in Rust. I think it is either worth soft-deprecating it by not enhancing it further and not recommending its use, or we should figure out what would make it more used (e.g., putting it in the prelude). I feel a bit uncomfortable proposing enhancements without addressing the deeper concern that it is perhaps not the best construct.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO many of the reasons it is underused are addressed by this PR, such as the ability to easily have defaults that aren't the same as the default values of the field types. I think enhancing it in this way provides a clear benefit, and doesn't contribute to any problems with Default today.

invert the pattern expression and initialize a `Config` like so (15):

```rust
let config = Config { width, height, .. };
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes the semantics of non_exhaustive from 'adding fields is backwards compatible' to 'adding default fields is backwards compatible', which I think is itself not a backwards compatible change (in some higher order manner, e.g., consider a library which has used non_exhaustive with the intention of later adding a non-default field, they can no longer do so).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a similar comment above, and agree that this feels like a misleading change to #[non_exhaustive]. IMO adding a private but defaulted field in lieu of using #[non_exhaustive] is a fine way to get the semantics proposed by this RFC.

The constructor functions `new_first_variant(..)` are not provided for you.
However, it should be possible to tweak `#[derive(new)]` to interact with
this RFC so that constructor functions are regained if so desired.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previous RFC: rust-lang#1806

text/0000-default-field-values.md Outdated Show resolved Hide resolved
text/0000-default-field-values.md Show resolved Hide resolved
```

# Motivation
[motivation]: #motivation
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integrate @cramertj's use cases... :)

```rust
let ls_cmd = LaunchCommand {
cmd: "ls".to_string(),
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't there be a .. in this and the next example?

@cramertj
Copy link

cramertj commented Oct 3, 2019

bump on this-- @Centril do you have time to chat about this soon-ish?

@jhpratt
Copy link

jhpratt commented Apr 5, 2021

Hey @Centril — mind if I rip some text from this for a formal RFC? I'd like to make a small one for #[default] on enums with nothing else, since that should be relatively simple and uncontroversial.

@Centril
Copy link
Owner Author

Centril commented Apr 6, 2021

@jhpratt Sure, go ahead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants