Skip to content

Breakage related to default field values (RFC 3681) #993

@obi1kenobi

Description

@obi1kenobi

RFC link; Tracking issue (not for discussion, just tracking): rust-lang/rust#132162

In short:

#[derive(Default)]
struct Pet {
    name: Option<String>, // impl Default for Pet will use Default::default() for name
    age: i128 = 42, // impl Default for Pet will use the literal 42 for age
}

// This works and produces:
// `Pet { name: Some(""), age: 42 }`
let _ = Pet { name: Some(String::new()), .. }

// Compilation error: `name` needs to be specified
let _ = Pet { .. }

Desirable SemVer major, deny by default lints:

  • default value removed from struct field, where the field continues to exist and the struct is still externally constructible with a literal
    • Witness: constructing the struct with { .. } syntax now requires supplying a value for that field.
    • It doesn't matter if the field is Default, since Default doesn't matter { .. }-style construction.
  • default value removed from enum struct variant field, where the field continues to exist and the variant is still constructible with a literal
    • Witness: constructing the variant with a literal now requires supplying a value for that field

Desirable SemVer major, warn by default lints:

  • default value changed on a struct field, from one explicitly-specified value to another
    • Reason to warn instead of error: it's possible the intended SemVer contract was "a default exists" rather than some specific value. It's situational, maintainers can promote this to error.
  • default value changed on an enum variant struct field, from one explicitly-specified value to another
    • Analogous to above case.
  • default value for a field (either struct or enum struct variant) changed from implicit Default::default() to a different, explicitly-specified value
    • Difficult! Need to determine if impl Default on the struct/enum is derived (hand-impls might not use the Default::default() for the field!), and also need to determine what Default::default() would return for the field's type. Default::default() isn't const in general, so we'd probably have to hardcode defaults for common built-in types.

Progress:

  • Waiting on RFC implementation in rustc
  • Waiting on rustdoc JSON to include field defaults
  • Need new schema in trustfall-rustdoc-adapter
  • Ready to write lints

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintArea: new or existing lintC-enhancementCategory: raise the bar on expectations

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions