fix(resolver): In errors, show rejected versions over alt versions

The user likely intended what they said and we should tell them why it
didn't work.
Rejected versions also imply alt versions below them.

Fixes #4260
This commit is contained in:
Ed Page 2024-12-11 13:08:42 -06:00
parent 784dfbe130
commit 28b5cb15ee
3 changed files with 50 additions and 53 deletions

View File

@ -221,7 +221,51 @@ pub(super) fn activation_error(
// give an error message that nothing was found.
let mut msg = String::new();
let mut hints = String::new();
if let Some(candidates) = alt_versions(registry, dep) {
if let Some(version_candidates) = rejected_versions(registry, dep) {
let version_candidates = match version_candidates {
Ok(c) => c,
Err(e) => return to_resolve_err(e),
};
let _ = writeln!(
&mut msg,
"no matching versions for `{}` found",
dep.package_name()
);
for candidate in version_candidates {
match candidate {
IndexSummary::Candidate(summary) => {
// HACK: If this was a real candidate, we wouldn't hit this case.
// so it must be a patch which get normalized to being a candidate
let _ = writeln!(&mut msg, " version {} is unavailable", summary.version());
}
IndexSummary::Yanked(summary) => {
let _ = writeln!(&mut msg, " version {} is yanked", summary.version());
}
IndexSummary::Offline(summary) => {
let _ = writeln!(&mut msg, " version {} is not cached", summary.version());
}
IndexSummary::Unsupported(summary, schema_version) => {
if let Some(rust_version) = summary.rust_version() {
// HACK: technically its unsupported and we shouldn't make assumptions
// about the entry but this is limited and for diagnostics purposes
let _ = writeln!(
&mut msg,
" version {} requires cargo {}",
summary.version(),
rust_version
);
} else {
let _ = writeln!(
&mut msg,
" version {} requires a Cargo version that supports index version {}",
summary.version(),
schema_version
);
}
}
}
}
} else if let Some(candidates) = alt_versions(registry, dep) {
let candidates = match candidates {
Ok(c) => c,
Err(e) => return to_resolve_err(e),
@ -286,50 +330,6 @@ pub(super) fn activation_error(
"\nperhaps a crate was updated and forgotten to be re-vendored?"
);
}
} else if let Some(version_candidates) = rejected_versions(registry, dep) {
let version_candidates = match version_candidates {
Ok(c) => c,
Err(e) => return to_resolve_err(e),
};
let _ = writeln!(
&mut msg,
"no matching versions for `{}` found",
dep.package_name()
);
for candidate in version_candidates {
match candidate {
IndexSummary::Candidate(summary) => {
// HACK: If this was a real candidate, we wouldn't hit this case.
// so it must be a patch which get normalized to being a candidate
let _ = writeln!(&mut msg, " version {} is unavailable", summary.version());
}
IndexSummary::Yanked(summary) => {
let _ = writeln!(&mut msg, " version {} is yanked", summary.version());
}
IndexSummary::Offline(summary) => {
let _ = writeln!(&mut msg, " version {} is not cached", summary.version());
}
IndexSummary::Unsupported(summary, schema_version) => {
if let Some(rust_version) = summary.rust_version() {
// HACK: technically its unsupported and we shouldn't make assumptions
// about the entry but this is limited and for diagnostics purposes
let _ = writeln!(
&mut msg,
" version {} requires cargo {}",
summary.version(),
rust_version
);
} else {
let _ = writeln!(
&mut msg,
" version {} requires a Cargo version that supports index version {}",
summary.version(),
schema_version
);
}
}
}
}
} else if let Some(name_candidates) = alt_names(registry, dep) {
let name_candidates = match name_candidates {
Ok(c) => c,

View File

@ -1752,10 +1752,9 @@ foo v0.1.0 ([ROOT]/foo)
.with_stderr_data(str![[r#"
[UPDATING] `dummy-registry` index
[ERROR] failed to select a version for the requirement `bar = "^1.0"` (locked to 1.0.1)
candidate versions found which didn't match: 1.0.0
version 1.0.1 requires a Cargo version that supports index version 3
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
required by package `foo v0.1.0 ([ROOT]/foo)`
perhaps a crate was updated and forgotten to be re-vendored?
"#]])
.run();

View File

@ -862,12 +862,11 @@ fn relying_on_a_yank_is_bad_http() {
let _server = setup_http();
relying_on_a_yank_is_bad(str![[r#"
[UPDATING] `dummy-registry` index
[ERROR] failed to select a version for the requirement `baz = "=0.0.2"`
candidate versions found which didn't match: 0.0.1
[ERROR] no matching versions for `baz` found
version 0.0.2 is yanked
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
required by package `bar v0.0.1`
... which satisfies dependency `bar = "*"` of package `foo v0.0.1 ([ROOT]/foo)`
perhaps a crate was updated and forgotten to be re-vendored?
"#]]);
}
@ -876,12 +875,11 @@ perhaps a crate was updated and forgotten to be re-vendored?
fn relying_on_a_yank_is_bad_git() {
relying_on_a_yank_is_bad(str![[r#"
[UPDATING] `dummy-registry` index
[ERROR] failed to select a version for the requirement `baz = "=0.0.2"`
candidate versions found which didn't match: 0.0.1
[ERROR] no matching versions for `baz` found
version 0.0.2 is yanked
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
required by package `bar v0.0.1`
... which satisfies dependency `bar = "*"` of package `foo v0.0.1 ([ROOT]/foo)`
perhaps a crate was updated and forgotten to be re-vendored?
"#]]);
}