Suppose you have an exhaustive switch statement which matches all the cases of
a Swift enum defined in a different module named `External`:
```
import External
var e: External.SomeEnum = //...
switch e {
case .a: break
}
```
If `External` is compiled with library evolution and `SomeEnum` is not frozen,
then the compiler will warn:
```
warning: switch covers known cases, but 'SomeEnum' may have additional unknown values
```
You add an `@unknown default` to the switch to resolve this warning. Now
suppose in another build configuration, `External` is built _without_ library
evolution. The compiler will complain about the unreachability of the default
case:
```
warning: Default will never be executed
```
These contradictory compiler diagnostics encourage the developer to change the
code in a way that will cause a diagnostic in the other configuration.
Developers should have the tools to address all warning diagnostics in a
reasonable fashion and this is a case where the compiler makes that especially
difficult. Given that writing `@unknown default` instead of `default` is a very
intentional action that would be the result of addressing the library evolution
configuration, it seems reasonable to suppress the `Default will never be
executed` diagnostic.
That is, when matching non-frozen enums at non-top-level positions:
switch (nonFrozenEnum1, nonFrozenEnum2) {
case (.singleKnownCase1, .singleKnownCase2): ...
unknown: ...
}
...it's sufficient to use '@unknown' to match
(.singleKnownCase1, .someFutureCase2)
(.someFutureCase1, .singleKnownCase2)
(.someFutureCase1, .someFutureCase2)
We still model the enums as non-exhaustive so that someone /can/
handle unknown cases, which may be important for imported enums. But
we won't diagnose a problem if the only missing case is '@unknown'.