mirror of https://github.com/rust-lang/cargo
Auto merge of #13776 - epage:msrv-resolver, r=weihanglo
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
This commit is contained in:
commit
14b46ecc62
|
@ -196,7 +196,7 @@ impl FeatureOpts {
|
|||
}
|
||||
match ws.resolve_behavior() {
|
||||
ResolveBehavior::V1 => {}
|
||||
ResolveBehavior::V2 => {
|
||||
ResolveBehavior::V2 | ResolveBehavior::V3 => {
|
||||
enable(&vec!["all".to_string()]).unwrap();
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
|
|
@ -111,6 +111,8 @@ pub enum ResolveBehavior {
|
|||
V1,
|
||||
/// V2 adds the new feature resolver.
|
||||
V2,
|
||||
/// V3 changes version preferences
|
||||
V3,
|
||||
}
|
||||
|
||||
impl ResolveBehavior {
|
||||
|
@ -118,6 +120,7 @@ impl 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
|
||||
|
@ -129,6 +132,7 @@ impl ResolveBehavior {
|
|||
match self {
|
||||
ResolveBehavior::V1 => "1",
|
||||
ResolveBehavior::V2 => "2",
|
||||
ResolveBehavior::V3 => "3",
|
||||
}
|
||||
.to_owned()
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -266,6 +266,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,
|
||||
|
@ -300,7 +306,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)?;
|
||||
let edition = resolved_package
|
||||
.resolved_edition()
|
||||
.expect("previously resolved")
|
||||
|
@ -432,6 +439,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>> {
|
||||
|
@ -559,6 +567,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))
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue