Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

This crate broke Hyper v0.10's compatibility with Rust v1.24 (Debian latest) #112

Closed
stevenroose opened this issue Aug 13, 2019 · 20 comments · Fixed by abonander/safemem#5
Closed

Comments

@stevenroose
Copy link

In our projects, we use Hyper version 0.10 because from 0.11 onwards is started using tokio which blew up the dependency tree. We also use Rust v1.24 (the newest version available on Debian) and the newest Hyper version doesn't support that Rust version anymore.

Hyper v0.10 has a dependency on base64 v0.9.

Note that in base64 v0.9.0, safemem 0.2 is used which is compatible with Rust v1.24. However, in base64 v0.9.3, the safemem dependency is bumped to the new major version 0.3 without bumping the base64 major version.

Since safemem 0.3 released an update 2 weeks ago that breaks with Rust v1.24, the result is that Hyper v0.10.19 is no longer compatible with Rust v1.24 (and this with Debian).

I don't like to fingerpoint, but I would just want to encourage the maintainers of this library to be cautious with dependency management. Especially for a crate as trivial as base64, extreme care should be applied when bumping dependencies.

The result in this case is that it's no longer possible to use Hyper without tokio on Debian.

@stevenroose stevenroose changed the title This crate broke Hyper v0.10's compatibility with Rust v1.24 This crate broke Hyper v0.10's compatibility with Rust v1.24 (Debian latest) Aug 13, 2019
@stevenroose
Copy link
Author

What I'd like to be the lesson learned here is that for crates with trivial and never-changing functionality like this crate, dependency management should be the primary consideration and thus the major version should be bumped whenever a dependency is changed.

@ignatenkobrain
Copy link
Contributor

Isn't this a problem of Debian shipping long-long-time-unsupported-version-of-rustc?

@stevenroose
Copy link
Author

I think it's mostly a problem of Cargo not having a field indicating the minimum Rust version the package is supposed to support. With that, it'd be more obvious when a version bump downstream can cause breaking changes upstream.

I know base64 is just the package in the middle here, but safemem did the right thing to make a breaking change from 0.2 to 0.3 so it's not to blame. And upstream nothing changed at all; base64 basically turned a major change (0.2->0.3) into a minor change (0.9.0->0.9.3).

@apoelstra
Copy link

@ignatenkobrain I strongly disagree that the "problem" with a minor version release failing to build when the previous version did, is anything other than a breaking release in a minor version.

Having said that, currently mrustc only supports rustc 1.19, meaning that anyone who wants to avoid "trusting trust" style attacks is limited to using 1.19 (or something a few versions later; but since each compiler requires the previous one to build, every additional version adds a huge amount of time to your toolchain build).

But even if this weren't true, rust is intended to be used by high-assurance high-performance projects where correctness is absolutely essential. In many such contexts (avionics, railway systems, spacecraft) the toolchain used needs to be certified by some body, an expensive and time-consuming process that cannot be repeated frequently. As far as I'm aware, nobody with such requirements is using Rust because of its rapid churn, something which makes sense for such a young language but still breaks my heart.

I think this attitude of "everyone should use the latest rustc" directly pushes such users away from the ecosystem, and by extension anybody who considers such users a priority. I think this is harmful to the Rust ecosystem and to the culture surrounding it, which is especially frustrating because the language itself provides features for these users that no other widely-used language does.

Even in the absence of certification requirements, it still makes sense for many people to pin their compiler/stdlib version and to be very averse to changing it. This gives them a well-tested platform with a known set of bugs, means that regressions are their own fault rather than in the toolchain, and tursn the continual trust requirement of downloading binaries from Mozilla into a periodic one. (It also allows them to outsource this trust to entities such as Debian, whose focus is primarily on distribution security and who've been doing this for a long time, rather than to the compiler team, whose main priority by far is shipping a compiler.)

In most contexts, even within the software industry, it's not normal to update your tooling every year, let alone multiple times a year. By nature of its simplicity and wide applicability, base64 winds up being pulled into all manner of projects as a dependency, so it's frustrating that its authors would require users to do so.

@CryZe
Copy link
Contributor

CryZe commented Aug 14, 2019

@stevenroose Can't you pin against the safemem version that is still compatible via safemem = "=0.3.0"? (Or is that also not supported? It's not entirely clear)

@stevenroose
Copy link
Author

@CryZe where? Doing that in my own project doesn't work, because that doesn't affect the safemem version that base64 will be using. So I would have to fork base64 just to change the safemem dependency line? In that case I might just as well fork base64 and make it Rust 1.19 compatible.

@CryZe
Copy link
Contributor

CryZe commented Aug 14, 2019

Doing that in my own project doesn't work, because that doesn't affect the safemem version that base64 will be using.

It will.

@stevenroose
Copy link
Author

That's not how dependencies work in a statically linked language like Rust (as opposed to runtime languages like Go and NodeJS where only a single version of every package can be loaded in the entire program).

Cargo picks dependencies for each dependency tree separately. So the app > base64 > safemem version is independent on the app > safemem version.

Perhaps if the two version are compatible, Cargo will pick one to avoid duplication, so you might be correct. But what if safemem releases a new version 0.4.0 that I want to use? Then I would have to include safemem = "0.4.0" and the versions will be incompatible, causing Cargo to pick the most recent one fulfilling ^0.3.0 for the crate > base64 > safemem dependency.

@CryZe
Copy link
Contributor

CryZe commented Aug 14, 2019

Yes, it's only a workaround for your specific current situation. In general you likely have to be careful about applying changes to your lockfile as long as you stay on that Rust version anyway (as there's probably more breakage of that kind incoming from other crates).

(Also if safemem 0.3.0 works, then the breakage was introduced there, not in this crate)

@stevenroose
Copy link
Author

(Also if safemem 0.3.0 works, then the breakage was introduced there, not in this crate)

It was the 0.2.x -> 0.3.x change that was breaking.

@CryZe
Copy link
Contributor

CryZe commented Aug 14, 2019

https://i.imgur.com/NdfRepg.png

That does not seem to be the case.

KamilaBorowska added a commit to KamilaBorowska/safemem that referenced this issue Aug 14, 2019
This ensures compatibility with older Rust releases.

Fixes marshallpierce/rust-base64#112.
@stevenroose
Copy link
Author

stevenroose commented Aug 14, 2019

Heh, you seem to be right. This seems to be the breaking change: abonander/safemem@219a273

Hmm, my apologies for the incorrect statement. While this doesn't of course change the fact that base64 did a minor version bump that included a downstream major version bump, it does mean that it's not directly responsible for breaking Rust 1.24 support.

@stevenroose
Copy link
Author

And I see that someone already created an issue in safemem. Great!

@CryZe
Copy link
Contributor

CryZe commented Aug 14, 2019

Yeah I know xfix, so I contacted them :D

@abonander
Copy link

abonander commented Aug 16, 2019

safemem compatibility has been widened to Rust 1.19, but the question is what version should that be released as: 0.3.2 or 0.4.0? It's technically a backwards-compatible change and 0.3.2 should mean a cargo update is all that's needed to fix this.

@stevenroose
Copy link
Author

Yeah I think safemem can just release a minor version since it's backwards compatible. I'm not fully sure of what the removing of the edition = "2018" from the Cargo.toml has as effects, but I think it should be ok.

@abonander
Copy link

safemem never had edition = "2018"

@abonander
Copy link

Published safemem 0.3.2

@marshallpierce
Copy link
Owner

I'm happy to depend on safemem 0.3.2. However, let's be clear: this crate didn't break anything. You updated versions of your dependencies while insisting on using an ancient compiler, and that choice had consequences. That's life.

  • Rust is abound with 0.x dependencies. Even if we all used semver, which we don't, 0.x plays by different rules:

Major version zero (0.y.z) is for initial development. Anything MAY change at any time. The public API SHOULD NOT be considered stable.

  • Debian is a pretty dodgy custodian of language runtimes, historically. If you choose to rope yourself to that anchor, that's your choice.
  • Since this crate is so "trivial and unchanging", just use an old version.

@abonander
Copy link

abonander commented Aug 26, 2019

A few things to note here:

It's not the fault of this crate's maintainers for breaking on a version of Rust they explicitly don't support. Anyone stuck on such an old version of Rust should expect to vet their dependencies for potential issues like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants