errors: share SilentEmitter
between rustc and rustfmt
Signed-off-by: David Wood <david@davidtw.co>
This commit is contained in:
parent
5a1e5449c8
commit
2ee0409f32
7 changed files with 131 additions and 108 deletions
|
@ -10,7 +10,6 @@
|
|||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{FileLines, FileName, SourceFile, Span};
|
||||
|
||||
use crate::error::TranslateError;
|
||||
use crate::snippet::{
|
||||
Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString,
|
||||
};
|
||||
|
@ -539,18 +538,9 @@ impl Emitter for HumanEmitter {
|
|||
/// Fatal diagnostics are forwarded to `fatal_dcx` to avoid silent
|
||||
/// failures of rustc, as witnessed e.g. in issue #89358.
|
||||
pub struct SilentEmitter {
|
||||
pub fallback_bundle: LazyFallbackBundle,
|
||||
pub fatal_dcx: DiagCtxt,
|
||||
pub fatal_note: String,
|
||||
}
|
||||
|
||||
pub fn silent_translate<'a>(message: &'a DiagMessage) -> Result<Cow<'_, str>, TranslateError<'_>> {
|
||||
match message {
|
||||
DiagMessage::Str(msg) | DiagMessage::Translated(msg) => Ok(Cow::Borrowed(msg)),
|
||||
DiagMessage::FluentIdentifier(identifier, _) => {
|
||||
// Any value works here.
|
||||
Ok(identifier.clone())
|
||||
}
|
||||
}
|
||||
pub fatal_note: Option<String>,
|
||||
}
|
||||
|
||||
impl Translate for SilentEmitter {
|
||||
|
@ -559,17 +549,9 @@ impl Translate for SilentEmitter {
|
|||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||
panic!("silent emitter attempted to translate message")
|
||||
}
|
||||
|
||||
// Override `translate_message` for the silent emitter because eager translation of
|
||||
// subdiagnostics result in a call to this.
|
||||
fn translate_message<'a>(
|
||||
&'a self,
|
||||
message: &'a DiagMessage,
|
||||
_: &'a FluentArgs<'_>,
|
||||
) -> Result<Cow<'_, str>, TranslateError<'_>> {
|
||||
silent_translate(message)
|
||||
// Ideally this field wouldn't be necessary and the fallback bundle in `fatal_dcx` would be
|
||||
// used but the lock prevents this.
|
||||
&self.fallback_bundle
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -580,7 +562,9 @@ impl Emitter for SilentEmitter {
|
|||
|
||||
fn emit_diagnostic(&mut self, mut diag: DiagInner) {
|
||||
if diag.level == Level::Fatal {
|
||||
diag.sub(Level::Note, self.fatal_note.clone(), MultiSpan::new());
|
||||
if let Some(fatal_note) = &self.fatal_note {
|
||||
diag.sub(Level::Note, fatal_note.clone(), MultiSpan::new());
|
||||
}
|
||||
self.fatal_dcx.emit_diagnostic(diag);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ use emitter::{is_case_difference, DynEmitter, Emitter};
|
|||
use registry::Registry;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::stable_hasher::{Hash128, StableHasher};
|
||||
use rustc_data_structures::sync::Lock;
|
||||
use rustc_data_structures::sync::{Lock, Lrc};
|
||||
use rustc_data_structures::AtomicRef;
|
||||
use rustc_lint_defs::LintExpectationId;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
|
@ -606,29 +606,54 @@ impl DiagCtxt {
|
|||
}
|
||||
|
||||
pub fn new(emitter: Box<DynEmitter>) -> Self {
|
||||
Self {
|
||||
inner: Lock::new(DiagCtxtInner {
|
||||
flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
|
||||
err_guars: Vec::new(),
|
||||
lint_err_guars: Vec::new(),
|
||||
delayed_bugs: Vec::new(),
|
||||
deduplicated_err_count: 0,
|
||||
deduplicated_warn_count: 0,
|
||||
emitter,
|
||||
must_produce_diag: false,
|
||||
has_printed: false,
|
||||
suppressed_expected_diag: false,
|
||||
taught_diagnostics: Default::default(),
|
||||
emitted_diagnostic_codes: Default::default(),
|
||||
emitted_diagnostics: Default::default(),
|
||||
stashed_diagnostics: Default::default(),
|
||||
future_breakage_diagnostics: Vec::new(),
|
||||
check_unstable_expect_diagnostics: false,
|
||||
unstable_expect_diagnostics: Vec::new(),
|
||||
fulfilled_expectations: Default::default(),
|
||||
ice_file: None,
|
||||
}),
|
||||
Self { inner: Lock::new(DiagCtxtInner::new(emitter)) }
|
||||
}
|
||||
|
||||
pub fn make_silent(&mut self, fallback_bundle: LazyFallbackBundle, fatal_note: Option<String>) {
|
||||
self.wrap_emitter(|old_dcx| {
|
||||
Box::new(emitter::SilentEmitter {
|
||||
fallback_bundle,
|
||||
fatal_dcx: DiagCtxt { inner: Lock::new(old_dcx) },
|
||||
fatal_note,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn wrap_emitter<F>(&mut self, f: F)
|
||||
where
|
||||
F: FnOnce(DiagCtxtInner) -> Box<DynEmitter>,
|
||||
{
|
||||
// A empty type that implements `Emitter` so that a `DiagCtxtInner` can be constructed
|
||||
// to temporarily swap in place of the real one, which will be used in constructing
|
||||
// its replacement.
|
||||
struct FalseEmitter;
|
||||
|
||||
impl Emitter for FalseEmitter {
|
||||
fn emit_diagnostic(&mut self, _: DiagInner) {
|
||||
unimplemented!("false emitter must only used during `wrap_emitter`")
|
||||
}
|
||||
|
||||
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
|
||||
unimplemented!("false emitter must only used during `wrap_emitter`")
|
||||
}
|
||||
}
|
||||
|
||||
impl translation::Translate for FalseEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
||||
unimplemented!("false emitter must only used during `wrap_emitter`")
|
||||
}
|
||||
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||
unimplemented!("false emitter must only used during `wrap_emitter`")
|
||||
}
|
||||
}
|
||||
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let mut prev_dcx = DiagCtxtInner::new(Box::new(FalseEmitter));
|
||||
std::mem::swap(&mut *inner, &mut prev_dcx);
|
||||
let new_emitter = f(prev_dcx);
|
||||
let mut new_dcx = DiagCtxtInner::new(new_emitter);
|
||||
std::mem::swap(&mut *inner, &mut new_dcx);
|
||||
}
|
||||
|
||||
/// Translate `message` eagerly with `args` to `SubdiagMessage::Eager`.
|
||||
|
@ -1345,6 +1370,30 @@ impl DiagCtxt {
|
|||
// `DiagCtxt::foo()` just borrows `inner` and forwards a call to
|
||||
// `DiagCtxtInner::foo`.
|
||||
impl DiagCtxtInner {
|
||||
fn new(emitter: Box<DynEmitter>) -> Self {
|
||||
Self {
|
||||
flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
|
||||
err_guars: Vec::new(),
|
||||
lint_err_guars: Vec::new(),
|
||||
delayed_bugs: Vec::new(),
|
||||
deduplicated_err_count: 0,
|
||||
deduplicated_warn_count: 0,
|
||||
emitter,
|
||||
must_produce_diag: false,
|
||||
has_printed: false,
|
||||
suppressed_expected_diag: false,
|
||||
taught_diagnostics: Default::default(),
|
||||
emitted_diagnostic_codes: Default::default(),
|
||||
emitted_diagnostics: Default::default(),
|
||||
stashed_diagnostics: Default::default(),
|
||||
future_breakage_diagnostics: Vec::new(),
|
||||
check_unstable_expect_diagnostics: false,
|
||||
unstable_expect_diagnostics: Vec::new(),
|
||||
fulfilled_expectations: Default::default(),
|
||||
ice_file: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Emit all stashed diagnostics.
|
||||
fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
|
||||
let mut guar = None;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue