Skip to content

Commit d420015

Browse files
committed
errors: share SilentEmitter between rustc and rustfmt
Signed-off-by: David Wood <[email protected]>
1 parent 7168c13 commit d420015

File tree

6 files changed

+72
-82
lines changed

6 files changed

+72
-82
lines changed

compiler/rustc_errors/src/emitter.rs

+8-26
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
use rustc_span::source_map::SourceMap;
1111
use rustc_span::{FileLines, FileName, SourceFile, Span};
1212

13-
use crate::error::TranslateError;
1413
use crate::snippet::{
1514
Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString,
1615
};
@@ -556,20 +555,9 @@ impl Emitter for HumanEmitter {
556555
/// Fatal diagnostics are forwarded to `fatal_dcx` to avoid silent
557556
/// failures of rustc, as witnessed e.g. in issue #89358.
558557
pub struct SilentEmitter {
558+
pub fallback_bundle: LazyFallbackBundle,
559559
pub fatal_dcx: DiagCtxt,
560-
pub fatal_note: String,
561-
}
562-
563-
pub fn silent_translate<'a>(
564-
message: &'a DiagnosticMessage,
565-
) -> Result<Cow<'_, str>, TranslateError<'_>> {
566-
match message {
567-
DiagnosticMessage::Str(msg) | DiagnosticMessage::Translated(msg) => Ok(Cow::Borrowed(msg)),
568-
DiagnosticMessage::FluentIdentifier(identifier, _) => {
569-
// Any value works here.
570-
Ok(identifier.clone())
571-
}
572-
}
560+
pub fatal_note: Option<String>,
573561
}
574562

575563
impl Translate for SilentEmitter {
@@ -578,17 +566,9 @@ impl Translate for SilentEmitter {
578566
}
579567

580568
fn fallback_fluent_bundle(&self) -> &FluentBundle {
581-
panic!("silent emitter attempted to translate message")
582-
}
583-
584-
// Override `translate_message` for the silent emitter because eager translation of
585-
// subdiagnostics result in a call to this.
586-
fn translate_message<'a>(
587-
&'a self,
588-
message: &'a DiagnosticMessage,
589-
_: &'a FluentArgs<'_>,
590-
) -> Result<Cow<'_, str>, TranslateError<'_>> {
591-
silent_translate(message)
569+
// Ideally this field wouldn't be necessary and the fallback bundle in `fatal_dcx` would be
570+
// used but the lock prevents this.
571+
&self.fallback_bundle
592572
}
593573
}
594574

@@ -599,7 +579,9 @@ impl Emitter for SilentEmitter {
599579

600580
fn emit_diagnostic(&mut self, mut diag: Diagnostic) {
601581
if diag.level == Level::Fatal {
602-
diag.sub(Level::Note, self.fatal_note.clone(), MultiSpan::new());
582+
if let Some(fatal_note) = &self.fatal_note {
583+
diag.sub(Level::Note, fatal_note.clone(), MultiSpan::new());
584+
}
603585
self.fatal_dcx.emit_diagnostic(diag);
604586
}
605587
}

compiler/rustc_interface/src/interface.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,10 @@ pub struct Compiler {
4545
pub(crate) fn parse_cfg(dcx: &DiagCtxt, cfgs: Vec<String>) -> Cfg {
4646
cfgs.into_iter()
4747
.map(|s| {
48-
let sess = ParseSess::with_silent_emitter(format!(
49-
"this error occurred on the command line: `--cfg={s}`"
50-
));
48+
let sess = ParseSess::with_silent_emitter(
49+
vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
50+
format!("this error occurred on the command line: `--cfg={s}`"),
51+
);
5152
let filename = FileName::cfg_spec_source_code(&s);
5253

5354
macro_rules! error {
@@ -107,9 +108,10 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg {
107108
let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() };
108109

109110
for s in specs {
110-
let sess = ParseSess::with_silent_emitter(format!(
111-
"this error occurred on the command line: `--check-cfg={s}`"
112-
));
111+
let sess = ParseSess::with_silent_emitter(
112+
vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
113+
format!("this error occurred on the command line: `--check-cfg={s}`"),
114+
);
113115
let filename = FileName::cfg_spec_source_code(&s);
114116

115117
macro_rules! error {

compiler/rustc_session/src/parse.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,17 @@ impl ParseSess {
263263
}
264264
}
265265

266-
pub fn with_silent_emitter(fatal_note: String) -> Self {
267-
let fallback_bundle = fallback_fluent_bundle(Vec::new(), false);
266+
pub fn with_silent_emitter(locale_resources: Vec<&'static str>, fatal_note: String) -> Self {
267+
let fallback_bundle = fallback_fluent_bundle(locale_resources, false);
268268
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
269-
let fatal_dcx = DiagCtxt::with_tty_emitter(None, fallback_bundle).disable_warnings();
270-
let dcx = DiagCtxt::with_emitter(Box::new(SilentEmitter { fatal_dcx, fatal_note }))
271-
.disable_warnings();
269+
let fatal_dcx =
270+
DiagCtxt::with_tty_emitter(None, fallback_bundle.clone()).disable_warnings();
271+
let dcx = DiagCtxt::with_emitter(Box::new(SilentEmitter {
272+
fallback_bundle,
273+
fatal_dcx,
274+
fatal_note: Some(fatal_note),
275+
}))
276+
.disable_warnings();
272277
ParseSess::with_dcx(dcx, sm)
273278
}
274279

src/tools/rustfmt/src/parse/session.rs

+36-45
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
use std::borrow::Cow;
21
use std::path::Path;
32
use std::sync::atomic::{AtomicBool, Ordering};
43

54
use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
6-
use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter};
5+
use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter, SilentEmitter};
76
use rustc_errors::translation::Translate;
87
use rustc_errors::{
98
ColorConfig, DiagCtxt, Diagnostic, DiagnosticBuilder, Level as DiagnosticLevel,
@@ -30,41 +29,6 @@ pub(crate) struct ParseSess {
3029
can_reset_errors: Lrc<AtomicBool>,
3130
}
3231

33-
/// Emitter which discards every error.
34-
struct SilentEmitter;
35-
36-
impl Translate for SilentEmitter {
37-
fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
38-
None
39-
}
40-
41-
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
42-
panic!("silent emitter attempted to translate a diagnostic");
43-
}
44-
45-
// Override `translate_message` for the silent emitter because eager translation of
46-
// subdiagnostics result in a call to this.
47-
fn translate_message<'a>(
48-
&'a self,
49-
message: &'a rustc_errors::DiagnosticMessage,
50-
_: &'a rustc_errors::translation::FluentArgs<'_>,
51-
) -> Result<Cow<'_, str>, rustc_errors::error::TranslateError<'_>> {
52-
rustc_errors::emitter::silent_translate(message)
53-
}
54-
}
55-
56-
impl Emitter for SilentEmitter {
57-
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
58-
None
59-
}
60-
61-
fn emit_diagnostic(&mut self, _db: Diagnostic) {}
62-
}
63-
64-
fn silent_emitter() -> Box<DynEmitter> {
65-
Box::new(SilentEmitter {})
66-
}
67-
6832
/// Emit errors against every files expect ones specified in the `ignore_path_set`.
6933
struct SilentOnIgnoredFilesEmitter {
7034
ignore_path_set: IntoDynSyncSend<Lrc<IgnorePathSet>>,
@@ -145,15 +109,24 @@ fn default_dcx(
145109
ColorConfig::Never
146110
};
147111

148-
let emitter = if hide_parse_errors {
149-
silent_emitter()
112+
let fallback_bundle = rustc_errors::fallback_fluent_bundle(
113+
rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
114+
false,
115+
);
116+
let emitter = Box::new(
117+
HumanEmitter::stderr(emit_color, fallback_bundle.clone()).sm(Some(source_map.clone())),
118+
);
119+
120+
let emitter: Box<DynEmitter> = if hide_parse_errors {
121+
Box::new(SilentEmitter {
122+
fallback_bundle,
123+
fatal_dcx: DiagCtxt::with_emitter(emitter),
124+
fatal_note: None,
125+
})
150126
} else {
151-
let fallback_bundle = rustc_errors::fallback_fluent_bundle(
152-
rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
153-
false,
154-
);
155-
Box::new(HumanEmitter::stderr(emit_color, fallback_bundle).sm(Some(source_map.clone())))
127+
emitter
156128
};
129+
157130
DiagCtxt::with_emitter(Box::new(SilentOnIgnoredFilesEmitter {
158131
has_non_ignorable_parser_errors: false,
159132
source_map,
@@ -231,7 +204,25 @@ impl ParseSess {
231204
}
232205

233206
pub(crate) fn set_silent_emitter(&mut self) {
234-
self.parse_sess.dcx = DiagCtxt::with_emitter(silent_emitter());
207+
// Ideally this invocation wouldn't be necessary and the fallback bundle in
208+
// `self.parse_sess.dcx` could be used.
209+
let fallback_bundle = rustc_errors::fallback_fluent_bundle(
210+
rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
211+
false,
212+
);
213+
// SAFETY: `fatal_dcx` will not be dropped while it is referenced by `self.parse_sess.dcx`,
214+
// and `self.parse_sess.dcx` is written to by `ptr::write` so won't drop `fatal_dcx`.
215+
unsafe {
216+
let fatal_dcx = std::ptr::read(&self.parse_sess.dcx);
217+
std::ptr::write(
218+
&mut self.parse_sess.dcx,
219+
DiagCtxt::with_emitter(Box::new(SilentEmitter {
220+
fallback_bundle,
221+
fatal_dcx,
222+
fatal_note: None,
223+
})),
224+
);
225+
}
235226
}
236227

237228
pub(crate) fn span_to_filename(&self, span: Span) -> FileName {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
macro_rules! test {
2+
($T:ident, $b:lifetime) => {
3+
Box<$T<$b>>
4+
};
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
macro_rules! test {
2+
($T:ident, $b:lifetime) => {
3+
Box<$T<$b>>
4+
};
5+
}

0 commit comments

Comments
 (0)