diff --git a/src/cargo/core/compiler/future_incompat.rs b/src/cargo/core/compiler/future_incompat.rs index b940bb2b7d0..d9638deddac 100644 --- a/src/cargo/core/compiler/future_incompat.rs +++ b/src/cargo/core/compiler/future_incompat.rs @@ -51,6 +51,7 @@ pub struct FutureBreakageItem { #[derive(Serialize, Deserialize)] pub struct Diagnostic { pub rendered: String, + pub level: String, } /// The filename in the top-level `target` directory where we store diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index e5ea065983b..88290875887 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -333,7 +333,20 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc) -> Car }, ) .map_err(verbose_if_simple_exit_code) - .with_context(|| format!("could not compile `{}`", name))?; + .with_context(|| { + // adapted from rustc_errors/src/lib.rs + let warnings = match output_options.warnings_seen { + 0 => String::new(), + 1 => "; 1 warning emitted".to_string(), + count => format!("; {} warnings emitted", count), + }; + let errors = match output_options.errors_seen { + 0 => String::new(), + 1 => " due to previous error".to_string(), + count => format!(" due to {} previous errors", count), + }; + format!("could not compile `{}`{}{}", name, errors, warnings) + })?; } if rustc_dep_info_loc.exists() { @@ -1161,6 +1174,8 @@ struct OutputOptions { /// Other types of messages are processed regardless /// of the value of this flag show_warnings: bool, + warnings_seen: usize, + errors_seen: usize, } impl OutputOptions { @@ -1177,6 +1192,8 @@ impl OutputOptions { color, cache_cell, show_warnings: true, + warnings_seen: 0, + errors_seen: 0, } } } @@ -1244,7 +1261,18 @@ fn on_stderr_line_inner( } }; + let count_diagnostic = |level, options: &mut OutputOptions| { + if level == "warning" { + options.warnings_seen += 1; + } else if level == "error" { + options.errors_seen += 1; + } + }; + if let Ok(report) = serde_json::from_str::(compiler_message.get()) { + for item in &report.future_incompat_report { + count_diagnostic(&*item.diagnostic.level, options); + } state.future_incompat_report(report.future_incompat_report); return Ok(true); } @@ -1265,8 +1293,14 @@ fn on_stderr_line_inner( #[derive(serde::Deserialize)] struct CompilerMessage { rendered: String, + message: String, + level: String, } if let Ok(mut error) = serde_json::from_str::(compiler_message.get()) { + if error.level == "error" && error.message.starts_with("aborting due to") { + // Skip this line; we'll print our own summary at the end. + return Ok(true); + } // state.stderr will add a newline if error.rendered.ends_with('\n') { error.rendered.pop(); @@ -1281,6 +1315,7 @@ fn on_stderr_line_inner( .expect("strip should never fail") }; if options.show_warnings { + count_diagnostic(&error.level, options); state.stderr(rendered)?; } return Ok(true); @@ -1368,6 +1403,14 @@ fn on_stderr_line_inner( return Ok(true); } + #[derive(serde::Deserialize)] + struct CompilerMessage { + level: String, + } + if let Ok(message) = serde_json::from_str::(compiler_message.get()) { + count_diagnostic(&message.level, options); + } + let msg = machine_message::FromCompiler { package_id, manifest_path, @@ -1399,6 +1442,8 @@ fn replay_output_cache( color, cache_cell: None, show_warnings, + warnings_seen: 0, + errors_seen: 0, }; Work::new(move |state| { if !path.exists() { diff --git a/tests/testsuite/build.rs b/tests/testsuite/build.rs index 595c5c687dc..40b63a669a4 100644 --- a/tests/testsuite/build.rs +++ b/tests/testsuite/build.rs @@ -588,12 +588,7 @@ fn cargo_compile_with_invalid_code() { p.cargo("build") .with_status(101) - .with_stderr_contains( - "\ -[ERROR] could not compile `foo` - -To learn more, run the command again with --verbose.\n", - ) + .with_stderr_contains("[ERROR] could not compile `foo` due to previous error\n") .run(); assert!(p.root().join("Cargo.lock").is_file()); } diff --git a/tests/testsuite/build_script.rs b/tests/testsuite/build_script.rs index da0bb4ba5eb..e9a24a32683 100644 --- a/tests/testsuite/build_script.rs +++ b/tests/testsuite/build_script.rs @@ -1458,7 +1458,7 @@ fn build_deps_not_for_normal() { .with_stderr_contains("[..]can't find crate for `aaaaa`[..]") .with_stderr_contains( "\ -[ERROR] could not compile `foo` +[ERROR] could not compile `foo` due to previous error Caused by: process didn't exit successfully: [..] diff --git a/tests/testsuite/check.rs b/tests/testsuite/check.rs index d4144eb17dc..e37d572f568 100644 --- a/tests/testsuite/check.rs +++ b/tests/testsuite/check.rs @@ -803,8 +803,7 @@ fn short_message_format() { .with_stderr_contains( "\ src/lib.rs:1:27: error[E0308]: mismatched types -error: aborting due to previous error -error: could not compile `foo` +error: could not compile `foo` due to previous error ", ) .run(); diff --git a/tests/testsuite/fix.rs b/tests/testsuite/fix.rs index fa0fa420b64..1d2877b4b16 100644 --- a/tests/testsuite/fix.rs +++ b/tests/testsuite/fix.rs @@ -28,7 +28,7 @@ fn do_not_fix_broken_builds() { p.cargo("fix --allow-no-vcs") .env("__CARGO_FIX_YOLO", "1") .with_status(101) - .with_stderr_contains("[ERROR] could not compile `foo`") + .with_stderr_contains("[ERROR] could not compile `foo` due to previous error") .run(); assert!(p.read_file("src/lib.rs").contains("let mut x = 3;")); } @@ -833,8 +833,6 @@ fn prepare_for_unstable() { [ERROR] cannot migrate src/lib.rs to edition {next} Edition {next} is unstable and not allowed in this release, consider trying the nightly release channel. error: could not compile `foo` - -To learn more, run the command again with --verbose. ", next=next)) .run(); diff --git a/tests/testsuite/install.rs b/tests/testsuite/install.rs index dfb5f96f19a..5d16ed99a03 100644 --- a/tests/testsuite/install.rs +++ b/tests/testsuite/install.rs @@ -742,9 +742,7 @@ fn compile_failure() { found at `[..]target` Caused by: - could not compile `foo` - -To learn more, run the command again with --verbose. + could not compile `foo` due to previous error ", ) .run();