-
Notifications
You must be signed in to change notification settings - Fork 109
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
Minimum Rust Version #201
Comments
The short answer is no: per current policy, MSRV bump is not considered a semver breaking change. I want to avoid every reverse dependency having to change their Cargo.tomls (and their own major version, if they happen to expose once_cell via a public API). After re-reading rust-lang/libs-team#72 couple of times, the policy I decided for once_cell is: We support workflows which target up-to-date, supported versions of Rust compiler, but we also give somewhat generous grace period, as keeping perfectly up-to-date is hard. We explicitly do not support workflows which depend on using the old compiler. Making sure that the latest once_cell can be compiled with If users of once_cell find themselves with an outdated compiler, the following actions are suggested:
The following considerations were the most salient for me:
An orthogonal policy is that MSRV bump is not considered semver breaking. There are two justifications for that: First, this creates ripple effect over ecosystem, where each reverse-dependency has upload a new version with a different Cargo.toml. If the crate also happens to be part of the public API or pushes revdep's own MSRV, the reverse dependency is required to bump its major as well. Practically, not every rev-dep will notice new once-cell, so an extra burden falls on folks maintaining applications with Cargo.locks, who now need to chase their upstreams to avoid duplicate entries in Cargo.lock. Second, bumping sevmer on MSRV makes the ecosystem less compatible with older compilers. Consider A: B: To rephrase this more mathematically, MSRV means that there exists a combination of dependencies which can be build with that compiler, not that any combination of dependencies can be build with it. The One practical problem with the above is that, if you naively test MSRV on CI, your CI might now be broken by upstream releasing a new version to crates.io. To solve this problem, the following rule is used: MSRV CI: if you are not using the latest stable compiler, you must use The suggested way to do this is to commit Lines 43 to 48 in 97edd07
Finally, there are three specific things anyone feeling strongly can do to improve the situation:
|
Given that this is where the ecosystem is going, I will likely have to stop maintaining my own libraries for old rust versions.
I can't even imagine how this works in the resolver given the complexities of this. The resolver would have to back out a huge chunk of the dependency graph if it first encounters an incompatible version of a library. I think the practical implication of this is that the community starts to restrict to test only against latest Rust again or maybe some quite recent version. |
`hashbrown` depends on `ahash` which depends on `once_cell`. Sadly, in matklad/once_cell#201 the `once_cell` maintainer decided they didn't want to do the work of having an MSRV policy for `once_cell`, making `ahash`, and thus `hashbrown` require the latest compiler. I've reached out to `ahash` to suggest they drop the dependency (as they could trivially work around not having it), but until then we simply downgrade `hashbrown`. `rust-bitcoin` also requires an older `hashbrown` so we're actually reducing our total `no-std` code here anyway.
One question I have here: today, once_cell's MSRV is described as "conservative" in readme and 11 months for me does sound conservative, though pretty close to the boundary. I'd like to get a rough "temperature reading" to use the words in a useful way: Could 11 months old MSRV be called conservative?
|
`hashbrown` depends on `ahash` which depends on `once_cell`. Sadly, in matklad/once_cell#201 the `once_cell` maintainer decided they didn't want to do the work of having an MSRV policy for `once_cell`, making `ahash`, and thus `hashbrown` require the latest compiler. I've reached out to `ahash` to suggest they drop the dependency (as they could trivially work around not having it), but until then we simply downgrade `hashbrown`. `rust-bitcoin` also requires an older `hashbrown` so we're actually reducing our total `no-std` code here anyway.
`hashbrown` depends on `ahash` which depends on `once_cell`. Sadly, in matklad/once_cell#201 the `once_cell` maintainer decided they didn't want to do the work of having an MSRV policy for `once_cell`, making `ahash`, and thus `hashbrown` require the latest compiler. I've reached out to `ahash` to suggest they drop the dependency (as they could trivially work around not having it), but until then we simply downgrade `hashbrown`. `rust-bitcoin` also requires an older `hashbrown` so we're actually reducing our total `no-std` code here anyway.
`once_cell` upgraded the MSRV to 1.56. This breaks the use of `iana-time-zone` transitively even though we only use it for Android targets. This PR replaces `once_cell` by using `static mut` + `std::sync::Once`. `once_cell` is more or less only a safe wrapper around both, but not actually needed. We already do the same in our Windows targets. Cf. <matklad/once_cell#201>
`hashbrown` depends on `ahash` which depends on `once_cell`. Sadly, in matklad/once_cell#201 the `once_cell` maintainer decided they didn't want to do the work of having an MSRV policy for `once_cell`, making `ahash`, and thus `hashbrown` require the latest compiler. I've reached out to `ahash` to suggest they drop the dependency (as they could trivially work around not having it), but until then we simply downgrade `hashbrown`. `rust-bitcoin` also requires an older `hashbrown` so we're actually reducing our total `no-std` code here anyway.
I think my answer would depend on whether 11 months is policy. Your long comment above to me suggests a more aggressive policy (on when we can expect MSRV updates) but as far as I can tell it doesn't actually specify when/how future updates would occur. I would agree your current choice of MSRV is (somewhat) conservative. |
It's a shame that MSRV update is not part of the semver breaking changes as it completely broke my builds for |
@GuillaumeGomez as per MSRV CI rule articulated above, ecosystems using precise rustc version could also use precise Cargo.lock to avoid any breakages. |
But that would prevent to automatically get any bugfix too. Tricky situation. 😆 |
Applications generally use a lock-file anyway, so they already don't get automatic bugfixes. For libraries, you want to run CI on stable without lockfile (to catch new upstream regressions) and on MSRV with lockfile (to catch MSRV/min-version regressions in your own code). |
@GuillaumeGomez I'd recommend https://github.com/dtolnay/rust-toolchain#toolchain-expressions instead of lockfile. This should be compatible with once_cell as implied by "we give somewhat generous grace period, as keeping perfectly up-to-date is hard" as long as the number of months/releases you pick for the CI build matches what once_cell would consider somewhat generous. |
No, I'll just enforce in my |
Except when installing through cargo install, which will default to resolving dependencies from scratch. |
This is the worst approach that's been mentioned so far. This blocks anybody from using new sysinfo features together with new once_cell features, even if their compiler supports it. |
I don't see how blocking the Also I just realized that it was used in other dependencies of So basically, I'm now forced to update MSRV version of sysinfo (and make a new major release) because a dependency decided to make a minor release with a breaking change. To be clear: I'm not opposed to a MSRV change, I'm opposed to a silent MSRV change. |
I can try to answer this. Semver very explicitly only applies to the documented public API. You first explain how your thing is intended to be used, and then everybody using it in that way can use the semver number to tell whether a particular update is potentially breaking. A great number of observable things are not covered by semver because they are not documented as part of the intended way to use a crate. For example code that reaches into doc(hidden) private macro internals doesn't get to complain when those things change, because they are not public API. Similarly code that transmutes types with private members. Or code that assumes undocumented implementation details of layout, such as the precise size of a type in bytes. In once_cell's case, the "public API" is that you build it with a recent enough compiler and stick to everything shown in the rendered rustdoc, and then once_cell's semver number will tell you which releases potentially break that usage. |
Thanks for the explanation. We all agree here that @matklad respected semver. What I'm complaining about here is that even though semver doesn't go over this, if the same code with no modification stop compiling because of a dependency, then it is a breaking change. Well, I think the situation won't change and @matklad won't make a medium/major release over this so I'll just wait for a few days and then make a new major release for |
I guess I will make my own sysinfo crate. :) |
Well, competition is always a good thing so go ahead. :) |
Lockfiles (or |
@Nemo157 that's not a very useful guarantee to give from where I stand and also increases the complexity greatly for everybody involved. |
I guess I don't really understand this. If you (as in the general "you") care about MSRV enough, then I don't understand why this isn't an acceptable price to pay. Someone has to pay the price somewhere. If you hold MSRV back, then you end up in a tangle like libc, and that has complexity costs too, because it can result in a nasty mess of conditional compilation. |
Correct, and I would like to pay this price on behalf of my users for at least Today I can publish a crate and declare a MSRV, but I cannot really guarantee it unless I also control all of my dependencies. Which means that I have to either let the user deal with this problem and publish some recommendations in the docs of known good upstream versions that support my MSRV. In that case they will have to manually Since someone needs to pay the price it seems to be easier for me (for now) to pick libraries that are more conservatives in MSRV bumps so that I am running less often into this issue. There is however a good chance that the community as a hole is becoming less interested in supporting older rustc versions and then I will likewise stop caring about it. Right now I'm here waiting and seeing. Another way to look at it is that the complexity of not using |
Some newer versions of transitive dev-dependencies don't work with the minimum supported Rust version (1.42.0), so I used to pin them in `Cargo.toml` whenever the MSRV build would break (tedious work). The disadvantage of that is that older versions of those deps are used even on newer Rust versions. The latest breakage is matklad/once_cell#201, but instead of pinning that to an older version too, this instead introduces a `Cargo.lock` file that is only used for the MSRV build. So newer Rust versions will continue to test against latest dependencies, while the MSRV build should continue to work with the older versions. One disadvantage with this is that consumers will need to figure out their own `Cargo.lock` with precise versions that work with older Rust versions, but that is expected to be a small number - especially because in this case they are all dev-dependencies anyway.
Some newer versions of transitive dev-dependencies don't work with the minimum supported Rust version (1.46.0), so I used to pin them in `Cargo.toml` whenever the MSRV build would break (tedious work). The disadvantage of that is that older versions of those deps are used even on newer Rust versions. The latest breakage is matklad/once_cell#201, but instead of pinning that to an older version too, this instead introduces a `Cargo.lock` file that is only used for the MSRV build. So newer Rust versions will continue to test against latest dependencies, while the MSRV build should continue to work with the older versions. One disadvantage with this is that consumers will need to figure out their own `Cargo.lock` with precise versions that work with older Rust versions, but that is expected to be a small number - especially because in this case they are all dev-dependencies anyway.
@matklad Would you consider adding a section to the README that lists the current MSRV? This will be useful in the future when we need to find the MSRV of a specific version of |
I'd rather keep https://github.com/matklad/once_cell/blob/master/Cargo.toml#L7 as a source of truth. |
I'll drop my regular reminder that I'm gathering stats for ecosystem-wide MSRV here: https://lib.rs/stats#rustc The current state is that MSRV < 1.56 is a waste of time. The latest edition, just like the previous one, is a major cliff. Already over a quarter of all crates have upgraded to edition 2021 (or equally new features). Those crates haven't upgraded yet are mainly dead unmaintained ones. Out of actively maintained crates, a whooping 80% require 1.56+. I don't think it's reasonably possible any more to develop a non-toy project that uses both up-to-date dependencies and Rust < 1.56. If you're spending effort on supporting old MSRV you're in the minority, and putting this all effort for an even smaller minority. MSRV has an incredibly "viral" negative network effect. The worst-MSRV-wins effect means that even if 99% of your dependencies try to support old Rust, and 1% doesn't, then your project and everyone using is still 100% broken. |
I think the discussion has run its course here, closing! I've clarified the exact supported range in #204, but otherwise the policy articulated in the first comment remains unchanged! |
Added a Cargo.lock file for MSRV support to pin once_cell back to 1.14.0 artifically with `cargo update -p once_cell --precise 1.14.0` since it broke MSRV compat. See matklad/once_cell#201 for details and why it'll remain broken.
Added a Cargo.lock file for MSRV support to pin once_cell back to 1.14.0 artifically with `cargo update -p once_cell --precise 1.14.0` since it broke MSRV compat. See matklad/once_cell#201 for details and why it'll remain broken.
`hashbrown` depends on `ahash` which depends on `once_cell`. Sadly, in matklad/once_cell#201 the `once_cell` maintainer decided they didn't want to do the work of having an MSRV policy for `once_cell`, making `ahash`, and thus `hashbrown` require the latest compiler. I've reached out to `ahash` to suggest they drop the dependency (as they could trivially work around not having it), but until then we simply downgrade `hashbrown`. `rust-bitcoin` also requires an older `hashbrown` so we're actually reducing our total `no-std` code here anyway.
I think that good to put MSRV in the README. Fix somehow matklad#201
The latest version of
once_cell
bumps up the minimum requirement up to 1.56 which is a huge jump. Is it conceivable to do a major version bump for this so that people who want to depend on it for libraries that wan to support older versions can stay on the old version?The text was updated successfully, but these errors were encountered: