Search code examples
rustenumspattern-matching

Struct update syntax equivalent for enum variants


Can we use fields of a pattern-matched enum variant to fill the fields of another variable of the same type? In other words, is it possible to make the following code work?

#[derive(Debug)]
enum Enum {
    Variant1 {field1: i32, field2: i32, field3: i32},
    Variant2
}

fn main() {
    let e1 = Enum::Variant1 {field1: 1, field2: 1, field3: 1};
    if let Enum::Variant1 {field1, ..} = e1 {
        // only field1 is used, the other fields must be inherited by e1
        let e2 = Enum::Variant1 {field1: field1 + 1, ..e1 };
        println!("{e2:?}");
    }
}

----------

error[E0436]: functional record update syntax requires a struct
  --> src/main.rs:10:56
   |
10 |         let e2 = Enum::Variant1 {field1: field1 + 1, ..e1 };
   |                                                        ^^

For more information about this error, try `rustc --explain E0436`.

Playground


Solution

  • No, the syntax only works for structs and doesn't extend to enum struct variants.

    For one thing, at the type level e1 is an Enum which means the expression wouldn't pass the type checker on the basis that it could be Variant2. It is possible this would be an option if "variant types" proposals get implemented (which such proposals think have developed into "pattern types"? not sure).

    To get close to this behavior, you'd need a proper struct to reflect the fields of Variant1:

    struct Variant1 {
        field1: i32,
        field2: i32,
        field3: i32,
    }
    
    enum Enum {
        Variant1(Variant1),
        Variant2,
    }
    
    fn main() {
        let e1 = Variant1 {field1: 1, field2: 1, field3: 1};
        let e2 = Enum::Variant1(Variant1 {field1: e1.field1 + 1, ..e1 });
    }