-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
MSRV-dependent dependency version resolution #9930
Comments
I think this probably makes more sense in the Cargo repository, since version resolution happens in Cargo -- might even make sense to do an RFC for it. @ehuss @Eh2406 what do you think? I can see the attraction of this feature, but I'm also worried about it -- if this behavior doesn't come with a warning, it's trivially possible that downstream crates no longer get updated to upstream dependencies that fixed security vulnerabilities, for example. While I usually deploy cargo-deny in CI to make sure I'm aware of this, as long as something similar is not integrated in Cargo it would be a little scary that semver-compatible updates no longer flow as freely as they used to. |
Yes, having a Cargo warning for cases when there are dependency updates with incompatible MSRV would be a good feature. As for security vulnerabilities, I think it should be solved by advisories like RustSec and by yanking affected versions. Also note that today crates can have minor (for pre-1.0, major otherwise) version updates with security fixes which do not get ported to older releases. So I don't think that the proposed MSRV-dependent version resolution is fundamentally different from the existing status quo in this regard. |
Transferred to Cargo. IMO one of the big problems blocking this is the error messages. The current Resolver has pretty bad messages, it just reports on the last thing that did not work. So In effect the Resolver will just ignore all versions with a different MSRV leaving no record of why newer versions were not considered. This may be on the list of things to consider when/if we use PubGrub. But that is just my opinion. |
Is this actually a good idea? I feel like |
broken code doesn't help anyone. If cargo update / upgrade gives warnings that your rust version is too old to bring in all the latest updates then people will be more likely to run cargo upgrade as they are more likely to get a result that works. Pragmatically some stuff upgraded is better than nothing upgraded. |
It was my main motivation for writing the MSRV RFC. Without it I (and many others) consider bumping MSRV a breaking change, since otherwise we risk breaking people's builds on older toolchains (e.g. think of Rust packaged with Debian). Printing an error is just slightly improves ergonomics, no solves the problem at the root. |
I think most maintainers have stepped away from the idea of MSRV bumps requiring a semver bump. Even fundamental things like serde have done it. Instead, just keep a conservative enough MSRV for your crate's audience. |
But keeping "a conservative enough MSRV for your crate's audience" is not_possible if your upstream dependencies don't do the same. If upstream crates raise their MSRV without a major version bump, then you have little choice but to follow suit. As @leo60228 suggested you could pin those crates versions to before their MSRV bump, but that causes a different problem: Cargo refuses to build two semver-compatible versions of a single crate in a single build. That can result in downstream users' builds breaking, even if they don't care about MSRV. So Rust really does need an MSRV-sensitive resolver. |
One way to resolve this concern is to make the behavior opt-in. By default, behavior is at is today (modulo a better error message), but you can pass |
In theory, this is true. In practice, I've found that upstream maintainers have usually been happy to accomodate my requests for changes to allow a more conservative MSRV -- just a matter of (a) being aware when changes happen and (b) engaging with upstream to voice your concerns/discuss trade-offs. |
How should this interact with |
Wouldn't it be viable to implement an MVP with bad error messages first and work on improving them later?
I think it should be fine to start with a simple warning if at least one dependency version was ignored due to the MSRV filtration. |
I came across a related problem, where a CI/CD pipeline failed due to a updated dependency which demanded a higher MSRV than specified for the downstream project. While I am not sure, that doing a automated MSRV-dependent dependency version resolution is a good idea in general, I would like a feature which notifies you if dependencies can't be build with the specified MSRV. Furthermore I am not completely sure how its meant to be specified: Should the developer ensure, that the MSRV of his Crate is at least as high as all upstream dependencies? RFC 2495 mentions this, but there seems to be no check implemented right now.
|
Cargo from Rust 1.56 and newer should yield an MSRV-specific error when trying to build a dependency that has its
Yes, there is currently no way that the tooling can ensure this. |
Just tried to provoke this behaviour with two freshly created crates, and can't really confirm this. When building crate A which depends on crate B, I can set |
I didn't say you would get an error in that situation. You're building with Cargo 1.61 and both of the crates have 1.61 or older, so there is no error. We currently don't check that depending crates have a newer or equal MSRV compared to the crate they're depending on. You can refer to the documentation here: https://doc.rust-lang.org/cargo/reference/manifest.html#the-rust-version-field. As far as I can tell, all of this discussion is off-topic for this issue, which is about influencing the Cargo resolver such that it would select the lower version of a dependency if that is a better match for the current Cargo version. |
Ok, thanks for the clarification. And yes its somewhat off-topic, my apologies. Initially I was just confused that the RFC excerpt I cited isn't implemented in some tooling right now and came up to this Issue. To contribute at least a bit here: If the Cargo resolver will make some decisions based on the MSRV, the tooling which hints the developer of incompatible MSRVs, is basically included in that. IMO that would be good to have. |
Perhaps there could be an unstable option similar to |
This is to help with rust-lang#9930 Example changes: ```diff -[LOCKING] 4 packages +[LOCKING] 4 packages to latest version -[LOCKING] 2 packages +[LOCKING] 2 packages to latest Rust 1.60.0 compatible versions -[LOCKING] 2 packages +[LOCKING] 2 packages to earliest versions ``` Benefits - The package count is of "added" packages and this makes that more logically clear - This gives users transparency into what is happening, especially with - what rust-version is use - the transition to this feature in the new edition - whether the planned config was applied or not (as I don't want it to require an MSRV bump) - Will make it easier in tests to show what changed - Provides more motiviation to show this message in `cargo update` and `cargo install` (that will be explored in a follow up PR) This does come at the cost of more verbose output but hopefully not too verbose. This is why I left off other factors, like avoid-dev-deps.
feat(resolve): Tell the user the style of resovle done ### What does this PR try to resolve? This is to help with #9930 Example changes: ```diff -[LOCKING] 4 packages +[LOCKING] 4 packages to latest compatible version -[LOCKING] 2 packages +[LOCKING] 2 packages to latest Rust 1.60.0 compatible versions -[LOCKING] 2 packages +[LOCKING] 2 packages to earliest compatible versions ``` Benefits - The package count is of "added" packages and this makes that more logically clear - This gives users transparency into what is happening, especially with - what rust-version is use - the transition to this feature in the new edition - whether the planned config was applied or not (as I don't want it to require an MSRV bump) - Will make it easier in tests to show what changed - Provides more motiviation to show this message in `cargo update` and `cargo install` (that will be explored in a follow up PR) This does come at the cost of more verbose output but hopefully not too verbose. This is why I left off other factors, like avoid-dev-deps. ### How should we test and review this PR? ### Additional information
This is a part of rust-lang#13540 which is a party of rust-lang#9930. The config is `resolver.something-like-precedence` with values: - `something-like-maximum` (default) - `something-like-rust-version` This is punting on the actual config schema so we can implement `package.resolver` and `edition = "2024"` support as we want the MSRV-aware resolver available without `cargo_features`.
This is a part of rust-lang#13540 which is a party of rust-lang#9930. The config is `resolver.something-like-precedence` with values: - `something-like-maximum` (default) - `something-like-rust-version` This is punting on the actual config schema so we can implement `package.resolver` and `edition = "2024"` support as we want the MSRV-aware resolver available without `cargo_features`.
This is a part of rust-lang#13540 which is a party of rust-lang#9930. The config is `resolver.something-like-precedence` with values: - `something-like-maximum` (default) - `something-like-rust-version` This is punting on the actual config schema so we can implement `package.resolver` and `edition = "2024"` support as we want the MSRV-aware resolver available without `cargo_features`.
fix(msrv): Put MSRV-aware resolver behind a config ### What does this PR try to resolve? This is a part of #13540 which is a party of #9930. The config is `resolver.something-like-precedence` with values: - `something-like-maximum` (default) - `something-like-rust-version` This is punting on the actual config schema so we can implement `package.resolver` and `edition = "2024"` support as we want the MSRV-aware resolver available without `cargo_features`. ### How should we test and review this PR? One of the included test cases shows a bug with `cargo install`. Resolving that will be tracked in #9930 ### Additional information
This is a part of rust-lang#9930 and is important for changing the default with the new edition.
This is a part of rust-lang#9930 and is important for changing the default with the new edition.
This is a part of rust-lang#9930 and is important for changing the default with the new edition.
This is a part of rust-lang#9930 and is important for changing the default with the new edition.
feat(resolver): Add v3 resolver for MSRV-aware resolving ### What does this PR try to resolve? This is a part of #9930 and is important for changing the default with the new edition. ### How should we test and review this PR? ### Additional information
fix(install): Don't respect MSRV for non-local installs ### What does this PR try to resolve? This is part of #9930 ### How should we test and review this PR? ### Additional information
fix(resolver): Treat unset MSRV as compatible ### What does this PR try to resolve? Have the resolver treat no-MSRV as `rust-version = "*"`, like `cargo add` does for version-requirement selection ### How should we test and review this PR? We last tweaked this logic in #13066. However, we noticed this was inconsistent with `cargo add` in automatically selecting version requirements. It looks like this is a revert of #13066, taking us back to the behavior in #12950. In #12950 there was a concern about the proliferation of no-MSRV and whether we should de-prioritize those to make the chance of success more likely. There are no right answes here, only which wrong answer is ok enough. - Do we treat lack of rust version as `rust-version = "*"` as some people expect or do we try to be smart? - If a user adds or removes `rust-version`, how should that affect the priority? One piece of new information is that the RFC for this has us trying to fill the no-MSRV gap with `rust-version = some-value-representing-the-current-toolchain>`. See also #9930 (comment) r? `@Eh2406` ### Additional information
In rust-lang#9930, it recommended improving the error for incompatible packages so people can better get to the root of the problem. For example, you might get an error about `clap_lex` but resolving the error for the higher level `clap` could make the problem with `clap_lex` go away. Because I generally saw earlier packages in the graph reported, I assumed we were reporting these errors bottom up. It turns out, we are reporting them in the `UnitGraph`s order, which is non-deterministic because it is built on a `HashMap`. So this adds determinism and shows all incompatible dependencies (not just the bottom or the root). This is a first step. We might find that we still want to only include the shallowest units, rather than all. At that point, we can add the complexity to address this by walking the unit graph. We could also further improve this by querying the index to suggest compatible versions of packages.
feat: Stabilize MSRV-aware resolver config ### What does this PR try to resolve? This includes - `cargo generate-lockfile --ignore-rust-version` - `cargo update --ignore-rust-version` This does not include - `edition = "2024"` - `resolver = "3"` This is part of #9930 ### How should we test and review this PR? ### Additional information This is stacked on top of #14636. The commits for this PR start with the commit with a title that matches the PR title. [FCP](#14639 (comment))
Based on RFC 2495 Rust now supports the
rust-version
field, which currently works as:This behavior is not ideal. If a project depends on crate
foo v0.1.0
with MSRV 1.56, then releasing cratefoo v0.1.1
with MSRV 1.60 will break build of the project on older toolchains after simplecargo update
. Ideally Cargo would selectfoo v0.1.0
on older tolchains, thus preventing the breakage.RFC 2495 has described MSRV-dependent version resolution as a potential future extension. This issue is intended for design discussions and tracking implementation progress of this feature.
Third-party support
rust-version
into account when updating lock file / manifest dependabot/dependabot-core#5423This has been approved as RFC #3537.
Implementation by stabilization milestone
cargo install
error (fix(install): Suggest an alternative version on MSRV failure #12798)rust-version
(docs: Provide pointers for MSRV #13056)cargo add
support (cargo add
takespackage.rust-version
into account when no version-req is specified #10653)rustc -V
(feat(add): Fallback torustc -v
when no MSRV is set #13516)cargo update
keeps user informed when using old versions (feat(update): Tell users when they are still behind #13372)rust-version
(fix(resolver): De-prioritize no-rust-version in MSRV resolver #13066)rustc -V
(feat(resolve): Fallback to 'rustc -V' for MSRV resolving #13743)--ignore-rust-version
support (feat(reslve): Respect '--ignore-rust-version' #13738)--ignore-rust-version
support forcargo update
/cargo-generate-lockfile
(feat(cli): Add --ignore-rust-version to update/generate-lockfile #13742)cargo update --precise
can select incompatible versions (fix(msrv): Put MSRV-aware resolver behind a config #13769)--ignore-rust-version
(see feat: respectrust-version
when generating lockfile #12861)--update-rust-version
supportcargo add
cargo update
cargo generate-lockfile
cargo new
templateChanges from RFC
Unresolved questions
cargo add
and the resolver have different behavior for unsetrust-version
, see fix(resolver): Treat unset MSRV as compatible #13791Deferred
cargo install
should do, see also Respectrust-version
when selecting a version forcargo install
#10903The text was updated successfully, but these errors were encountered: