Skip to content

Commit 92b38d3

Browse files
committed
Overhaul rustc_codegen_ssa::back::write::Diagnostic.
- Make it more closely match `rustc_errors::Diagnostic`, by making the field names match, and adding `children`, which requires adding `rustc_codegen_ssa::back::write::Subdiagnostic`. - Check that we aren't missing important info when converting diagnostics. - Add better comments. - Tweak `rustc_errors::Diagnostic::replace_args` so that we don't need to do any cloning when converting diagnostics.
1 parent ee9c7c9 commit 92b38d3

File tree

3 files changed

+68
-29
lines changed

3 files changed

+68
-29
lines changed

compiler/rustc_codegen_ssa/src/back/write.rs

+58-25
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_errors::emitter::Emitter;
1717
use rustc_errors::translation::Translate;
1818
use rustc_errors::{
1919
DiagCtxt, DiagnosticArgName, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, ErrCode,
20-
FatalError, FluentBundle, Level, Style,
20+
FatalError, 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,28 @@ 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`: because `MultiSpan` doesn't impl `Send`.
1006+
// - `suggestions`: because it doesn't impl `Send`, and is not worth the complexity.
1007+
// - `sort_span`: because `Span` doesn't impl `Send`.
1008+
// - `is_lint`: because lints aren't relevant during codegen.
1009+
// - `emitted_at`: not worth the complexity.
10021010
struct Diagnostic {
1003-
msgs: Vec<(DiagnosticMessage, Style)>,
1004-
args: FxHashMap<DiagnosticArgName, DiagnosticArgValue>,
1011+
level: Level,
1012+
messages: Vec<(DiagnosticMessage, Style)>,
10051013
code: Option<ErrCode>,
1006-
lvl: Level,
1014+
children: Vec<Subdiagnostic>,
1015+
args: FxHashMap<DiagnosticArgName, DiagnosticArgValue>,
1016+
}
1017+
1018+
// A cut-down version of `rustc_errors::SubDiagnostic` that impls `Send`. It's
1019+
// missing the following fields from `rustc_errors::SubDiagnostic`.
1020+
// - `span`: because `MultiSpan` doesn't impl `Send`.
1021+
pub struct Subdiagnostic {
1022+
level: Level,
1023+
messages: Vec<(DiagnosticMessage, Style)>,
10071024
}
10081025

10091026
#[derive(PartialEq, Clone, Copy, Debug)]
@@ -1812,23 +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: FxHashMap<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+
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 = diag.replace_args(FxHashMap::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+
);
18321855
drop(self.sender.send(SharedEmitterMessage::AbortIfErrors));
18331856
}
18341857

@@ -1854,11 +1877,21 @@ impl SharedEmitterMain {
18541877

18551878
match message {
18561879
Ok(SharedEmitterMessage::Diagnostic(diag)) => {
1880+
// The diagnostic has been received on the main thread.
1881+
// Convert it back to a full `Diagnostic` and emit.
18571882
let dcx = sess.dcx();
1858-
let mut d = rustc_errors::Diagnostic::new_with_messages(diag.lvl, diag.msgs);
1859-
if let Some(code) = diag.code {
1860-
d.code(code);
1861-
}
1883+
let mut d =
1884+
rustc_errors::Diagnostic::new_with_messages(diag.level, diag.messages);
1885+
d.code = diag.code;
1886+
d.children = diag
1887+
.children
1888+
.into_iter()
1889+
.map(|sub| rustc_errors::SubDiagnostic {
1890+
level: sub.level,
1891+
messages: sub.messages,
1892+
span: MultiSpan::new(),
1893+
})
1894+
.collect();
18621895
d.replace_args(diag.args);
18631896
dcx.emit_diagnostic(d);
18641897
}

compiler/rustc_errors/src/diagnostic.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ pub struct Diagnostic {
105105
pub span: MultiSpan,
106106
pub children: Vec<SubDiagnostic>,
107107
pub suggestions: Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
108+
109+
// Non-`pub` so that the getter method can be marked with
110+
// `#[allow(rustc::potential_query_instability)]`.
108111
args: FxHashMap<DiagnosticArgName, DiagnosticArgValue>,
109112

110113
/// This is not used for highlighting or rendering any error message. Rather, it can be used
@@ -914,8 +917,11 @@ impl Diagnostic {
914917
self
915918
}
916919

917-
pub fn replace_args(&mut self, args: FxHashMap<DiagnosticArgName, DiagnosticArgValue>) {
918-
self.args = args;
920+
pub fn replace_args(
921+
&mut self,
922+
args: FxHashMap<DiagnosticArgName, DiagnosticArgValue>,
923+
) -> FxHashMap<DiagnosticArgName, DiagnosticArgValue> {
924+
std::mem::replace(&mut self.args, args)
919925
}
920926

921927
/// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by

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)