August 1st, 2024

Rust Just Failed an Important Test

Ethan McCue faced a build error while updating a Rust project, raising concerns about Rust's stability. He resolved the issue by pinning a library version but remains uneasy about the language's reliability.

Read original articleLink Icon
Rust Just Failed an Important Test

A developer, Ethan McCue, reported encountering a build error while updating a Rust project, specifically a fork of the Rust Playground for running Java code. Despite not changing any dependencies, the error arose during the Continuous Integration/Continuous Deployment (CI/CD) process. The error message indicated that type annotations were needed for a variable, which led to a loss of confidence in Rust's ability to maintain code stability over time. Although McCue resolved the issue by pinning a higher version of the time library, he expressed disappointment and concern about the language's resilience to "bit-rot." He reflected on the importance of a programming language's reliability and whether code will continue to function correctly in the future. This experience has left him feeling uneasy about Rust, despite previously having high expectations due to its editions.

Link Icon 11 comments
By @shepmaster - 9 months
(Rust playground maintainer here) Incidentally, I also updated the Rust playground today. My usual process is to update everything [0] that is SemVer compatible and then one-by-one update packages with SemVer incompatible version bumps.

During the upgrade, I was thinking to myself how generally I’m fairly blasé about these updates — I don’t even attempt to build the code with the SemVer compatible updates because it’s so rare for a crate maintainer to stuff up such an update. The SemVer incompatible updates get a build just as a sanity check.

Contrast this to the JS dependencies where an upgrade tends to instill more dread in me. Part of this is a lack of confidence in my test suite, part of it is that it’s the more UI heavy component which is hard to write tests for in the first place, but a non-zero part is my lack of trust in the JS libraries and tooling. I wonder how much of that is still true today versus how much I am once bitten, twice shy.

[0]: https://github.com/rust-lang/rust-playground/pull/1079

By @joshka - 9 months
To clarify this a bit:

1. The widely used Time crate had some code which converted to an unspecified type. The code then converted this again in a following line. Because there was only a single possible (identity) conversion, this code was a noop. Regardless this was fixed in time@0.1.35 (released in April 9, 2024). [1]

2. Rust 1.80 (released July 27, 2024) introduced a new trait implementations that made the second conversion now cause the first conversions to have two possible inferences. [2]

3. Rust packages that upgraded the compiler to 1.80.0, but used a version of the time crate prior to 0.1.35 fail to build the time dependency. This is mitigated by the fact that 0.1.35 is a semver compatible update, which just requires running cargo update to use.

[1]: https://github.com/time-rs/time/pull/671

[2]: https://blog.rust-lang.org/2024/07/25/Rust-1.80.0.html#stabi...

Something that would be neat to see from Rust here would be a way to measure the impact of these sorts of compiler and dependency bumps in order to reduce the blast radius of this sort of thing. Ideally being able to say "this change requires X devs to do process which cost Y minutes, so it's worth investing Z minutes to avoid / document it". I often want to make public API changes to a library I maintain, but the best tool I have for understanding who those changes will affect is often a GitHub search for code.

By @estebank - 9 months
To expand on some of the things already said:

This issue was caught during a crater run. An earlier version of time had (accidentally) an "identity" conversion (<T as Into>::into(T)), which was caught by a blanket trait implementation. That call shouldn't have been in the library in the first place (it was speculated by its author that it was used in some transitory test in the past). Inference is brittle, there's no way around that. Adding a new trait impl can break down streams. The project makes an effort to avoid big blast radius when this happens, including backing off on the change and/or letting the ecosystem adapt before actually introducing the change. In this case there was a decision made to bite the bullet given that time would have a fix. Personally I would have preferred to delay the landing of the impl in order to add a migration lint for at least one release cycle. Today you can pin your rustc version to avoid these kind of surprises, but you shouldn't have to. I am personally concerned about being able to build random projects from today in 10 years, and I hope we can manage that. Looking at the root problem here, I'm gonna see if I can write a lint against the identity conversion impl in expressions to see how many more potential mines are in the ecosystem. If there aren't that many, we can enable that lint by default and prevent future occurrences of this. I would also like to extend the diagnostic people hit in this case to be more actionable (but end users wouldn't see that until 1.82 at the latest when compiling against an older time, it might be worth it for future users only). Completely freezing std to completely avoid these issues is not reasonable. End users can always smoke test against beta in order to get advance notice of these kind of issues. These kind of issues should be rare. If they are not, it's a fuck-up, and we'd love to see bug reports so that we can rework our release process accordingly.

By @WiSaGaN - 9 months
Backward compatibility (in terms of successful compilation) is never absolute. It's just Rust makes it very rare, and usually justifiable (say, fixing sound issue), while still allows making good progress. In this case, it's an inference change, which is easily fixable. Inference breakage is explicitly allowed in Rust compiler policy. You won't get any new methods in standard library if you want absolute backward compatibility.
By @mustache_kimono - 9 months
> When I did that, despite having not changed any dependencies, I got a build error in CI/CD.

Isn't this resolved by passing `--locked` to `cargo`? If you don't want it to resolve deps, don't let it. This isn't bit rot.

This lament seems similar to "I can't compile this Rust code (using an older version of rustc)".

By @tyleo - 9 months
I’d love someone to comment on this who’s knowledgeable. I know we have a few rust experts in HN. I’m curious if this is a bug with the update. My novice brain tells me this shouldn’t have happened.
By @winnie_ua - 9 months
Article is just whining! Author didn't investigate what caused an issue.