From 3a18c89a55cbe249e69042b0f51d329726a16d15 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 7 Jan 2020 14:30:15 -0800 Subject: [PATCH 1/2] Migrate from the `failure` crate to `anyhow` The `anyhow` crate interoperates with the `std::error::Error` trait rather than a custom `Fail` trait, and this is the general trend of error handling in Rust as well. Note that this is mostly mechanical (sed) and intended to get the test suite passing. As usual there's still more idiomatic cleanup that can happen, but that's left to later commits. --- Cargo.toml | 4 +- crates/cargo-test-support/src/lib.rs | 6 +- crates/crates-io/Cargo.toml | 2 +- crates/crates-io/lib.rs | 4 +- src/bin/cargo/commands/bench.rs | 2 +- src/bin/cargo/commands/check.rs | 2 +- src/bin/cargo/commands/clippy.rs | 2 +- src/bin/cargo/commands/fix.rs | 4 +- src/bin/cargo/commands/locate_project.rs | 2 +- src/bin/cargo/commands/rustc.rs | 2 +- src/bin/cargo/commands/test.rs | 12 +-- src/bin/cargo/commands/vendor.rs | 2 +- src/bin/cargo/main.rs | 2 +- src/cargo/core/compiler/build_config.rs | 2 +- .../compiler/build_context/target_info.rs | 6 +- src/cargo/core/compiler/build_plan.rs | 6 +- src/cargo/core/compiler/compilation.rs | 2 +- src/cargo/core/compiler/compile_kind.rs | 6 +- .../compiler/context/compilation_files.rs | 4 +- src/cargo/core/compiler/custom_build.rs | 8 +- src/cargo/core/compiler/fingerprint.rs | 8 +- src/cargo/core/compiler/job_queue.rs | 4 +- src/cargo/core/compiler/links.rs | 2 +- src/cargo/core/compiler/mod.rs | 2 +- src/cargo/core/compiler/standard_lib.rs | 4 +- src/cargo/core/features.rs | 2 +- src/cargo/core/manifest.rs | 2 +- src/cargo/core/package.rs | 8 +- src/cargo/core/package_id_spec.rs | 12 +-- src/cargo/core/profiles.rs | 16 +-- src/cargo/core/registry.rs | 22 ++--- src/cargo/core/resolver/context.rs | 2 +- src/cargo/core/resolver/dep_cache.rs | 14 +-- src/cargo/core/resolver/encode.rs | 6 +- src/cargo/core/resolver/errors.rs | 18 ++-- src/cargo/core/resolver/mod.rs | 4 +- src/cargo/core/resolver/resolve.rs | 8 +- src/cargo/core/shell.rs | 2 +- src/cargo/core/source/source_id.rs | 7 +- src/cargo/core/summary.rs | 22 ++--- src/cargo/core/workspace.rs | 28 +++--- src/cargo/lib.rs | 36 ++----- src/cargo/ops/cargo_clean.rs | 4 +- src/cargo/ops/cargo_compile.rs | 25 +++-- src/cargo/ops/cargo_doc.rs | 8 +- src/cargo/ops/cargo_generate_lockfile.rs | 6 +- src/cargo/ops/cargo_install.rs | 2 +- src/cargo/ops/cargo_new.rs | 40 ++++---- src/cargo/ops/cargo_output_metadata.rs | 2 +- src/cargo/ops/cargo_package.rs | 16 +-- src/cargo/ops/cargo_pkgid.rs | 2 +- src/cargo/ops/cargo_read_manifest.rs | 10 +- src/cargo/ops/cargo_run.rs | 8 +- src/cargo/ops/cargo_uninstall.rs | 2 +- .../ops/common_for_install_and_uninstall.rs | 2 +- src/cargo/ops/fix.rs | 12 +-- src/cargo/ops/lockfile.rs | 4 +- src/cargo/ops/registry.rs | 4 +- src/cargo/ops/resolve.rs | 4 +- src/cargo/ops/vendor.rs | 2 +- src/cargo/sources/config.rs | 2 +- src/cargo/sources/directory.rs | 6 +- src/cargo/sources/git/source.rs | 2 +- src/cargo/sources/git/utils.rs | 10 +- src/cargo/sources/path.rs | 2 +- src/cargo/sources/registry/index.rs | 8 +- src/cargo/sources/registry/local.rs | 6 +- src/cargo/sources/registry/mod.rs | 2 +- src/cargo/sources/registry/remote.rs | 4 +- src/cargo/util/canonical_url.rs | 2 +- src/cargo/util/command_prelude.rs | 12 +-- src/cargo/util/config/de.rs | 2 +- src/cargo/util/config/mod.rs | 48 ++++----- src/cargo/util/config/target.rs | 2 +- src/cargo/util/diagnostic_server.rs | 4 +- src/cargo/util/errors.rs | 97 +++++++++++-------- src/cargo/util/flock.rs | 4 +- src/cargo/util/important_paths.rs | 4 +- src/cargo/util/into_url.rs | 4 +- src/cargo/util/into_url_with_base.rs | 4 +- src/cargo/util/lockserver.rs | 12 +-- src/cargo/util/mod.rs | 2 +- src/cargo/util/network.rs | 12 +-- src/cargo/util/paths.rs | 16 +-- src/cargo/util/process_builder.rs | 19 ++-- src/cargo/util/rustc.rs | 4 +- src/cargo/util/to_semver.rs | 2 +- src/cargo/util/toml/mod.rs | 16 +-- src/cargo/util/toml/targets.rs | 24 ++--- src/cargo/util/workspace.rs | 4 +- tests/testsuite/config.rs | 19 +++- tests/testsuite/config_cli.rs | 22 +++-- tests/testsuite/config_include.rs | 18 +++- tests/testsuite/workspaces.rs | 6 +- 94 files changed, 427 insertions(+), 436 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2154dbd03a9..679f2bff65d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ curl = { version = "0.4.23", features = ["http2"] } curl-sys = "0.4.22" env_logger = "0.7.0" pretty_env_logger = { version = "0.3", optional = true } -failure = "0.1.5" +anyhow = "1.0" filetime = "0.2" flate2 = { version = "1.0.3", features = ["zlib"] } fs2 = "0.4" @@ -51,7 +51,7 @@ num_cpus = "1.0" opener = "0.4" percent-encoding = "2.0" remove_dir_all = "0.5.2" -rustfix = "0.4.6" +rustfix = "0.5.0" same-file = "1" semver = { version = "0.9.0", features = ["serde"] } serde = { version = "1.0.82", features = ["derive"] } diff --git a/crates/cargo-test-support/src/lib.rs b/crates/cargo-test-support/src/lib.rs index d18fa5ddaa3..3c4473bc7b8 100644 --- a/crates/cargo-test-support/src/lib.rs +++ b/crates/cargo-test-support/src/lib.rs @@ -916,11 +916,7 @@ impl Execs { { return self.match_output(out); } - let mut s = format!("could not exec process {}: {}", process, e); - for cause in e.iter_causes() { - s.push_str(&format!("\ncaused by: {}", cause)); - } - Err(s) + Err(format!("could not exec process {}: {:?}", process, e)) } } } diff --git a/crates/crates-io/Cargo.toml b/crates/crates-io/Cargo.toml index acb8151e63c..b9524a3d517 100644 --- a/crates/crates-io/Cargo.toml +++ b/crates/crates-io/Cargo.toml @@ -15,7 +15,7 @@ path = "lib.rs" [dependencies] curl = "0.4" -failure = "0.1.1" +anyhow = "1.0.0" percent-encoding = "2.0" serde = { version = "1.0", features = ['derive'] } serde_derive = "1.0" diff --git a/crates/crates-io/lib.rs b/crates/crates-io/lib.rs index ed7af44fabf..d0f59c96cd1 100644 --- a/crates/crates-io/lib.rs +++ b/crates/crates-io/lib.rs @@ -8,14 +8,12 @@ use std::io::Cursor; use std::time::Instant; use curl::easy::{Easy, List}; -use failure::bail; +use anyhow::{bail, Result}; use percent_encoding::{percent_encode, NON_ALPHANUMERIC}; use serde::{Deserialize, Serialize}; use serde_json; use url::Url; -pub type Result = std::result::Result; - pub struct Registry { /// The base URL for issuing API requests. host: String, diff --git a/src/bin/cargo/commands/bench.rs b/src/bin/cargo/commands/bench.rs index 036f1a457f1..306d9cd793b 100644 --- a/src/bin/cargo/commands/bench.rs +++ b/src/bin/cargo/commands/bench.rs @@ -100,7 +100,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { match err { None => Ok(()), Some(err) => Err(match err.exit.as_ref().and_then(|e| e.code()) { - Some(i) => CliError::new(failure::format_err!("bench failed"), i), + Some(i) => CliError::new(anyhow::format_err!("bench failed"), i), None => CliError::new(err.into(), 101), }), } diff --git a/src/bin/cargo/commands/check.rs b/src/bin/cargo/commands/check.rs index d93fe19fbc4..880b0d91d1a 100644 --- a/src/bin/cargo/commands/check.rs +++ b/src/bin/cargo/commands/check.rs @@ -60,7 +60,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { Some("test") => true, None => false, Some(profile) => { - let err = failure::format_err!( + let err = anyhow::format_err!( "unknown profile: `{}`, only `test` is \ currently supported", profile diff --git a/src/bin/cargo/commands/clippy.rs b/src/bin/cargo/commands/clippy.rs index a27b3f7e857..d395a9d1c90 100644 --- a/src/bin/cargo/commands/clippy.rs +++ b/src/bin/cargo/commands/clippy.rs @@ -66,7 +66,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { args.compile_options(config, mode, Some(&ws), ProfileChecking::Checked)?; if !config.cli_unstable().unstable_options { - return Err(failure::format_err!( + return Err(anyhow::format_err!( "`clippy-preview` is unstable, pass `-Z unstable-options` to enable it" ) .into()); diff --git a/src/bin/cargo/commands/fix.rs b/src/bin/cargo/commands/fix.rs index 9f78319d387..7bd7079e194 100644 --- a/src/bin/cargo/commands/fix.rs +++ b/src/bin/cargo/commands/fix.rs @@ -120,7 +120,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { Some("test") => true, None => false, Some(profile) => { - let err = failure::format_err!( + let err = anyhow::format_err!( "unknown profile: `{}`, only `test` is \ currently supported", profile @@ -143,7 +143,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { .filter(|_| use_clippy); if use_clippy && !config.cli_unstable().unstable_options { - return Err(failure::format_err!( + return Err(anyhow::format_err!( "`cargo fix --clippy` is unstable, pass `-Z unstable-options` to enable it" ) .into()); diff --git a/src/bin/cargo/commands/locate_project.rs b/src/bin/cargo/commands/locate_project.rs index a48e387b411..df0c424aa4a 100644 --- a/src/bin/cargo/commands/locate_project.rs +++ b/src/bin/cargo/commands/locate_project.rs @@ -21,7 +21,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { let root = root .to_str() .ok_or_else(|| { - failure::format_err!( + anyhow::format_err!( "your package path contains characters \ not representable in Unicode" ) diff --git a/src/bin/cargo/commands/rustc.rs b/src/bin/cargo/commands/rustc.rs index b2121caf869..82fdcfd44e4 100644 --- a/src/bin/cargo/commands/rustc.rs +++ b/src/bin/cargo/commands/rustc.rs @@ -55,7 +55,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { Some("bench") => CompileMode::Bench, Some("check") => CompileMode::Check { test: false }, Some(mode) => { - let err = failure::format_err!( + let err = anyhow::format_err!( "unknown profile: `{}`, use dev, test, or bench", mode diff --git a/src/bin/cargo/commands/test.rs b/src/bin/cargo/commands/test.rs index 7972aaa46ec..d0e879c1c0b 100644 --- a/src/bin/cargo/commands/test.rs +++ b/src/bin/cargo/commands/test.rs @@ -1,7 +1,7 @@ use crate::command_prelude::*; +use anyhow::Error; use cargo::ops::{self, CompileFilter, FilterRule, LibRule}; use cargo::util::errors; -use failure::Fail; pub fn cli() -> App { subcommand("test") @@ -126,13 +126,13 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { if doc { if let CompileFilter::Only { .. } = compile_opts.filter { return Err(CliError::new( - failure::format_err!("Can't mix --doc with other target selecting options"), + anyhow::format_err!("Can't mix --doc with other target selecting options"), 101, )); } if no_run { return Err(CliError::new( - failure::format_err!("Can't skip running doc tests with --no-run"), + anyhow::format_err!("Can't skip running doc tests with --no-run"), 101, )); } @@ -166,12 +166,12 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { match err { None => Ok(()), Some(err) => { - let context = failure::format_err!("{}", err.hint(&ws, &ops.compile_opts)); + let context = anyhow::format_err!("{}", err.hint(&ws, &ops.compile_opts)); let e = match err.exit.as_ref().and_then(|e| e.code()) { // Don't show "process didn't exit successfully" for simple errors. Some(i) if errors::is_simple_exit_code(i) => CliError::new(context, i), - Some(i) => CliError::new(err.context(context).into(), i), - None => CliError::new(err.context(context).into(), 101), + Some(i) => CliError::new(Error::from(err).context(context), i), + None => CliError::new(Error::from(err).context(context), 101), }; Err(e) } diff --git a/src/bin/cargo/commands/vendor.rs b/src/bin/cargo/commands/vendor.rs index 315c269e6c6..176d3abd825 100644 --- a/src/bin/cargo/commands/vendor.rs +++ b/src/bin/cargo/commands/vendor.rs @@ -90,7 +90,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { None }; if let Some(flag) = crates_io_cargo_vendor_flag { - return Err(failure::format_err!( + return Err(anyhow::format_err!( "\ the crates.io `cargo vendor` command has now been merged into Cargo itself and does not support the flag `{}` currently; to continue using the flag you diff --git a/src/bin/cargo/main.rs b/src/bin/cargo/main.rs index 7966a9ebb28..66e4a67bbfe 100644 --- a/src/bin/cargo/main.rs +++ b/src/bin/cargo/main.rs @@ -133,7 +133,7 @@ fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> Cli let aliases = list_aliases(config); let suggestions = commands.iter().chain(aliases.iter()); let did_you_mean = closest_msg(cmd, suggestions, |c| c); - let err = failure::format_err!("no such subcommand: `{}`{}", cmd, did_you_mean); + let err = anyhow::format_err!("no such subcommand: `{}`{}", cmd, did_you_mean); return Err(CliError::new(err, 101)); } }; diff --git a/src/cargo/core/compiler/build_config.rs b/src/cargo/core/compiler/build_config.rs index 9824c9fc2a2..2fe68bda426 100644 --- a/src/cargo/core/compiler/build_config.rs +++ b/src/cargo/core/compiler/build_config.rs @@ -78,7 +78,7 @@ impl BuildConfig { }; if jobs == Some(0) { - failure::bail!("jobs must be at least 1") + anyhow::bail!("jobs must be at least 1") } if jobs.is_some() && config.jobserver_from_env().is_some() { config.shell().warn( diff --git a/src/cargo/core/compiler/build_context/target_info.rs b/src/cargo/core/compiler/build_context/target_info.rs index 6e2822ae4b2..c3407e9d6fa 100644 --- a/src/cargo/core/compiler/build_context/target_info.rs +++ b/src/cargo/core/compiler/build_context/target_info.rs @@ -137,7 +137,7 @@ impl TargetInfo { let line = match lines.next() { Some(line) => line, - None => failure::bail!( + None => anyhow::bail!( "output of --print=sysroot missing when learning about \ target-specific information from rustc\n{}", output_err_info(&process, &output, &error) @@ -329,7 +329,7 @@ fn parse_crate_type( } let line = match lines.next() { Some(line) => line, - None => failure::bail!( + None => anyhow::bail!( "malformed output when learning about crate-type {} information\n{}", crate_type, output_err_info(cmd, output, error) @@ -339,7 +339,7 @@ fn parse_crate_type( let prefix = parts.next().unwrap(); let suffix = match parts.next() { Some(part) => part, - None => failure::bail!( + None => anyhow::bail!( "output of --print=file-names has changed in the compiler, cannot parse\n{}", output_err_info(cmd, output, error) ), diff --git a/src/cargo/core/compiler/build_plan.rs b/src/cargo/core/compiler/build_plan.rs index 69e61970d79..48072ba7aeb 100644 --- a/src/cargo/core/compiler/build_plan.rs +++ b/src/cargo/core/compiler/build_plan.rs @@ -74,13 +74,13 @@ impl Invocation { self.program = cmd .get_program() .to_str() - .ok_or_else(|| failure::format_err!("unicode program string required"))? + .ok_or_else(|| anyhow::format_err!("unicode program string required"))? .to_string(); self.cwd = Some(cmd.get_cwd().unwrap().to_path_buf()); for arg in cmd.get_args().iter() { self.args.push( arg.to_str() - .ok_or_else(|| failure::format_err!("unicode argument string required"))? + .ok_or_else(|| anyhow::format_err!("unicode argument string required"))? .to_string(), ); } @@ -93,7 +93,7 @@ impl Invocation { var.clone(), value .to_str() - .ok_or_else(|| failure::format_err!("unicode environment value required"))? + .ok_or_else(|| anyhow::format_err!("unicode environment value required"))? .to_string(), ); } diff --git a/src/cargo/core/compiler/compilation.rs b/src/cargo/core/compiler/compilation.rs index 0fb5419a19c..0fa25ab5856 100644 --- a/src/cargo/core/compiler/compilation.rs +++ b/src/cargo/core/compiler/compilation.rs @@ -304,7 +304,7 @@ fn target_runner( .filter(|(key, _runner)| CfgExpr::matches_key(key, target_cfg)); let matching_runner = cfgs.next(); if let Some((key, runner)) = cfgs.next() { - failure::bail!( + anyhow::bail!( "several matching instances of `target.'cfg(..)'.runner` in `.cargo/config`\n\ first match `{}` located in {}\n\ second match `{}` located in {}", diff --git a/src/cargo/core/compiler/compile_kind.rs b/src/cargo/core/compiler/compile_kind.rs index dbfdbbdef67..551f01c1109 100644 --- a/src/cargo/core/compiler/compile_kind.rs +++ b/src/cargo/core/compiler/compile_kind.rs @@ -77,7 +77,7 @@ impl CompileTarget { pub fn new(name: &str) -> CargoResult { let name = name.trim(); if name.is_empty() { - failure::bail!("target was empty"); + anyhow::bail!("target was empty"); } if !name.ends_with(".json") { return Ok(CompileTarget { name: name.into() }); @@ -88,12 +88,12 @@ impl CompileTarget { // with different paths always produce the same result. let path = Path::new(name) .canonicalize() - .chain_err(|| failure::format_err!("target path {:?} is not a valid file", name))?; + .chain_err(|| anyhow::format_err!("target path {:?} is not a valid file", name))?; let name = path .into_os_string() .into_string() - .map_err(|_| failure::format_err!("target path is not valid unicode"))?; + .map_err(|_| anyhow::format_err!("target path is not valid unicode"))?; Ok(CompileTarget { name: name.into() }) } diff --git a/src/cargo/core/compiler/context/compilation_files.rs b/src/cargo/core/compiler/context/compilation_files.rs index 37dfa67210d..e3971b44c48 100644 --- a/src/cargo/core/compiler/context/compilation_files.rs +++ b/src/cargo/core/compiler/context/compilation_files.rs @@ -431,7 +431,7 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { } if ret.is_empty() { if !unsupported.is_empty() { - failure::bail!( + anyhow::bail!( "cannot produce {} for `{}` as the target `{}` \ does not support these crate types", unsupported.join(", "), @@ -439,7 +439,7 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { unit.kind.short_name(bcx), ) } - failure::bail!( + anyhow::bail!( "cannot compile `{}` as the target `{}` does not \ support any of the output crate types", unit.pkg, diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index ffe3537f674..c35df661dd6 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -460,7 +460,7 @@ impl BuildOutput { let (key, value) = match (key, value) { (Some(a), Some(b)) => (a, b.trim_end()), // Line started with `cargo:` but didn't match `key=value`. - _ => failure::bail!("Wrong output in {}: `{}`", whence, line), + _ => anyhow::bail!("Wrong output in {}: `{}`", whence, line), }; // This will rewrite paths if the target directory has been moved. @@ -520,7 +520,7 @@ impl BuildOutput { if value.is_empty() { value = match flags_iter.next() { Some(v) => v, - None => failure::bail! { + None => anyhow::bail! { "Flag in rustc-flags has no value in {}: {}", whence, value @@ -536,7 +536,7 @@ impl BuildOutput { _ => unreachable!(), }; } else { - failure::bail!( + anyhow::bail!( "Only `-l` and `-L` flags are allowed in {}: `{}`", whence, value @@ -552,7 +552,7 @@ impl BuildOutput { let val = iter.next(); match (name, val) { (Some(n), Some(v)) => Ok((n.to_owned(), v.to_owned())), - _ => failure::bail!("Variable rustc-env has no value in {}: {}", whence, value), + _ => anyhow::bail!("Variable rustc-env has no value in {}: {}", whence, value), } } } diff --git a/src/cargo/core/compiler/fingerprint.rs b/src/cargo/core/compiler/fingerprint.rs index c2fdd99a737..84d20073400 100644 --- a/src/cargo/core/compiler/fingerprint.rs +++ b/src/cargo/core/compiler/fingerprint.rs @@ -194,7 +194,7 @@ use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; use std::time::SystemTime; -use failure::{bail, format_err}; +use anyhow::{bail, format_err}; use filetime::FileTime; use log::{debug, info}; use serde::de; @@ -1414,11 +1414,7 @@ fn log_compare(unit: &Unit<'_>, compare: &CargoResult<()>) { "fingerprint error for {}/{:?}/{:?}", unit.pkg, unit.mode, unit.target, ); - info!(" err: {}", ce); - - for cause in ce.iter_causes() { - info!(" cause: {}", cause); - } + info!(" err: {:?}", ce); } // Parse the dep-info into a list of paths diff --git a/src/cargo/core/compiler/job_queue.rs b/src/cargo/core/compiler/job_queue.rs index 58034c3f35b..b958770546b 100644 --- a/src/cargo/core/compiler/job_queue.rs +++ b/src/cargo/core/compiler/job_queue.rs @@ -7,8 +7,8 @@ use std::sync::mpsc::{channel, Receiver, Sender}; use std::sync::Arc; use std::time::Duration; +use anyhow::format_err; use crossbeam_utils::thread::Scope; -use failure::format_err; use jobserver::{Acquired, HelperThread}; use log::{debug, info, trace}; @@ -393,7 +393,7 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> { self.emit_warnings(Some(msg), &unit, cx)?; if !self.active.is_empty() { - error = Some(failure::format_err!("build failed")); + error = Some(anyhow::format_err!("build failed")); handle_error(&e, &mut *cx.bcx.config.shell()); cx.bcx.config.shell().warn( "build failed, waiting for other \ diff --git a/src/cargo/core/compiler/links.rs b/src/cargo/core/compiler/links.rs index cc021e3a15d..89fe2b29261 100644 --- a/src/cargo/core/compiler/links.rs +++ b/src/cargo/core/compiler/links.rs @@ -39,7 +39,7 @@ pub fn validate_links(resolve: &Resolve, unit_graph: &UnitGraph<'_>) -> CargoRes dep_path_desc }; - failure::bail!( + anyhow::bail!( "multiple packages link to native library `{}`, \ but a native library can be linked only once\n\ \n\ diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 0018d4c97d5..c5aea7610ed 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -23,7 +23,7 @@ use std::io::{BufRead, Write}; use std::path::PathBuf; use std::sync::Arc; -use failure::Error; +use anyhow::Error; use lazycell::LazyCell; use log::debug; diff --git a/src/cargo/core/compiler/standard_lib.rs b/src/cargo/core/compiler/standard_lib.rs index b0d633854e7..2881f4dd843 100644 --- a/src/cargo/core/compiler/standard_lib.rs +++ b/src/cargo/core/compiler/standard_lib.rs @@ -161,12 +161,12 @@ fn detect_sysroot_src_path(ws: &Workspace<'_>) -> CargoResult { let rustc = ws.config().load_global_rustc(Some(ws))?; let output = rustc.process().arg("--print=sysroot").exec_with_output()?; let s = String::from_utf8(output.stdout) - .map_err(|e| failure::format_err!("rustc didn't return utf8 output: {:?}", e))?; + .map_err(|e| anyhow::format_err!("rustc didn't return utf8 output: {:?}", e))?; let sysroot = PathBuf::from(s.trim()); let src_path = sysroot.join("lib").join("rustlib").join("src").join("rust"); let lock = src_path.join("Cargo.lock"); if !lock.exists() { - failure::bail!( + anyhow::bail!( "{:?} does not exist, unable to build with the standard \ library, try:\n rustup component add rust-src", lock diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index 5bfab2eee74..c34fe07880d 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -50,7 +50,7 @@ use std::env; use std::fmt; use std::str::FromStr; -use failure::{bail, Error}; +use anyhow::{bail, Error}; use serde::{Deserialize, Serialize}; use crate::util::errors::CargoResult; diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index 96561d2cc9b..bf307d1290a 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -514,7 +514,7 @@ impl Manifest { self.features .require(Feature::test_dummy_unstable()) .chain_err(|| { - failure::format_err!( + anyhow::format_err!( "the `im-a-teapot` manifest key is unstable and may \ not work properly in England" ) diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 8a3035c8f18..f45867febde 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -7,10 +7,10 @@ use std::mem; use std::path::{Path, PathBuf}; use std::time::{Duration, Instant}; +use anyhow::Context; use bytesize::ByteSize; use curl::easy::{Easy, HttpVersion}; use curl::multi::{EasyHandle, Multi}; -use failure::ResultExt; use lazycell::LazyCell; use log::{debug, warn}; use semver::Version; @@ -485,8 +485,8 @@ macro_rules! try_old_curl { warn!("ignoring libcurl {} error: {}", $msg, e); } } else { - result.with_context(|_| { - failure::format_err!("failed to enable {}, is curl not built right?", $msg) + result.with_context(|| { + anyhow::format_err!("failed to enable {}, is curl not built right?", $msg) })?; } }; @@ -525,7 +525,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { .ok_or_else(|| internal(format!("couldn't find source for `{}`", id)))?; let pkg = source .download(id) - .chain_err(|| failure::format_err!("unable to get packages from source"))?; + .chain_err(|| anyhow::format_err!("unable to get packages from source"))?; let (url, descriptor) = match pkg { MaybePackage::Ready(pkg) => { debug!("{} doesn't need a download", id); diff --git a/src/cargo/core/package_id_spec.rs b/src/cargo/core/package_id_spec.rs index 9fd01cf1984..ff70bfae3b1 100644 --- a/src/cargo/core/package_id_spec.rs +++ b/src/cargo/core/package_id_spec.rs @@ -79,7 +79,7 @@ impl PackageIdSpec { I: IntoIterator, { let spec = PackageIdSpec::parse(spec) - .chain_err(|| failure::format_err!("invalid package ID specification: `{}`", spec))?; + .chain_err(|| anyhow::format_err!("invalid package ID specification: `{}`", spec))?; spec.query(i) } @@ -96,16 +96,16 @@ impl PackageIdSpec { /// Tries to convert a valid `Url` to a `PackageIdSpec`. fn from_url(mut url: Url) -> CargoResult { if url.query().is_some() { - failure::bail!("cannot have a query string in a pkgid: {}", url) + anyhow::bail!("cannot have a query string in a pkgid: {}", url) } let frag = url.fragment().map(|s| s.to_owned()); url.set_fragment(None); let (name, version) = { let mut path = url .path_segments() - .ok_or_else(|| failure::format_err!("pkgid urls must have a path: {}", url))?; + .ok_or_else(|| anyhow::format_err!("pkgid urls must have a path: {}", url))?; let path_name = path.next_back().ok_or_else(|| { - failure::format_err!( + anyhow::format_err!( "pkgid urls must have at least one path \ component: {}", url @@ -183,7 +183,7 @@ impl PackageIdSpec { let mut ids = i.into_iter().filter(|p| self.matches(*p)); let ret = match ids.next() { Some(id) => id, - None => failure::bail!( + None => anyhow::bail!( "package ID specification `{}` \ matched no packages", self @@ -204,7 +204,7 @@ impl PackageIdSpec { let mut vec = vec![ret, other]; vec.extend(ids); minimize(&mut msg, &vec, self); - Err(failure::format_err!("{}", msg)) + Err(anyhow::format_err!("{}", msg)) } None => Ok(ret), }; diff --git a/src/cargo/core/profiles.rs b/src/cargo/core/profiles.rs index 13b2260f024..0be1c19c35d 100644 --- a/src/cargo/core/profiles.rs +++ b/src/cargo/core/profiles.rs @@ -240,7 +240,7 @@ impl Profiles { match &profile.inherits { None => {} Some(_) => { - failure::bail!( + anyhow::bail!( "An 'inherits' must not specified root profile '{}'", name ); @@ -278,7 +278,7 @@ impl Profiles { Some(name) => { let name = name.to_owned(); if set.get(&name).is_some() { - failure::bail!( + anyhow::bail!( "Inheritance loop of profiles cycles with profile '{}'", name ); @@ -287,13 +287,13 @@ impl Profiles { set.insert(name.clone()); match profiles.get(&name) { None => { - failure::bail!("Profile '{}' not found in Cargo.toml", name); + anyhow::bail!("Profile '{}' not found in Cargo.toml", name); } Some(parent) => self.process_chain(&name, parent, set, result, profiles), } } None => { - failure::bail!( + anyhow::bail!( "An 'inherits' directive is needed for all \ profiles that are not 'dev' or 'release'. Here \ it is missing from '{}'", @@ -415,7 +415,7 @@ impl Profiles { }; match self.by_name.get(profile_name) { - None => failure::bail!("Profile `{}` undefined", profile_kind.name()), + None => anyhow::bail!("Profile `{}` undefined", profile_kind.name()), Some(r) => Ok(r.get_profile(None, true, UnitFor::new_normal())), } } @@ -546,7 +546,7 @@ impl ProfileMaker { .map(|spec| spec.to_string()) .collect::>() .join(", "); - failure::bail!( + anyhow::bail!( "multiple package overrides in profile `{}` match package `{}`\n\ found package specs: {}", self.default.name, @@ -1021,13 +1021,13 @@ impl ConfigProfiles { if let Some(ref profile) = self.dev { profile .validate("dev", features, warnings) - .chain_err(|| failure::format_err!("config profile `profile.dev` is not valid"))?; + .chain_err(|| anyhow::format_err!("config profile `profile.dev` is not valid"))?; } if let Some(ref profile) = self.release { profile .validate("release", features, warnings) .chain_err(|| { - failure::format_err!("config profile `profile.release` is not valid") + anyhow::format_err!("config profile `profile.release` is not valid") })?; } Ok(()) diff --git a/src/cargo/core/registry.rs b/src/cargo/core/registry.rs index cbfb5dc05fd..0cbb831b896 100644 --- a/src/cargo/core/registry.rs +++ b/src/cargo/core/registry.rs @@ -1,6 +1,6 @@ use std::collections::{HashMap, HashSet}; -use failure::bail; +use anyhow::bail; use log::{debug, trace}; use semver::VersionReq; use url::Url; @@ -255,7 +255,7 @@ impl<'cfg> PackageRegistry<'cfg> { // corresponding to this `dep`. self.ensure_loaded(dep.source_id(), Kind::Normal) .chain_err(|| { - failure::format_err!( + anyhow::format_err!( "failed to load source for a dependency \ on `{}`", dep.package_name() @@ -271,7 +271,7 @@ impl<'cfg> PackageRegistry<'cfg> { let summary = match summaries.next() { Some(summary) => summary, - None => failure::bail!( + None => anyhow::bail!( "patch for `{}` in `{}` did not resolve to any crates. If this is \ unexpected, you may wish to consult: \ https://github.com/rust-lang/cargo/issues/4678", @@ -280,14 +280,14 @@ impl<'cfg> PackageRegistry<'cfg> { ), }; if summaries.next().is_some() { - failure::bail!( + anyhow::bail!( "patch for `{}` in `{}` resolved to more than one candidate", dep.package_name(), url ) } if *summary.package_id().source_id().canonical_url() == canonical { - failure::bail!( + anyhow::bail!( "patch for `{}` in `{}` points to the same source, but \ patches must point to different sources", dep.package_name(), @@ -297,7 +297,7 @@ impl<'cfg> PackageRegistry<'cfg> { Ok(summary) }) .collect::>>() - .chain_err(|| failure::format_err!("failed to resolve patches for `{}`", url))?; + .chain_err(|| anyhow::format_err!("failed to resolve patches for `{}`", url))?; let mut name_and_version = HashSet::new(); for summary in unlocked_summaries.iter() { @@ -364,7 +364,7 @@ impl<'cfg> PackageRegistry<'cfg> { let _p = profile::start(format!("updating: {}", source_id)); self.sources.get_mut(source_id).unwrap().update() })() - .chain_err(|| failure::format_err!("Unable to update {}", source_id))?; + .chain_err(|| anyhow::format_err!("Unable to update {}", source_id))?; Ok(()) } @@ -516,7 +516,7 @@ impl<'cfg> Registry for PackageRegistry<'cfg> { // Ensure the requested source_id is loaded self.ensure_loaded(dep.source_id(), Kind::Normal) .chain_err(|| { - failure::format_err!( + anyhow::format_err!( "failed to load source for a dependency \ on `{}`", dep.package_name() @@ -525,7 +525,7 @@ impl<'cfg> Registry for PackageRegistry<'cfg> { let source = self.sources.get_mut(dep.source_id()); match (override_summary, source) { - (Some(_), None) => failure::bail!("override found but no real ones"), + (Some(_), None) => anyhow::bail!("override found but no real ones"), (None, None) => return Ok(()), // If we don't have an override then we just ship @@ -565,7 +565,7 @@ impl<'cfg> Registry for PackageRegistry<'cfg> { // the summaries it gives us though. (Some(override_summary), Some(source)) => { if !patches.is_empty() { - failure::bail!("found patches and a path override") + anyhow::bail!("found patches and a path override") } let mut n = 0; let mut to_warn = None; @@ -587,7 +587,7 @@ impl<'cfg> Registry for PackageRegistry<'cfg> { }; if n > 1 { - failure::bail!("found an override with a non-locked list"); + anyhow::bail!("found an override with a non-locked list"); } else if let Some(summary) = to_warn { self.warn_bad_override(&override_summary, &summary)?; } diff --git a/src/cargo/core/resolver/context.rs b/src/cargo/core/resolver/context.rs index 376d9b7751c..9f21ebfe79f 100644 --- a/src/cargo/core/resolver/context.rs +++ b/src/cargo/core/resolver/context.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use std::num::NonZeroU64; use std::rc::Rc; -use failure::format_err; +use anyhow::format_err; use log::debug; use crate::core::interning::InternedString; diff --git a/src/cargo/core/resolver/dep_cache.rs b/src/cargo/core/resolver/dep_cache.rs index 75b10935ad6..6365b1029e1 100644 --- a/src/cargo/core/resolver/dep_cache.rs +++ b/src/cargo/core/resolver/dep_cache.rs @@ -104,7 +104,7 @@ impl<'a> RegistryQueryer<'a> { let mut summaries = self.registry.query_vec(dep, false)?.into_iter(); let s = summaries.next().ok_or_else(|| { - failure::format_err!( + anyhow::format_err!( "no matching package for override `{}` found\n\ location searched: {}\n\ version required: {}", @@ -119,7 +119,7 @@ impl<'a> RegistryQueryer<'a> { .iter() .map(|s| format!(" * {}", s.package_id())) .collect::>(); - failure::bail!( + anyhow::bail!( "the replacement specification `{}` matched \ multiple packages:\n * {}\n{}", spec, @@ -144,7 +144,7 @@ impl<'a> RegistryQueryer<'a> { // Make sure no duplicates if let Some(&(ref spec, _)) = potential_matches.next() { - failure::bail!( + anyhow::bail!( "overlapping replacement specifications found:\n\n \ * {}\n * {}\n\nboth specifications match: {}", matched_spec, @@ -277,7 +277,7 @@ pub fn resolve_features<'b>( .any(|d| d.is_optional() && d.name_in_toml() == dep.name_in_toml()); if always_required && base.0 { return Err(match parent { - None => failure::format_err!( + None => anyhow::format_err!( "Package `{}` does not have feature `{}`. It has a required dependency \ with that name, but only optional dependencies can be used as features.", s.package_id(), @@ -295,7 +295,7 @@ pub fn resolve_features<'b>( base.extend(dep.features().iter()); for feature in base.iter() { if feature.contains('/') { - return Err(failure::format_err!( + return Err(anyhow::format_err!( "feature names may not contain slashes: `{}`", feature ) @@ -318,7 +318,7 @@ pub fn resolve_features<'b>( if !remaining.is_empty() { let features = remaining.join(", "); return Err(match parent { - None => failure::format_err!( + None => anyhow::format_err!( "Package `{}` does not have these features: `{}`", s.package_id(), features @@ -437,7 +437,7 @@ impl Requirements<'_> { .expect("must be a valid feature") { match *fv { - FeatureValue::Feature(ref dep_feat) if **dep_feat == *feat => failure::bail!( + FeatureValue::Feature(ref dep_feat) if **dep_feat == *feat => anyhow::bail!( "cyclic feature dependency: feature `{}` depends on itself", feat ), diff --git a/src/cargo/core/resolver/encode.rs b/src/cargo/core/resolver/encode.rs index 6375a9dffc1..8f9d915f5e9 100644 --- a/src/cargo/core/resolver/encode.rs +++ b/src/cargo/core/resolver/encode.rs @@ -160,7 +160,7 @@ impl EncodableResolve { }; if !all_pkgs.insert(enc_id.clone()) { - failure::bail!("package `{}` is specified twice in the lockfile", pkg.name); + anyhow::bail!("package `{}` is specified twice in the lockfile", pkg.name); } let id = match pkg.source.as_ref().or_else(|| path_deps.get(&pkg.name)) { // We failed to find a local package in the workspace. @@ -474,7 +474,7 @@ impl fmt::Display for EncodablePackageId { } impl FromStr for EncodablePackageId { - type Err = failure::Error; + type Err = anyhow::Error; fn from_str(s: &str) -> CargoResult { let mut s = s.splitn(3, ' '); @@ -485,7 +485,7 @@ impl FromStr for EncodablePackageId { if s.starts_with('(') && s.ends_with(')') { Some(SourceId::from_url(&s[1..s.len() - 1])?) } else { - failure::bail!("invalid serialized PackageId") + anyhow::bail!("invalid serialized PackageId") } } None => None, diff --git a/src/cargo/core/resolver/errors.rs b/src/cargo/core/resolver/errors.rs index 369801eccde..807555c86ee 100644 --- a/src/cargo/core/resolver/errors.rs +++ b/src/cargo/core/resolver/errors.rs @@ -3,7 +3,7 @@ use std::fmt; use crate::core::{Dependency, PackageId, Registry, Summary}; use crate::util::lev_distance::lev_distance; use crate::util::Config; -use failure::{Error, Fail}; +use anyhow::Error; use semver; use super::context::Context; @@ -30,9 +30,9 @@ impl ResolveError { } } -impl Fail for ResolveError { - fn cause(&self) -> Option<&dyn Fail> { - self.cause.as_fail().cause() +impl std::error::Error for ResolveError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.cause.source() } } @@ -52,12 +52,12 @@ pub type ActivateResult = Result; #[derive(Debug)] pub enum ActivateError { - Fatal(failure::Error), + Fatal(anyhow::Error), Conflict(PackageId, ConflictReason), } -impl From<::failure::Error> for ActivateError { - fn from(t: ::failure::Error) -> Self { +impl From<::anyhow::Error> for ActivateError { + fn from(t: ::anyhow::Error) -> Self { ActivateError::Fatal(t) } } @@ -185,7 +185,7 @@ pub(super) fn activation_error( msg.push_str(&*dep.package_name()); msg.push_str("` which could resolve this conflict"); - return to_resolve_err(failure::format_err!("{}", msg)); + return to_resolve_err(anyhow::format_err!("{}", msg)); } // We didn't actually find any candidates, so we need to @@ -324,7 +324,7 @@ pub(super) fn activation_error( } } - to_resolve_err(failure::format_err!("{}", msg)) + to_resolve_err(anyhow::format_err!("{}", msg)) } /// Returns String representation of dependency chain for a particular `pkgid`. diff --git a/src/cargo/core/resolver/mod.rs b/src/cargo/core/resolver/mod.rs index 86947ca8efd..17728120aab 100644 --- a/src/cargo/core/resolver/mod.rs +++ b/src/cargo/core/resolver/mod.rs @@ -1012,7 +1012,7 @@ fn check_cycles(resolve: &Resolve) -> CargoResult<()> { path.push(id); // See if we visited ourselves if !visited.insert(id) { - failure::bail!( + anyhow::bail!( "cyclic package dependency: package `{}` depends on itself. Cycle:\n{}", id, errors::describe_path(&path.iter().rev().collect::>()), @@ -1062,7 +1062,7 @@ fn check_duplicate_pkgs_in_lockfile(resolve: &Resolve) -> CargoResult<()> { for pkg_id in resolve.iter() { let encodable_pkd_id = encode::encodable_package_id(pkg_id, &state); if let Some(prev_pkg_id) = unique_pkg_ids.insert(encodable_pkd_id, pkg_id) { - failure::bail!( + anyhow::bail!( "package collision in the lockfile: packages {} and {} are different, \ but only one can be written to lockfile unambiguously", prev_pkg_id, diff --git a/src/cargo/core/resolver/resolve.rs b/src/cargo/core/resolver/resolve.rs index 430ad39b85b..78703fa9c41 100644 --- a/src/cargo/core/resolver/resolve.rs +++ b/src/cargo/core/resolver/resolve.rs @@ -150,7 +150,7 @@ impl Resolve { // desires stronger checksum guarantees than can be afforded // elsewhere. if cksum.is_none() { - failure::bail!( + anyhow::bail!( "\ checksum for `{}` was not previously calculated, but a checksum could now \ be calculated @@ -172,7 +172,7 @@ this could be indicative of a few possible situations: // more realistically we were overridden with a source that does // not have checksums. } else if mine.is_none() { - failure::bail!( + anyhow::bail!( "\ checksum for `{}` could not be calculated, but a checksum is listed in \ the existing lock file @@ -193,7 +193,7 @@ unable to verify that `{0}` is the same as when the lockfile was generated // must both be Some, in which case the checksum now differs. // That's quite bad! } else { - failure::bail!( + anyhow::bail!( "\ checksum for `{}` changed between lock files @@ -338,7 +338,7 @@ unable to verify that `{0}` is the same as when the lockfile was generated }); let name = names.next().unwrap_or_else(|| crate_name.clone()); for n in names { - failure::ensure!( + anyhow::ensure!( n == name, "the crate `{}` depends on crate `{}` multiple times with different names", from, diff --git a/src/cargo/core/shell.rs b/src/cargo/core/shell.rs index dfa195943bf..30033285e45 100644 --- a/src/cargo/core/shell.rs +++ b/src/cargo/core/shell.rs @@ -252,7 +252,7 @@ impl Shell { Some("auto") | None => ColorChoice::CargoAuto, - Some(arg) => failure::bail!( + Some(arg) => anyhow::bail!( "argument for --color must be auto, always, or \ never, but found `{}`", arg diff --git a/src/cargo/core/source/source_id.rs b/src/cargo/core/source/source_id.rs index 9755b5006fe..a864954edac 100644 --- a/src/cargo/core/source/source_id.rs +++ b/src/cargo/core/source/source_id.rs @@ -112,7 +112,7 @@ impl SourceId { let kind = parts.next().unwrap(); let url = parts .next() - .ok_or_else(|| failure::format_err!("invalid source `{}`", string))?; + .ok_or_else(|| anyhow::format_err!("invalid source `{}`", string))?; match kind { "git" => { @@ -141,10 +141,7 @@ impl SourceId { let url = url.into_url()?; SourceId::new(Kind::Path, url) } - kind => Err(failure::format_err!( - "unsupported source protocol: {}", - kind - )), + kind => Err(anyhow::format_err!("unsupported source protocol: {}", kind)), } } diff --git a/src/cargo/core/summary.rs b/src/cargo/core/summary.rs index d6732ec8997..365c9e29fba 100644 --- a/src/cargo/core/summary.rs +++ b/src/cargo/core/summary.rs @@ -46,14 +46,14 @@ impl Summary { for dep in dependencies.iter() { let feature = dep.name_in_toml(); if !namespaced_features && features.get(&*feature).is_some() { - failure::bail!( + anyhow::bail!( "Features and dependencies cannot have the \ same name: `{}`", feature ) } if dep.is_optional() && !dep.is_transitive() { - failure::bail!( + anyhow::bail!( "Dev-dependencies are not allowed to be optional: `{}`", feature ) @@ -180,7 +180,7 @@ where match dep_map.get(feature.borrow()) { Some(dep_data) => { if !dep_data.iter().any(|d| d.is_optional()) { - failure::bail!( + anyhow::bail!( "Feature `{}` includes the dependency of the same name, but this is \ left implicit in the features included by this feature.\n\ Additionally, the dependency must be marked as optional to be \ @@ -249,7 +249,7 @@ where (&Feature(feat), dep_exists, false) => { if namespaced && !features.contains_key(&*feat) { if dep_exists { - failure::bail!( + anyhow::bail!( "Feature `{}` includes `{}` which is not defined as a feature.\n\ A non-optional dependency of the same name is defined; consider \ adding `optional = true` to its definition", @@ -257,7 +257,7 @@ where feat ) } else { - failure::bail!( + anyhow::bail!( "Feature `{}` includes `{}` which is not defined as a feature", feature, feat @@ -272,7 +272,7 @@ where // just to provide the correct string for the crate dependency in the error. (&Crate(ref dep), true, false) => { if namespaced { - failure::bail!( + anyhow::bail!( "Feature `{}` includes `crate:{}` which is not an \ optional dependency.\nConsider adding \ `optional = true` to the dependency", @@ -280,7 +280,7 @@ where dep ) } else { - failure::bail!( + anyhow::bail!( "Feature `{}` depends on `{}` which is not an \ optional dependency.\nConsider adding \ `optional = true` to the dependency", @@ -295,14 +295,14 @@ where // namespaced here is just to provide the correct string in the error. (&Crate(ref dep), false, _) => { if namespaced { - failure::bail!( + anyhow::bail!( "Feature `{}` includes `crate:{}` which is not a known \ dependency", feature, dep ) } else { - failure::bail!( + anyhow::bail!( "Feature `{}` includes `{}` which is neither a dependency nor \ another feature", feature, @@ -313,7 +313,7 @@ where (&Crate(_), true, true) => {} // If the value is a feature for one of the dependencies, bail out if no such // dependency is actually defined in the manifest. - (&CrateFeature(ref dep, _), false, _) => failure::bail!( + (&CrateFeature(ref dep, _), false, _) => anyhow::bail!( "Feature `{}` requires a feature of `{}` which is not a \ dependency", feature, @@ -327,7 +327,7 @@ where if !dependency_found { // If we have not found the dependency of the same-named feature, we should // bail here. - failure::bail!( + anyhow::bail!( "Feature `{}` includes the optional dependency of the \ same name, but this is left implicit in the features \ included by this feature.\nConsider adding \ diff --git a/src/cargo/core/workspace.rs b/src/cargo/core/workspace.rs index 16e65987d55..e29f22b5c6d 100644 --- a/src/cargo/core/workspace.rs +++ b/src/cargo/core/workspace.rs @@ -224,7 +224,7 @@ impl<'cfg> Workspace<'cfg> { /// indicating that something else should be passed. pub fn current(&self) -> CargoResult<&Package> { let pkg = self.current_opt().ok_or_else(|| { - failure::format_err!( + anyhow::format_err!( "manifest path `{}` is a virtual manifest, but this \ command requires running against an actual package in \ this workspace", @@ -467,7 +467,7 @@ impl<'cfg> Workspace<'cfg> { None }; } - _ => failure::bail!( + _ => anyhow::bail!( "root of a workspace inferred but wasn't a root: {}", root_manifest_path.display() ), @@ -482,7 +482,7 @@ impl<'cfg> Workspace<'cfg> { for path in default { let manifest_path = paths::normalize_path(&path.join("Cargo.toml")); if !self.members.contains(&manifest_path) { - failure::bail!( + anyhow::bail!( "package `{}` is listed in workspace’s default-members \ but is not a member.", path.display() @@ -592,7 +592,7 @@ impl<'cfg> Workspace<'cfg> { MaybePackage::Virtual(_) => continue, }; if let Some(prev) = names.insert(name, member) { - failure::bail!( + anyhow::bail!( "two packages named `{}` in this workspace:\n\ - {}\n\ - {}", @@ -605,7 +605,7 @@ impl<'cfg> Workspace<'cfg> { } match roots.len() { - 0 => failure::bail!( + 0 => anyhow::bail!( "`package.workspace` configuration points to a crate \ which is not configured with [workspace]: \n\ configuration at: {}\n\ @@ -615,7 +615,7 @@ impl<'cfg> Workspace<'cfg> { ), 1 => {} _ => { - failure::bail!( + anyhow::bail!( "multiple workspace roots found in the same workspace:\n{}", roots .iter() @@ -634,7 +634,7 @@ impl<'cfg> Workspace<'cfg> { match root { Some(root) => { - failure::bail!( + anyhow::bail!( "package `{}` is a member of the wrong workspace\n\ expected: {}\n\ actual: {}", @@ -644,7 +644,7 @@ impl<'cfg> Workspace<'cfg> { ); } None => { - failure::bail!( + anyhow::bail!( "workspace member `{}` is not hierarchically below \ the workspace root `{}`", member.display(), @@ -696,7 +696,7 @@ impl<'cfg> Workspace<'cfg> { } } }; - failure::bail!( + anyhow::bail!( "current package believes it's in a workspace when it's not:\n\ current: {}\n\ workspace: {}\n\n{}\n\ @@ -746,7 +746,7 @@ impl<'cfg> Workspace<'cfg> { pub fn load(&self, manifest_path: &Path) -> CargoResult { match self.packages.maybe_get(manifest_path) { Some(&MaybePackage::Package(ref p)) => return Ok(p.clone()), - Some(&MaybePackage::Virtual(_)) => failure::bail!("cannot load workspace root"), + Some(&MaybePackage::Virtual(_)) => anyhow::bail!("cannot load workspace root"), None => {} } @@ -800,9 +800,9 @@ impl<'cfg> Workspace<'cfg> { let path = path.join("Cargo.toml"); for warning in warnings { if warning.is_critical { - let err = failure::format_err!("{}", warning.message); + let err = anyhow::format_err!("{}", warning.message); let cx = - failure::format_err!("failed to parse manifest at `{}`", path.display()); + anyhow::format_err!("failed to parse manifest at `{}`", path.display()); return Err(err.context(cx).into()); } else { let msg = if self.root_manifest.is_none() { @@ -941,10 +941,10 @@ impl WorkspaceRootConfig { None => return Ok(Vec::new()), }; let res = - glob(path).chain_err(|| failure::format_err!("could not parse pattern `{}`", &path))?; + glob(path).chain_err(|| anyhow::format_err!("could not parse pattern `{}`", &path))?; let res = res .map(|p| { - p.chain_err(|| failure::format_err!("unable to match path to pattern `{}`", &path)) + p.chain_err(|| anyhow::format_err!("unable to match path to pattern `{}`", &path)) }) .collect::, _>>()?; Ok(res) diff --git a/src/cargo/lib.rs b/src/cargo/lib.rs index 0c214c3d38b..492e34ee4af 100644 --- a/src/cargo/lib.rs +++ b/src/cargo/lib.rs @@ -30,15 +30,12 @@ // https://github.com/rust-lang/cargo/pull/7251#pullrequestreview-274914270 #![allow(clippy::identity_conversion)] -use std::fmt; -use std::io; - -use failure::Error; -use log::debug; -use serde::ser; - use crate::core::shell::Verbosity::Verbose; use crate::core::Shell; +use anyhow::Error; +use log::debug; +use serde::ser; +use std::fmt; pub use crate::util::errors::Internal; pub use crate::util::{CargoResult, CliError, CliResult, Config}; @@ -140,7 +137,7 @@ pub fn exit_with_error(err: CliError, shell: &mut Shell) -> ! { std::process::exit(exit_code) } -pub fn handle_error(err: &failure::Error, shell: &mut Shell) { +pub fn handle_error(err: &Error, shell: &mut Shell) { debug!("handle_error; err={:?}", err); let _ignored_result = shell.error(err); @@ -153,18 +150,10 @@ fn handle_cause(cargo_err: &Error, shell: &mut Shell) -> bool { drop(writeln!(shell.err(), " {}", error)); } - fn print_stderror_causes(error: &dyn std::error::Error, shell: &mut Shell) { - let mut cur = std::error::Error::source(error); - while let Some(err) = cur { - print(&err.to_string(), shell); - cur = std::error::Error::source(err); - } - } - let verbose = shell.verbosity(); // The first error has already been printed to the shell. - for err in cargo_err.iter_causes() { + for err in cargo_err.chain().skip(1) { // If we're not in verbose mode then print remaining errors until one // marked as `Internal` appears. if verbose != Verbose && err.downcast_ref::().is_some() { @@ -172,19 +161,6 @@ fn handle_cause(cargo_err: &Error, shell: &mut Shell) -> bool { } print(&err.to_string(), shell); - - // Using the `failure` crate currently means that when using - // `iter_causes` we're only iterating over the `failure` causes, but - // this doesn't include the causes from the standard library `Error` - // trait. We don't have a great way of getting an `&dyn Error` from a - // `&dyn Fail`, so we currently just special case a few errors that are - // known to maybe have causes and we try to print them here. - // - // Note that this isn't an exhaustive match since causes for - // `std::error::Error` aren't the most common thing in the world. - if let Some(io) = err.downcast_ref::() { - print_stderror_causes(io, shell); - } } true diff --git a/src/cargo/ops/cargo_clean.rs b/src/cargo/ops/cargo_clean.rs index d2fa5cbec93..6ceef99d514 100644 --- a/src/cargo/ops/cargo_clean.rs +++ b/src/cargo/ops/cargo_clean.rs @@ -155,13 +155,13 @@ fn rm_rf(path: &Path, config: &Config) -> CargoResult<()> { .shell() .verbose(|shell| shell.status("Removing", path.display()))?; paths::remove_dir_all(path) - .chain_err(|| failure::format_err!("could not remove build directory"))?; + .chain_err(|| anyhow::format_err!("could not remove build directory"))?; } else if m.is_ok() { config .shell() .verbose(|shell| shell.status("Removing", path.display()))?; paths::remove_file(path) - .chain_err(|| failure::format_err!("failed to remove build artifact"))?; + .chain_err(|| anyhow::format_err!("failed to remove build artifact"))?; } Ok(()) } diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index 30f1aeab0ad..0f9a871bd3a 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -111,7 +111,7 @@ impl Packages { Ok(match (all, exclude.len(), package.len()) { (false, 0, 0) => Packages::Default, (false, 0, _) => Packages::Packages(package), - (false, _, _) => failure::bail!("--exclude can only be used together with --workspace"), + (false, _, _) => anyhow::bail!("--exclude can only be used together with --workspace"), (true, 0, _) => Packages::All, (true, _, _) => Packages::OptOut(exclude), }) @@ -160,13 +160,13 @@ impl Packages { }; if specs.is_empty() { if ws.is_virtual() { - failure::bail!( + anyhow::bail!( "manifest path `{}` contains no package: The manifest is virtual, \ and the workspace has no members.", ws.root().display() ) } - failure::bail!("no packages to compile") + anyhow::bail!("no packages to compile") } Ok(specs) } @@ -185,7 +185,7 @@ impl Packages { ws.members() .find(|pkg| pkg.name().as_str() == name) .ok_or_else(|| { - failure::format_err!( + anyhow::format_err!( "package `{}` is not a member of the workspace", name ) @@ -325,7 +325,7 @@ pub fn compile_ws<'a>( // TODO: This should eventually be fixed. Unfortunately it is not // easy to get the host triple in BuildConfig. Consider changing // requested_target to an enum, or some other approach. - failure::bail!("-Zbuild-std requires --target"); + anyhow::bail!("-Zbuild-std requires --target"); } let (mut std_package_set, std_resolve) = standard_lib::resolve_std(ws, crates)?; remove_dylib_crate_type(&mut std_package_set)?; @@ -359,7 +359,7 @@ pub fn compile_ws<'a>( && !ws.is_member(pkg) && pkg.dependencies().iter().any(|dep| !dep.is_transitive()) { - failure::bail!( + anyhow::bail!( "package `{}` cannot be tested because it requires dev-dependencies \ and is not a member of the workspace", pkg.name() @@ -430,7 +430,7 @@ pub fn compile_ws<'a>( if let Some(args) = extra_args { if units.len() != 1 { - failure::bail!( + anyhow::bail!( "extra arguments to `{}` can only be passed to one \ target, consider filtering\nthe package by passing, \ e.g., `--lib` or `--bin NAME` to specify a single target", @@ -793,12 +793,9 @@ fn generate_targets<'a>( if !all_targets && libs.is_empty() && *lib == LibRule::True { let names = packages.iter().map(|pkg| pkg.name()).collect::>(); if names.len() == 1 { - failure::bail!("no library targets found in package `{}`", names[0]); + anyhow::bail!("no library targets found in package `{}`", names[0]); } else { - failure::bail!( - "no library targets found in packages: {}", - names.join(", ") - ); + anyhow::bail!("no library targets found in packages: {}", names.join(", ")); } } proposals.extend(libs); @@ -887,7 +884,7 @@ fn generate_targets<'a>( .iter() .map(|s| format!("`{}`", s)) .collect(); - failure::bail!( + anyhow::bail!( "target `{}` in package `{}` requires the features: {}\n\ Consider enabling them by passing, e.g., `--features=\"{}\"`", target.name(), @@ -991,7 +988,7 @@ fn find_named_targets<'a>( .filter(|target| is_expected_kind(target)) }); let suggestion = closest_msg(target_name, targets, |t| t.name()); - failure::bail!( + anyhow::bail!( "no {} target named `{}`{}", target_desc, target_name, diff --git a/src/cargo/ops/cargo_doc.rs b/src/cargo/ops/cargo_doc.rs index c8523232dd7..d95c41d6ee6 100644 --- a/src/cargo/ops/cargo_doc.rs +++ b/src/cargo/ops/cargo_doc.rs @@ -2,8 +2,6 @@ use crate::core::resolver::ResolveOpts; use crate::core::{Shell, Workspace}; use crate::ops; use crate::util::CargoResult; -use failure::Fail; -use opener; use std::collections::HashMap; use std::path::Path; use std::process::Command; @@ -41,7 +39,7 @@ pub fn doc(ws: &Workspace<'_>, options: &DocOptions<'_>) -> CargoResult<()> { for target in package.targets().iter().filter(|t| t.documented()) { if target.is_lib() { if let Some(prev) = lib_names.insert(target.crate_name(), package) { - failure::bail!( + anyhow::bail!( "The library `{}` is specified by packages `{}` and \ `{}` but can only be documented once. Consider renaming \ or marking one of the targets as `doc = false`.", @@ -51,7 +49,7 @@ pub fn doc(ws: &Workspace<'_>, options: &DocOptions<'_>) -> CargoResult<()> { ); } } else if let Some(prev) = bin_names.insert(target.crate_name(), package) { - failure::bail!( + anyhow::bail!( "The binary `{}` is specified by packages `{}` and \ `{}` but can be documented only once. Consider renaming \ or marking one of the targets as `doc = false`.", @@ -100,7 +98,7 @@ fn open_docs(path: &Path, shell: &mut Shell) -> CargoResult<()> { None => { if let Err(e) = opener::open(&path) { shell.warn(format!("Couldn't open docs: {}", e))?; - for cause in (&e as &dyn Fail).iter_chain() { + for cause in anyhow::Error::new(e).chain().skip(1) { shell.warn(format!("Caused by:\n {}", cause))?; } } diff --git a/src/cargo/ops/cargo_generate_lockfile.rs b/src/cargo/ops/cargo_generate_lockfile.rs index 45c0aa68874..ff5ed4ab467 100644 --- a/src/cargo/ops/cargo_generate_lockfile.rs +++ b/src/cargo/ops/cargo_generate_lockfile.rs @@ -36,15 +36,15 @@ pub fn generate_lockfile(ws: &Workspace<'_>) -> CargoResult<()> { pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoResult<()> { if opts.aggressive && opts.precise.is_some() { - failure::bail!("cannot specify both aggressive and precise simultaneously") + anyhow::bail!("cannot specify both aggressive and precise simultaneously") } if ws.members().count() == 0 { - failure::bail!("you can't generate a lockfile for an empty workspace.") + anyhow::bail!("you can't generate a lockfile for an empty workspace.") } if opts.config.offline() { - failure::bail!("you can't update in the offline mode"); + anyhow::bail!("you can't update in the offline mode"); } // Updates often require a lot of modifications to the registry, so ensure diff --git a/src/cargo/ops/cargo_install.rs b/src/cargo/ops/cargo_install.rs index a5ebba0262b..a2c5565e79f 100644 --- a/src/cargo/ops/cargo_install.rs +++ b/src/cargo/ops/cargo_install.rs @@ -3,7 +3,7 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use std::{env, fs}; -use failure::{bail, format_err}; +use anyhow::{bail, format_err}; use tempfile::Builder as TempFileBuilder; use crate::core::compiler::Freshness; diff --git a/src/cargo/ops/cargo_new.rs b/src/cargo/ops/cargo_new.rs index bd02a0ed4fa..2be8be085bb 100644 --- a/src/cargo/ops/cargo_new.rs +++ b/src/cargo/ops/cargo_new.rs @@ -1,5 +1,5 @@ use crate::core::{compiler, Workspace}; -use crate::util::errors::{self, CargoResult, CargoResultExt}; +use crate::util::errors::{CargoResult, CargoResultExt}; use crate::util::{existing_vcs_repo, FossilRepo, GitRepo, HgRepo, PijulRepo}; use crate::util::{paths, validate_package_name, Config}; use git2::Config as GitConfig; @@ -26,16 +26,16 @@ pub enum VersionControl { } impl FromStr for VersionControl { - type Err = failure::Error; + type Err = anyhow::Error; - fn from_str(s: &str) -> Result { + fn from_str(s: &str) -> Result { match s { "git" => Ok(VersionControl::Git), "hg" => Ok(VersionControl::Hg), "pijul" => Ok(VersionControl::Pijul), "fossil" => Ok(VersionControl::Fossil), "none" => Ok(VersionControl::NoVcs), - other => failure::bail!("unknown vcs specification: `{}`", other), + other => anyhow::bail!("unknown vcs specification: `{}`", other), } } } @@ -110,7 +110,7 @@ impl NewOptions { registry: Option, ) -> CargoResult { let kind = match (bin, lib) { - (true, true) => failure::bail!("can't specify both lib and binary outputs"), + (true, true) => anyhow::bail!("can't specify both lib and binary outputs"), (false, true) => NewProjectKind::Lib, // default to bin (_, false) => NewProjectKind::Bin, @@ -142,14 +142,14 @@ fn get_name<'a>(path: &'a Path, opts: &'a NewOptions) -> CargoResult<&'a str> { } let file_name = path.file_name().ok_or_else(|| { - failure::format_err!( + anyhow::format_err!( "cannot auto-detect package name from path {:?} ; use --name to override", path.as_os_str() ) })?; file_name.to_str().ok_or_else(|| { - failure::format_err!( + anyhow::format_err!( "cannot create package with a non-unicode name: {:?}", file_name ) @@ -174,7 +174,7 @@ fn check_name(name: &str, opts: &NewOptions) -> CargoResult<()> { "true", "type", "typeof", "unsafe", "unsized", "use", "virtual", "where", "while", "yield", ]; if blacklist.contains(&name) || (opts.kind.is_bin() && compiler::is_bad_artifact_name(name)) { - failure::bail!( + anyhow::bail!( "The name `{}` cannot be used as a crate name{}", name, name_help @@ -183,7 +183,7 @@ fn check_name(name: &str, opts: &NewOptions) -> CargoResult<()> { if let Some(ref c) = name.chars().nth(0) { if c.is_digit(10) { - failure::bail!( + anyhow::bail!( "Package names starting with a digit cannot be used as a crate name{}", name_help ) @@ -283,7 +283,7 @@ fn detect_source_paths_and_types( for i in detected_files { if i.bin { if let Some(x) = BTreeMap::get::(&duplicates_checker, i.target_name.as_ref()) { - failure::bail!( + anyhow::bail!( "\ multiple possible binary sources found: {} @@ -296,7 +296,7 @@ cannot automatically generate Cargo.toml as the main target would be ambiguous", duplicates_checker.insert(i.target_name.as_ref(), i); } else { if let Some(plp) = previous_lib_relpath { - failure::bail!( + anyhow::bail!( "cannot have a package with \ multiple libraries, \ found both `{}` and `{}`", @@ -330,7 +330,7 @@ fn plan_new_source_file(bin: bool, package_name: String) -> SourceFileInformatio pub fn new(opts: &NewOptions, config: &Config) -> CargoResult<()> { let path = &opts.path; if fs::metadata(path).is_ok() { - failure::bail!( + anyhow::bail!( "destination `{}` already exists\n\n\ Use `cargo init` to initialize the directory", path.display() @@ -351,7 +351,7 @@ pub fn new(opts: &NewOptions, config: &Config) -> CargoResult<()> { }; mk(config, &mkopts).chain_err(|| { - failure::format_err!( + anyhow::format_err!( "Failed to create package `{}` at `{}`", name, path.display() @@ -364,7 +364,7 @@ pub fn init(opts: &NewOptions, config: &Config) -> CargoResult<()> { let path = &opts.path; if fs::metadata(&path.join("Cargo.toml")).is_ok() { - failure::bail!("`cargo init` cannot be run on existing Cargo packages") + anyhow::bail!("`cargo init` cannot be run on existing Cargo packages") } let name = get_name(path, opts)?; @@ -410,7 +410,7 @@ pub fn init(opts: &NewOptions, config: &Config) -> CargoResult<()> { // if none exists, maybe create git, like in `cargo new` if num_detected_vsces > 1 { - failure::bail!( + anyhow::bail!( "more than one of .hg, .git, .pijul, .fossil configurations \ found and the ignore file can't be filled in as \ a result. specify --vcs to override detection" @@ -429,7 +429,7 @@ pub fn init(opts: &NewOptions, config: &Config) -> CargoResult<()> { }; mk(config, &mkopts).chain_err(|| { - failure::format_err!( + anyhow::format_err!( "Failed to create package `{}` at `{}`", name, path.display() @@ -527,7 +527,7 @@ fn write_ignore_file( let ignore: String = match fs::File::open(&fp_ignore) { Err(why) => match why.kind() { ErrorKind::NotFound => list.format_new(vcs), - _ => return Err(failure::format_err!("{}", why)), + _ => return Err(anyhow::format_err!("{}", why)), }, Ok(file) => list.format_existing(BufReader::new(file), vcs), }; @@ -713,8 +713,8 @@ mod tests { if let Err(e) = Workspace::new(&path.join("Cargo.toml"), config) { let msg = format!( "compiling this new crate may not work due to invalid \ - workspace configuration\n\n{}", - errors::display_causes(&e) + workspace configuration\n\n{:?}", + e, ); config.shell().warn(msg)?; } @@ -752,7 +752,7 @@ fn discover_author() -> CargoResult<(String, Option)> { Some(name) => name, None => { let username_var = if cfg!(windows) { "USERNAME" } else { "USER" }; - failure::bail!( + anyhow::bail!( "could not determine the current user, please set ${}", username_var ) diff --git a/src/cargo/ops/cargo_output_metadata.rs b/src/cargo/ops/cargo_output_metadata.rs index b6fee6ea06f..6c3ef3ea8c7 100644 --- a/src/cargo/ops/cargo_output_metadata.rs +++ b/src/cargo/ops/cargo_output_metadata.rs @@ -24,7 +24,7 @@ pub struct OutputMetadataOptions { /// format to stdout. pub fn output_metadata(ws: &Workspace<'_>, opt: &OutputMetadataOptions) -> CargoResult { if opt.version != VERSION { - failure::bail!( + anyhow::bail!( "metadata version {} not supported, only {} is currently supported", opt.version, VERSION diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs index 4fb1bfe4d36..1fbcd717651 100644 --- a/src/cargo/ops/cargo_package.rs +++ b/src/cargo/ops/cargo_package.rs @@ -123,7 +123,7 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult