From 85c36d7e9fe556c5b660d3b6bb9a20f5c7ba3801 Mon Sep 17 00:00:00 2001 From: "Samuel E. Moelius III" Date: Mon, 11 Oct 2021 19:27:32 -0400 Subject: [PATCH] Improve error messages --- cargo-dylint/tests/custom_toolchain.rs | 4 +- cargo-dylint/tests/package_options.rs | 10 +++- dylint-link/src/main.rs | 10 +++- dylint/src/driver_builder.rs | 74 +++++++++++++++++--------- dylint/src/lib.rs | 6 ++- dylint/src/package_options.rs | 56 ++++++++++++++----- examples/clippy/tests/ui.rs | 21 +++++--- internal/src/command.rs | 12 +++-- internal/src/examples.rs | 18 ++++--- internal/src/filename.rs | 1 + internal/src/packaging.rs | 27 ++++++---- internal/src/rustup.rs | 5 +- internal/src/sed.rs | 5 +- scripts/lint.sh | 4 -- utils/testing/src/lib.rs | 26 ++++++--- 15 files changed, 192 insertions(+), 87 deletions(-) diff --git a/cargo-dylint/tests/custom_toolchain.rs b/cargo-dylint/tests/custom_toolchain.rs index 148bea485..d86ef052d 100644 --- a/cargo-dylint/tests/custom_toolchain.rs +++ b/cargo-dylint/tests/custom_toolchain.rs @@ -2,7 +2,7 @@ // "Only the MSVC toolchain is supported on Windows" #[cfg(not(target_os = "windows"))] mod custom_toolchain { - use anyhow::{anyhow, Result}; + use anyhow::{anyhow, Context, Result}; use dylint_internal::{ find_and_replace, rustup::{toolchain_path, SanitizeEnvironment}, @@ -36,7 +36,7 @@ mod custom_toolchain { } fn random_string() -> Result { - let tempfile = NamedTempFile::new()?; + let tempfile = NamedTempFile::new().with_context(|| "Could not create named temp file")?; tempfile .path() .file_name() diff --git a/cargo-dylint/tests/package_options.rs b/cargo-dylint/tests/package_options.rs index 374a2477e..cb214ba83 100644 --- a/cargo-dylint/tests/package_options.rs +++ b/cargo-dylint/tests/package_options.rs @@ -1,4 +1,4 @@ -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, Context, Result}; use assert_cmd::prelude::*; use dylint_internal::rustup::SanitizeEnvironment; use regex::Regex; @@ -95,7 +95,13 @@ fn upgrade_package() { fn rust_version(path: &Path) -> Result { let re = Regex::new(r#"^clippy_utils = .*\btag = "rust-([^"]*)""#).unwrap(); - let file = read_to_string(path.join("Cargo.toml"))?; + let manifest = path.join("Cargo.toml"); + let file = read_to_string(&manifest).with_context(|| { + format!( + "`read_to_string` failed for `{}`", + manifest.to_string_lossy() + ) + })?; let rust_version = file .lines() .find_map(|line| re.captures(line).map(|captures| captures[1].to_owned())) diff --git a/dylint-link/src/main.rs b/dylint-link/src/main.rs index 1a4f44f6b..a3c91cbaa 100644 --- a/dylint-link/src/main.rs +++ b/dylint-link/src/main.rs @@ -4,7 +4,7 @@ #[cfg(target_os = "windows")] use anyhow::ensure; -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, Context, Result}; use dylint_internal::{ env::{self, var}, library_filename, Command, @@ -137,7 +137,13 @@ fn copy_library(path: &Path) -> Result<()> { .parent() .ok_or_else(|| anyhow!("Could not get parent directory"))?; let path_with_toolchain = strip_deps(parent).join(filename_with_toolchain); - copy(path, path_with_toolchain)?; + copy(&path, &path_with_toolchain).with_context(|| { + format!( + "Could not copy `{}` to `{}`", + path.to_string_lossy(), + path_with_toolchain.to_string_lossy() + ) + })?; } } diff --git a/dylint/src/driver_builder.rs b/dylint/src/driver_builder.rs index c31d5bbad..80c747adf 100644 --- a/dylint/src/driver_builder.rs +++ b/dylint/src/driver_builder.rs @@ -1,5 +1,5 @@ use crate::error::warn; -use anyhow::{anyhow, ensure, Result}; +use anyhow::{anyhow, ensure, Context, Result}; use cargo_metadata::MetadataCommand; use dylint_internal::{ env::{self, var}, @@ -71,7 +71,12 @@ pub fn get(opts: &crate::Dylint, toolchain: &str) -> Result { let driver_dir = dylint_drivers.join(&toolchain); if !driver_dir.is_dir() { - create_dir_all(&driver_dir)?; + create_dir_all(&driver_dir).with_context(|| { + format!( + "`create_dir_all` failed for `{}`", + driver_dir.to_string_lossy() + ) + })?; } let driver = driver_dir.join("dylint-driver"); @@ -91,8 +96,16 @@ fn dylint_drivers() -> Result { let home = dirs::home_dir().ok_or_else(|| anyhow!("Could not find HOME directory"))?; let dylint_drivers = Path::new(&home).join(".dylint_drivers"); if !dylint_drivers.is_dir() { - create_dir_all(&dylint_drivers)?; - write(dylint_drivers.join("README.txt"), README_TXT)?; + create_dir_all(&dylint_drivers).with_context(|| { + format!( + "`create_dir_all` failed for `{}`", + dylint_drivers.to_string_lossy() + ) + })?; + let readme_txt = dylint_drivers.join("README.txt"); + write(&readme_txt, README_TXT).with_context(|| { + format!("`write` failed for `{}`", readme_txt.to_string_lossy()) + })?; } Ok(dylint_drivers) } @@ -104,9 +117,9 @@ fn is_outdated(opts: &crate::Dylint, toolchain: &str, driver: &Path) -> Result Result { warn( opts, - &format!("Could not determine driver version: {}", err), + &format!("Could not parse driver version `{}`: {}", theirs, err), ); return Ok(true); } @@ -129,7 +142,7 @@ fn is_outdated(opts: &crate::Dylint, toolchain: &str, driver: &Path) -> Result Result<()> { - let tempdir = tempdir()?; + let tempdir = tempdir().with_context(|| "`tempdir` failed")?; let package = tempdir.path(); initialize(toolchain, package)?; @@ -160,14 +173,18 @@ fn build(opts: &crate::Dylint, toolchain: &str, driver: &Path) -> Result<()> { } command.success()?; - copy( - metadata.target_directory.join("debug").join(format!( - "dylint_driver-{}{}", - toolchain, - consts::EXE_SUFFIX - )), - driver, - )?; + let binary = metadata.target_directory.join("debug").join(format!( + "dylint_driver-{}{}", + toolchain, + consts::EXE_SUFFIX + )); + copy(&binary, driver).with_context(|| { + format!( + "Could not copy `{}` to `{}`", + binary, + driver.to_string_lossy() + ) + })?; Ok(()) } @@ -180,6 +197,7 @@ fn initialize(toolchain: &str, package: &Path) -> Result<()> { #[cfg(any(not(debug_assertions), not(feature = "dylint_driver_local")))] let path_spec = ""; #[cfg(all(debug_assertions, feature = "dylint_driver_local"))] + #[allow(clippy::expect_used)] let path_spec = format!( ", path = \"{}\"", Path::new(env!("CARGO_MANIFEST_DIR")) @@ -192,14 +210,22 @@ fn initialize(toolchain: &str, package: &Path) -> Result<()> { let dylint_driver_spec = format!("{}{}", version_spec, path_spec); - write( - package.join("Cargo.toml"), - cargo_toml(toolchain, &dylint_driver_spec), - )?; - write(package.join("rust-toolchain"), rust_toolchain(toolchain))?; + let cargo_toml_path = package.join("Cargo.toml"); + write(&cargo_toml_path, cargo_toml(toolchain, &dylint_driver_spec)) + .with_context(|| format!("`write` failed for `{}`", cargo_toml_path.to_string_lossy()))?; + let rust_toolchain_path = package.join("rust-toolchain"); + write(&rust_toolchain_path, rust_toolchain(toolchain)).with_context(|| { + format!( + "`write` failed for `{}`", + rust_toolchain_path.to_string_lossy() + ) + })?; let src = package.join("src"); - create_dir_all(&src)?; - write(&src.join("main.rs"), MAIN_RS)?; + create_dir_all(&src) + .with_context(|| format!("`create_dir_all` failed for `{}`", src.to_string_lossy()))?; + let main_rs = src.join("main.rs"); + write(&main_rs, MAIN_RS) + .with_context(|| format!("`write` failed for `{}`", main_rs.to_string_lossy()))?; Ok(()) } diff --git a/dylint/src/lib.rs b/dylint/src/lib.rs index eff46bc76..56621deb3 100644 --- a/dylint/src/lib.rs +++ b/dylint/src/lib.rs @@ -142,9 +142,11 @@ fn dylint_libraries_in( ) -> Result>> { let iter = read_dir(path) .with_context(|| format!("`read_dir` failed for `{}`", path.to_string_lossy()))?; + let path = path.to_path_buf(); Ok(iter - .map(|entry| -> Result> { - let entry = entry?; + .map(move |entry| -> Result> { + let entry = entry + .with_context(|| format!("`read_dir` failed for `{}`", path.to_string_lossy()))?; let path = entry.path(); Ok(if let Some(filename) = path.file_name() { diff --git a/dylint/src/package_options.rs b/dylint/src/package_options.rs index 7c291aff3..0d91dd2b4 100644 --- a/dylint/src/package_options.rs +++ b/dylint/src/package_options.rs @@ -1,8 +1,8 @@ use crate::Dylint; -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, Context, Result}; use dylint_internal::find_and_replace; use git2::Repository; -use heck::*; +use heck::{CamelCase, KebabCase, ShoutySnakeCase, SnakeCase}; use lazy_static::lazy_static; use semver::Version; use std::{ @@ -35,8 +35,8 @@ pub fn new_package(opts: &Dylint, path: &Path) -> Result<()> { .map(|s| s.to_string_lossy().to_string()) .ok_or_else(|| anyhow!("Could not determine library name from {:?}", path))?; - let checked_out = tempdir()?; - let filtered = tempdir()?; + let checked_out = tempdir().with_context(|| "`tempdir` failed")?; + let filtered = tempdir().with_context(|| "`tempdir` failed")?; dylint_internal::clone(DYLINT_TEMPLATE_URL, "master", checked_out.path())?; @@ -55,13 +55,25 @@ fn filter(name: &str, from: &Path, to: &Path) -> Result<()> { let lower_snake_case = name.to_snake_case(); for path in &*PATHS { + let from_path = from.join(path); let to_path = if path == &Path::new("src").join("fill_me_in.rs") { to.join("src").join(&lower_snake_case).with_extension("rs") } else { to.join(path) }; - to_path.parent().map(create_dir_all).transpose()?; - copy(from.join(path), to_path)?; + let parent = to_path + .parent() + .ok_or_else(|| anyhow!("Could not get parent directory"))?; + create_dir_all(parent).with_context(|| { + format!("`create_dir_all` failed for `{}`", parent.to_string_lossy()) + })?; + copy(&from_path, &to_path).with_context(|| { + format!( + "Could not copy `{}` to `{}`", + from_path.to_string_lossy(), + to_path.to_string_lossy() + ) + })?; } Ok(()) @@ -99,15 +111,28 @@ fn rename(name: &str, from: &Path, to: &Path) -> Result<()> { &[&format!(r#"s/\bFillMeIn\b/{}/g"#, camel_case)], )?; - to.join(rel_path).parent().map(create_dir_all).transpose()?; - copy(from.join(rel_path), to.join(rel_path))?; + let from_path = from.join(rel_path); + let to_path = to.join(rel_path); + let parent = to_path + .parent() + .ok_or_else(|| anyhow!("Could not get parent directory"))?; + create_dir_all(parent).with_context(|| { + format!("`create_dir_all` failed for `{}`", parent.to_string_lossy()) + })?; + copy(&from_path, &to_path).with_context(|| { + format!( + "Could not copy `{}` to `{}`", + from_path.to_string_lossy(), + to_path.to_string_lossy() + ) + })?; } Ok(()) } pub fn upgrade_package(opts: &Dylint, path: &Path) -> Result<()> { - let tempdir = tempdir()?; + let tempdir = tempdir().with_context(|| "`tempdir` failed")?; let refname = match &opts.rust_version { Some(rust_version) => format!("rust-{}", rust_version), @@ -120,7 +145,7 @@ pub fn upgrade_package(opts: &Dylint, path: &Path) -> Result<()> { Some(rust_version) => format!("rust-{}", rust_version), None => { let version = latest_rust_version(&repository)?; - format!("rust-{}", version.to_string()) + format!("rust-{}", version) } }; @@ -148,8 +173,7 @@ fn latest_rust_version(repository: &Repository) -> Result { let tags = repository.tag_names(Some("rust-*"))?; let mut rust_versions = tags .iter() - .map(|s| s.map(|s| s.strip_prefix("rust-")).flatten()) - .flatten() + .filter_map(|s| s.and_then(|s| s.strip_prefix("rust-"))) .map(Version::parse) .collect::, _>>()?; rust_versions.sort(); @@ -159,7 +183,13 @@ fn latest_rust_version(repository: &Repository) -> Result { } fn channel_line(path: &Path) -> Result { - let file = read_to_string(path.join("rust-toolchain"))?; + let rust_toolchain = path.join("rust-toolchain"); + let file = read_to_string(&rust_toolchain).with_context(|| { + format!( + "`read_to_string` failed for `{}`", + rust_toolchain.to_string_lossy(), + ) + })?; file.lines() .find(|line| line.starts_with("channel = ")) .map(ToOwned::to_owned) diff --git a/examples/clippy/tests/ui.rs b/examples/clippy/tests/ui.rs index 2bfd7594c..06f1c6553 100644 --- a/examples/clippy/tests/ui.rs +++ b/examples/clippy/tests/ui.rs @@ -1,4 +1,4 @@ -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, Context, Result}; use cargo_metadata::Dependency; use dylint_internal::{cargo::current_metadata, env, find_and_replace, packaging::isolate}; use std::{ @@ -100,8 +100,11 @@ fn clippy_lints_dependency() -> Result { } fn disable_rustfix(src_base: &Path) -> Result<()> { - for entry in read_dir(src_base)? { - let entry = entry?; + for entry in read_dir(src_base) + .with_context(|| format!("`read_dir` failed for `{}`", src_base.to_string_lossy()))? + { + let entry = entry + .with_context(|| format!("`read_dir` failed for `{}`", src_base.to_string_lossy()))?; let path = entry.path(); if path.extension() != Some(OsStr::new("rs")) { continue; @@ -118,7 +121,12 @@ fn disable_rustfix(src_base: &Path) -> Result<()> { #[allow(clippy::shadow_unrelated)] fn adjust_macro_use_imports_test(src_base: &Path) -> Result<()> { let stderr_file = src_base.join("macro_use_imports.stderr"); - let contents = read_to_string(&stderr_file)?; + let contents = read_to_string(&stderr_file).with_context(|| { + format!( + "`read_to_string` failed for `{}`", + stderr_file.to_string_lossy() + ) + })?; let lines: Vec = contents.lines().map(ToString::to_string).collect(); let (first_error, rest) = lines.split_at(ERROR_LINES); @@ -151,12 +159,13 @@ fn adjust_macro_use_imports_test(src_base: &Path) -> Result<()> { assert_eq!(lines_sorted, permuted_sorted); write( - stderr_file, + &stderr_file, permuted .iter() .map(|line| format!("{}\n", line)) .collect::(), - )?; + ) + .with_context(|| format!("Could not write to `{}`", stderr_file.to_string_lossy()))?; Ok(()) } diff --git a/internal/src/command.rs b/internal/src/command.rs index 94d8f5b27..5b863be86 100644 --- a/internal/src/command.rs +++ b/internal/src/command.rs @@ -1,5 +1,5 @@ use crate::env::{self, var}; -use anyhow::{ensure, Result}; +use anyhow::{ensure, Context, Result}; use std::{ env::{join_paths, split_paths}, ffi::{OsStr, OsString}, @@ -62,7 +62,10 @@ impl Command { log::debug!("{:?}", self.envs); log::debug!("{:?}", self.command); - let output = self.command.output()?; + let output = self + .command + .output() + .with_context(|| format!("Could not get output of `{:?}`", self.command))?; ensure!( output.status.success(), @@ -81,7 +84,10 @@ impl Command { log::debug!("{:?}", self.envs); log::debug!("{:?}", self.command); - let status = self.command.status()?; + let status = self + .command + .status() + .with_context(|| format!("Could not get status of `{:?}`", self.command))?; ensure!(status.success(), "command failed: {:?}", self.command); diff --git a/internal/src/examples.rs b/internal/src/examples.rs index 99fed02ea..c4a7bf8b9 100644 --- a/internal/src/examples.rs +++ b/internal/src/examples.rs @@ -1,5 +1,5 @@ use crate::rustup::SanitizeEnvironment; -use anyhow::Result; +use anyhow::{Context, Result}; use std::{ fs::read_dir, path::{Path, PathBuf}, @@ -28,14 +28,16 @@ pub fn build() -> Result<()> { } pub fn iter() -> Result>> { - let iter = read_dir( - Path::new(env!("CARGO_MANIFEST_DIR")) - .join("..") - .join("examples"), - )?; + let examples = Path::new(env!("CARGO_MANIFEST_DIR")) + .join("..") + .join("examples"); + let iter = read_dir(&examples) + .with_context(|| format!("`read_dir` failed for `{}`", examples.to_string_lossy()))?; Ok(iter - .map(|entry| -> Result> { - let entry = entry?; + .map(move |entry| -> Result> { + let entry = entry.with_context(|| { + format!("`read_dir` failed for `{}`", examples.to_string_lossy()) + })?; let path = entry.path(); Ok(if path.is_dir() { Some(path) } else { None }) }) diff --git a/internal/src/filename.rs b/internal/src/filename.rs index 86e8c85db..9b458ca86 100644 --- a/internal/src/filename.rs +++ b/internal/src/filename.rs @@ -1,5 +1,6 @@ use std::env::consts; +#[must_use] pub fn library_filename(lib_name: &str, toolchain: &str) -> String { format!( "{}{}@{}{}", diff --git a/internal/src/packaging.rs b/internal/src/packaging.rs index 550889585..260ec03e6 100644 --- a/internal/src/packaging.rs +++ b/internal/src/packaging.rs @@ -2,19 +2,22 @@ use crate::{ cargo::{current_metadata, package}, sed::find_and_replace, }; -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, Context, Result}; use std::{fs::OpenOptions, io::Write, path::Path}; // smoelius: If a package is checked out in the current directory, this must be dealt with: // error: current package believes it's in a workspace when it's not pub fn isolate(path: &Path) -> Result<()> { + let manifest = path.join("Cargo.toml"); let mut file = OpenOptions::new() .write(true) .append(true) - .open(path.join("Cargo.toml"))?; + .open(&manifest) + .with_context(|| format!("Could not open `{}`", manifest.to_string_lossy()))?; - writeln!(file)?; - writeln!(file, "[workspace]")?; + writeln!(file) + .and_then(|_| writeln!(file, "[workspace]")) + .with_context(|| format!("Could not write to `{}`", manifest.to_string_lossy()))?; Ok(()) } @@ -35,23 +38,29 @@ pub fn use_local_packages(path: &Path) -> Result<()> { ], )?; - let mut file = OpenOptions::new().write(true).append(true).open(manifest)?; + let mut file = OpenOptions::new() + .write(true) + .append(true) + .open(&manifest) + .with_context(|| format!("Could not open `{}`", manifest.to_string_lossy()))?; - writeln!(file)?; - writeln!(file, "[patch.crates-io]")?; + writeln!(file) + .and_then(|_| writeln!(file, "[patch.crates-io]")) + .with_context(|| format!("Could not write to `{}`", manifest.to_string_lossy()))?; for package_id in &metadata.workspace_members { let package = package(&metadata, package_id)?; let path = package .manifest_path .parent() - .ok_or_else(|| anyhow!("Could not get parent"))?; + .ok_or_else(|| anyhow!("Could not get parent directory"))?; writeln!( file, r#"{} = {{ path = "{}" }}"#, package.name, path.to_string().replace('\\', "\\\\") - )?; + ) + .with_context(|| format!("Could not write to `{}`", manifest.to_string_lossy()))?; } Ok(()) diff --git a/internal/src/rustup.rs b/internal/src/rustup.rs index d9d10f5ef..4f8c9be9e 100644 --- a/internal/src/rustup.rs +++ b/internal/src/rustup.rs @@ -24,9 +24,8 @@ pub fn active_toolchain(path: &Path) -> Result { .output()?; let stdout = std::str::from_utf8(&output.stdout)?; stdout - .splitn(2, ' ') - .next() - .map(ToOwned::to_owned) + .split_once(' ') + .map(|pair| pair.0.to_owned()) .ok_or_else(|| anyhow!("Could not determine active toolchain")) } diff --git a/internal/src/sed.rs b/internal/src/sed.rs index be1362daa..25dbaa30c 100644 --- a/internal/src/sed.rs +++ b/internal/src/sed.rs @@ -1,4 +1,4 @@ -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, Context, Result}; use std::{ fs::{read_to_string, write}, path::Path, @@ -9,7 +9,8 @@ where I: IntoIterator, I::Item: AsRef, { - let before = read_to_string(path)?; + let before = read_to_string(path) + .with_context(|| format!("`read_to_string` failed for `{}`", path.to_string_lossy()))?; let after = sedregex::find_and_replace(&before, commands).map_err(|error| anyhow!("{}", error))?; write(path, after.as_bytes()).map_err(Into::into) diff --git a/scripts/lint.sh b/scripts/lint.sh index 17d614057..1e029246b 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -19,10 +19,6 @@ EXAMPLES="$(find examples -mindepth 1 -maxdepth 1 -type d | xargs -n 1 basename) # different toolchain than the other examples. EXAMPLES="$(echo "$EXAMPLES" | sed 's/\[[:space:]]*//')" -# smoelius: Also remove `try_io_result`. It will need to be integrated eventually. But right now, it -# wreaks havoc. -EXAMPLES="$(echo "$EXAMPLES" | sed 's/\[[:space:]]*//')" - DIRS=". driver" for EXAMPLE in $EXAMPLES; do DIRS="$DIRS examples/$EXAMPLE" diff --git a/utils/testing/src/lib.rs b/utils/testing/src/lib.rs index 8b293fe7b..01ce617fd 100644 --- a/utils/testing/src/lib.rs +++ b/utils/testing/src/lib.rs @@ -1,4 +1,4 @@ -use anyhow::{anyhow, ensure, Result}; +use anyhow::{anyhow, ensure, Context, Result}; use cargo_metadata::{Metadata, Package, Target}; use compiletest_rs::{self as compiletest, common::Mode as TestMode}; use dylint_internal::{ @@ -110,11 +110,17 @@ fn run_example_test( .file_name() .ok_or_else(|| anyhow!("Could not get file name"))?; - let tempdir = tempfile::tempdir()?; + let tempdir = tempfile::tempdir().with_context(|| "`tempdir` failed")?; let src_base = tempdir.path(); let to = src_base.join(file_name); - copy(&target.src_path, &to)?; + copy(&target.src_path, &to).with_context(|| { + format!( + "Could not copy `{}` to `{}`", + target.src_path, + to.to_string_lossy() + ) + })?; copy_with_extension(&target.src_path, &to, "stderr").unwrap_or_default(); copy_with_extension(&target.src_path, &to, "stdout").unwrap_or_default(); @@ -193,7 +199,8 @@ fn rustc_flags(metadata: &Metadata, package: &Package, target: &Target) -> Resul .stderr .lines() .map(|line| { - let line = line?; + let line = + line.with_context(|| format!("Could not read from `{}`", package.manifest_path))?; Ok((*RE).captures(&line).and_then(|captures| { let args = captures[1] .split(' ') @@ -225,8 +232,11 @@ fn rustc_flags(metadata: &Metadata, package: &Package, target: &Target) -> Resul } fn remove_example(metadata: &Metadata, _package: &Package, target: &Target) -> Result<()> { - for entry in read_dir(metadata.target_directory.join("debug").join("examples"))? { - let entry = entry?; + let examples = metadata.target_directory.join("debug").join("examples"); + for entry in + read_dir(&examples).with_context(|| format!("`read_dir` failed for `{}`", examples))? + { + let entry = entry.with_context(|| format!("`read_dir` failed for `{}`", examples))?; let path = entry.path(); if let Some(file_name) = path.file_name() { @@ -234,7 +244,9 @@ fn remove_example(metadata: &Metadata, _package: &Package, target: &Target) -> R if s == target.name.clone() + consts::EXE_SUFFIX || s.starts_with(&(target.name.clone() + "-")) { - remove_file(path)?; + remove_file(&path).with_context(|| { + format!("`remove_file` failed for `{}`", path.to_string_lossy()) + })?; } } }