Describe the problem you are trying to solve
In Rust-Embedded land, we are struggling with the management of our Minimum Supported Rust Version. That is, the promise we make to our users that compilers all the way back to our MSRV will compile this code, and we won't use any features stabilised after that compiler was released.
Currently we set an MSRV like a stake in the sand, and then time moves on and the stake gets further and further away. One of our crates has an MSRV of 1.30 - thats 72 weeks old at the time of writing. What I'd like to do is bring that MSRV along with us - trailing it behind us on a piece of string.
Describe the solution you'd like
Basically in my CI files I want to "rustup install stable-2", and if stable is 1.40, it would install 1.38. If stable was 1.51 it would install 1.49. Then I can set my Travis CI matrix to build on:
And I never have to touch the CI file again.
Notes
At the moment, to achieve a rolling MSRV we would have to touch the CI file every six weeks when there's a new stable release. That or rustup install stable, grok the current version with some grep/sed foo, subtract two minor versions (not easy in Bash) and then install that version.
It's an interesting idea, certainly. However it wouldn't fit directly with rustup's current model. That's not to say it couldn't be made to work, just that it'd be awkward.
If you're insistent on doing it via a Travis matrix then it'd have to be rustup or else travis would have to have some special behaviour to achieve that. Currently rustup is able to just go and ask static.rust-lang.org for channel data. I wonder if, perhaps, it might be sensible to have a rolling set of stable-{1,2,3,4,5} channel symlinks on there?
At that point, we could add support for the requisite channel name shape to rustup and wouldn't need special handling otherwise.
I guess the Debian equivalent would be old-stable and old-old-stable, if the numeric component causes an issue.
I think oldstable and oldoldstable are more plausible just because - is used to separate the elements of toolchain names. In theory ~ could be used too but that introduces a whole host of usability issues potentially. @pietroalbini If I were to propose adding some channel symlinks (or however we deal with stable/nightly vs. the numbered/dated equivalents currently) which approach do you think would fly?
Do we know from channel data the stable version? We could do the arithmetic easily enough in rustup to synthesise new pseudo channels, no?
Such synthesis would change the download-channel-install-channel model which IMO would be moderately awkward; though as I said before yes it'd be possible. However the ideal would be if the pseudochannels were handled on static.rlo, otherwise we have to start faffing with working out which patch level is the newest for a version (e.g. if stable is 1.35.0 and the user wants stable~1 do we install 1.34.0 or the more useful 1.34.2 ?) So many roundtrips would make rustup update expensive and slow. And yes, I know we do that for nightly backtracking but that's only one dimension (date) rather than more (channel / minor / patch)
I think a good approach would be to create new manifests for 1.MINOR.x (like 1.43.x, 1.34.x...) that always point to the latest patch release of that minor version. This would allow to:
stable~N in just two requests (as we can subtract from the minor of the current stable, and fetch the .x channel of the resulting version).1.31 you'd use 1.31.x as the MSRV toolchain).Yeah, I like using stable~<number> too. Feels like using git reset HEAD~<number>.
if stable is 1.35.0 and the user wants stable~1
The good default to me is using latest patch release. As patch releases often
backport soundness and compatible/build fixes.
Edit: minor -> patch
if stable is 1.35.0 and the user wants stable~1
The good default to me is using latest minor release. As minor releases often
backport soundness and compatible/build fixes.
I'd call that the patch release, as the 35 in 1.35.0 is the minor, and the 1 is the major. But yes, I can't see why anyone would want to not pick up the highest patch release for a given major/minor pair.
So I like both @pietroalbini 's idea of MAJOR.MINOR.x being the latest PATCH for MAJOR.MINOR though I'd note that might confuse people who do numeric ordering and assume the dots separate numbers. and I like the idea of stable~1 being "one back from current stable". The .x links have the advantage that they're only updated on a release of that MAJOR.MINOR series, but the stable~n would have to be updated every stable release. If we do the latter, I don't think we should do it for beta or nightly though.
I'd prefer not to have stable~N as actual manifests on static.rlo (keeping them up to date is going to be a bit of a pain). Could we go with MAJOR.MINOR.x on static.rlo, and implement stable~N on the rustup client?
I guess we could have a go. I don't like the double-downloading of manifests but I suppose if the user is opting in then they're prepared to pay the cost. So we define stable~N to mean major(STABLE).(minor(STABLE)-N).x and then fetch that? Will we backfill static.rlo with the MAJOR.MINOR.x for all the releases? Presumably that'd be fairly cheap.
Yeah pretty sure we can backfill static.rlo.
We now have major.minor channel files present on the dist server, so we're a step closer to being able to do this.
If someone wanted to have a go at implementing the channel parsing and handling the double-manifest-download then we can see how it works.
Most helpful comment
I'd call that the patch release, as the
35in1.35.0is the minor, and the1is the major. But yes, I can't see why anyone would want to not pick up the highest patch release for a given major/minor pair.