And never forget a break. And triple check the type of those case labels. And keep them short, so all of the above is verifiable.
Or, alternatively, you can default to some syntax where the compiler will help you, and leave switches to use with care only where they bring a huge gain.
Lack of 'break' is a very useful bit of syntax I use somewhat frequently for categorization. AKA you have a handful of case values that fall into a smaller subset of catagories. Rather than an unreadable set of if/else's that all have multiple if
"a||b||c||d.." conditions, vs a big state machine, or match structure.
Then if one enforces a clearer formatting style than is common on most open source projects the lack of "break" statements stick out visually and it becomes much harder to miss a break statement when the intentionally missing ones have lines like
"// Intentional fall-through"
Or you use a "nobreak" macro and enforce the use of break/nobreak in the automated style/linter.
But if you had a syntax that allowed inner/embedded functions, exhaustive matching, and the ability to combine a|b..e, you might never ever EVER need fallthrough. The case statement in Ada is the best control flow structure (I'm not very familiar with advanced FP-style pattern matching, but I can read and follow Ada's with almost closed eyes, and they're exhaustive by default you won't compile until you've handled all the cases), and Ada2012 added case- and if-expressions, and now it seems there's some ongoing work on making it a bit more powerful...
This kind of construction makes the power of enumerated types, and restricted range types so much more evident.
Also be careful about declaring variables within a case unless you explicitly introduce a block statement.
Honestly the potential for mistakes using a switch are so numerous that I absolutely agree with you about reflexively avoiding them and preferring the use of an if statement. The optimization benefit no longer holds on modern compilers so all you're left with is fall through to simplify some really complex branching needs.
Or, alternatively, you can default to some syntax where the compiler will help you, and leave switches to use with care only where they bring a huge gain.