Roman Mahotskyi
Roman Mahotskyi

Reputation: 6625

How to prevent "match hell" when destructuring nested enums?

Is there a better/cleaner way of destructuring rust enums without introducing nested hell of a match calls?

My current approach to destructuring multiple nested enums looks like this:

enum Top {
    Middle(Middle)
}

enum Middle {
    Bottom(Bottom)
}

enum Bottom {
    Value(i32)
}

fn foo () -> Top {
    Top::Middle(Middle::Bottom(Bottom::Value(17)))
}

fn main() {
    match foo() {
        Top::Middle(middle) => match middle {
            Middle::Bottom(bottom) => match bottom {
                Bottom::Value(value) => println!("Value {}", value)
            }
        }
    }
}

or Rust Playground

If I increase the number of "layers" between Top and Bottom enums the pattern matching becomes "harder" to maintain.

Is there a "linear" way of handling nested enums without losing all functionality that match provides (e.g. notify when some matches are missing etc.)?

I'm looking for something like this

// cut

fn main() {
    match foo() {
      Top::Middle(Middle::Bottom(Bottom::Value(value))) => println!("Value {}", value)
    }
}

Upvotes: 1

Views: 525

Answers (1)

Roman Mahotskyi
Roman Mahotskyi

Reputation: 6625

Thanks to @Caesar

I'm looking for something like this

fn main() {
   match foo() {
     Top::Middle(Middle::Bottom(Bottom::Value(value))) => println!("Value >{}", value)
   }
}

My assumptions were correct. This code works. See playground

Is there a "linear" way of handling nested enums without losing all functionality that match provides (e.g. notify when some matches are missing etc.)?

I was wondering if the "linear" approach would notify if there are missing enums? Yes, it will notify.

I added one more option to the Bottom enum

// cut

enum Bottom {
    Value(i32),
    Data(String)
}

// cut

and it shows errors during compilation

   Compiling playground v0.0.1 (/playground)
error[E0004]: non-exhaustive patterns: `Middle(Bottom(Data(_)))` not covered
  --> src/main.rs:20:11
   |
20 |     match foo() {
   |           ^^^^^ pattern `Middle(Bottom(Data(_)))` not covered
   |
note: `Top` defined here
  --> src/main.rs:3:5
   |
2  | enum Top {
   |      ---
3  |     Middle(Middle)
   |     ^^^^^^ not covered
   = note: the matched value is of type `Top`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
   |
21 ~         Top::Middle(Middle::Bottom(Bottom::Value(value))) => println!("Value {}", value),
22 +         Middle(Bottom(Data(_))) => todo!()
   |

For more information about this error, try `rustc --explain E0004`.
error: could not compile `playground` due to previous error

See playground

Upvotes: 2

Related Questions