Skip to content

Commit d2fcf6b

Browse files
committed
fix(resolver): Report unmatched versions, rather than saying no package
1 parent 015e980 commit d2fcf6b

File tree

7 files changed

+68
-10
lines changed

7 files changed

+68
-10
lines changed

crates/resolver-tests/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ pub fn resolve_with_global_context_raw(
143143
for summary in self.list.iter() {
144144
let matched = match kind {
145145
QueryKind::Exact => dep.matches(summary),
146+
QueryKind::AlternativeVersions => dep.matches(summary),
146147
QueryKind::AlternativeNames => true,
147148
QueryKind::Normalized => true,
148149
};

src/cargo/core/resolver/errors.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::task::Poll;
44

55
use crate::core::{Dependency, PackageId, Registry, Summary};
66
use crate::sources::source::QueryKind;
7+
use crate::sources::IndexSummary;
78
use crate::util::edit_distance::edit_distance;
89
use crate::util::{GlobalContext, OptVersionReq, VersionExt};
910
use anyhow::Error;
@@ -302,6 +303,19 @@ pub(super) fn activation_error(
302303

303304
msg
304305
} else {
306+
// Maybe something is wrong with the available versions
307+
let mut version_candidates = loop {
308+
match registry.query_vec(&new_dep, QueryKind::AlternativeVersions) {
309+
Poll::Ready(Ok(candidates)) => break candidates,
310+
Poll::Ready(Err(e)) => return to_resolve_err(e),
311+
Poll::Pending => match registry.block_until_ready() {
312+
Ok(()) => continue,
313+
Err(e) => return to_resolve_err(e),
314+
},
315+
}
316+
};
317+
version_candidates.sort_unstable_by_key(|a| a.as_summary().version().clone());
318+
305319
// Maybe the user mistyped the name? Like `dep-thing` when `Dep_Thing`
306320
// was meant. So we try asking the registry for a `fuzzy` search for suggestions.
307321
let name_candidates = loop {
@@ -327,7 +341,37 @@ pub(super) fn activation_error(
327341
name_candidates.sort_by_key(|o| o.0);
328342

329343
let mut msg = String::new();
330-
if !name_candidates.is_empty() {
344+
if !version_candidates.is_empty() {
345+
let _ = writeln!(
346+
&mut msg,
347+
"no matching versions for `{}` found",
348+
dep.package_name()
349+
);
350+
for candidate in version_candidates {
351+
match candidate {
352+
IndexSummary::Candidate(summary) => {
353+
// HACK: If this was a real candidate, we wouldn't hit this case.
354+
// so it must be a patch which get normalized to being a candidate
355+
let _ =
356+
writeln!(&mut msg, " version {} is unavailable", summary.version());
357+
}
358+
IndexSummary::Yanked(summary) => {
359+
let _ = writeln!(&mut msg, " version {} is yanked", summary.version());
360+
}
361+
IndexSummary::Offline(summary) => {
362+
let _ = writeln!(&mut msg, " version {} is not cached", summary.version());
363+
}
364+
IndexSummary::Unsupported(summary, schema_version) => {
365+
let _ = writeln!(
366+
&mut msg,
367+
" version {} requires a Cargo version that supports index version {}",
368+
summary.version(),
369+
schema_version
370+
);
371+
}
372+
}
373+
}
374+
} else if !name_candidates.is_empty() {
331375
let _ = writeln!(&mut msg, "no matching package found",);
332376
let _ = writeln!(&mut msg, "searched package name: `{}`", dep.package_name());
333377
let mut names = name_candidates

src/cargo/sources/directory.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ impl<'gctx> Source for DirectorySource<'gctx> {
108108
}
109109
let packages = self.packages.values().map(|p| &p.0);
110110
let matches = packages.filter(|pkg| match kind {
111-
QueryKind::Exact => dep.matches(pkg.summary()),
111+
QueryKind::Exact | QueryKind::AlternativeVersions => dep.matches(pkg.summary()),
112112
QueryKind::AlternativeNames => true,
113113
QueryKind::Normalized => dep.matches(pkg.summary()),
114114
});

src/cargo/sources/path.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ impl<'gctx> Source for PathSource<'gctx> {
145145
self.load()?;
146146
if let Some(s) = self.package.as_ref().map(|p| p.summary()) {
147147
let matched = match kind {
148-
QueryKind::Exact => dep.matches(s),
148+
QueryKind::Exact | QueryKind::AlternativeVersions => dep.matches(s),
149149
QueryKind::AlternativeNames => true,
150150
QueryKind::Normalized => dep.matches(s),
151151
};
@@ -332,7 +332,7 @@ impl<'gctx> Source for RecursivePathSource<'gctx> {
332332
.map(|p| p.summary())
333333
{
334334
let matched = match kind {
335-
QueryKind::Exact => dep.matches(s),
335+
QueryKind::Exact | QueryKind::AlternativeVersions => dep.matches(s),
336336
QueryKind::AlternativeNames => true,
337337
QueryKind::Normalized => dep.matches(s),
338338
};

src/cargo/sources/registry/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,7 @@ impl<'gctx> Source for RegistrySource<'gctx> {
799799
.index
800800
.query_inner(dep.package_name(), &req, &mut *self.ops, &mut |s| {
801801
let matched = match kind {
802-
QueryKind::Exact => {
802+
QueryKind::Exact | QueryKind::AlternativeVersions => {
803803
if req.is_precise() && self.gctx.cli_unstable().unstable_options {
804804
dep.matches_prerelease(s.as_summary())
805805
} else {
@@ -816,6 +816,7 @@ impl<'gctx> Source for RegistrySource<'gctx> {
816816
// leak through if they're in a whitelist (aka if they were
817817
// previously in `Cargo.lock`
818818
match s {
819+
s @ _ if kind == QueryKind::AlternativeVersions => callback(s),
819820
s @ IndexSummary::Candidate(_) => callback(s),
820821
s @ IndexSummary::Yanked(_) => {
821822
if self.yanked_whitelist.contains(&s.package_id()) {

src/cargo/sources/source.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,13 @@ pub enum QueryKind {
183183
/// Each source gets to define what `close` means for it.
184184
///
185185
/// Path/Git sources may return all dependencies that are at that URI,
186+
/// whereas an `Registry` source may return dependencies that are yanked or invalid.
187+
AlternativeVersions,
188+
/// A query for packages close to the given dependency requirement.
189+
///
190+
/// Each source gets to define what `close` means for it.
191+
///
192+
/// Path/Git sources may return all dependencies that are at that URI,
186193
/// whereas an `Registry` source may return dependencies that have the same
187194
/// canonicalization.
188195
AlternativeNames,

tests/testsuite/registry.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -924,7 +924,8 @@ fn yanks_in_lockfiles_are_ok_http() {
924924
"#]],
925925
str![[r#"
926926
[UPDATING] `dummy-registry` index
927-
[ERROR] no matching package named `bar` found
927+
[ERROR] no matching versions for `bar` found
928+
version 0.0.1 is yanked
928929
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
929930
required by package `foo v0.0.1 ([ROOT]/foo)`
930931
@@ -941,7 +942,8 @@ fn yanks_in_lockfiles_are_ok_git() {
941942
"#]],
942943
str![[r#"
943944
[UPDATING] `dummy-registry` index
944-
[ERROR] no matching package named `bar` found
945+
[ERROR] no matching versions for `bar` found
946+
version 0.0.1 is yanked
945947
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
946948
required by package `foo v0.0.1 ([ROOT]/foo)`
947949
@@ -993,7 +995,8 @@ fn yanks_in_lockfiles_are_ok_for_other_update_http() {
993995
"#]],
994996
str![[r#"
995997
[UPDATING] `dummy-registry` index
996-
[ERROR] no matching package named `bar` found
998+
[ERROR] no matching versions for `bar` found
999+
version 0.0.1 is yanked
9971000
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
9981001
required by package `foo v0.0.1 ([ROOT]/foo)`
9991002
@@ -1016,7 +1019,8 @@ fn yanks_in_lockfiles_are_ok_for_other_update_git() {
10161019
"#]],
10171020
str![[r#"
10181021
[UPDATING] `dummy-registry` index
1019-
[ERROR] no matching package named `bar` found
1022+
[ERROR] no matching versions for `bar` found
1023+
version 0.0.1 is yanked
10201024
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
10211025
required by package `foo v0.0.1 ([ROOT]/foo)`
10221026
@@ -3225,7 +3229,8 @@ fn unknown_index_version_error() {
32253229
.with_status(101)
32263230
.with_stderr_data(str![[r#"
32273231
[UPDATING] `dummy-registry` index
3228-
[ERROR] no matching package named `bar` found
3232+
[ERROR] no matching versions for `bar` found
3233+
version 1.0.1 requires a Cargo version that supports index version 4294967295
32293234
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
32303235
required by package `foo v0.1.0 ([ROOT]/foo)`
32313236

0 commit comments

Comments
 (0)