better error messages
authorEh2406 <YeomanYaacov@gmail.com>
Wed, 7 Feb 2018 16:51:40 +0000 (11:51 -0500)
committerEh2406 <YeomanYaacov@gmail.com>
Fri, 9 Feb 2018 16:52:14 +0000 (11:52 -0500)
src/cargo/core/resolver/mod.rs
tests/build.rs
tests/directory.rs
tests/path.rs
tests/registry.rs
tests/resolve.rs

index fe23ce442292055a51fe9653b466d85ee52bcdf8..05fa4f5a0aaeaca6d8865e28d56e210a215085ab 100644 (file)
@@ -786,30 +786,28 @@ fn activation_error(cx: &Context,
                     prev_active: &[Summary],
                     candidates: &[Candidate],
                     config: Option<&Config>) -> CargoError {
+    let graph = cx.graph();
+    let describe_path = |pkgid: &PackageId| -> String {
+        use std::fmt::Write;
+        let dep_path = graph.path_to_top(pkgid);
+        let mut dep_path_desc = format!("package `{}`", dep_path[0]);
+        for dep in dep_path.iter().skip(1) {
+            write!(dep_path_desc,
+                   "\n    ... which is depended on by `{}`",
+                   dep).unwrap();
+        }
+        dep_path_desc
+    };
     if !candidates.is_empty() {
-        let mut msg = format!("failed to select a version for `{}` \
-                               (required by `{}`):\n\
+        let mut msg = format!("failed to select a version for `{0}`\n\
                                all possible versions conflict with \
-                               previously selected versions of `{}`",
-                              dep.name(), parent.name(),
+                               previously selected versions of `{0}`\n",
                               dep.name());
-        let graph = cx.graph();
-        'outer: for v in prev_active.iter() {
-            for node in graph.iter() {
-                let edges = match graph.edges(node) {
-                    Some(edges) => edges,
-                    None => continue,
-                };
-                for edge in edges {
-                    if edge != v.package_id() { continue }
-
-                    msg.push_str(&format!("\n  version {} in use by {}",
-                                          v.version(), edge));
-                    continue 'outer;
-                }
-            }
-            msg.push_str(&format!("\n  version {} in use by ??",
-                                  v.version()));
+        msg.push_str("required by ");
+        msg.push_str(&describe_path(parent.package_id()));
+        for v in prev_active.iter() {
+            msg.push_str("\n  previously selected ");
+            msg.push_str(&describe_path(v.package_id()));
         }
 
         msg.push_str(&format!("\n  possible versions to select: {}",
@@ -853,15 +851,15 @@ fn activation_error(cx: &Context,
             versions.join(", ")
         };
 
-        let mut msg = format!("no matching version `{}` found for package `{}` \
-                               (required by `{}`)\n\
+        let mut msg = format!("no matching version `{}` found for package `{}`\n\
                                location searched: {}\n\
-                               versions found: {}",
+                               versions found: {}\n",
                               dep.version_req(),
                               dep.name(),
-                              parent.name(),
                               dep.source_id(),
                               versions);
+        msg.push_str("required by ");
+        msg.push_str(&describe_path(parent.package_id()));
 
         // If we have a path dependency with a locked version, then this may
         // indicate that we updated a sub-package and forgot to run `cargo
@@ -874,13 +872,13 @@ fn activation_error(cx: &Context,
 
         msg
     } else {
-        format!("no matching package named `{}` found \
-                 (required by `{}`)\n\
-                 location searched: {}\n\
-                 version required: {}",
-                dep.name(), parent.name(),
-                dep.source_id(),
-                dep.version_req())
+        let mut msg = format!("no matching package named `{}` found\n\
+                 location searched: {}\n",
+                dep.name(), dep.source_id());
+        msg.push_str("required by ");
+        msg.push_str(&describe_path(parent.package_id()));
+
+        msg
     };
 
     if let Some(config) = config {
index 75aa8a2745efa5789c493232fa689beefa0af2f7..a39ea600505c23c51e882e373e7b94b8919d625d 100644 (file)
@@ -784,9 +784,9 @@ fn cargo_compile_with_dep_name_mismatch() {
 
     assert_that(p.cargo("build"),
                 execs().with_status(101).with_stderr(&format!(
-r#"[ERROR] no matching package named `notquitebar` found (required by `foo`)
+r#"error: no matching package named `notquitebar` found
 location searched: {proj_dir}/bar
-version required: *
+required by package `foo v0.0.1 ({proj_dir})`
 "#, proj_dir = p.url())));
 }
 
@@ -921,9 +921,9 @@ fn cargo_compile_offline_not_try_update() {
     assert_that(p.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
                 execs().with_status(101)
                     .with_stderr("\
-error: no matching package named `not_cached_dep` found (required by `bar`)
+error: no matching package named `not_cached_dep` found
 location searched: registry `[..]`
-version required: ^1.2.5
+required by package `bar v0.1.0 ([..])`
 As a reminder, you're using offline mode (-Z offline) \
 which can sometimes cause surprising resolution failures, \
 if this error is too confusing you may with to retry \
@@ -1026,10 +1026,16 @@ fn incompatible_dependencies() {
     assert_that(p.cargo("build"),
         execs().with_status(101)
             .with_stderr_contains("\
-error: failed to select a version for `bad` (required by `baz`):
+error: failed to select a version for `bad`
 all possible versions conflict with previously selected versions of `bad`
-  version 0.1.0 in use by bad v0.1.0
-  version 1.0.0 in use by bad v1.0.0
+required by package `baz v0.1.0`
+    ... which is depended on by `incompatible_dependencies v0.0.1 ([..])`
+  previously selected package `bad v0.1.0`
+    ... which is depended on by `foo v0.1.0`
+    ... which is depended on by `incompatible_dependencies v0.0.1 ([..])`
+  previously selected package `bad v1.0.0`
+    ... which is depended on by `bar v0.1.0`
+    ... which is depended on by `incompatible_dependencies v0.0.1 ([..])`
   possible versions to select: 1.0.2, 1.0.1"));
 }
 
@@ -1068,9 +1074,10 @@ fn compile_offline_while_transitive_dep_not_cached() {
     assert_that(p.cargo("build").masquerade_as_nightly_cargo().arg("-Zoffline"),
         execs().with_status(101)
             .with_stderr("\
-error: no matching package named `bar` found (required by `foo`)
+error: no matching package named `bar` found
 location searched: registry `[..]`
-version required: = 1.0.0
+required by package `foo v0.1.0`
+    ... which is depended on by `transitive_load_test v0.0.1 ([..]/transitive_load_test)`
 As a reminder, you're using offline mode (-Z offline) \
 which can sometimes cause surprising resolution failures, \
 if this error is too confusing you may with to retry \
@@ -1110,9 +1117,10 @@ fn compile_path_dep_then_change_version() {
 
     assert_that(p.cargo("build"),
                 execs().with_status(101).with_stderr("\
-[ERROR] no matching version `= 0.0.1` found for package `bar` (required by `foo`)
+error: no matching version `= 0.0.1` found for package `bar`
 location searched: [..]
 versions found: 0.0.2
+required by package `foo v0.0.1 ([..]/foo)`
 consider running `cargo update` to update a path dependency's locked version
 "));
 }
index 6dde10e97e8ba0d0ada08d77aae6fb0031d6414a..17c17c1437940175fa91fe86169a5952e27bac22 100644 (file)
@@ -195,9 +195,9 @@ fn simple_install_fail() {
 error: failed to compile `bar v0.1.0`, intermediate artifacts can be found at `[..]`
 
 Caused by:
-  no matching package named `baz` found (required by `bar`)
+  no matching package named `baz` found
 location searched: registry `https://github.com/rust-lang/crates.io-index`
-version required: ^9.8.7
+required by package `bar v0.1.0`
 "));
 }
 
@@ -276,9 +276,9 @@ fn not_there() {
 
     assert_that(p.cargo("build"),
                 execs().with_status(101).with_stderr("\
-error: no matching package named `foo` found (required by `bar`)
+error: no matching package named `foo` found
 location searched: [..]
-version required: ^0.1.0
+required by package `bar v0.1.0 ([..])`
 "));
 }
 
index 4936aee17ae85b544aa6d2a4847d7e2f6abbc94e..5a2ebab1920a4e933b33394985f5c4212b7d8fb5 100644 (file)
@@ -950,9 +950,9 @@ fn invalid_path_dep_in_workspace_with_lockfile() {
     assert_that(p.cargo("build"),
                 execs().with_status(101)
                        .with_stderr("\
-error: no matching package named `bar` found (required by `foo`)
+error: no matching package named `bar` found
 location searched: [..]
-version required: *
+required by package `foo v0.5.0 ([..])`
 "));
 }
 
index a5de44f53d52eca2dfdc6a17df618dff23b95a28..89c879a0004e39666d4e412e4c47d21ebc5cf7e8 100644 (file)
@@ -110,9 +110,9 @@ fn nonexistent() {
     assert_that(p.cargo("build"),
                 execs().with_status(101).with_stderr("\
 [UPDATING] registry [..]
-[ERROR] no matching package named `nonexistent` found (required by `foo`)
+error: no matching package named `nonexistent` found
 location searched: registry [..]
-version required: >= 0.0.0
+required by package `foo v0.0.1 ([..])`
 "));
 }
 
@@ -136,9 +136,10 @@ fn wrong_version() {
 
     assert_that(p.cargo("build"),
                 execs().with_status(101).with_stderr_contains("\
-[ERROR] no matching version `>= 1.0.0` found for package `foo` (required by `foo`)
+error: no matching version `>= 1.0.0` found for package `foo`
 location searched: registry [..]
 versions found: 0.0.2, 0.0.1
+required by package `foo v0.0.1 ([..])`
 "));
 
     Package::new("foo", "0.0.3").publish();
@@ -146,9 +147,10 @@ versions found: 0.0.2, 0.0.1
 
     assert_that(p.cargo("build"),
                 execs().with_status(101).with_stderr_contains("\
-[ERROR] no matching version `>= 1.0.0` found for package `foo` (required by `foo`)
+error: no matching version `>= 1.0.0` found for package `foo`
 location searched: registry [..]
 versions found: 0.0.4, 0.0.3, 0.0.2, ...
+required by package `foo v0.0.1 ([..])`
 "));
 }
 
@@ -204,9 +206,9 @@ fn update_registry() {
 
     assert_that(p.cargo("build"),
                 execs().with_status(101).with_stderr_contains("\
-[ERROR] no matching package named `notyet` found (required by `foo`)
-location searched: registry [..]
-version required: >= 0.0.0
+error: no matching package named `notyet` found
+location searched: registry `[..]`
+required by package `foo v0.0.1 ([..])`
 "));
 
     Package::new("notyet", "0.0.1").publish();
@@ -256,9 +258,9 @@ fn package_with_path_deps() {
 [ERROR] failed to verify package tarball
 
 Caused by:
-  no matching package named `notyet` found (required by `foo`)
+  no matching package named `notyet` found
 location searched: registry [..]
-version required: ^0.0.1
+required by package `foo v0.0.1 ([..])`
 "));
 
     Package::new("notyet", "0.0.1").publish();
@@ -401,9 +403,10 @@ fn relying_on_a_yank_is_bad() {
 
     assert_that(p.cargo("build"),
                 execs().with_status(101).with_stderr_contains("\
-[ERROR] no matching version `= 0.0.2` found for package `baz` (required by `bar`)
-location searched: registry [..]
+error: no matching version `= 0.0.2` found for package `baz`
+location searched: registry `[..]`
 versions found: 0.0.1
+required by package `bar v0.0.1`
 "));
 }
 
@@ -436,9 +439,9 @@ fn yanks_in_lockfiles_are_ok() {
 
     assert_that(p.cargo("update"),
                 execs().with_status(101).with_stderr_contains("\
-[ERROR] no matching package named `bar` found (required by `foo`)
+error: no matching package named `bar` found
 location searched: registry [..]
-version required: *
+required by package `foo v0.0.1 ([..])`
 "));
 }
 
index 6e43528fa3f680b91d3efc5e6540d9aa67b66d17..f2a6b6dfb8f58b5604d216b59d0da0b8e007e84e 100644 (file)
@@ -513,9 +513,9 @@ fn resolving_but_no_exists() {
     assert!(res.is_err());
 
     assert_eq!(res.err().unwrap().to_string(), "\
-no matching package named `foo` found (required by `root`)
-location searched: registry `http://example.com/`
-version required: ^1\
+no matching package named `foo` found\n\
+location searched: registry `http://example.com/`\n\
+required by package `root v1.0.0 (registry `http://example.com/`)`\
 ");
 }