Comment by kibwen
3 hours ago
Note that Java makes breaking changes all the time, which is why it publishes a compatibility guide with each major release. These are usually judged to be minor breakages, but if you have a codebase on the order of millions of lines, there's a very good chance that at least one thing will break and require a little bit of work to upgrade. And Java's not unique here, every stable language makes changes all the time that have the potential to break some user in some edge case.
Sure, though most of the time it's library-only, not language change (with the only exception I have in mind is new keywords, but those are pretty rare with java).
All in all, Java is pretty unique in the level of backwards compatibility it provides, I don't think any other language is comparable to this level. Especially that it is both source and binary compatibility.
> Sure, though most of the time it's library-only, not language change
While this distinction is often useful, here we have to think about it from the perspective of users: you press the button to upgrade your toolchain, and code that formerly worked stops working. If a language supported upgrading your compiler/interpreter separately from your standard library then that would be different, but generally a standard library version is considered tightly coupled to a language version.
Not that I need to tell you of all people, but I do find that Rust's editions system is one of the better ways to minimise this issue.
Indeed, editions are brilliant for making relatively large changes in a way that fully preserves backwards compatibility for codebases in the wild, but the existence of editions doesn't mean that Rust is exempt from sometimes desiring to make minor breaking changes in new versions for all editions. For that, it has the mechanism of future incompatibility lints, to give people ample advance warning: https://doc.rust-lang.org/rustc/lints/index.html#future-inco...