Skip to content

Commit 18a5940

Browse files
committed
fix(msrv): Put MSRV-aware resolver behind a config
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`.
1 parent 7af4bcf commit 18a5940

File tree

4 files changed

+71
-9
lines changed

4 files changed

+71
-9
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/rust_version.rs

+2
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,7 @@ fn resolve_unstable_config_on_stable() {
576576
)
577577
.with_stderr(
578578
"\
579+
[WARNING] ignoring `resolver` config table without `-Zmsrv-policy`
579580
[UPDATING] `dummy-registry` index
580581
[LOCKING] 3 packages to latest compatible versions
581582
",
@@ -595,6 +596,7 @@ foo v0.0.1 ([CWD])
595596
.env("CARGO_RESOLVER_SOMETHING_LIKE_PRECEDENCE", "non-existent")
596597
.with_stderr(
597598
"\
599+
[WARNING] ignoring `resolver` config table without `-Zmsrv-policy`
598600
[UPDATING] `dummy-registry` index
599601
[LOCKING] 3 packages to latest compatible versions
600602
",

0 commit comments

Comments
 (0)