Skip to content

Commit 0fcc90d

Browse files
committed
Auto merge of #12950 - epage:msrv, r=Eh2406
fix(resolver): Prefer MSRV, rather than ignore incompatible ### What does this PR try to resolve? This is another experiment for #9930. Comparing preferring over exclusively using MSRV compatible: Benefits - Better error messages - `--ignore-rust-version` is implicitly sticky Downsides - Can't backtrack for MSRV compatible version - Still requires workspace-wide MSRV (compared to our desired end state of declaring MSRV as yet another dependency) ### How should we test and review this PR? ### Additional information Note: `--ignore-rust-version` is not yet implemented for the resolver. This builds on #12930
2 parents 87ee3e9 + 0d29d3f commit 0fcc90d

File tree

4 files changed

+71
-37
lines changed

4 files changed

+71
-37
lines changed

src/cargo/core/resolver/version_prefs.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ impl VersionPreferences {
5858
///
5959
/// Sort order:
6060
/// 1. Preferred packages
61-
/// 2. `first_version`, falling back to [`VersionPreferences::version_ordering`] when `None`
61+
/// 2. [`VersionPreferences::max_rust_version`]
62+
/// 3. `first_version`, falling back to [`VersionPreferences::version_ordering`] when `None`
6263
///
6364
/// Filtering:
64-
/// - [`VersionPreferences::max_rust_version`]
6565
/// - `first_version`
6666
pub fn sort_summaries(
6767
&self,
@@ -76,9 +76,6 @@ impl VersionPreferences {
7676
.map(|deps| deps.iter().any(|d| d.matches_id(*pkg_id)))
7777
.unwrap_or(false)
7878
};
79-
if self.max_rust_version.is_some() {
80-
summaries.retain(|s| s.rust_version() <= self.max_rust_version.as_ref());
81-
}
8279
summaries.sort_unstable_by(|a, b| {
8380
let prefer_a = should_prefer(&a.package_id());
8481
let prefer_b = should_prefer(&b.package_id());
@@ -87,6 +84,15 @@ impl VersionPreferences {
8784
return previous_cmp;
8885
}
8986

87+
if self.max_rust_version.is_some() {
88+
let msrv_a = a.rust_version() <= self.max_rust_version.as_ref();
89+
let msrv_b = b.rust_version() <= self.max_rust_version.as_ref();
90+
let msrv_cmp = msrv_a.cmp(&msrv_b).reverse();
91+
if msrv_cmp != Ordering::Equal {
92+
return msrv_cmp;
93+
}
94+
}
95+
9096
let cmp = a.version().cmp(b.version());
9197
match first_version.unwrap_or(self.version_ordering) {
9298
VersionOrdering::MaximumVersionsFirst => cmp.reverse(),
@@ -236,14 +242,14 @@ mod test {
236242
vp.sort_summaries(&mut summaries, None);
237243
assert_eq!(
238244
describe(&summaries),
239-
"foo/1.2.3, foo/1.1.0, foo/1.0.9".to_string()
245+
"foo/1.2.3, foo/1.1.0, foo/1.0.9, foo/1.2.4".to_string()
240246
);
241247

242248
vp.version_ordering(VersionOrdering::MinimumVersionsFirst);
243249
vp.sort_summaries(&mut summaries, None);
244250
assert_eq!(
245251
describe(&summaries),
246-
"foo/1.0.9, foo/1.1.0, foo/1.2.3".to_string()
252+
"foo/1.0.9, foo/1.1.0, foo/1.2.3, foo/1.2.4".to_string()
247253
);
248254
}
249255
}

tests/testsuite/cargo_add/rust_version_ignore/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ fn case() {
2626
.current_dir(cwd)
2727
.masquerade_as_nightly_cargo(&["msrv-policy"])
2828
.assert()
29-
.code(101)
29+
.code(0)
3030
.stdout_matches_path(curr_dir!().join("stdout.log"))
3131
.stderr_matches_path(curr_dir!().join("stderr.log"));
3232

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,2 @@
11
Updating `dummy-registry` index
22
Adding rust-version-user v0.2.1 to dependencies.
3-
error: failed to select a version for the requirement `rust-version-user = "^0.2.1"`
4-
candidate versions found which didn't match: 0.2.1, 0.1.0
5-
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
6-
required by package `cargo-list-test-fixture v0.0.0 ([ROOT]/case)`
7-
perhaps a crate was updated and forgotten to be re-vendored?

tests/testsuite/rust_version.rs

Lines changed: 57 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -245,49 +245,81 @@ fn dependency_rust_version_newer_than_package() {
245245
.file("src/main.rs", "fn main(){}")
246246
.build();
247247

248+
p.cargo("check")
249+
.arg("-Zmsrv-policy")
250+
.masquerade_as_nightly_cargo(&["msrv-policy"])
251+
.run();
248252
p.cargo("check --ignore-rust-version")
249253
.arg("-Zmsrv-policy")
250254
.masquerade_as_nightly_cargo(&["msrv-policy"])
251-
// This shouldn't fail
252-
.with_status(101)
255+
.run();
256+
}
257+
258+
#[cargo_test]
259+
fn dependency_rust_version_older_and_newer_than_package() {
260+
Package::new("bar", "1.5.0")
261+
.rust_version("1.55.0")
262+
.file("src/lib.rs", "fn other_stuff() {}")
263+
.publish();
264+
Package::new("bar", "1.6.0")
265+
.rust_version("1.65.0")
266+
.file("src/lib.rs", "fn other_stuff() {}")
267+
.publish();
268+
269+
let p = project()
270+
.file(
271+
"Cargo.toml",
272+
r#"
273+
[package]
274+
name = "foo"
275+
version = "0.0.1"
276+
authors = []
277+
rust-version = "1.60.0"
278+
[dependencies]
279+
bar = "1.0.0"
280+
"#,
281+
)
282+
.file("src/main.rs", "fn main(){}")
283+
.build();
284+
285+
p.cargo("check --ignore-rust-version")
286+
.arg("-Zmsrv-policy")
287+
.masquerade_as_nightly_cargo(&["msrv-policy"])
288+
// This should pick 1.6.0
253289
.with_stderr(
254290
"\
255291
[UPDATING] `dummy-registry` index
256-
[ERROR] failed to select a version for the requirement `bar = \"^1.0.0\"`
257-
candidate versions found which didn't match: 1.6.0
258-
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
259-
required by package `foo v0.0.1 ([CWD])`
260-
perhaps a crate was updated and forgotten to be re-vendored?
292+
[DOWNLOADING] crates ...
293+
[DOWNLOADED] bar v1.5.0 (registry `dummy-registry`)
294+
[CHECKING] bar v1.5.0
295+
[CHECKING] [..]
296+
[FINISHED] [..]
261297
",
262298
)
263299
.run();
264300
p.cargo("check")
265301
.arg("-Zmsrv-policy")
266302
.masquerade_as_nightly_cargo(&["msrv-policy"])
267-
.with_status(101)
268-
// This should have a better error message
269303
.with_stderr(
270304
"\
271-
[UPDATING] `dummy-registry` index
272-
[ERROR] failed to select a version for the requirement `bar = \"^1.0.0\"`
273-
candidate versions found which didn't match: 1.6.0
274-
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
275-
required by package `foo v0.0.1 ([CWD])`
276-
perhaps a crate was updated and forgotten to be re-vendored?
305+
[FINISHED] [..]
277306
",
278307
)
279308
.run();
280309
}
281310

282311
#[cargo_test]
283-
fn dependency_rust_version_older_and_newer_than_package() {
284-
Package::new("bar", "1.5.0")
285-
.rust_version("1.55.0")
312+
fn dependency_rust_version_backtracking() {
313+
Package::new("has-rust-version", "1.6.0")
314+
.rust_version("1.65.0")
286315
.file("src/lib.rs", "fn other_stuff() {}")
287316
.publish();
288-
Package::new("bar", "1.6.0")
289-
.rust_version("1.65.0")
317+
Package::new("no-rust-version", "2.1.0")
318+
.file("src/lib.rs", "fn other_stuff() {}")
319+
.publish();
320+
Package::new("no-rust-version", "2.2.0")
290321
.file("src/lib.rs", "fn other_stuff() {}")
322+
.dep("has-rust-version", "1.6.0")
291323
.publish();
292324

293325
let p = project()
@@ -300,7 +332,7 @@ fn dependency_rust_version_older_and_newer_than_package() {
300332
authors = []
301333
rust-version = "1.60.0"
302334
[dependencies]
303-
bar = "1.0.0"
335+
no-rust-version = "2"
304336
"#,
305337
)
306338
.file("src/main.rs", "fn main(){}")
@@ -309,13 +341,14 @@ fn dependency_rust_version_older_and_newer_than_package() {
309341
p.cargo("check --ignore-rust-version")
310342
.arg("-Zmsrv-policy")
311343
.masquerade_as_nightly_cargo(&["msrv-policy"])
312-
// This should pick 1.6.0
313344
.with_stderr(
314345
"\
315346
[UPDATING] `dummy-registry` index
316347
[DOWNLOADING] crates ...
317-
[DOWNLOADED] bar v1.5.0 (registry `dummy-registry`)
318-
[CHECKING] bar v1.5.0
348+
[DOWNLOADED] no-rust-version v2.2.0 (registry `dummy-registry`)
349+
[DOWNLOADED] has-rust-version v1.6.0 (registry `dummy-registry`)
350+
[CHECKING] has-rust-version v1.6.0
351+
[CHECKING] no-rust-version v2.2.0
319352
[CHECKING] [..]
320353
[FINISHED] [..]
321354
",

0 commit comments

Comments
 (0)