Skip to content

Commit 2956296

Browse files
committed
Auto merge of #13769 - epage:msrv-config, r=weihanglo
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
2 parents 39b8f17 + 18a5940 commit 2956296

File tree

12 files changed

+331
-10
lines changed

12 files changed

+331
-10
lines changed

src/cargo/core/workspace.rs

+42-6
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ use crate::util::errors::{CargoResult, ManifestError};
2626
use crate::util::interning::InternedString;
2727
use crate::util::lints::check_implicit_features;
2828
use crate::util::toml::{read_manifest, InheritableFields};
29-
use crate::util::{context::ConfigRelativePath, Filesystem, GlobalContext, IntoUrl};
29+
use crate::util::{
30+
context::CargoResolverConfig, context::CargoResolverPrecedence, context::ConfigRelativePath,
31+
Filesystem, GlobalContext, IntoUrl,
32+
};
3033
use cargo_util::paths;
3134
use cargo_util::paths::normalize_path;
3235
use cargo_util_schemas::manifest;
@@ -100,6 +103,7 @@ pub struct Workspace<'gctx> {
100103

101104
/// The resolver behavior specified with the `resolver` field.
102105
resolve_behavior: ResolveBehavior,
106+
resolve_honors_rust_version: bool,
103107
honor_rust_version: Option<bool>,
104108

105109
/// Workspace-level custom metadata
@@ -207,7 +211,7 @@ impl<'gctx> Workspace<'gctx> {
207211
.load_workspace_config()?
208212
.and_then(|cfg| cfg.custom_metadata);
209213
ws.find_members()?;
210-
ws.set_resolve_behavior();
214+
ws.set_resolve_behavior()?;
211215
ws.validate()?;
212216
Ok(ws)
213217
}
@@ -230,6 +234,7 @@ impl<'gctx> Workspace<'gctx> {
230234
loaded_packages: RefCell::new(HashMap::new()),
231235
ignore_lock: false,
232236
resolve_behavior: ResolveBehavior::V1,
237+
resolve_honors_rust_version: false,
233238
honor_rust_version: None,
234239
custom_metadata: None,
235240
}
@@ -248,7 +253,7 @@ impl<'gctx> Workspace<'gctx> {
248253
.packages
249254
.insert(root_path, MaybePackage::Virtual(manifest));
250255
ws.find_members()?;
251-
ws.set_resolve_behavior();
256+
ws.set_resolve_behavior()?;
252257
// TODO: validation does not work because it walks up the directory
253258
// tree looking for the root which is a fake file that doesn't exist.
254259
Ok(ws)
@@ -284,11 +289,11 @@ impl<'gctx> Workspace<'gctx> {
284289
ws.members.push(ws.current_manifest.clone());
285290
ws.member_ids.insert(id);
286291
ws.default_members.push(ws.current_manifest.clone());
287-
ws.set_resolve_behavior();
292+
ws.set_resolve_behavior()?;
288293
Ok(ws)
289294
}
290295

291-
fn set_resolve_behavior(&mut self) {
296+
fn set_resolve_behavior(&mut self) -> CargoResult<()> {
292297
// - If resolver is specified in the workspace definition, use that.
293298
// - If the root package specifies the resolver, use that.
294299
// - If the root package specifies edition 2021, use v2.
@@ -299,7 +304,36 @@ impl<'gctx> Workspace<'gctx> {
299304
.resolve_behavior()
300305
.unwrap_or_else(|| p.manifest().edition().default_resolve_behavior()),
301306
MaybePackage::Virtual(vm) => vm.resolve_behavior().unwrap_or(ResolveBehavior::V1),
307+
};
308+
309+
match self.gctx().get::<CargoResolverConfig>("resolver") {
310+
Ok(CargoResolverConfig {
311+
something_like_precedence: Some(precedence),
312+
}) => {
313+
if self.gctx().cli_unstable().msrv_policy {
314+
self.resolve_honors_rust_version =
315+
precedence == CargoResolverPrecedence::SomethingLikeRustVersion;
316+
} else {
317+
self.gctx()
318+
.shell()
319+
.warn("ignoring `resolver` config table without `-Zmsrv-policy`")?;
320+
}
321+
}
322+
Ok(CargoResolverConfig {
323+
something_like_precedence: None,
324+
}) => {}
325+
Err(err) => {
326+
if self.gctx().cli_unstable().msrv_policy {
327+
return Err(err);
328+
} else {
329+
self.gctx()
330+
.shell()
331+
.warn("ignoring `resolver` config table without `-Zmsrv-policy`")?;
332+
}
333+
}
302334
}
335+
336+
Ok(())
303337
}
304338

305339
/// Returns the current package of this workspace.
@@ -616,7 +650,9 @@ impl<'gctx> Workspace<'gctx> {
616650
}
617651

618652
pub fn resolve_honors_rust_version(&self) -> bool {
619-
self.gctx().cli_unstable().msrv_policy && self.honor_rust_version.unwrap_or(true)
653+
// Give CLI precedence
654+
self.honor_rust_version
655+
.unwrap_or(self.resolve_honors_rust_version)
620656
}
621657

622658
pub fn custom_metadata(&self) -> Option<&toml::Value> {

src/cargo/util/context/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -2644,6 +2644,19 @@ impl BuildTargetConfig {
26442644
}
26452645
}
26462646

2647+
#[derive(Debug, Deserialize)]
2648+
#[serde(rename_all = "kebab-case")]
2649+
pub struct CargoResolverConfig {
2650+
pub something_like_precedence: Option<CargoResolverPrecedence>,
2651+
}
2652+
2653+
#[derive(Debug, Deserialize, PartialEq, Eq)]
2654+
#[serde(rename_all = "kebab-case")]
2655+
pub enum CargoResolverPrecedence {
2656+
SomethingLikeMaximum,
2657+
SomethingLikeRustVersion,
2658+
}
2659+
26472660
#[derive(Deserialize, Default)]
26482661
#[serde(rename_all = "kebab-case")]
26492662
pub struct TermConfig {

src/doc/src/reference/unstable.md

+14-3
Original file line numberDiff line numberDiff line change
@@ -336,15 +336,26 @@ This was stabilized in 1.79 in [#13608](https://github.com/rust-lang/cargo/pull/
336336

337337
### MSRV-aware resolver
338338

339-
By default, `-Zmsrv-policy` enables an MSRV-aware resolver.
339+
`-Zmsrv-policy` allows access to an MSRV-aware resolver which can be enabled with:
340+
- `resolver.something-like-precedence` config field
341+
340342
The resolver will prefer dependencies with a `package.rust-version` that is the same or older than your project's MSRV.
341343
Your project's MSRV is determined by taking the lowest `package.rust-version` set among your workspace members.
342344
If there is none set, your toolchain version will be used with the intent to pick up the version from rustup's `rust-toolchain.toml`, if present.
343345

344-
MSRV-incompatible dependencies can still be selected by:
346+
#### `resolver.something-like-precedence`
347+
* Type: string
348+
* Default: "something-like-maximum"
349+
* Environment: `CARGO_RESOLVER_SOMETHING_LIKE_PRECEDENCE`
350+
351+
Select which policy should be used when resolving dependencies. Values include
352+
- `something-like-maximum`: prefer highest compatible versions of a package
353+
- `something-like-rust-version`: prefer versions of packages compatible with your project's Rust version
354+
355+
Can be overridden with
356+
- `--ignore-rust-version` CLI option
345357
- Setting the dependency's version requirement too high
346358
- Specifying the version to `cargo update` with `--precise`
347-
- Passing `--ignore-rust-version`
348359

349360
## precise-pre-release
350361

tests/testsuite/cargo_add/rust_version_ignore/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ fn case() {
2525
.arg("--ignore-rust-version")
2626
.arg_line("rust-version-user")
2727
.current_dir(cwd)
28+
.env(
29+
"CARGO_RESOLVER_SOMETHING_LIKE_PRECEDENCE",
30+
"something-like-rust-version",
31+
)
2832
.masquerade_as_nightly_cargo(&["msrv-policy"])
2933
.assert()
3034
.code(0)

tests/testsuite/cargo_add/rust_version_incompatible/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ fn case() {
2727
.arg("add")
2828
.arg_line("rust-version-user")
2929
.current_dir(cwd)
30+
.env(
31+
"CARGO_RESOLVER_SOMETHING_LIKE_PRECEDENCE",
32+
"something-like-rust-version",
33+
)
3034
.masquerade_as_nightly_cargo(&["msrv-policy"])
3135
.assert()
3236
.failure()

tests/testsuite/cargo_add/rust_version_latest/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ fn case() {
2424
.arg("add")
2525
.arg_line("rust-version-user")
2626
.current_dir(cwd)
27+
.env(
28+
"CARGO_RESOLVER_SOMETHING_LIKE_PRECEDENCE",
29+
"something-like-rust-version",
30+
)
2731
.masquerade_as_nightly_cargo(&["msrv-policy"])
2832
.assert()
2933
.success()

tests/testsuite/cargo_add/rust_version_older/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ fn case() {
2424
.arg("add")
2525
.arg_line("rust-version-user")
2626
.current_dir(cwd)
27+
.env(
28+
"CARGO_RESOLVER_SOMETHING_LIKE_PRECEDENCE",
29+
"something-like-rust-version",
30+
)
2731
.masquerade_as_nightly_cargo(&["msrv-policy"])
2832
.assert()
2933
.success()

tests/testsuite/cargo_add/rustc_ignore/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ fn case() {
2828
.arg("--ignore-rust-version")
2929
.arg_line("rust-version-user")
3030
.current_dir(cwd)
31+
.env(
32+
"CARGO_RESOLVER_SOMETHING_LIKE_PRECEDENCE",
33+
"something-like-rust-version",
34+
)
3135
.masquerade_as_nightly_cargo(&["msrv-policy"])
3236
.assert()
3337
.code(0)

tests/testsuite/cargo_add/rustc_incompatible/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ fn case() {
2121
.arg("add")
2222
.arg_line("rust-version-user")
2323
.current_dir(cwd)
24+
.env(
25+
"CARGO_RESOLVER_SOMETHING_LIKE_PRECEDENCE",
26+
"something-like-rust-version",
27+
)
2428
.masquerade_as_nightly_cargo(&["msrv-policy"])
2529
.assert()
2630
.failure()

tests/testsuite/cargo_add/rustc_latest/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ fn case() {
2727
.arg("add")
2828
.arg_line("rust-version-user")
2929
.current_dir(cwd)
30+
.env(
31+
"CARGO_RESOLVER_SOMETHING_LIKE_PRECEDENCE",
32+
"something-like-rust-version",
33+
)
3034
.masquerade_as_nightly_cargo(&["msrv-policy"])
3135
.assert()
3236
.success()

tests/testsuite/cargo_add/rustc_older/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ fn case() {
2727
.arg("add")
2828
.arg_line("rust-version-user")
2929
.current_dir(cwd)
30+
.env(
31+
"CARGO_RESOLVER_SOMETHING_LIKE_PRECEDENCE",
32+
"something-like-rust-version",
33+
)
3034
.masquerade_as_nightly_cargo(&["msrv-policy"])
3135
.assert()
3236
.success()

0 commit comments

Comments
 (0)