about summary refs log tree commit diff
path: root/compiler/rustc_errors/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_errors/src')
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs11
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs3
-rw-r--r--compiler/rustc_errors/src/emitter.rs23
-rw-r--r--compiler/rustc_errors/src/lib.rs71
-rw-r--r--compiler/rustc_errors/src/translation.rs4
5 files changed, 80 insertions, 32 deletions
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index b14a12175c7..d31321b48d0 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -852,17 +852,10 @@ impl Diagnostic {
     }
 
     /// Add a subdiagnostic from a type that implements `Subdiagnostic` (see
-    /// [rustc_macros::Subdiagnostic]).
-    pub fn subdiagnostic(&mut self, subdiagnostic: impl AddToDiagnostic) -> &mut Self {
-        subdiagnostic.add_to_diagnostic(self);
-        self
-    }
-
-    /// Add a subdiagnostic from a type that implements `Subdiagnostic` (see
     /// [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).
-    pub fn eager_subdiagnostic(
+    pub fn subdiagnostic(
         &mut self,
         dcx: &crate::DiagCtxt,
         subdiagnostic: impl AddToDiagnostic,
@@ -921,7 +914,7 @@ impl Diagnostic {
     /// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by
     /// combining it with the primary message of the diagnostic (if translatable, otherwise it just
     /// passes the user's string along).
-    fn subdiagnostic_message_to_diagnostic_message(
+    pub(crate) fn subdiagnostic_message_to_diagnostic_message(
         &self,
         attr: impl Into<SubdiagnosticMessage>,
     ) -> DiagnosticMessage {
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index e484bef0e0b..0572df69ca9 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -404,9 +404,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
         name: impl Into<Cow<'static, str>>, arg: impl IntoDiagnosticArg,
     ));
     forward!((subdiagnostic, with_subdiagnostic)(
-        subdiagnostic: impl crate::AddToDiagnostic,
-    ));
-    forward!((eager_subdiagnostic, with_eager_subdiagnostic)(
         dcx: &DiagCtxt,
         subdiagnostic: impl crate::AddToDiagnostic,
     ));
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 38c6661377b..00b7c50ad17 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -10,6 +10,7 @@
 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,
 };
@@ -559,6 +560,18 @@ pub struct SilentEmitter {
     pub fatal_note: String,
 }
 
+pub fn silent_translate<'a>(
+    message: &'a DiagnosticMessage,
+) -> Result<Cow<'_, str>, TranslateError<'_>> {
+    match message {
+        DiagnosticMessage::Str(msg) | DiagnosticMessage::Translated(msg) => Ok(Cow::Borrowed(msg)),
+        DiagnosticMessage::FluentIdentifier(identifier, _) => {
+            // Any value works here.
+            Ok(identifier.clone())
+        }
+    }
+}
+
 impl Translate for SilentEmitter {
     fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
         None
@@ -567,6 +580,16 @@ 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 DiagnosticMessage,
+        _: &'a FluentArgs<'_>,
+    ) -> Result<Cow<'_, str>, TranslateError<'_>> {
+        silent_translate(message)
+    }
 }
 
 impl Emitter for SilentEmitter {
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index b738ecb54ff..986e87cd2e2 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -640,7 +640,8 @@ impl DiagCtxt {
         message: DiagnosticMessage,
         args: impl Iterator<Item = DiagnosticArg<'a>>,
     ) -> SubdiagnosticMessage {
-        SubdiagnosticMessage::Eager(Cow::from(self.eagerly_translate_to_string(message, args)))
+        let inner = self.inner.borrow();
+        inner.eagerly_translate(message, args)
     }
 
     /// Translate `message` eagerly with `args` to `String`.
@@ -650,8 +651,7 @@ impl DiagCtxt {
         args: impl Iterator<Item = DiagnosticArg<'a>>,
     ) -> String {
         let inner = self.inner.borrow();
-        let args = crate::translation::to_fluent_args(args);
-        inner.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string()
+        inner.eagerly_translate_to_string(message, args)
     }
 
     // This is here to not allow mutation of flags;
@@ -1446,6 +1446,25 @@ impl DiagCtxtInner {
             .or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
     }
 
+    /// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`.
+    pub fn eagerly_translate<'a>(
+        &self,
+        message: DiagnosticMessage,
+        args: impl Iterator<Item = DiagnosticArg<'a>>,
+    ) -> SubdiagnosticMessage {
+        SubdiagnosticMessage::Translated(Cow::from(self.eagerly_translate_to_string(message, args)))
+    }
+
+    /// Translate `message` eagerly with `args` to `String`.
+    pub fn eagerly_translate_to_string<'a>(
+        &self,
+        message: DiagnosticMessage,
+        args: impl Iterator<Item = DiagnosticArg<'a>>,
+    ) -> String {
+        let args = crate::translation::to_fluent_args(args);
+        self.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string()
+    }
+
     fn flush_delayed(&mut self) {
         if self.delayed_bugs.is_empty() {
             return;
@@ -1484,15 +1503,22 @@ impl DiagCtxtInner {
             }
 
             let mut bug =
-                if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner };
+                if backtrace || self.ice_file.is_none() { bug.decorate(self) } else { bug.inner };
 
             // "Undelay" the delayed bugs (into plain `Bug`s).
             if bug.level != DelayedBug {
                 // NOTE(eddyb) not panicking here because we're already producing
                 // an ICE, and the more information the merrier.
-                bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel {
+                let subdiag = InvalidFlushedDelayedDiagnosticLevel {
                     span: bug.span.primary_span().unwrap(),
                     level: bug.level,
+                };
+                // FIXME: Cannot use `Diagnostic::subdiagnostic` which takes `DiagCtxt`, but it
+                // just uses `DiagCtxtInner` functions.
+                subdiag.add_to_diagnostic_with(&mut bug, |diag, msg| {
+                    let args = diag.args();
+                    let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
+                    self.eagerly_translate(msg, args)
                 });
             }
             bug.level = Bug;
@@ -1527,25 +1553,35 @@ impl DelayedDiagnostic {
         DelayedDiagnostic { inner: diagnostic, note: backtrace }
     }
 
-    fn decorate(mut self) -> Diagnostic {
+    fn decorate(mut self, dcx: &DiagCtxtInner) -> Diagnostic {
+        // FIXME: Cannot use `Diagnostic::subdiagnostic` which takes `DiagCtxt`, but it
+        // just uses `DiagCtxtInner` functions.
+        let subdiag_with = |diag: &mut Diagnostic, msg| {
+            let args = diag.args();
+            let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
+            dcx.eagerly_translate(msg, args)
+        };
+
         match self.note.status() {
             BacktraceStatus::Captured => {
                 let inner = &self.inner;
-                self.inner.subdiagnostic(DelayedAtWithNewline {
+                let subdiag = DelayedAtWithNewline {
                     span: inner.span.primary_span().unwrap_or(DUMMY_SP),
                     emitted_at: inner.emitted_at.clone(),
                     note: self.note,
-                });
+                };
+                subdiag.add_to_diagnostic_with(&mut self.inner, subdiag_with);
             }
             // Avoid the needless newline when no backtrace has been captured,
             // the display impl should just be a single line.
             _ => {
                 let inner = &self.inner;
-                self.inner.subdiagnostic(DelayedAtWithoutNewline {
+                let subdiag = DelayedAtWithoutNewline {
                     span: inner.span.primary_span().unwrap_or(DUMMY_SP),
                     emitted_at: inner.emitted_at.clone(),
                     note: self.note,
-                });
+                };
+                subdiag.add_to_diagnostic_with(&mut self.inner, subdiag_with);
             }
         }
 
@@ -1691,15 +1727,15 @@ impl Level {
 }
 
 // FIXME(eddyb) this doesn't belong here AFAICT, should be moved to callsite.
-pub fn add_elided_lifetime_in_path_suggestion(
+pub fn add_elided_lifetime_in_path_suggestion<E: EmissionGuarantee>(
     source_map: &SourceMap,
-    diag: &mut Diagnostic,
+    diag: &mut DiagnosticBuilder<'_, E>,
     n: usize,
     path_span: Span,
     incl_angl_brckt: bool,
     insertion_span: Span,
 ) {
-    diag.subdiagnostic(ExpectedLifetimeParameter { span: path_span, count: n });
+    diag.subdiagnostic(diag.dcx, ExpectedLifetimeParameter { span: path_span, count: n });
     if !source_map.is_span_accessible(insertion_span) {
         // Do not try to suggest anything if generated by a proc-macro.
         return;
@@ -1708,11 +1744,10 @@ pub fn add_elided_lifetime_in_path_suggestion(
     let suggestion =
         if incl_angl_brckt { format!("<{anon_lts}>") } else { format!("{anon_lts}, ") };
 
-    diag.subdiagnostic(IndicateAnonymousLifetime {
-        span: insertion_span.shrink_to_hi(),
-        count: n,
-        suggestion,
-    });
+    diag.subdiagnostic(
+        diag.dcx,
+        IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion },
+    );
 }
 
 pub fn report_ambiguity_error<'a, G: EmissionGuarantee>(
diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs
index 5bdac367d55..5f074dbbbad 100644
--- a/compiler/rustc_errors/src/translation.rs
+++ b/compiler/rustc_errors/src/translation.rs
@@ -2,7 +2,7 @@ use crate::error::{TranslateError, TranslateErrorKind};
 use crate::snippet::Style;
 use crate::{DiagnosticArg, DiagnosticMessage, FluentBundle};
 use rustc_data_structures::sync::Lrc;
-use rustc_error_messages::FluentArgs;
+pub use rustc_error_messages::FluentArgs;
 use std::borrow::Cow;
 use std::env;
 use std::error::Report;
@@ -61,7 +61,7 @@ pub trait Translate {
     ) -> Result<Cow<'_, str>, TranslateError<'_>> {
         trace!(?message, ?args);
         let (identifier, attr) = match message {
-            DiagnosticMessage::Str(msg) | DiagnosticMessage::Eager(msg) => {
+            DiagnosticMessage::Str(msg) | DiagnosticMessage::Translated(msg) => {
                 return Ok(Cow::Borrowed(msg));
             }
             DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),