Wandering Thoughts archives

2021-06-13

A strong commitment to backwards compatibility means keeping your mistakes

Plenty of people like backwards compatibility, especially strong backwards compatibility. But it has what is a sometimes unpleasant consequence, which is that a strong commitment to backwards compatibility requires keeping your mistakes. Or at least many of them. To put it one way, you need to keep mistakes that work, and of course you have to keep them giving the same result as they currently do. For example if you provide an API that people can use to express potentially conflicting things and you don't reject the attempt but instead give some deterministic result, you're stuck with it.

You don't have to have a strong commitment to backwards compatibility, of course, and many people think it's better not to. Microsoft Windows is a big example of such a strong commitment (what has sometimes been called 'bug for bug compatibility'), and while it's given Microsoft a lot of commercial success it's also left them with a lot of technical challenges that have required heroic (and expensive) work to deal with. Backwards compatibility in general is definitely something that helps some groups at the potential expense of others, and it has a cost regardless of whatever benefits it gives to people.

But if you're going to make a strong commitment to backwards compatibility, it comes with the warts, including that your mistakes have to be preserved. If you don't want to have to preserve your mistakes, you should be honest about the limits of your commitment. You don't have to do this (you don't have to do anything), but if you don't it can surprise people and make them unhappy.

(These days, one limit you might want to write in is that you'll break backwards compatibility if it's the only way to fix a sufficiently serious security issue.)

Another way to not have to preserve your mistakes is to do your best to make sure you aren't making any before you commit to something. This can mean not shipping something at all until you're confident in it, or only shipping something as explicitly not covered. The latter is dangerous, though, because regardless of what you say some people will come to rely on your 'experimental' feature and then have problems when it changes.

(Among other reasons, people will rely on experimental features when it's the only way to get their work done. If your choice is 'don't do this at all' or 'rely on an experimental feature', a lot of people will be strongly pushed to the latter. These people are not making a mistake; they're doing something you can predict in advance if you want to.)

tech/MistakesAndBackwardCompatibility written at 23:54:30; Add Comment

Rust 1.x seems to not always be backward compatible in practice

For a long time now, I've needed (or at least wanted) to simultaneously put a stress load on a test NFS fileserver and a stress CPU and memory load on another machine. Back in the old days on Linux, I would have done this by compiling the Linux kernel repeatedly, but in today's modern age the Linux kernel isn't big enough any more; it builds too fast and isn't big enough. I eventually settled on repeatedly building Firefox from source, partly because it's something I'm already familiar with. Specifically, on one of our Ubuntu 18.04 LTS machines I wound up building the then current release version of Firefox with a then current Rust version installed into a custom location with Rustup. Everything worked fine for a long time, and then one day I made the mistake of absently deciding to run 'rustup upgrade' on my custom Rust location. My Firefox builds immediately blew up with a series of Cargo errors and then later Rust errors.

I was unable to fix this and restore my Firefox build environment to a working state. In particular, it appears that older versions of Firefox (beyond some point I didn't try to determine precisely) can't be built with modern versions of Rust and Cargo (which is tightly coupled to Rust). You can to some extent patch Cargo.toml files so that Cargo will accept them, but the Rust errors were beyond my ability to deal with. My eventual solution was to obtain the current Firefox release, the current Rust release, and run Firefox's own 'build a custom virtual environment with all of your build dependencies' script. Someday this too will break, and in the mean time any performance measurements from before this transition aren't compatible with those after it, since I'm building different things with a different toolchain.

All of this was very startling to me, especially the Rust compile time errors. I'm used to Go, where there is a strong commitment to keeping old Go code building properly even as Go moves forward (but unfortunately less commitment to how the Go equivalent of Cargo works). Rust is evidently moving more aggressively than that to develop their language and are willing to invalidate older code if they feel strongly enough about this. When I am in a bad mood, I feel that means that 'Rust 1.x' is not really '1.x' as I would consider it. Either Rust has not really reached 1.0 yet or there have been a whole series of '2.0', '3.0' and so on Rust releases that are not actually labeled as such.

Update: Much of this is a Firefox problem, where Mozilla has apparently specifically set an environment variable to enabled unstable and changing Rust features in the stable Rust compiler. The effect is to tie specific Firefox versions to a narrow range of Rust stable compiler versions that implement the specific unstable features that Firefox's code expects.

I'm sure that Rust people have a whole series of good explanations for why all of this was necessary and why it's a good thing that I can no longer build older versions of Firefox (for instance, some of the Rust errors may be for things that were unsafe but not previously detected). All I can say is that as an outsider, the resulting experience is not a particularly good one.

(Rust is not the only language and build environment that can suffer from this; C compilers can give you issues if you tell them to abort on warnings.)

(This elaborates on some Tweets of mine at the time.)

programming/Rust1BackwardIncompatibility written at 00:04:46; Add Comment


Page tools: See As Normal.
Search:
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.