Skip to content

Commit

Permalink
feat(resolver): Add v3 resolver for MSRV-aware resolving
Browse files Browse the repository at this point in the history
This is a part of rust-lang#9930 and is important for changing the default with
the new edition.
  • Loading branch information
epage committed Apr 18, 2024
1 parent 7e9c2ef commit 72d51cc
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 4 deletions.
4 changes: 2 additions & 2 deletions src/cargo/core/resolver/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ impl FeatureOpts {
}
match ws.resolve_behavior() {
ResolveBehavior::V1 => {}
ResolveBehavior::V2 => {
ResolveBehavior::V2 | ResolveBehavior::V3 => {
enable(&vec!["all".to_string()]).unwrap();
}
}
Expand All @@ -214,7 +214,7 @@ impl FeatureOpts {
pub fn new_behavior(behavior: ResolveBehavior, has_dev_units: HasDevUnits) -> FeatureOpts {
match behavior {
ResolveBehavior::V1 => FeatureOpts::default(),
ResolveBehavior::V2 => FeatureOpts {
ResolveBehavior::V2 | ResolveBehavior::V3 => FeatureOpts {
decouple_host_deps: true,
decouple_dev_deps: has_dev_units == HasDevUnits::No,
ignore_inactive_targets: true,
Expand Down
4 changes: 4 additions & 0 deletions src/cargo/core/resolver/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,16 @@ pub enum ResolveBehavior {
V1,
/// V2 adds the new feature resolver.
V2,
/// V3 changes version preferences
V3,
}

impl ResolveBehavior {
pub fn from_manifest(resolver: &str) -> CargoResult<ResolveBehavior> {
match resolver {
"1" => Ok(ResolveBehavior::V1),
"2" => Ok(ResolveBehavior::V2),
"3" => Ok(ResolveBehavior::V3),
s => anyhow::bail!(
"`resolver` setting `{}` is not valid, valid options are \"1\" or \"2\"",
s
Expand All @@ -129,6 +132,7 @@ impl ResolveBehavior {
match self {
ResolveBehavior::V1 => "1",
ResolveBehavior::V2 => "2",
ResolveBehavior::V3 => "3",
}
.to_owned()
}
Expand Down
13 changes: 12 additions & 1 deletion src/cargo/core/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,17 @@ impl<'gctx> Workspace<'gctx> {
MaybePackage::Virtual(vm) => vm.resolve_behavior().unwrap_or(ResolveBehavior::V1),
};

match self.resolve_behavior() {
ResolveBehavior::V1 | ResolveBehavior::V2 => {}
ResolveBehavior::V3 => {
if self.resolve_behavior == ResolveBehavior::V3 {
if !self.gctx().cli_unstable().msrv_policy {
anyhow::bail!("`resolver=\"3\"` requires `-Zmsrv-policy`");
}
self.resolve_honors_rust_version = true;
}
}
}
match self.gctx().get::<CargoResolverConfig>("resolver") {
Ok(CargoResolverConfig {
something_like_precedence: Some(precedence),
Expand Down Expand Up @@ -869,7 +880,7 @@ impl<'gctx> Workspace<'gctx> {
self.is_virtual()
|| match self.resolve_behavior() {
ResolveBehavior::V1 => false,
ResolveBehavior::V2 => true,
ResolveBehavior::V2 | ResolveBehavior::V3 => true,
}
}

Expand Down
15 changes: 14 additions & 1 deletion src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,12 @@ fn resolve_toml(
warnings: &mut Vec<String>,
_errors: &mut Vec<String>,
) -> CargoResult<manifest::TomlManifest> {
if let Some(workspace) = &original_toml.workspace {
if workspace.resolver.as_deref() == Some("3") {
features.require(Feature::edition2024())?;
}
}

let mut resolved_toml = manifest::TomlManifest {
cargo_features: original_toml.cargo_features.clone(),
package: None,
Expand Down Expand Up @@ -299,7 +305,8 @@ fn resolve_toml(
};

if let Some(original_package) = original_toml.package() {
let resolved_package = resolve_package_toml(original_package, package_root, &inherit)?;
let resolved_package =
resolve_package_toml(original_package, features, package_root, &inherit)?;
resolved_toml.package = Some(resolved_package);

resolved_toml.dependencies = resolve_dependencies(
Expand Down Expand Up @@ -399,6 +406,7 @@ fn resolve_toml(
#[tracing::instrument(skip_all)]
fn resolve_package_toml<'a>(
original_package: &manifest::TomlPackage,
features: &Features,
package_root: &Path,
inherit: &dyn Fn() -> CargoResult<&'a InheritableFields>,
) -> CargoResult<Box<manifest::TomlPackage>> {
Expand Down Expand Up @@ -526,6 +534,11 @@ fn resolve_package_toml<'a>(
metadata: original_package.metadata.clone(),
_invalid_cargo_features: Default::default(),
};

if resolved_package.resolver.as_deref() == Some("3") {
features.require(Feature::edition2024())?;
}

Ok(Box::new(resolved_package))
}

Expand Down
1 change: 1 addition & 0 deletions src/doc/src/reference/unstable.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ This was stabilized in 1.79 in [#13608](https://github.com/rust-lang/cargo/pull/

`-Zmsrv-policy` allows access to an MSRV-aware resolver which can be enabled with:
- `resolver.something-like-precedence` config field
- `workspace.resolver = "3"` / `package.resolver = "3"`

The resolver will prefer dependencies with a `package.rust-version` that is the same or older than your project's MSRV.
Your project's MSRV is determined by taking the lowest `package.rust-version` set among your workspace members.
Expand Down
127 changes: 127 additions & 0 deletions tests/testsuite/rust_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,133 @@ foo v0.0.1 ([CWD])
.run();
}

#[cargo_test(nightly, reason = "edition2024 in rustc is unstable")]
fn resolve_v3() {
Package::new("only-newer", "1.6.0")
.rust_version("1.65.0")
.file("src/lib.rs", "fn other_stuff() {}")
.publish();
Package::new("newer-and-older", "1.5.0")
.rust_version("1.55.0")
.file("src/lib.rs", "fn other_stuff() {}")
.publish();
Package::new("newer-and-older", "1.6.0")
.rust_version("1.65.0")
.file("src/lib.rs", "fn other_stuff() {}")
.publish();

let p = project()
.file(
"Cargo.toml",
r#"
cargo-features = ["edition2024"]
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
rust-version = "1.60.0"
resolver = "3"
[dependencies]
only-newer = "1.0.0"
newer-and-older = "1.0.0"
"#,
)
.file("src/main.rs", "fn main(){}")
.build();

// v3 should resolve for MSRV
p.cargo("generate-lockfile")
.arg("-Zmsrv-policy")
.masquerade_as_nightly_cargo(&["edition2024", "msrv-policy"])
.with_stderr(
"\
[UPDATING] `dummy-registry` index
[LOCKING] 3 packages to latest Rust 1.60.0 compatible versions
[ADDING] newer-and-older v1.5.0 (latest: v1.6.0)
",
)
.run();
p.cargo("tree")
.arg("-Zmsrv-policy")
.masquerade_as_nightly_cargo(&["edition2024", "msrv-policy"])
.with_stdout(
"\
foo v0.0.1 ([CWD])
├── newer-and-older v1.5.0
└── only-newer v1.6.0
",
)
.run();

// `--ignore-rust-version` has precedence over v3
p.cargo("generate-lockfile --ignore-rust-version")
.with_stderr(
"\
[UPDATING] `dummy-registry` index
[LOCKING] 3 packages to latest compatible versions
",
)
.arg("-Zmsrv-policy")
.masquerade_as_nightly_cargo(&["msrv-policy"])
.run();
p.cargo("tree")
.arg("-Zmsrv-policy")
.masquerade_as_nightly_cargo(&["edition2024", "msrv-policy"])
.with_stdout(
"\
foo v0.0.1 ([CWD])
├── newer-and-older v1.6.0
└── only-newer v1.6.0
",
)
.run();

// config has precedence over v3
p.cargo("generate-lockfile")
.env(
"CARGO_RESOLVER_SOMETHING_LIKE_PRECEDENCE",
"something-like-maximum",
)
.with_stderr(
"\
[UPDATING] `dummy-registry` index
[LOCKING] 3 packages to latest compatible versions
",
)
.arg("-Zmsrv-policy")
.masquerade_as_nightly_cargo(&["msrv-policy"])
.run();
p.cargo("tree")
.arg("-Zmsrv-policy")
.masquerade_as_nightly_cargo(&["edition2024", "msrv-policy"])
.with_stdout(
"\
foo v0.0.1 ([CWD])
├── newer-and-older v1.6.0
└── only-newer v1.6.0
",
)
.run();

// unstable
p.cargo("generate-lockfile")
.with_status(101)
.with_stderr(
"\
[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`
Caused by:
the cargo feature `edition2024` requires a nightly version of Cargo, but this is the `stable` channel
See https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels.
See https://doc.rust-lang.org/cargo/reference/unstable.html#edition-2024 for more information about using this feature.
",
)
.run();
}

#[cargo_test]
fn generate_lockfile_ignore_rust_version_is_unstable() {
Package::new("bar", "1.5.0")
Expand Down

0 comments on commit 72d51cc

Please sign in to comment.