When a new state is added to an enum, we want the code to not compile so that we can fix all the places that need updating.
When a new state is added to an enum, we want the code to not compile so that we can fix all the places that need updating.
However sometimes you are a dependency and you want to give up this restriction to gain the ability to add things without having to bump your major version number.
By far the most common example is error enums which don't necessarily need all of their downstream crates to handle every error, they likely are bucketing most of them anyway and non_exhaustive ensures they support that.
This is a decision library users should be making, not library writers.
If you want to do that, you could edit your own copy of the library's source code and nobody will mind. Maybe that's enough?
It seems like you shouldn't be able to publish a crate where you're using an upstream library in a way they don't consent to, because now you're involving others in this dispute. A basic requirement for publishing to a shared open source ecosystem should be that you're resolving any disputes you have with upstream libraries and not just going your own way.
Of course, the trade-off is obviously that by choosing to make things continue to compile when something changes, you are no longer causing things to fail to compile when something changes. I'm uncertain how this tension will be resolved in the long run.
(Context: used to do iOS dev w/ obj-c; haven't used Swift, but keeping an eye on it, mostly out of curiosity.)
There is the Xcode migration which auto updates source code to the new version, which I’m sure you are aware of and leaves you annoyed. Thou it’s more than “no effort”
Yes, some enums are intended to be expanded. Still, as long as something is a compile-time error, I don't care about having to update my code when I choose to upgrade compilers.
In fact, even if the enum is intended to be expanded, I prefer to hear about new features and changes on APIs I actually use in a given project. It allows me to review mu choices and many times in complex APIs there are new options or flags that are useful to know about and otherwise get ignored. It allows me to update all callers as needed.
I have heard too many times the backwards compatibility story in the C++ world and I never valued it for things that are errors rather than behavior changes. It makes the libraries and the language way too rigid and makes evolving it a pain.
As long as you don't change the meaning of code that compiles cleanly, feel free to change things.
If you really want to keep code compilable because you are doing a chance that you believe will be a PITA, you could always offer a (truly) automated tool.
It's not just your code; it could be the code of any of your dependencies (or their dependencies, recursively). Besides, the Rust team does intend to keep older code compiling unchanged on newer releases of the Rust compiler, unless the breakage is caused by fixing a soundness hole.
The best example of a non-exhaustive enum, in my opinion, would be std::io::ErrorKind (https://doc.rust-lang.org/std/io/enum.ErrorKind.html). Several Rust releases ago, I added a new variant to that enum (the last one, UnexpectedEof, used by std::io::Read::read_exact - notice how that variant comes after "Other", which used to be the last one). If that enum were not non-exhaustive (non-exhaustive enums already existed since Rust 1.0, though using a doc-hidden trick instead of formal compiler support), I would not have been able to add that new variant, since it would risk breaking anything which matched on every variant of that enum.
For example suppose you add another image format to the `image` library:
https://docs.rs/image/0.23.0-preview.0/image/enum.ImageForma...
What's more annoying - a major version bump every time you support a new format, or not being able to exhaustively match on all 10 formats?