diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 83c918a0332e..07a908f96338 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -1742,6 +1742,33 @@ fn on_stderr_line_inner( return Ok(true); } + #[derive(serde::Deserialize)] + struct CompilerMessage { + rendered: String, + message: String, + level: String, + children: Vec, + } + + // A partial rustfix::diagnostics::Diagnostic. We deserialize only a + // subset of the fields because rustc's output can be extremely + // deeply nested JSON in pathological cases involving macro + // expansion. Rustfix's Diagnostic struct is recursive containing a + // field `children: Vec`, and it can cause deserialization to + // hit serde_json's default recursion limit, or overflow the stack + // if we turn that off. Cargo only cares about the 1 field listed + // here. + #[derive(serde::Deserialize)] + struct PartialDiagnostic { + spans: Vec, + } + + // A partial rustfix::diagnostics::DiagnosticSpan. + #[derive(serde::Deserialize)] + struct PartialDiagnosticSpan { + suggestion_applicability: Option, + } + // Depending on what we're emitting from Cargo itself, we figure out what to // do with this JSON message. match options.format { @@ -1755,32 +1782,6 @@ fn on_stderr_line_inner( render_diagnostics: true, .. } => { - #[derive(serde::Deserialize)] - struct CompilerMessage { - rendered: String, - message: String, - level: String, - children: Vec, - } - - // A partial rustfix::diagnostics::Diagnostic. We deserialize only a - // subset of the fields because rustc's output can be extremely - // deeply nested JSON in pathological cases involving macro - // expansion. Rustfix's Diagnostic struct is recursive containing a - // field `children: Vec`, and it can cause deserialization to - // hit serde_json's default recursion limit, or overflow the stack - // if we turn that off. Cargo only cares about the 1 field listed - // here. - #[derive(serde::Deserialize)] - struct PartialDiagnostic { - spans: Vec, - } - - // A partial rustfix::diagnostics::DiagnosticSpan. - #[derive(serde::Deserialize)] - struct PartialDiagnosticSpan { - suggestion_applicability: Option, - } if let Ok(mut msg) = serde_json::from_str::(compiler_message.get()) { if msg.message.starts_with("aborting due to") @@ -1865,12 +1866,30 @@ 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); + if let Ok(msg) = serde_json::from_str::(compiler_message.get()) { + if msg.message.starts_with("aborting due to") + || msg.message.ends_with("warning emitted") + || msg.message.ends_with("warnings emitted") + { + // Skip this line; we'll print our own summary at the end. + return Ok(true); + } + let rendered = msg.rendered; + if options.show_diagnostics { + let machine_applicable: bool = msg + .children + .iter() + .map(|child| { + child + .spans + .iter() + .filter_map(|span| span.suggestion_applicability) + .any(|app| app == Applicability::MachineApplicable) + }) + .any(|b| b); + count_diagnostic(&msg.level, options); + state.emit_diag(msg.level, rendered, machine_applicable)?; + } } let msg = machine_message::FromCompiler {