Skip to content

Commit

Permalink
Use context to create a chain of errors
Browse files Browse the repository at this point in the history
There's an existing bug (#7782) in Cargo which exacerbates the issue
here but in general having a stack of errors is a bit easier to read and
work with than having a big long error message.
  • Loading branch information
alexcrichton committed Jan 9, 2020
1 parent d4ccae3 commit d7b45f9
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 39 deletions.
6 changes: 3 additions & 3 deletions src/cargo/util/config/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,9 +468,9 @@ impl<'de, 'config> de::MapAccess<'de> for ValueDeserializer<'config> {
// If this is the first time around we deserialize the `value` field
// which is the actual deserializer
if self.hits == 1 {
return seed.deserialize(self.de.clone()).map_err(|e| {
e.with_key_context(&self.de.key, self.definition.clone())
});
return seed
.deserialize(self.de.clone())
.map_err(|e| e.with_key_context(&self.de.key, self.definition.clone()));
}

// ... otherwise we're deserializing the `definition` field, so we need
Expand Down
3 changes: 2 additions & 1 deletion src/cargo/util/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1236,7 +1236,8 @@ impl ConfigError {

fn with_key_context(self, key: &ConfigKey, definition: Definition) -> ConfigError {
ConfigError {
error: anyhow!("could not load config key `{}`: {}", key, self),
error: anyhow::Error::from(self)
.context(format!("could not load config key `{}`", key)),
definition: Some(definition),
}
}
Expand Down
28 changes: 19 additions & 9 deletions tests/testsuite/bad_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,10 @@ fn bad_cargo_config_jobs() {
.with_stderr(
"\
[ERROR] error in [..].cargo/config: \
could not load config key `build.jobs`: \
invalid value: integer `-1`, expected u32
could not load config key `build.jobs`
Caused by:
invalid value: integer `-1`, expected u32
",
)
.run();
Expand Down Expand Up @@ -1102,8 +1104,12 @@ fn bad_source_config6() {
p.cargo("build")
.with_status(101)
.with_stderr(
"[ERROR] error in [..]/foo/.cargo/config: `source.crates-io.replace-with` \
expected a string, but found a array",
"\
[ERROR] error in [..]/foo/.cargo/config: could not load config key `source.crates-io.replace-with`
Caused by:
error in [..]/foo/.cargo/config: `source.crates-io.replace-with` expected a string, but found a array
"
)
.run();
}
Expand Down Expand Up @@ -1342,11 +1348,15 @@ fn bad_target_cfg() {
.with_stderr(
"\
[ERROR] error in [..]/foo/.cargo/config: \
could not load config key `target.cfg(not(target_os = \"none\")).runner`: \
error in [..]/foo/.cargo/config: \
could not load config key `target.cfg(not(target_os = \"none\")).runner`: \
failed to deserialize, expected a string or array of strings: \
data did not match any variant of untagged enum Target
could not load config key `target.cfg(not(target_os = \"none\")).runner`
Caused by:
error in [..]/foo/.cargo/config: \
could not load config key `target.cfg(not(target_os = \"none\")).runner`
Caused by:
failed to deserialize, expected a string or array of strings: \
data did not match any variant of untagged enum Target
",
)
.run();
Expand Down
71 changes: 45 additions & 26 deletions tests/testsuite/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,9 +495,11 @@ c = ['c']
let config = ConfigBuilder::new().env("CARGO_A", "x y").build();
assert_error(
config.get::<VSOB>("a").unwrap_err(),
"error in environment variable `CARGO_A`: \
could not load config key `a`: \
invalid type: string \"x y\", expected a boolean or vector of strings",
"\
error in environment variable `CARGO_A`: could not load config key `a`
Caused by:
invalid type: string \"x y\", expected a boolean or vector of strings",
);

// Normal env.
Expand Down Expand Up @@ -570,9 +572,11 @@ opt-level = 'foo'

assert_error(
config.get::<toml::TomlProfile>("profile.dev").unwrap_err(),
"error in [..]/.cargo/config: \
could not load config key `profile.dev.opt-level`: \
must be an integer, `z`, or `s`, but found: foo",
"\
error in [..]/.cargo/config: could not load config key `profile.dev.opt-level`
Caused by:
must be an integer, `z`, or `s`, but found: foo",
);

let config = ConfigBuilder::new()
Expand All @@ -581,9 +585,11 @@ opt-level = 'foo'

assert_error(
config.get::<toml::TomlProfile>("profile.dev").unwrap_err(),
"error in environment variable `CARGO_PROFILE_DEV_OPT_LEVEL`: \
could not load config key `profile.dev.opt-level`: \
must be an integer, `z`, or `s`, but found: asdf",
"\
error in environment variable `CARGO_PROFILE_DEV_OPT_LEVEL`: could not load config key `profile.dev.opt-level`
Caused by:
must be an integer, `z`, or `s`, but found: asdf",
);
}

Expand Down Expand Up @@ -653,8 +659,11 @@ big = 123456789
);
assert_error(
config.get::<u8>("S.big").unwrap_err(),
"error in [..].cargo/config: could not load config key `S.big`: \
invalid value: integer `123456789`, expected u8",
"\
error in [..].cargo/config: could not load config key `S.big`
Caused by:
invalid value: integer `123456789`, expected u8",
);

// Environment variable type errors.
Expand All @@ -664,9 +673,11 @@ big = 123456789
);
assert_error(
config.get::<i8>("e.big").unwrap_err(),
"error in environment variable `CARGO_E_BIG`: \
could not load config key `e.big`: \
invalid value: integer `123456789`, expected i8",
"\
error in environment variable `CARGO_E_BIG`: could not load config key `e.big`
Caused by:
invalid value: integer `123456789`, expected i8",
);

#[derive(Debug, Deserialize)]
Expand Down Expand Up @@ -952,27 +963,35 @@ i64max = 9223372036854775807

assert_error(
config.get::<u32>("nneg").unwrap_err(),
"error in [..].cargo/config: \
could not load config key `nneg`: \
invalid value: integer `-123456789`, expected u32",
"\
error in [..].cargo/config: could not load config key `nneg`
Caused by:
invalid value: integer `-123456789`, expected u32",
);
assert_error(
config.get::<u32>("eneg").unwrap_err(),
"error in environment variable `CARGO_ENEG`: \
could not load config key `eneg`: \
invalid value: integer `-1`, expected u32",
"\
error in environment variable `CARGO_ENEG`: could not load config key `eneg`
Caused by:
invalid value: integer `-1`, expected u32",
);
assert_error(
config.get::<i8>("npos").unwrap_err(),
"error in [..].cargo/config: \
could not load config key `npos`: \
invalid value: integer `123456789`, expected i8",
"\
error in [..].cargo/config: could not load config key `npos`
Caused by:
invalid value: integer `123456789`, expected i8",
);
assert_error(
config.get::<i8>("epos").unwrap_err(),
"error in environment variable `CARGO_EPOS`: \
could not load config key `epos`: \
invalid value: integer `123456789`, expected i8",
"\
error in environment variable `CARGO_EPOS`: could not load config key `epos`
Caused by:
invalid value: integer `123456789`, expected i8",
);
}

Expand Down

0 comments on commit d7b45f9

Please sign in to comment.