diff options
Diffstat (limited to 'compiler/rustc_errors/src')
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic.rs | 31 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/emitter.rs | 32 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/lib.rs | 135 |
3 files changed, 135 insertions, 63 deletions
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 5390dda9b21..c186d5b284f 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -598,6 +598,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// /// In the meantime, though, callsites are required to deal with the "bug" /// locally in whichever way makes the most sense. + #[rustc_lint_diagnostics] #[track_caller] pub fn downgrade_to_delayed_bug(&mut self) { assert!( @@ -631,6 +632,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_span_labels, /// Labels all the given spans with the provided label. /// See [`Self::span_label()`] for more information. + #[rustc_lint_diagnostics] pub fn span_labels(&mut self, spans: impl IntoIterator<Item = Span>, label: &str) -> &mut Self { for span in spans { self.span_label(span, label.to_string()); @@ -638,6 +640,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } } + #[rustc_lint_diagnostics] pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self { let before = self.span.clone(); self.span(after); @@ -653,6 +656,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } + #[rustc_lint_diagnostics] pub fn note_expected_found( &mut self, expected_label: &dyn fmt::Display, @@ -663,6 +667,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self.note_expected_found_extra(expected_label, expected, found_label, found, &"", &"") } + #[rustc_lint_diagnostics] pub fn note_expected_found_extra( &mut self, expected_label: &dyn fmt::Display, @@ -705,6 +710,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } + #[rustc_lint_diagnostics] pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self { self.highlighted_note(vec![ StringPart::normal(format!("`{name}` from trait: `")), @@ -722,12 +728,14 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } } + #[rustc_lint_diagnostics] fn highlighted_note(&mut self, msg: Vec<StringPart>) -> &mut Self { self.sub_with_highlights(Level::Note, msg, MultiSpan::new()); self } /// This is like [`Diag::note()`], but it's only printed once. + #[rustc_lint_diagnostics] pub fn note_once(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self { self.sub(Level::OnceNote, msg, MultiSpan::new()); self @@ -748,6 +756,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// Prints the span with a note above it. /// This is like [`Diag::note_once()`], but it gets its own span. + #[rustc_lint_diagnostics] pub fn span_note_once<S: Into<MultiSpan>>( &mut self, sp: S, @@ -786,12 +795,14 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { } } /// This is like [`Diag::help()`], but it's only printed once. + #[rustc_lint_diagnostics] pub fn help_once(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self { self.sub(Level::OnceHelp, msg, MultiSpan::new()); self } /// Add a help message attached to this diagnostic with a customizable highlighted message. + #[rustc_lint_diagnostics] pub fn highlighted_help(&mut self, msg: Vec<StringPart>) -> &mut Self { self.sub_with_highlights(Level::Help, msg, MultiSpan::new()); self @@ -812,12 +823,14 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// Disallow attaching suggestions this diagnostic. /// Any suggestions attached e.g. with the `span_suggestion_*` methods /// (before and after the call to `disable_suggestions`) will be ignored. + #[rustc_lint_diagnostics] pub fn disable_suggestions(&mut self) -> &mut Self { self.suggestions = Err(SuggestionsDisabled); self } /// Helper for pushing to `self.suggestions`, if available (not disable). + #[rustc_lint_diagnostics] fn push_suggestion(&mut self, suggestion: CodeSuggestion) { for subst in &suggestion.substitutions { for part in &subst.parts { @@ -838,6 +851,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_multipart_suggestion, /// Show a suggestion that has multiple parts to it. /// In other words, multiple changes need to be applied as part of this suggestion. + #[rustc_lint_diagnostics] pub fn multipart_suggestion( &mut self, msg: impl Into<SubdiagMessage>, @@ -854,6 +868,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// Show a suggestion that has multiple parts to it, always as it's own subdiagnostic. /// In other words, multiple changes need to be applied as part of this suggestion. + #[rustc_lint_diagnostics] pub fn multipart_suggestion_verbose( &mut self, msg: impl Into<SubdiagMessage>, @@ -869,6 +884,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { } /// [`Diag::multipart_suggestion()`] but you can set the [`SuggestionStyle`]. + #[rustc_lint_diagnostics] pub fn multipart_suggestion_with_style( &mut self, msg: impl Into<SubdiagMessage>, @@ -911,6 +927,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// be from the message, showing the span label inline would be visually unpleasant /// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't /// improve understandability. + #[rustc_lint_diagnostics] pub fn tool_only_multipart_suggestion( &mut self, msg: impl Into<SubdiagMessage>, @@ -943,6 +960,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// * may contain a name of a function, variable, or type, but not whole expressions /// /// See `CodeSuggestion` for more information. + #[rustc_lint_diagnostics] pub fn span_suggestion( &mut self, sp: Span, @@ -961,6 +979,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { } } /// [`Diag::span_suggestion()`] but you can set the [`SuggestionStyle`]. + #[rustc_lint_diagnostics] pub fn span_suggestion_with_style( &mut self, sp: Span, @@ -986,6 +1005,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_span_suggestion_verbose, /// Always show the suggested change. + #[rustc_lint_diagnostics] pub fn span_suggestion_verbose( &mut self, sp: Span, @@ -1006,6 +1026,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_span_suggestions, /// Prints out a message with multiple suggested edits of the code. /// See also [`Diag::span_suggestion()`]. + #[rustc_lint_diagnostics] pub fn span_suggestions( &mut self, sp: Span, @@ -1022,6 +1043,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { ) } } + #[rustc_lint_diagnostics] pub fn span_suggestions_with_style( &mut self, sp: Span, @@ -1052,6 +1074,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// Prints out a message with multiple suggested edits of the code, where each edit consists of /// multiple parts. /// See also [`Diag::multipart_suggestion()`]. + #[rustc_lint_diagnostics] pub fn multipart_suggestions( &mut self, msg: impl Into<SubdiagMessage>, @@ -1098,6 +1121,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// inline, it will only show the message and not the suggestion. /// /// See `CodeSuggestion` for more information. + #[rustc_lint_diagnostics] pub fn span_suggestion_short( &mut self, sp: Span, @@ -1121,6 +1145,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// be from the message, showing the span label inline would be visually unpleasant /// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't /// improve understandability. + #[rustc_lint_diagnostics] pub fn span_suggestion_hidden( &mut self, sp: Span, @@ -1165,6 +1190,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// [rustc_macros::Subdiagnostic]). Performs eager translation of any translatable messages /// used in the subdiagnostic, so suitable for use with repeated messages (i.e. re-use of /// interpolated variables). + #[rustc_lint_diagnostics] pub fn subdiagnostic( &mut self, dcx: &crate::DiagCtxt, @@ -1180,6 +1206,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_span, /// Add a span. + #[rustc_lint_diagnostics] pub fn span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self { self.span = sp.into(); if let Some(span) = self.span.primary_span() { @@ -1188,6 +1215,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } } + #[rustc_lint_diagnostics] pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self { self.is_lint = Some(IsLint { name, has_future_breakage }); self @@ -1195,6 +1223,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_code, /// Add an error code. + #[rustc_lint_diagnostics] pub fn code(&mut self, code: ErrCode) -> &mut Self { self.code = Some(code); self @@ -1202,6 +1231,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_primary_message, /// Add a primary message. + #[rustc_lint_diagnostics] pub fn primary_message(&mut self, msg: impl Into<DiagMessage>) -> &mut Self { self.messages[0] = (msg.into(), Style::NoStyle); self @@ -1209,6 +1239,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_arg, /// Add an argument. + #[rustc_lint_diagnostics] pub fn arg( &mut self, name: impl Into<DiagArgName>, diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 293d8f01e67..57b8df52f4b 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -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); } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 0a6d66f52da..76b44f73f47 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -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`. @@ -1076,32 +1101,36 @@ impl DiagCtxt { // Functions beginning with `struct_`/`create_` create a diagnostic. Other // functions create and emit a diagnostic all in one go. impl DiagCtxt { - // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. + // No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't + // user-facing. #[track_caller] - pub fn struct_bug(&self, msg: impl Into<DiagMessage>) -> Diag<'_, BugAbort> { - Diag::new(self, Bug, msg) + pub fn struct_bug(&self, msg: impl Into<Cow<'static, str>>) -> Diag<'_, BugAbort> { + Diag::new(self, Bug, msg.into()) } - // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. + // No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't + // user-facing. #[track_caller] - pub fn bug(&self, msg: impl Into<DiagMessage>) -> ! { + pub fn bug(&self, msg: impl Into<Cow<'static, str>>) -> ! { self.struct_bug(msg).emit() } - // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. + // No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't + // user-facing. #[track_caller] pub fn struct_span_bug( &self, span: impl Into<MultiSpan>, - msg: impl Into<DiagMessage>, + msg: impl Into<Cow<'static, str>>, ) -> Diag<'_, BugAbort> { self.struct_bug(msg).with_span(span) } - // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. + // No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't + // user-facing. #[track_caller] - pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) -> ! { - self.struct_span_bug(span, msg).emit() + pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<Cow<'static, str>>) -> ! { + self.struct_span_bug(span, msg.into()).emit() } #[track_caller] @@ -1215,24 +1244,28 @@ impl DiagCtxt { } /// Ensures that an error is printed. See `Level::DelayedBug`. - // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. + // + // No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't + // user-facing. #[track_caller] - pub fn delayed_bug(&self, msg: impl Into<DiagMessage>) -> ErrorGuaranteed { - Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg).emit() + pub fn delayed_bug(&self, msg: impl Into<Cow<'static, str>>) -> ErrorGuaranteed { + Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).emit() } /// Ensures that an error is printed. See `Level::DelayedBug`. /// /// Note: this function used to be called `delay_span_bug`. It was renamed /// to match similar functions like `span_err`, `span_warn`, etc. - // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing. + // + // No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't + // user-facing. #[track_caller] pub fn span_delayed_bug( &self, sp: impl Into<MultiSpan>, - msg: impl Into<DiagMessage>, + msg: impl Into<Cow<'static, str>>, ) -> ErrorGuaranteed { - Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg).with_span(sp).emit() + Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).with_span(sp).emit() } #[rustc_lint_diagnostics] @@ -1345,6 +1378,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; |
