Skip to content

Commit ad5d7f4

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 b38ed1a commit ad5d7f4

File tree

2 files changed

+60
-24
lines changed

2 files changed

+60
-24
lines changed

Diff for: compiler/rustc_codegen_ssa/src/back/write.rs

+58-22
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, DiagnosticArgMap, DiagnosticBuilder, DiagnosticMessage, ErrCode, FatalError,
20-
FluentBundle, Level, Style,
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: DiagnosticArgMap,
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)]
@@ -1812,23 +1830,29 @@ impl Translate for SharedEmitter {
18121830
}
18131831

18141832
impl Emitter for SharedEmitter {
1815-
fn emit_diagnostic(&mut self, diag: rustc_errors::Diagnostic) {
1816-
let args: DiagnosticArgMap =
1817-
diag.args.iter().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-
}
1833+
fn emit_diagnostic(&mut self, mut diag: rustc_errors::Diagnostic) {
1834+
// Check that we aren't missing anything interesting when converting to
1835+
// the cut-down local `Diagnostic`.
1836+
assert_eq!(diag.span, MultiSpan::new());
1837+
assert_eq!(diag.suggestions, Ok(vec![]));
1838+
assert_eq!(diag.sort_span, rustc_span::DUMMY_SP);
1839+
assert_eq!(diag.is_lint, None);
1840+
// No sensible check for `diag.emitted_at`.
1841+
1842+
let args = mem::replace(&mut diag.args, DiagnosticArgMap::default());
1843+
drop(
1844+
self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
1845+
level: diag.level(),
1846+
messages: diag.messages,
1847+
code: diag.code,
1848+
children: diag
1849+
.children
1850+
.into_iter()
1851+
.map(|child| Subdiagnostic { level: child.level, messages: child.messages })
1852+
.collect(),
1853+
args,
1854+
})),
1855+
);
18321856
drop(self.sender.send(SharedEmitterMessage::AbortIfErrors));
18331857
}
18341858

@@ -1854,9 +1878,21 @@ impl SharedEmitterMain {
18541878

18551879
match message {
18561880
Ok(SharedEmitterMessage::Diagnostic(diag)) => {
1881+
// The diagnostic has been received on the main thread.
1882+
// Convert it back to a full `Diagnostic` and emit.
18571883
let dcx = sess.dcx();
1858-
let mut d = rustc_errors::Diagnostic::new_with_messages(diag.lvl, diag.msgs);
1884+
let mut d =
1885+
rustc_errors::Diagnostic::new_with_messages(diag.level, diag.messages);
18591886
d.code = diag.code; // may be `None`, that's ok
1887+
d.children = diag
1888+
.children
1889+
.into_iter()
1890+
.map(|sub| rustc_errors::SubDiagnostic {
1891+
level: sub.level,
1892+
messages: sub.messages,
1893+
span: MultiSpan::new(),
1894+
})
1895+
.collect();
18601896
d.args = diag.args;
18611897
dcx.emit_diagnostic(d);
18621898
}

Diff for: 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)