Brainstorming: how to help old code locked to old `time` build on new toolchains

There have been other discussions on time, like Type inference breakage in 1.80 has not been handled well

Here I want to focus specifically on what, if anything, we can do so that old code can still build. We have package-specific hacks in cargo and rustc today. Is there room for us to extend one for this situation or add a new one?

In Workaround for type inference breakage in the time crate by kornelski · Pull Request #14452 · rust-lang/cargo · GitHub, the idea was proposed to have Cargo implicitly patch registry+https://github.com/rust-lang/crates.io-index#time@0.3.18 through registry+https://github.com/rust-lang/crates.io-index#time@0.3.34.

There are implementation and correctness complexities to this. There are also likely corner cases in how it affects other aspects of the ecosystem (vendoring, nix, etc).

1 Like

Modifying rustc to allow for this crate to work might be possible, but there's little desire amongst compiler team members to indulge in such a change, specially not long-term. Given this is not the first time such a hack has been desired (or introduced), it might make sense to have t-compiler and t-cargo come up with respective policies about how to handle these (irrespective of time) so that we can at least go back to it and avoid re litigating any specific position every time (even though, it must be noted, this comes up rarely).

6 Likes

if it wasn't a 0.x crate it would be pretty easy, just publish a new patch release for every minor release..

4 part semver would fix this

0.x makes absolutely no difference, there is a semver-compatible fixed version available, all the discussion has been about how this has impacted everyone that hasn't updated.

10 Likes

Extra semver granularity would allow publishing an earlier fix for folks who can't fully update for other reasons -- but I don't know how common that kind of case is.

1 Like

Perhaps if the author of certain highly-used-in-the-ecosystem crates was not prone to making it so that his crate did not compile against any nightly rustc but the most current one, crates would not feel compelled to rapidly upgrade their dependence on it to the latest version, allowing it to float as appropriate.

Alas, crates wish to test against nightly, which is a behavior which we wish to encourage. Sometimes the easiest way to make sure that the crate builds against the latest nightly is to bump a dependency which so-frequently requires it.

I have even seen people try to test against -Zminimal-versions, which of course such behavior makes impossible, thwarting experimentation with cargo's nightly features.

5 Likes

IMO (and I do this) the -Zminimal-versions build should build with the minimal rustc version as well. I see little motivation to support "we can update our toolchain but not our dependencies" arguments.

3 Likes

Reminder that RFC-3240 had a proposed mechanism to avoid breakage by leveraging editions.

So the solution would be, to revert the change that broke time, and re-add it later but changing inference only for crates in 2024 edition?

In such a way that crates before edition 2024 would continue to compile without adding new type annotations, but to migrate to Rust 2024, you would need to add those annotations. (And then the bad versions of time will just continue to work forever, because they are not written in Rust 2024 even if other crates in your program are)

However: the RFC is about tying method resolution to editions, not tying type inference to editions. So this would be a further extension to the RFC?

Reverting the change would be a breaking change as well. This was discussed in Revert "alloc: implement FromIterator for Box<str>" by estebank · Pull Request #129379 · rust-lang/rust · GitHub

RFC 3240 isn't so much relevant for this discussion (what can we do about time specifically) and more about how we can improve this for the next time.

4 Likes

Pardon if this is a stupid question, but is there anything analogous to "yanking" for rustc versions? I searched through the release notes and I didn't see an equivalent, though I do know there is a (sort of..?) similar precedent in the Python world where they refuse to provide binaries for deprecated versions of CPython.

1 Like

That ship has sailed. 1.80 is much more than just that change, and "yanking" the release would break other users in other ways.

We have a chance to ship some mitigation in 1.81.

2 Likes

Can Cargo automatically update the time crate? Ignore the known-bad versions in the lockfiles?

The Cargo team discussed Workaround for type inference breakage in the time crate by kornelski · Pull Request #14452 · rust-lang/cargo · GitHub and decided trying to solve something like that in a time crunch is too risky. See Workaround for type inference breakage in the time crate by kornelski · Pull Request #14452 · rust-lang/cargo · GitHub for more details.

On the surface this sounds good but I think it could easily lead into unintended side effects like Workaround for type inference breakage in the time crate by kornelski · Pull Request #14452 · rust-lang/cargo · GitHub. For example, this would likely break cargo vendor. Yes, we could then put a hack on top of the other hack but more the point is the risk profile of this work. Especially if you are trying to get this into 1.81 which is already in beta and will be released in one week.

5 Likes

Unfortunately, that’s breaking. I’ve described my case in the issue thread, but TL;DR that would force-update transitive dependencies (namely serde), which are not neccessarily actually backwards-compatible, despite being semver-compatible.

I think time can release a patch-update for the old version (without requiring new dependencies), and cargo could auto-update to that version instead.

It's risky, but the projects locked to these crates are broken anyway. Projects that have vendored these crates or try to vendor them are already doomed to fail. If they got broken in a different way that would be unfortunate, but not really change the outcome.

Do you think there could be some mitigation for 1.82?

I'm certain that if this doesn't get rushed and is left to get an architecturally correct fix, it will slip indefinitely and won't save Rust users from dealing with the breakage head-on without mitigation.

I don't think time can release a patch version since they are on 0.x.y. It seems like an upgrade to serde would have been done for a reason so this wouldn't be easily downgradable - but maybe worth a try if this is exacerbating the problem?

Ecosystem crates often seem hesitant to go to 1.0 (because it is seen as a sign that things won't change again, which absolutely can't be true) as well as to go past 1.0 (equally not great, quiet breakage). Unfortunately you are stuck between one of each...

1 Like

Well it breaks a much smaller set of code, because 1.80 was released in July. The problem with the time breakage is the amount of code that has the affected releases in Cargo.lock (some of which can't be readily upgraded)

But anyway, what about a soft revert, but affecting only crates named time within a given version range? Hacky, but with way less than unintended side effects than implicitly updating crates locked into Cargo.lock, breaking reproducibility.