Non-exhaustively matching a Struct Variant


#1

I have a somewhat complex Enum, but given this reduced case, do I have an option besides an exhaustive match?

enum E {
    A { <fields> },
    B(<obj>),
    ...
}

let foo = E::B(<obj>);

if let E::B(bar) = foo {
    // do conditional thing on bar
}
// use foo generically from here forth
...

Basically, I’m trying to do a single statement if foo is variant B, while doing nothing if its A (or any other of the many variants I might have). Given the format of this enum, this is the only way I know to make this work:

match foo {
     // do the condition thing on bar
     E::B(bar) => { ... },
     // ugly catchall do nothing
     _ => (),
}
// use foo generically from here forth
...

Ergonomically it feels like there should be some way to write an if on a variant conditionally, but the if let syntax seems not to work with struct variants according to this error I’m getting:

expected tuple struct/variant, found struct variant

Is there another way to write this, or am I stuck using a match?


#2

That should work – can you provide a more complete code sample? Here’s a playground that compiles and does what you’re trying to do:

https://play.rust-lang.org/?gist=f5c9b6402dce9500d358bd65c119e7e4&version=stable


#3

If-let should work, if used correctly. Please show a minimized but compilable code example that shows your problem.


#4

The if let you have should work - can you show a runnable example of the issue?


#5

Here is a gist of what triggers the error - I’m trying to match on a struct variant, should have remembered they were different in the OP.

I imagine there is a syntactic way to write that if let statement correctly, but looking through all the reference material isn’t showing me an obvious way.


#6

The pattern needs to use {} (since it’s a struct variant with multiple named fields, you need to name the fields in the pattern) and match on the field names: https://play.rust-lang.org/?gist=645135ab8d8600eedf29f7d1fa58c811&version=stable

You can also ignore fields using something like this: https://play.rust-lang.org/?gist=a7a31bf084712e78b118ebcccfbf72c5&version=stable


#7

This: https://play.rust-lang.org/?gist=1df5fcdcd8d500a77f2a1756b9354055&version=undefined


#8

Yep, that’s it, thank you so much!

I had reread the Rust book versions 1 and 2 and Rust by Example and none of the sections on matching seemed to show an example of this form.


#9

Also, note that the compiler error tells you the correct syntax


#10

I was misconstruing that message to mean to construct a new E::A. I wasn’t even aware you could destructure variant bodies like this.

I was having a “I don’t want curly braces in my if statements!” automatic reaction to seeing it.