Skip to content

Commit

Permalink
Show information about abnormal fix errors.
Browse files Browse the repository at this point in the history
  • Loading branch information
ehuss committed Aug 17, 2021
1 parent 649822b commit 5f274b0
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 4 deletions.
19 changes: 16 additions & 3 deletions src/cargo/ops/fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ use std::process::{self, Command, ExitStatus};
use std::str;

use anyhow::{bail, Context, Error};
use cargo_util::{paths, ProcessBuilder};
use cargo_util::{exit_status_to_string, is_simple_exit_code, paths, ProcessBuilder};
use log::{debug, trace, warn};
use rustfix::diagnostics::Diagnostic;
use rustfix::{self, CodeFix};
Expand Down Expand Up @@ -374,7 +374,7 @@ pub fn fix_maybe_exec_rustc(config: &Config) -> CargoResult<bool> {
paths::write(path, &file.original_code)?;
}
}
log_failed_fix(&output.stderr)?;
log_failed_fix(&output.stderr, output.status)?;
}
}

Expand Down Expand Up @@ -662,7 +662,7 @@ fn exit_with(status: ExitStatus) -> ! {
process::exit(status.code().unwrap_or(3));
}

fn log_failed_fix(stderr: &[u8]) -> Result<(), Error> {
fn log_failed_fix(stderr: &[u8], status: ExitStatus) -> Result<(), Error> {
let stderr = str::from_utf8(stderr).context("failed to parse rustc stderr as utf-8")?;

let diagnostics = stderr
Expand All @@ -677,6 +677,13 @@ fn log_failed_fix(stderr: &[u8]) -> Result<(), Error> {
files.insert(span.file_name);
}
}
// Include any abnormal messages (like an ICE or whatever).
errors.extend(
stderr
.lines()
.filter(|x| !x.starts_with('{'))
.map(|x| x.to_string()),
);
let mut krate = None;
let mut prev_dash_dash_krate_name = false;
for arg in env::args() {
Expand All @@ -692,10 +699,16 @@ fn log_failed_fix(stderr: &[u8]) -> Result<(), Error> {
}

let files = files.into_iter().collect();
let abnormal_exit = if status.code().map_or(false, is_simple_exit_code) {
None
} else {
Some(exit_status_to_string(status))
};
Message::FixFailed {
files,
krate,
errors,
abnormal_exit,
}
.post()?;

Expand Down
9 changes: 9 additions & 0 deletions src/cargo/util/diagnostic_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub enum Message {
files: Vec<String>,
krate: Option<String>,
errors: Vec<String>,
abnormal_exit: Option<String>,
},
ReplaceFailed {
file: String,
Expand Down Expand Up @@ -135,6 +136,7 @@ impl<'a> DiagnosticPrinter<'a> {
files,
krate,
errors,
abnormal_exit,
} => {
if let Some(ref krate) = *krate {
self.config.shell().warn(&format!(
Expand Down Expand Up @@ -171,6 +173,13 @@ impl<'a> DiagnosticPrinter<'a> {
}
}
}
if let Some(exit) = abnormal_exit {
writeln!(
self.config.shell().err(),
"rustc exited abnormally: {}",
exit
)?;
}
writeln!(
self.config.shell().err(),
"Original diagnostics will follow.\n"
Expand Down
81 changes: 80 additions & 1 deletion tests/testsuite/fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use cargo::core::Edition;
use cargo_test_support::compare::assert_match_exact;
use cargo_test_support::git;
use cargo_test_support::paths::CargoPathExt;
use cargo_test_support::paths::{self, CargoPathExt};
use cargo_test_support::registry::{Dependency, Package};
use cargo_test_support::tools;
use cargo_test_support::{basic_manifest, is_nightly, project};
Expand Down Expand Up @@ -1597,3 +1597,82 @@ fn fix_shared_cross_workspace() {
&p.read_file("foo/src/shared.rs"),
);
}

#[cargo_test]
fn abnormal_exit() {
// rustc fails unexpectedly after applying fixes, should show some error information.
//
// This works with a proc-macro that runs three times:
// - First run (collect diagnostics pass): writes a file, exits normally.
// - Second run (verify diagnostics work): it detects the presence of the
// file, removes the file, and aborts the process.
// - Third run (collecting messages to display): file not found, exits normally.
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
pm = {path="pm"}
"#,
)
.file(
"src/lib.rs",
r#"
pub fn f() {
let mut x = 1;
pm::crashme!();
}
"#,
)
.file(
"pm/Cargo.toml",
r#"
[package]
name = "pm"
version = "0.1.0"
edition = "2018"
[lib]
proc-macro = true
"#,
)
.file(
"pm/src/lib.rs",
r#"
use proc_macro::TokenStream;
#[proc_macro]
pub fn crashme(_input: TokenStream) -> TokenStream {
// Use a file to succeed on the first pass, and fail on the second.
let p = std::env::var_os("ONCE_PATH").unwrap();
let check_path = std::path::Path::new(&p);
if check_path.exists() {
eprintln!("I'm not a diagnostic.");
std::fs::remove_file(check_path).unwrap();
std::process::abort();
} else {
std::fs::write(check_path, "").unwrap();
"".parse().unwrap()
}
}
"#,
)
.build();

p.cargo("fix --lib --allow-no-vcs")
.env(
"ONCE_PATH",
paths::root().join("proc-macro-run-once").to_str().unwrap(),
)
.with_stderr_contains(
"[WARNING] failed to automatically apply fixes suggested by rustc to crate `foo`",
)
.with_stderr_contains("I'm not a diagnostic.")
// "signal: 6, SIGABRT: process abort signal" on some platforms
.with_stderr_contains("rustc exited abnormally: [..]")
.with_stderr_contains("Original diagnostics will follow.")
.run();
}

0 comments on commit 5f274b0

Please sign in to comment.