|
| 1 | +- Start Date: 2014-10-25 |
| 2 | +- RFC PR: |
| 3 | +- Rust Issue: |
| 4 | + |
| 5 | +# Summary |
| 6 | + |
| 7 | +Just like structs, variants can come in three forms - unit-like, tuple-like, |
| 8 | +or struct-like: |
| 9 | +```rust |
| 10 | +enum Foo { |
| 11 | + Foo, |
| 12 | + Bar(int, String), |
| 13 | + Baz { a: int, b: String } |
| 14 | +} |
| 15 | +``` |
| 16 | +The last form is currently feature gated. This RFC proposes to remove that gate |
| 17 | +before 1.0. |
| 18 | + |
| 19 | +# Motivation |
| 20 | + |
| 21 | +Tuple variants with multiple fields can become difficult to work with, |
| 22 | +especially when the types of the fields don't make it obvious what each one is. |
| 23 | +It is not an uncommon sight in the compiler to see inline comments used to help |
| 24 | +identify the various variants of an enum, such as this snippet from |
| 25 | +`rustc::middle::def`: |
| 26 | +```rust |
| 27 | +pub enum Def { |
| 28 | + // ... |
| 29 | + DefVariant(ast::DefId /* enum */, ast::DefId /* variant */, bool /* is_structure */), |
| 30 | + DefTy(ast::DefId, bool /* is_enum */), |
| 31 | + // ... |
| 32 | +} |
| 33 | +``` |
| 34 | +If these were changed to struct variants, this ad-hoc documentation would move |
| 35 | +into the names of the fields themselves. These names are visible in rustdoc, |
| 36 | +so a developer doesn't have to go source diving to figure out what's going on. |
| 37 | +In addition, the fields of struct variants can have documentation attached. |
| 38 | +```rust |
| 39 | +pub enum Def { |
| 40 | + // ... |
| 41 | + DefVariant { |
| 42 | + enum_did: ast::DefId, |
| 43 | + variant_did: ast::DefId, |
| 44 | + /// Identifies the variant as tuple-like or struct-like |
| 45 | + is_structure: bool, |
| 46 | + }, |
| 47 | + DefTy { |
| 48 | + did: ast::DefId, |
| 49 | + is_enum: bool, |
| 50 | + }, |
| 51 | + // ... |
| 52 | +} |
| 53 | +``` |
| 54 | + |
| 55 | +As the number of fields in a variant increases, it becomes increasingly crucial |
| 56 | +to use struct variants. For example, consider this snippet from |
| 57 | +`rust-postgres`: |
| 58 | +```rust |
| 59 | +enum FrontendMessage<'a> { |
| 60 | + // ... |
| 61 | + Bind { |
| 62 | + pub portal: &'a str, |
| 63 | + pub statement: &'a str, |
| 64 | + pub formats: &'a [i16], |
| 65 | + pub values: &'a [Option<Vec<u8>>], |
| 66 | + pub result_formats: &'a [i16] |
| 67 | + }, |
| 68 | + // ... |
| 69 | +} |
| 70 | +``` |
| 71 | +If we convert `Bind` to a tuple variant: |
| 72 | +```rust |
| 73 | +enum FrontendMessage<'a> { |
| 74 | + // ... |
| 75 | + Bind(&'a str, &'a str, &'a [i16], &'a [Option<Vec<u8>>], &'a [i16]), |
| 76 | + // ... |
| 77 | +} |
| 78 | +``` |
| 79 | +we run into both the documentation issues discussed above, as well as ergonomic |
| 80 | +issues. If code only cares about the `values` and `formats` fields, working |
| 81 | +with a struct variant is nicer: |
| 82 | +```rust |
| 83 | +match msg { |
| 84 | + // you can reorder too! |
| 85 | + Bind { values, formats, .. } => ... |
| 86 | + // ... |
| 87 | +} |
| 88 | +``` |
| 89 | +versus |
| 90 | +```rust |
| 91 | +match msg { |
| 92 | + Bind(_, _, formats, values, _) => ... |
| 93 | + // ... |
| 94 | +} |
| 95 | +``` |
| 96 | + |
| 97 | +This feature gate was originally put in place because there were many serious |
| 98 | +bugs in the compiler's support for struct variants. This is not the case today. |
| 99 | +The issue tracker does not appear have any open correctness issues related to |
| 100 | +struct variants and many libraries, including rustc itself, have been using |
| 101 | +them without trouble for a while. |
| 102 | + |
| 103 | +# Detailed design |
| 104 | + |
| 105 | +Change the `Status` of the `struct_variant` feature from `Active` to |
| 106 | +`Accepted`. |
| 107 | + |
| 108 | +# Drawbacks |
| 109 | + |
| 110 | +Adding formal support for a feature increases the maintenance burden of rustc. |
| 111 | + |
| 112 | +# Alternatives |
| 113 | + |
| 114 | +If struct variants remain feature gated at 1.0, libraries that want to ensure |
| 115 | +that they will continue working into the future will be forced to avoid struct |
| 116 | +variants since there are no guarantees about backwards compatibility of |
| 117 | +feature-gated parts of the language. |
| 118 | + |
| 119 | +# Unresolved questions |
| 120 | + |
| 121 | +N/A |
0 commit comments