Skip to content

Commit aa4cab3

Browse files
committed
Auto merge of #6112 - alexcrichton:better-errors, r=Eh2406
Try to improve "version not found" error This commit tweaks the wording for when versions aren't found in a source, notably including more location information other than the source id but rather also taking into account replaced sources and such. It's hoped that this gives more information to make it a bit more clear what's going on. Closes #6111
2 parents cca192a + 20cfb41 commit aa4cab3

File tree

12 files changed

+145
-21
lines changed

12 files changed

+145
-21
lines changed

src/cargo/core/registry.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ pub trait Registry {
2121
self.query(dep, &mut |s| ret.push(s), fuzzy)?;
2222
Ok(ret)
2323
}
24+
25+
fn describe_source(&self, source: &SourceId) -> String;
26+
fn is_replaced(&self, source: &SourceId) -> bool;
2427
}
2528

2629
/// This structure represents a registry of known packages. It internally
@@ -528,6 +531,20 @@ impl<'cfg> Registry for PackageRegistry<'cfg> {
528531
f(self.lock(override_summary));
529532
Ok(())
530533
}
534+
535+
fn describe_source(&self, id: &SourceId) -> String {
536+
match self.sources.get(id) {
537+
Some(src) => src.describe(),
538+
None => id.to_string(),
539+
}
540+
}
541+
542+
fn is_replaced(&self, id: &SourceId) -> bool {
543+
match self.sources.get(id) {
544+
Some(src) => src.is_replaced(),
545+
None => false,
546+
}
547+
}
531548
}
532549

533550
fn lock(locked: &LockedMap, patches: &HashMap<Url, Vec<PackageId>>, summary: Summary) -> Summary {

src/cargo/core/resolver/mod.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -933,13 +933,13 @@ fn activation_error(
933933
};
934934

935935
let mut msg = format!(
936-
"no matching version `{}` found for package `{}`\n\
937-
location searched: {}\n\
938-
versions found: {}\n",
939-
dep.version_req(),
936+
"failed to select a version for the requirement `{} = \"{}\"`\n \
937+
candidate versions found which didn't match: {}\n \
938+
location searched: {}\n",
940939
dep.package_name(),
941-
dep.source_id(),
942-
versions
940+
dep.version_req(),
941+
versions,
942+
registry.describe_source(dep.source_id()),
943943
);
944944
msg.push_str("required by ");
945945
msg.push_str(&describe_path(&graph.path_to_top(parent.package_id())));
@@ -954,6 +954,10 @@ fn activation_error(
954954
);
955955
}
956956

957+
if registry.is_replaced(dep.source_id()) {
958+
msg.push_str("\nperhaps a crate was updated and forgotten to be re-vendored?");
959+
}
960+
957961
msg
958962
} else {
959963
// Maybe the user mistyped the name? Like `dep-thing` when `Dep_Thing`

src/cargo/core/source/mod.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,15 @@ pub trait Source {
7575
fn verify(&self, _pkg: &PackageId) -> CargoResult<()> {
7676
Ok(())
7777
}
78+
79+
/// Describes this source in a human readable fashion, used for display in
80+
/// resolver error messages currently.
81+
fn describe(&self) -> String;
82+
83+
/// Returns whether a source is being replaced by another here
84+
fn is_replaced(&self) -> bool {
85+
false
86+
}
7887
}
7988

8089
pub enum MaybePackage {
@@ -139,6 +148,14 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
139148
fn verify(&self, pkg: &PackageId) -> CargoResult<()> {
140149
(**self).verify(pkg)
141150
}
151+
152+
fn describe(&self) -> String {
153+
(**self).describe()
154+
}
155+
156+
fn is_replaced(&self) -> bool {
157+
(**self).is_replaced()
158+
}
142159
}
143160

144161
impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T {
@@ -185,6 +202,14 @@ impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T {
185202
fn verify(&self, pkg: &PackageId) -> CargoResult<()> {
186203
(**self).verify(pkg)
187204
}
205+
206+
fn describe(&self) -> String {
207+
(**self).describe()
208+
}
209+
210+
fn is_replaced(&self) -> bool {
211+
(**self).is_replaced()
212+
}
188213
}
189214

190215
/// A `HashMap` of `SourceId` -> `Box<Source>`

src/cargo/sources/directory.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,4 +212,8 @@ impl<'cfg> Source for DirectorySource<'cfg> {
212212

213213
Ok(())
214214
}
215+
216+
fn describe(&self) -> String {
217+
format!("directory source `{}`", self.root.display())
218+
}
215219
}

src/cargo/sources/git/source.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,10 @@ impl<'cfg> Source for GitSource<'cfg> {
229229
fn fingerprint(&self, _pkg: &Package) -> CargoResult<String> {
230230
Ok(self.rev.as_ref().unwrap().to_string())
231231
}
232+
233+
fn describe(&self) -> String {
234+
format!("git repository {}", self.source_id)
235+
}
232236
}
233237

234238
#[cfg(test)]

src/cargo/sources/path.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,4 +558,11 @@ impl<'cfg> Source for PathSource<'cfg> {
558558
let (max, max_path) = self.last_modified_file(pkg)?;
559559
Ok(format!("{} ({})", max, max_path.display()))
560560
}
561+
562+
fn describe(&self) -> String {
563+
match self.source_id.url().to_file_path() {
564+
Ok(path) => path.display().to_string(),
565+
Err(_) => self.source_id.to_string(),
566+
}
567+
}
561568
}

src/cargo/sources/registry/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,4 +585,8 @@ impl<'cfg> Source for RegistrySource<'cfg> {
585585
fn fingerprint(&self, pkg: &Package) -> CargoResult<String> {
586586
Ok(pkg.package_id().version().to_string())
587587
}
588+
589+
fn describe(&self) -> String {
590+
self.source_id.display_registry()
591+
}
588592
}

src/cargo/sources/replaced.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,12 @@ impl<'cfg> Source for ReplacedSource<'cfg> {
103103
let id = id.with_source_id(&self.replace_with);
104104
self.inner.verify(&id)
105105
}
106+
107+
fn describe(&self) -> String {
108+
format!("{} (which is replacing {})", self.inner.describe(), self.to_replace)
109+
}
110+
111+
fn is_replaced(&self) -> bool {
112+
true
113+
}
106114
}

tests/testsuite/directory.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,3 +683,45 @@ fn workspace_different_locations() {
683683
",
684684
).run();
685685
}
686+
687+
#[test]
688+
fn version_missing() {
689+
setup();
690+
691+
VendorPackage::new("foo")
692+
.file("src/lib.rs", "pub fn foo() {}")
693+
.build();
694+
695+
VendorPackage::new("bar")
696+
.file(
697+
"Cargo.toml",
698+
r#"
699+
[package]
700+
name = "bar"
701+
version = "0.1.0"
702+
authors = []
703+
704+
[dependencies]
705+
foo = "2"
706+
"#,
707+
)
708+
.file("src/main.rs", "fn main() {}")
709+
.build();
710+
711+
cargo_process("install bar")
712+
.with_stderr(
713+
"\
714+
[INSTALLING] bar v0.1.0
715+
error: failed to compile [..]
716+
717+
Caused by:
718+
failed to select a version for the requirement `foo = \"^2\"`
719+
candidate versions found which didn't match: 0.0.1
720+
location searched: directory source `[..] (which is replacing registry `[..]`)
721+
required by package `bar v0.1.0`
722+
perhaps a crate was updated and forgotten to be re-vendored?
723+
",
724+
)
725+
.with_status(101)
726+
.run();
727+
}

tests/testsuite/registry.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,9 @@ fn wrong_version() {
219219
.with_status(101)
220220
.with_stderr_contains(
221221
"\
222-
error: no matching version `>= 1.0.0` found for package `foo`
223-
location searched: registry [..]
224-
versions found: 0.0.2, 0.0.1
222+
error: failed to select a version for the requirement `foo = \">= 1.0.0\"`
223+
candidate versions found which didn't match: 0.0.2, 0.0.1
224+
location searched: `[..]` index (which is replacing registry `[..]`)
225225
required by package `foo v0.0.1 ([..])`
226226
",
227227
).run();
@@ -233,9 +233,9 @@ required by package `foo v0.0.1 ([..])`
233233
.with_status(101)
234234
.with_stderr_contains(
235235
"\
236-
error: no matching version `>= 1.0.0` found for package `foo`
237-
location searched: registry [..]
238-
versions found: 0.0.4, 0.0.3, 0.0.2, ...
236+
error: failed to select a version for the requirement `foo = \">= 1.0.0\"`
237+
candidate versions found which didn't match: 0.0.4, 0.0.3, 0.0.2, ...
238+
location searched: `[..]` index (which is replacing registry `[..]`)
239239
required by package `foo v0.0.1 ([..])`
240240
",
241241
).run();
@@ -520,10 +520,11 @@ fn relying_on_a_yank_is_bad() {
520520
.with_status(101)
521521
.with_stderr_contains(
522522
"\
523-
error: no matching version `= 0.0.2` found for package `baz`
524-
location searched: registry `[..]`
525-
versions found: 0.0.1
523+
error: failed to select a version for the requirement `baz = \"= 0.0.2\"`
524+
candidate versions found which didn't match: 0.0.1
525+
location searched: `[..]` index (which is replacing registry `[..]`)
526526
required by package `bar v0.0.1`
527+
... which is depended on by `foo [..]`
527528
",
528529
).run();
529530
}

tests/testsuite/resolve.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ use proptest::prelude::*;
1717

1818
proptest! {
1919
#![proptest_config(ProptestConfig {
20-
cases:
21-
if env::var("CI").is_ok() {
22-
256 // we have a lot of builds in CI so one or another of them will find problems
23-
} else {
24-
1024 // but locally try and find it in the one build
25-
},
20+
// Note that this is a little low in terms of cases we'd like to test,
21+
// but this number affects how long this function takes. It can be
22+
// increased locally to execute more tests and try to find more bugs,
23+
// but for now it's semi-low to run in a small-ish amount of time on CI
24+
// and locally.
25+
cases: 256,
2626
max_shrink_iters:
2727
if env::var("CI").is_ok() {
2828
// This attempts to make sure that CI will fail fast,

tests/testsuite/support/resolver.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ pub fn resolve_with_config(
4646
}
4747
Ok(())
4848
}
49+
50+
fn describe_source(&self, _src: &SourceId) -> String {
51+
String::new()
52+
}
53+
54+
fn is_replaced(&self, _src: &SourceId) -> bool {
55+
false
56+
}
4957
}
5058
let mut registry = MyRegistry(registry);
5159
let summary = Summary::new(

0 commit comments

Comments
 (0)