I’ve got this error in my code: Switch covers known cases, but 'BottomSheetView.Variant' may have additional unknown values; this is an error in the Swift 6 language mode.
Why is the default mandatory now? What’s the use? What if I deliberately want to tell the devs “Hey you should implement all of the cases separately, even those that will be added in the future. You should always make it exhaustive so if you add a case, you have to add the implementation. No default case!“
I get that, but why is it mandatory and will show an error in Swift 6? I want to deliberately tell my coworkers that it is their responsibility to add implementations in future cases and not to use default case. I want the compiler to deliberately fail when the cases aren't handled.
Depending on a "resilient library" (like Apple frameworks) means that this library can and will evolve independently from your code, hence the term "library evolution".
So, whatever cases you code against is only today's interface - tomorrow the library could ship with an added case. You code will not be recompiled.
I know and I deliberately want it to fail to compile in some cases. This is the same as optionals. Sometimes I don't want to silently ignore the optional when it is nil. For this I use force unwrap to make it deliberately crash because that variable should not be nil or the app should not run at all. So the dev will know that they need to fix it Defensive Programming style, and not to ignore it. Or another way is using a guard with fatalError. But force unwrap is easier.
I use defaults in some cases, but in some other I don't because I need each of them to be handled individually and not ignore it. And I expect the new cases must be implemented by the coworkers that use this internal library or it won't compile.
I just don't get the benefit of enforcing default. This way, it will just ignore any new cases and the app will still run normally without them, until some users use the new case and complain that it didn't do anything.
If you are dealing with a nonfrozen enum, meaning new cases might be added in the future without your app being recompiled, then indeed you must include a default case to handle them.
The options for doing so are default and @unknown default. Both of them will make your compiled binary “future-proof” in the same way. The difference between the two is what happens when you try to recompile your app after new cases have been added to the enum.
If you just use default, then the app will recompile without any indication that new cases were added.
But if you use @unknown default then there will be a warning when you recompile the app, informing you that new cases have been added.
Do I understand correctly that you are looking for some way to upgrade that warning to an error?
If you're not concerned about breaking binary compatibility by adding new cases to your enum, you can either mark your enum as @frozen, or build your library with "Build for Distribution" (that's the -enable-library-evolution compiler flag) turned off. If you do that, switching over your enum from another module will not require a default case.
Another way to avoid being asked to add an @unknown default case is to give the library and its clients the same -package-name. Modules in the same package (from the package access control modifier point of view) are allowed to skip supplying a default case, even when the module that defines the enum is compiled with -enable-library-evolution, because the compiler assumes that modules that are packaged together are always recompiled together before distribution.
I'd advise against that when building with SwiftPM, which adds a value for that option based on actual package name, so providing your own via unsafeFlags will most probably break things.