Skip to content

Commit f70f19f

Browse files
committed
Auto merge of rust-lang#121129 - nnethercote:codegen-Diags, r=estebank
Improve codegen diagnostic handling Clarify the workings of the temporary `Diagnostic` type used to send diagnostics from codegen threads to the main thread. r? `@estebank`
2 parents 026b3b8 + 6efffd7 commit f70f19f

File tree

11 files changed

+81
-56
lines changed

11 files changed

+81
-56
lines changed

compiler/rustc_codegen_llvm/src/errors.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ParseTargetMachineConfig<'_
103103
fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
104104
let diag: DiagnosticBuilder<'_, G> = self.0.into_diagnostic(dcx, level);
105105
let (message, _) = diag.messages.first().expect("`LlvmError` with no message");
106-
let message = dcx.eagerly_translate_to_string(message.clone(), diag.args());
107-
106+
let message = dcx.eagerly_translate_to_string(message.clone(), diag.args.iter());
108107
DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config)
109108
.with_arg("error", message)
110109
}

compiler/rustc_codegen_ssa/src/back/write.rs

+61-29
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use rustc_data_structures::sync::Lrc;
1616
use rustc_errors::emitter::Emitter;
1717
use rustc_errors::translation::Translate;
1818
use rustc_errors::{
19-
DiagCtxt, DiagnosticArgName, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, ErrCode,
20-
FatalError, FluentBundle, Level, Style,
19+
DiagCtxt, DiagnosticArgMap, DiagnosticBuilder, DiagnosticMessage, ErrCode, FatalError,
20+
FluentBundle, Level, MultiSpan, Style,
2121
};
2222
use rustc_fs_util::link_or_copy;
2323
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
@@ -999,11 +999,29 @@ pub(crate) enum Message<B: WriteBackendMethods> {
999999
/// process another codegen unit.
10001000
pub struct CguMessage;
10011001

1002+
// A cut-down version of `rustc_errors::Diagnostic` that impls `Send`, which
1003+
// can be used to send diagnostics from codegen threads to the main thread.
1004+
// It's missing the following fields from `rustc_errors::Diagnostic`.
1005+
// - `span`: it doesn't impl `Send`.
1006+
// - `suggestions`: it doesn't impl `Send`, and isn't used for codegen
1007+
// diagnostics.
1008+
// - `sort_span`: it doesn't impl `Send`.
1009+
// - `is_lint`: lints aren't relevant during codegen.
1010+
// - `emitted_at`: not used for codegen diagnostics.
10021011
struct Diagnostic {
1003-
msgs: Vec<(DiagnosticMessage, Style)>,
1004-
args: FxIndexMap<DiagnosticArgName, DiagnosticArgValue>,
1012+
level: Level,
1013+
messages: Vec<(DiagnosticMessage, Style)>,
10051014
code: Option<ErrCode>,
1006-
lvl: Level,
1015+
children: Vec<Subdiagnostic>,
1016+
args: DiagnosticArgMap,
1017+
}
1018+
1019+
// A cut-down version of `rustc_errors::SubDiagnostic` that impls `Send`. It's
1020+
// missing the following fields from `rustc_errors::SubDiagnostic`.
1021+
// - `span`: it doesn't impl `Send`.
1022+
pub struct Subdiagnostic {
1023+
level: Level,
1024+
messages: Vec<(DiagnosticMessage, Style)>,
10071025
}
10081026

10091027
#[derive(PartialEq, Clone, Copy, Debug)]
@@ -1766,7 +1784,6 @@ fn spawn_work<'a, B: ExtraBackendMethods>(
17661784
enum SharedEmitterMessage {
17671785
Diagnostic(Diagnostic),
17681786
InlineAsmError(u32, String, Level, Option<(String, Vec<InnerSpan>)>),
1769-
AbortIfErrors,
17701787
Fatal(String),
17711788
}
17721789

@@ -1812,24 +1829,29 @@ impl Translate for SharedEmitter {
18121829
}
18131830

18141831
impl Emitter for SharedEmitter {
1815-
fn emit_diagnostic(&mut self, diag: rustc_errors::Diagnostic) {
1816-
let args: FxIndexMap<DiagnosticArgName, DiagnosticArgValue> =
1817-
diag.args().map(|(name, arg)| (name.clone(), arg.clone())).collect();
1818-
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
1819-
msgs: diag.messages.clone(),
1820-
args: args.clone(),
1821-
code: diag.code,
1822-
lvl: diag.level(),
1823-
})));
1824-
for child in &diag.children {
1825-
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
1826-
msgs: child.messages.clone(),
1827-
args: args.clone(),
1828-
code: None,
1829-
lvl: child.level,
1830-
})));
1831-
}
1832-
drop(self.sender.send(SharedEmitterMessage::AbortIfErrors));
1832+
fn emit_diagnostic(&mut self, mut diag: rustc_errors::Diagnostic) {
1833+
// Check that we aren't missing anything interesting when converting to
1834+
// the cut-down local `Diagnostic`.
1835+
assert_eq!(diag.span, MultiSpan::new());
1836+
assert_eq!(diag.suggestions, Ok(vec![]));
1837+
assert_eq!(diag.sort_span, rustc_span::DUMMY_SP);
1838+
assert_eq!(diag.is_lint, None);
1839+
// No sensible check for `diag.emitted_at`.
1840+
1841+
let args = mem::replace(&mut diag.args, DiagnosticArgMap::default());
1842+
drop(
1843+
self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
1844+
level: diag.level(),
1845+
messages: diag.messages,
1846+
code: diag.code,
1847+
children: diag
1848+
.children
1849+
.into_iter()
1850+
.map(|child| Subdiagnostic { level: child.level, messages: child.messages })
1851+
.collect(),
1852+
args,
1853+
})),
1854+
);
18331855
}
18341856

18351857
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
@@ -1854,11 +1876,24 @@ impl SharedEmitterMain {
18541876

18551877
match message {
18561878
Ok(SharedEmitterMessage::Diagnostic(diag)) => {
1879+
// The diagnostic has been received on the main thread.
1880+
// Convert it back to a full `Diagnostic` and emit.
18571881
let dcx = sess.dcx();
1858-
let mut d = rustc_errors::Diagnostic::new_with_messages(diag.lvl, diag.msgs);
1882+
let mut d =
1883+
rustc_errors::Diagnostic::new_with_messages(diag.level, diag.messages);
18591884
d.code = diag.code; // may be `None`, that's ok
1860-
d.replace_args(diag.args);
1885+
d.children = diag
1886+
.children
1887+
.into_iter()
1888+
.map(|sub| rustc_errors::SubDiagnostic {
1889+
level: sub.level,
1890+
messages: sub.messages,
1891+
span: MultiSpan::new(),
1892+
})
1893+
.collect();
1894+
d.args = diag.args;
18611895
dcx.emit_diagnostic(d);
1896+
sess.dcx().abort_if_errors();
18621897
}
18631898
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
18641899
assert!(matches!(level, Level::Error | Level::Warning | Level::Note));
@@ -1891,9 +1926,6 @@ impl SharedEmitterMain {
18911926

18921927
err.emit();
18931928
}
1894-
Ok(SharedEmitterMessage::AbortIfErrors) => {
1895-
sess.dcx().abort_if_errors();
1896-
}
18971929
Ok(SharedEmitterMessage::Fatal(msg)) => {
18981930
sess.dcx().fatal(msg);
18991931
}

compiler/rustc_const_eval/src/errors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ pub trait ReportErrorExt {
437437
let mut diag = dcx.struct_allow(DiagnosticMessage::Str(String::new().into()));
438438
let message = self.diagnostic_message();
439439
self.add_args(&mut diag);
440-
let s = dcx.eagerly_translate_to_string(message, diag.args());
440+
let s = dcx.eagerly_translate_to_string(message, diag.args.iter());
441441
diag.cancel();
442442
s
443443
})
@@ -864,7 +864,7 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> {
864864
let dummy_level = Level::Bug;
865865
let dummy_diag: DiagnosticBuilder<'_, ()> =
866866
e.into_diagnostic().into_diagnostic(diag.dcx, dummy_level);
867-
for (name, val) in dummy_diag.args() {
867+
for (name, val) in dummy_diag.args.iter() {
868868
diag.arg(name.clone(), val.clone());
869869
}
870870
dummy_diag.cancel();

compiler/rustc_const_eval/src/interpret/eval_context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ pub fn format_interp_error<'tcx>(dcx: &DiagCtxt, e: InterpErrorInfo<'tcx>) -> St
446446
let mut diag = dcx.struct_allow("");
447447
let msg = e.diagnostic_message();
448448
e.add_args(&mut diag);
449-
let s = dcx.eagerly_translate_to_string(msg, diag.args());
449+
let s = dcx.eagerly_translate_to_string(msg, diag.args.iter());
450450
diag.cancel();
451451
s
452452
}

compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl Translate for AnnotateSnippetEmitter {
4545
impl Emitter for AnnotateSnippetEmitter {
4646
/// The entry point for the diagnostics generation
4747
fn emit_diagnostic(&mut self, mut diag: Diagnostic) {
48-
let fluent_args = to_fluent_args(diag.args());
48+
let fluent_args = to_fluent_args(diag.args.iter());
4949

5050
let mut suggestions = diag.suggestions.unwrap_or(vec![]);
5151
self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args);

compiler/rustc_errors/src/diagnostic.rs

+5-11
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ pub enum DiagnosticArgValue {
4343
StrListSepByAnd(Vec<Cow<'static, str>>),
4444
}
4545

46+
pub type DiagnosticArgMap = FxIndexMap<DiagnosticArgName, DiagnosticArgValue>;
47+
4648
/// Trait for types that `DiagnosticBuilder::emit` can return as a "guarantee"
4749
/// (or "proof") token that the emission happened.
4850
pub trait EmissionGuarantee: Sized {
@@ -275,7 +277,7 @@ pub struct Diagnostic {
275277
pub span: MultiSpan,
276278
pub children: Vec<SubDiagnostic>,
277279
pub suggestions: Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
278-
args: FxIndexMap<DiagnosticArgName, DiagnosticArgValue>,
280+
pub args: DiagnosticArgMap,
279281

280282
/// This is not used for highlighting or rendering any error message. Rather, it can be used
281283
/// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of
@@ -403,14 +405,6 @@ impl Diagnostic {
403405
self.args.insert(name.into(), arg.into_diagnostic_arg());
404406
}
405407

406-
pub fn args(&self) -> impl Iterator<Item = DiagnosticArg<'_>> {
407-
self.args.iter()
408-
}
409-
410-
pub fn replace_args(&mut self, args: FxIndexMap<DiagnosticArgName, DiagnosticArgValue>) {
411-
self.args = args;
412-
}
413-
414408
/// Fields used for Hash, and PartialEq trait.
415409
fn keys(
416410
&self,
@@ -431,7 +425,7 @@ impl Diagnostic {
431425
&self.span,
432426
&self.children,
433427
&self.suggestions,
434-
self.args().collect(),
428+
self.args.iter().collect(),
435429
// omit self.sort_span
436430
&self.is_lint,
437431
// omit self.emitted_at
@@ -1165,7 +1159,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
11651159
subdiagnostic: impl AddToDiagnostic,
11661160
) -> &mut Self {
11671161
subdiagnostic.add_to_diagnostic_with(self, |diag, msg| {
1168-
let args = diag.args();
1162+
let args = diag.args.iter();
11691163
let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
11701164
dcx.eagerly_translate(msg, args)
11711165
});

compiler/rustc_errors/src/emitter.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ impl Emitter for HumanEmitter {
519519
}
520520

521521
fn emit_diagnostic(&mut self, mut diag: Diagnostic) {
522-
let fluent_args = to_fluent_args(diag.args());
522+
let fluent_args = to_fluent_args(diag.args.iter());
523523

524524
let mut suggestions = diag.suggestions.unwrap_or(vec![]);
525525
self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args);

compiler/rustc_errors/src/json.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ struct UnusedExterns<'a, 'b, 'c> {
341341

342342
impl Diagnostic {
343343
fn from_errors_diagnostic(diag: crate::Diagnostic, je: &JsonEmitter) -> Diagnostic {
344-
let args = to_fluent_args(diag.args());
344+
let args = to_fluent_args(diag.args.iter());
345345
let sugg = diag.suggestions.iter().flatten().map(|sugg| {
346346
let translated_message =
347347
je.translate_message(&sugg.msg, &args).map_err(Report::new).unwrap();

compiler/rustc_errors/src/lib.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,10 @@ extern crate self as rustc_errors;
3737

3838
pub use codes::*;
3939
pub use diagnostic::{
40-
AddToDiagnostic, BugAbort, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgName,
41-
DiagnosticArgValue, DiagnosticBuilder, DiagnosticStyledString, EmissionGuarantee, FatalAbort,
42-
IntoDiagnostic, IntoDiagnosticArg, StringPart, SubDiagnostic, SubdiagnosticMessageOp,
40+
AddToDiagnostic, BugAbort, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgMap,
41+
DiagnosticArgName, DiagnosticArgValue, DiagnosticBuilder, DiagnosticStyledString,
42+
EmissionGuarantee, FatalAbort, IntoDiagnostic, IntoDiagnosticArg, StringPart, SubDiagnostic,
43+
SubdiagnosticMessageOp,
4344
};
4445
pub use diagnostic_impls::{
4546
DiagnosticArgFromDisplay, DiagnosticSymbolList, ExpectedLifetimeParameter,
@@ -1496,9 +1497,8 @@ impl DiagCtxtInner {
14961497
diag: &Diagnostic,
14971498
msg: impl Into<SubdiagnosticMessage>,
14981499
) -> SubdiagnosticMessage {
1499-
let args = diag.args();
15001500
let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
1501-
self.eagerly_translate(msg, args)
1501+
self.eagerly_translate(msg, diag.args.iter())
15021502
}
15031503

15041504
fn flush_delayed(&mut self) {

src/librustdoc/passes/lint/check_code_block_syntax.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ impl Emitter for BufferEmitter {
159159
fn emit_diagnostic(&mut self, diag: Diagnostic) {
160160
let mut buffer = self.buffer.borrow_mut();
161161

162-
let fluent_args = to_fluent_args(diag.args());
162+
let fluent_args = to_fluent_args(diag.args.iter());
163163
let translated_main_message = self
164164
.translate_message(&diag.messages[0].0, &fluent_args)
165165
.unwrap_or_else(|e| panic!("{e}"));

tests/ui/lto/issue-11154.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
error: cannot prefer dynamic linking when performing LTO
2-
3-
note: only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
2+
|
3+
= note: only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
44

55
error: aborting due to 1 previous error
66

0 commit comments

Comments
 (0)