about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-02-03 21:29:42 +0100
committerGitHub <noreply@github.com>2024-02-03 21:29:42 +0100
commitb9c87b41d3d8c4c930748997f17f4dfcad5c35d0 (patch)
tree534bc48b96c0b9daa2539d46847d6da51b2ad8bc
parent7c932d9940d412f8b605254833994621468caf1b (diff)
parentbe648028547291dfe64938a0c059640a629ea0b2 (diff)
downloadrust-b9c87b41d3d8c4c930748997f17f4dfcad5c35d0.tar.gz
rust-b9c87b41d3d8c4c930748997f17f4dfcad5c35d0.zip
Rollup merge of #120571 - nnethercote:misc-diagnostics, r=oli-obk
Miscellaneous diagnostics cleanups

All found while working on some speculative, invasive changes, but worth doing in their own right.

r? `@oli-obk`
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/errors.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs5
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs9
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs96
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs8
-rw-r--r--compiler/rustc_errors/src/emitter.rs14
-rw-r--r--compiler/rustc_errors/src/lib.rs28
-rw-r--r--compiler/rustc_errors/src/snippet.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs6
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs4
-rw-r--r--compiler/rustc_interface/src/interface.rs16
-rw-r--r--compiler/rustc_middle/src/error.rs7
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs6
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs4
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs2
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs2
-rw-r--r--compiler/rustc_parse/src/lib.rs2
-rw-r--r--compiler/rustc_session/src/parse.rs2
-rw-r--r--compiler/rustc_session/src/session.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs24
-rw-r--r--tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs2
-rw-r--r--tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr2
25 files changed, 110 insertions, 154 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 0a6b758efa5..5eb85d59fee 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -198,12 +198,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     {
                         let span = self.body.local_decls[local].source_info.span;
                         mut_error = Some(span);
-                        if let Some((buffer, c)) = self.get_buffered_mut_error(span) {
+                        if let Some((buffered_err, c)) = self.get_buffered_mut_error(span) {
                             // We've encountered a second (or more) attempt to mutably borrow an
                             // immutable binding, so the likely problem is with the binding
                             // declaration, not the use. We collect these in a single diagnostic
                             // and make the binding the primary span of the error.
-                            err = buffer;
+                            err = buffered_err;
                             count = c + 1;
                             if count == 2 {
                                 err.replace_span_with(span, false);
diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
index d82ff6656f4..e839d278bea 100644
--- a/compiler/rustc_codegen_llvm/src/errors.rs
+++ b/compiler/rustc_codegen_llvm/src/errors.rs
@@ -102,7 +102,7 @@ pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>);
 impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ParseTargetMachineConfig<'_> {
     fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
         let diag: DiagnosticBuilder<'_, G> = self.0.into_diagnostic(dcx, level);
-        let (message, _) = diag.messages().first().expect("`LlvmError` with no message");
+        let (message, _) = diag.messages.first().expect("`LlvmError` with no message");
         let message = dcx.eagerly_translate_to_string(message.clone(), diag.args());
 
         DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config)
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 06edb794537..4211f875dd0 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -39,7 +39,6 @@ use rustc_target::spec::{MergeFunctions, SanitizerSet};
 
 use crate::errors::ErrorCreatingRemarkDir;
 use std::any::Any;
-use std::borrow::Cow;
 use std::fs;
 use std::io;
 use std::marker::PhantomData;
@@ -1812,12 +1811,12 @@ impl Translate for SharedEmitter {
 
 impl Emitter for SharedEmitter {
     fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) {
-        let args: FxHashMap<Cow<'_, str>, DiagnosticArgValue> =
+        let args: FxHashMap<DiagnosticArgName, DiagnosticArgValue> =
             diag.args().map(|(name, arg)| (name.clone(), arg.clone())).collect();
         drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
             msgs: diag.messages.clone(),
             args: args.clone(),
-            code: diag.code.clone(),
+            code: diag.code,
             lvl: diag.level(),
         })));
         for child in &diag.children {
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index dabf78ef90e..1ebc82ad6d4 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -1,6 +1,8 @@
 use std::mem;
 
-use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, IntoDiagnostic, IntoDiagnosticArg};
+use rustc_errors::{
+    DiagnosticArgName, DiagnosticArgValue, DiagnosticMessage, IntoDiagnostic, IntoDiagnosticArg,
+};
 use rustc_hir::CRATE_HIR_ID;
 use rustc_middle::mir::AssertKind;
 use rustc_middle::query::TyCtxtAt;
@@ -32,10 +34,7 @@ impl MachineStopType for ConstEvalErrKind {
             AssertFailure(x) => x.diagnostic_message(),
         }
     }
-    fn add_args(
-        self: Box<Self>,
-        adder: &mut dyn FnMut(std::borrow::Cow<'static, str>, DiagnosticArgValue),
-    ) {
+    fn add_args(self: Box<Self>, adder: &mut dyn FnMut(DiagnosticArgName, DiagnosticArgValue)) {
         use ConstEvalErrKind::*;
         match *self {
             ConstAccessesStatic | ModifiedGlobal => {}
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index b87eef07fd5..8ad4925cff2 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -33,7 +33,10 @@ pub type DiagnosticArgName = Cow<'static, str>;
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
 pub enum DiagnosticArgValue {
     Str(Cow<'static, str>),
-    Number(i128),
+    // This gets converted to a `FluentNumber`, which is an `f64`. An `i32`
+    // safely fits in an `f64`. Any integers bigger than that will be converted
+    // to strings in `into_diagnostic_arg` and stored using the `Str` variant.
+    Number(i32),
     StrListSepByAnd(Vec<Cow<'static, str>>),
 }
 
@@ -113,7 +116,7 @@ pub struct Diagnostic {
 
     /// With `-Ztrack_diagnostics` enabled,
     /// we print where in rustc this error was emitted.
-    pub emitted_at: DiagnosticLocation,
+    pub(crate) emitted_at: DiagnosticLocation,
 }
 
 #[derive(Clone, Debug, Encodable, Decodable)]
@@ -162,10 +165,10 @@ impl DiagnosticStyledString {
         DiagnosticStyledString(vec![])
     }
     pub fn push_normal<S: Into<String>>(&mut self, t: S) {
-        self.0.push(StringPart::Normal(t.into()));
+        self.0.push(StringPart::normal(t));
     }
     pub fn push_highlighted<S: Into<String>>(&mut self, t: S) {
-        self.0.push(StringPart::Highlighted(t.into()));
+        self.0.push(StringPart::highlighted(t));
     }
     pub fn push<S: Into<String>>(&mut self, t: S, highlight: bool) {
         if highlight {
@@ -175,35 +178,34 @@ impl DiagnosticStyledString {
         }
     }
     pub fn normal<S: Into<String>>(t: S) -> DiagnosticStyledString {
-        DiagnosticStyledString(vec![StringPart::Normal(t.into())])
+        DiagnosticStyledString(vec![StringPart::normal(t)])
     }
 
     pub fn highlighted<S: Into<String>>(t: S) -> DiagnosticStyledString {
-        DiagnosticStyledString(vec![StringPart::Highlighted(t.into())])
+        DiagnosticStyledString(vec![StringPart::highlighted(t)])
     }
 
     pub fn content(&self) -> String {
-        self.0.iter().map(|x| x.content()).collect::<String>()
+        self.0.iter().map(|x| x.content.as_str()).collect::<String>()
     }
 }
 
 #[derive(Debug, PartialEq, Eq)]
-pub enum StringPart {
-    Normal(String),
-    Highlighted(String),
+pub struct StringPart {
+    content: String,
+    style: Style,
 }
 
 impl StringPart {
-    pub fn content(&self) -> &str {
-        match self {
-            &StringPart::Normal(ref s) | &StringPart::Highlighted(ref s) => s,
-        }
+    pub fn normal<S: Into<String>>(content: S) -> StringPart {
+        StringPart { content: content.into(), style: Style::NoStyle }
+    }
+
+    pub fn highlighted<S: Into<String>>(content: S) -> StringPart {
+        StringPart { content: content.into(), style: Style::Highlight }
     }
 }
 
-// Note: most of these methods are setters that return `&mut Self`. The small
-// number of simple getter functions all have `get_` prefixes to distinguish
-// them from the setters.
 impl Diagnostic {
     #[track_caller]
     pub fn new<M: Into<DiagnosticMessage>>(level: Level, message: M) -> Self {
@@ -389,19 +391,16 @@ impl Diagnostic {
         } else {
             (0, found_label.len() - expected_label.len())
         };
-        let mut msg: Vec<_> =
-            vec![(format!("{}{} `", " ".repeat(expected_padding), expected_label), Style::NoStyle)];
-        msg.extend(expected.0.iter().map(|x| match *x {
-            StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
-            StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
-        }));
-        msg.push((format!("`{expected_extra}\n"), Style::NoStyle));
-        msg.push((format!("{}{} `", " ".repeat(found_padding), found_label), Style::NoStyle));
-        msg.extend(found.0.iter().map(|x| match *x {
-            StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
-            StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
-        }));
-        msg.push((format!("`{found_extra}"), Style::NoStyle));
+        let mut msg = vec![StringPart::normal(format!(
+            "{}{} `",
+            " ".repeat(expected_padding),
+            expected_label
+        ))];
+        msg.extend(expected.0.into_iter());
+        msg.push(StringPart::normal(format!("`{expected_extra}\n")));
+        msg.push(StringPart::normal(format!("{}{} `", " ".repeat(found_padding), found_label)));
+        msg.extend(found.0.into_iter());
+        msg.push(StringPart::normal(format!("`{found_extra}")));
 
         // For now, just attach these as notes.
         self.highlighted_note(msg);
@@ -410,9 +409,9 @@ impl Diagnostic {
 
     pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self {
         self.highlighted_note(vec![
-            (format!("`{name}` from trait: `"), Style::NoStyle),
-            (signature, Style::Highlight),
-            ("`".to_string(), Style::NoStyle),
+            StringPart::normal(format!("`{name}` from trait: `")),
+            StringPart::highlighted(signature),
+            StringPart::normal("`"),
         ]);
         self
     }
@@ -424,10 +423,7 @@ impl Diagnostic {
         self
     }
 
-    fn highlighted_note<M: Into<SubdiagnosticMessage>>(
-        &mut self,
-        msg: Vec<(M, Style)>,
-    ) -> &mut Self {
+    fn highlighted_note(&mut self, msg: Vec<StringPart>) -> &mut Self {
         self.sub_with_highlights(Level::Note, msg, MultiSpan::new());
         self
     }
@@ -496,7 +492,7 @@ impl Diagnostic {
     }
 
     /// Add a help message attached to this diagnostic with a customizable highlighted message.
-    pub fn highlighted_help(&mut self, msg: Vec<(String, Style)>) -> &mut Self {
+    pub fn highlighted_help(&mut self, msg: Vec<StringPart>) -> &mut Self {
         self.sub_with_highlights(Level::Help, msg, MultiSpan::new());
         self
     }
@@ -890,15 +886,6 @@ impl Diagnostic {
         self
     }
 
-    pub fn clear_code(&mut self) -> &mut Self {
-        self.code = None;
-        self
-    }
-
-    pub fn get_code(&self) -> Option<ErrCode> {
-        self.code
-    }
-
     pub fn primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self {
         self.messages[0] = (msg.into(), Style::NoStyle);
         self
@@ -913,7 +900,7 @@ impl Diagnostic {
 
     pub fn arg(
         &mut self,
-        name: impl Into<Cow<'static, str>>,
+        name: impl Into<DiagnosticArgName>,
         arg: impl IntoDiagnosticArg,
     ) -> &mut Self {
         self.args.insert(name.into(), arg.into_diagnostic_arg());
@@ -924,10 +911,6 @@ impl Diagnostic {
         self.args = args;
     }
 
-    pub fn messages(&self) -> &[(DiagnosticMessage, Style)] {
-        &self.messages
-    }
-
     /// 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).
@@ -958,15 +941,10 @@ impl Diagnostic {
 
     /// Convenience function for internal use, clients should use one of the
     /// public methods above.
-    fn sub_with_highlights<M: Into<SubdiagnosticMessage>>(
-        &mut self,
-        level: Level,
-        messages: Vec<(M, Style)>,
-        span: MultiSpan,
-    ) {
+    fn sub_with_highlights(&mut self, level: Level, messages: Vec<StringPart>, span: MultiSpan) {
         let messages = messages
             .into_iter()
-            .map(|m| (self.subdiagnostic_message_to_diagnostic_message(m.0), m.1))
+            .map(|m| (self.subdiagnostic_message_to_diagnostic_message(m.content), m.style))
             .collect();
         let sub = SubDiagnostic { level, messages, span };
         self.children.push(sub);
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index faab3fc663a..15effd3cbec 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -63,12 +63,8 @@ macro_rules! into_diagnostic_arg_for_number {
         $(
             impl IntoDiagnosticArg for $ty {
                 fn into_diagnostic_arg(self) -> DiagnosticArgValue {
-                    // HACK: `FluentNumber` the underline backing struct represent
-                    // numbers using a f64 which can't represent all the i128 numbers
-                    // So in order to be able to use fluent selectors and still
-                    // have all the numbers representable we only convert numbers
-                    // below a certain threshold.
-                    if let Ok(n) = TryInto::<i128>::try_into(self) && n >= -100 && n <= 100 {
+                    // Convert to a string if it won't fit into `Number`.
+                    if let Ok(n) = TryInto::<i32>::try_into(self) {
                         DiagnosticArgValue::Number(n)
                     } else {
                         self.to_string().into_diagnostic_arg()
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 9f76c1dd248..4be5ed923e5 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -558,7 +558,7 @@ impl Emitter for HumanEmitter {
 /// failures of rustc, as witnessed e.g. in issue #89358.
 pub struct SilentEmitter {
     pub fatal_dcx: DiagCtxt,
-    pub fatal_note: Option<String>,
+    pub fatal_note: String,
 }
 
 impl Translate for SilentEmitter {
@@ -576,13 +576,11 @@ impl Emitter for SilentEmitter {
         None
     }
 
-    fn emit_diagnostic(&mut self, d: &Diagnostic) {
-        if d.level == Level::Fatal {
-            let mut d = d.clone();
-            if let Some(ref note) = self.fatal_note {
-                d.note(note.clone());
-            }
-            self.fatal_dcx.emit_diagnostic(d);
+    fn emit_diagnostic(&mut self, diag: &Diagnostic) {
+        if diag.level == Level::Fatal {
+            let mut diag = diag.clone();
+            diag.note(self.fatal_note.clone());
+            self.fatal_dcx.emit_diagnostic(diag);
         }
     }
 }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 960b68196ff..b2bd4d8eb95 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -34,7 +34,7 @@ extern crate self as rustc_errors;
 pub use codes::*;
 pub use diagnostic::{
     AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgName,
-    DiagnosticArgValue, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
+    DiagnosticArgValue, DiagnosticStyledString, IntoDiagnosticArg, StringPart, SubDiagnostic,
 };
 pub use diagnostic_builder::{
     BugAbort, DiagnosticBuilder, EmissionGuarantee, FatalAbort, IntoDiagnostic,
@@ -102,7 +102,6 @@ pub type PResult<'a, T> = Result<T, PErr<'a>>;
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 
 // `PResult` is used a lot. Make sure it doesn't unintentionally get bigger.
-// (See also the comment on `DiagnosticBuilderInner`'s `diagnostic` field.)
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 rustc_data_structures::static_assert_size!(PResult<'_, ()>, 16);
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
@@ -1039,10 +1038,6 @@ impl DiagCtxt {
         }
     }
 
-    pub fn take_future_breakage_diagnostics(&self) -> Vec<Diagnostic> {
-        std::mem::take(&mut self.inner.borrow_mut().future_breakage_diagnostics)
-    }
-
     pub fn abort_if_errors(&self) {
         let mut inner = self.inner.borrow_mut();
         inner.emit_stashed_diagnostics();
@@ -1150,8 +1145,12 @@ impl DiagCtxt {
         self.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type);
     }
 
-    pub fn emit_future_breakage_report(&self, diags: Vec<Diagnostic>) {
-        self.inner.borrow_mut().emitter.emit_future_breakage_report(diags)
+    pub fn emit_future_breakage_report(&self) {
+        let mut inner = self.inner.borrow_mut();
+        let diags = std::mem::take(&mut inner.future_breakage_diagnostics);
+        if !diags.is_empty() {
+            inner.emitter.emit_future_breakage_report(diags);
+        }
     }
 
     pub fn emit_unused_externs(
@@ -1224,9 +1223,8 @@ impl DiagCtxtInner {
     /// Emit all stashed diagnostics.
     fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
         let has_errors = self.has_errors();
-        let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::<Vec<_>>();
         let mut reported = None;
-        for diag in diags {
+        for (_, diag) in std::mem::take(&mut self.stashed_diagnostics).into_iter() {
             // Decrement the count tracking the stash; emitting will increment it.
             if diag.is_error() {
                 if diag.is_lint.is_some() {
@@ -1254,7 +1252,7 @@ impl DiagCtxtInner {
         // be stored. Instead, they are buffered until the `LintExpectationId` is replaced by
         // a stable one by the `LintLevelsBuilder`.
         if let Some(LintExpectationId::Unstable { .. }) = diagnostic.level.get_expectation_id() {
-            self.unstable_expect_diagnostics.push(diagnostic.clone());
+            self.unstable_expect_diagnostics.push(diagnostic);
             return None;
         }
 
@@ -1269,16 +1267,14 @@ impl DiagCtxtInner {
             DelayedBug(DelayedBugKind::Normal) => {
                 let backtrace = std::backtrace::Backtrace::capture();
                 self.span_delayed_bugs
-                    .push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));
-
+                    .push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace));
                 #[allow(deprecated)]
                 return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
             }
             DelayedBug(DelayedBugKind::GoodPath) => {
                 let backtrace = std::backtrace::Backtrace::capture();
                 self.good_path_delayed_bugs
-                    .push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));
-
+                    .push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace));
                 return None;
             }
             _ => {}
@@ -1424,7 +1420,7 @@ impl DiagCtxtInner {
                     &mut out,
                     "delayed span bug: {}\n{}\n",
                     bug.inner
-                        .messages()
+                        .messages
                         .iter()
                         .filter_map(|(msg, _)| msg.as_str())
                         .collect::<String>(),
diff --git a/compiler/rustc_errors/src/snippet.rs b/compiler/rustc_errors/src/snippet.rs
index 98eb70b5fce..b55f7853885 100644
--- a/compiler/rustc_errors/src/snippet.rs
+++ b/compiler/rustc_errors/src/snippet.rs
@@ -197,7 +197,7 @@ pub struct StyledString {
     pub style: Style,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
 pub enum Style {
     MainHeaderMsg,
     HeaderMsg,
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 3674a760cbf..5cdcc1bb860 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -590,7 +590,6 @@ fn infer_placeholder_type<'a>(
 
                 // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
                 // We are typeck and have the real type, so remove that and suggest the actual type.
-                // FIXME(eddyb) this looks like it should be functionality on `Diagnostic`.
                 if let Ok(suggestions) = &mut err.suggestions {
                     suggestions.clear();
                 }
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index b7f28ef958a..fcf4b59e93f 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -576,7 +576,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if (lhs, rhs).references_error() {
             err.downgrade_to_delayed_bug();
         }
-        if self.tcx.sess.teach(err.get_code().unwrap()) {
+        if self.tcx.sess.teach(err.code.unwrap()) {
             err.note(
                 "In a match expression, only numbers and characters can be matched \
                     against a range. This is because the compiler checks that the range \
@@ -847,7 +847,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 type_str
             );
             err.span_label(span, format!("type `{type_str}` cannot be dereferenced"));
-            if self.tcx.sess.teach(err.get_code().unwrap()) {
+            if self.tcx.sess.teach(err.code.unwrap()) {
                 err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ);
             }
             return Err(err.emit());
@@ -1669,7 +1669,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
         }
-        if tcx.sess.teach(err.get_code().unwrap()) {
+        if tcx.sess.teach(err.code.unwrap()) {
             err.note(
                 "This error indicates that a struct pattern attempted to \
                  extract a nonexistent field from a struct. Struct fields \
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index 0e7c641e0e0..0452d4fe6c8 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -195,7 +195,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             }
                         }
                         diag.help("type parameters must be constrained to match other types");
-                        if tcx.sess.teach(diag.get_code().unwrap()) {
+                        if tcx.sess.teach(diag.code.unwrap()) {
                             diag.help(
                                 "given a type parameter `T` and a method `foo`:
 ```
@@ -678,7 +678,7 @@ impl<T> Trait<T> for X {
                  https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
             );
         }
-        if tcx.sess.teach(diag.get_code().unwrap()) {
+        if tcx.sess.teach(diag.code.unwrap()) {
             diag.help(
                 "given an associated type `T` and a method `foo`:
 ```
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 5ca88090996..8a4705e0056 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -45,20 +45,19 @@ pub struct Compiler {
 pub(crate) fn parse_cfg(dcx: &DiagCtxt, cfgs: Vec<String>) -> Cfg {
     cfgs.into_iter()
         .map(|s| {
-            let sess = ParseSess::with_silent_emitter(Some(format!(
+            let sess = ParseSess::with_silent_emitter(format!(
                 "this error occurred on the command line: `--cfg={s}`"
-            )));
+            ));
             let filename = FileName::cfg_spec_source_code(&s);
 
             macro_rules! error {
                 ($reason: expr) => {
                     #[allow(rustc::untranslatable_diagnostic)]
                     #[allow(rustc::diagnostic_outside_of_impl)]
-                    dcx.struct_fatal(format!(
+                    dcx.fatal(format!(
                         concat!("invalid `--cfg` argument: `{}` (", $reason, ")"),
                         s
-                    ))
-                    .emit();
+                    ));
                 };
             }
 
@@ -108,20 +107,19 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg {
     let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() };
 
     for s in specs {
-        let sess = ParseSess::with_silent_emitter(Some(format!(
+        let sess = ParseSess::with_silent_emitter(format!(
             "this error occurred on the command line: `--check-cfg={s}`"
-        )));
+        ));
         let filename = FileName::cfg_spec_source_code(&s);
 
         macro_rules! error {
             ($reason:expr) => {
                 #[allow(rustc::untranslatable_diagnostic)]
                 #[allow(rustc::diagnostic_outside_of_impl)]
-                dcx.struct_fatal(format!(
+                dcx.fatal(format!(
                     concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"),
                     s
                 ))
-                .emit()
             };
         }
 
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index 211da800202..3ebbcd65030 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -1,7 +1,6 @@
-use std::borrow::Cow;
 use std::fmt;
 
-use rustc_errors::{codes::*, DiagnosticArgValue, DiagnosticMessage};
+use rustc_errors::{codes::*, DiagnosticArgName, DiagnosticArgValue, DiagnosticMessage};
 use rustc_macros::Diagnostic;
 use rustc_span::{Span, Symbol};
 
@@ -95,14 +94,14 @@ pub(super) struct ConstNotUsedTraitAlias {
 
 pub struct CustomSubdiagnostic<'a> {
     pub msg: fn() -> DiagnosticMessage,
-    pub add_args: Box<dyn FnOnce(&mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue)) + 'a>,
+    pub add_args: Box<dyn FnOnce(&mut dyn FnMut(DiagnosticArgName, DiagnosticArgValue)) + 'a>,
 }
 
 impl<'a> CustomSubdiagnostic<'a> {
     pub fn label(x: fn() -> DiagnosticMessage) -> Self {
         Self::label_and_then(x, |_| {})
     }
-    pub fn label_and_then<F: FnOnce(&mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue)) + 'a>(
+    pub fn label_and_then<F: FnOnce(&mut dyn FnMut(DiagnosticArgName, DiagnosticArgValue)) + 'a>(
         msg: fn() -> DiagnosticMessage,
         f: F,
     ) -> Self {
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 95574aee499..0f69ab93452 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -5,7 +5,9 @@ use crate::mir::{ConstAlloc, ConstValue};
 use crate::ty::{layout, tls, Ty, TyCtxt, ValTree};
 
 use rustc_data_structures::sync::Lock;
-use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg};
+use rustc_errors::{
+    DiagnosticArgName, DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg,
+};
 use rustc_macros::HashStable;
 use rustc_session::CtfeBacktrace;
 use rustc_span::{def_id::DefId, Span, DUMMY_SP};
@@ -485,7 +487,7 @@ pub trait MachineStopType: Any + fmt::Debug + Send {
     fn diagnostic_message(&self) -> DiagnosticMessage;
     /// Add diagnostic arguments by passing name and value pairs to `adder`, which are passed to
     /// fluent for formatting the translated diagnostic message.
-    fn add_args(self: Box<Self>, adder: &mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue));
+    fn add_args(self: Box<Self>, adder: &mut dyn FnMut(DiagnosticArgName, DiagnosticArgValue));
 }
 
 impl dyn MachineStopType {
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 37c5bba46a7..c9e69253701 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -14,7 +14,9 @@ use crate::ty::{AdtDef, InstanceDef, UserTypeAnnotationIndex};
 use crate::ty::{GenericArg, GenericArgsRef};
 
 use rustc_data_structures::captures::Captures;
-use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg};
+use rustc_errors::{
+    DiagnosticArgName, DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg,
+};
 use rustc_hir::def::{CtorKind, Namespace};
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
 use rustc_hir::{self, CoroutineDesugaring, CoroutineKind, ImplicitSelfKind};
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 0fe33e441f4..91b7952bec5 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -292,7 +292,7 @@ impl<O> AssertKind<O> {
         }
     }
 
-    pub fn add_args(self, adder: &mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue))
+    pub fn add_args(self, adder: &mut dyn FnMut(DiagnosticArgName, DiagnosticArgValue))
     where
         O: fmt::Debug,
     {
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index c49f92f4f85..eba62aae60f 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -34,7 +34,7 @@ pub(crate) macro throw_machine_stop_str($($tt:tt)*) {{
 
         fn add_args(
             self: Box<Self>,
-            _: &mut dyn FnMut(std::borrow::Cow<'static, str>, rustc_errors::DiagnosticArgValue),
+            _: &mut dyn FnMut(rustc_errors::DiagnosticArgName, rustc_errors::DiagnosticArgValue),
         ) {}
     }
     throw_machine_stop!(Zst)
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 49e036c3801..d5fa1108687 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -39,7 +39,7 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 // uses a HOF to parse anything, and <source> includes file and
 // `source_str`.
 
-/// A variant of 'panictry!' that works on a `Vec<Diagnostic>` instead of a single
+/// A variant of 'panictry!' that works on a `Vec<DiagnosticBuilder>` instead of a single
 /// `DiagnosticBuilder`.
 macro_rules! panictry_buffer {
     ($e:expr) => {{
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 1cfaa49401d..8adb0cbcc9d 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -258,7 +258,7 @@ impl ParseSess {
         }
     }
 
-    pub fn with_silent_emitter(fatal_note: Option<String>) -> Self {
+    pub fn with_silent_emitter(fatal_note: String) -> Self {
         let fallback_bundle = fallback_fluent_bundle(Vec::new(), false);
         let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
         let fatal_dcx = DiagCtxt::with_tty_emitter(None, fallback_bundle).disable_warnings();
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 3a0ae74dd92..f6af5a4f87e 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -288,19 +288,9 @@ impl Session {
     pub fn finish_diagnostics(&self, registry: &Registry) {
         self.check_miri_unleashed_features();
         self.dcx().print_error_count(registry);
-        self.emit_future_breakage();
-    }
-
-    fn emit_future_breakage(&self) {
-        if !self.opts.json_future_incompat {
-            return;
-        }
-
-        let diags = self.dcx().take_future_breakage_diagnostics();
-        if diags.is_empty() {
-            return;
+        if self.opts.json_future_incompat {
+            self.dcx().emit_future_breakage_report();
         }
-        self.dcx().emit_future_breakage_report(diags);
     }
 
     /// Returns true if the crate is a testing one.
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 5bab57ca56c..2dec27a6126 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2717,7 +2717,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             let (trait_name, trait_verb) =
                 if name == sym::Send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
 
-            err.clear_code();
+            err.code = None;
             err.primary_message(format!(
                 "{future_or_coroutine} cannot be {trait_verb} between threads safely"
             ));
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index dee3e14f3c9..d9c5de17af8 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -20,7 +20,7 @@ use crate::traits::{
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_errors::{
     codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder,
-    ErrorGuaranteed, MultiSpan, StashKey, Style,
+    ErrorGuaranteed, MultiSpan, StashKey, StringPart,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace, Res};
@@ -2059,11 +2059,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()),
                     });
                 err.highlighted_help(vec![
-                    (format!("the trait `{}` ", cand.print_trait_sugared()), Style::NoStyle),
-                    ("is".to_string(), Style::Highlight),
-                    (" implemented for `".to_string(), Style::NoStyle),
-                    (cand.self_ty().to_string(), Style::Highlight),
-                    ("`".to_string(), Style::NoStyle),
+                    StringPart::normal(format!("the trait `{}` ", cand.print_trait_sugared())),
+                    StringPart::highlighted("is"),
+                    StringPart::normal(" implemented for `"),
+                    StringPart::highlighted(cand.self_ty().to_string()),
+                    StringPart::normal("`"),
                 ]);
 
                 if let [TypeError::Sorts(exp_found)] = &terrs[..] {
@@ -2095,12 +2095,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         _ => (" implemented for `", ""),
                     };
                 err.highlighted_help(vec![
-                    (format!("the trait `{}` ", cand.print_trait_sugared()), Style::NoStyle),
-                    ("is".to_string(), Style::Highlight),
-                    (desc.to_string(), Style::NoStyle),
-                    (cand.self_ty().to_string(), Style::Highlight),
-                    ("`".to_string(), Style::NoStyle),
-                    (mention_castable.to_string(), Style::NoStyle),
+                    StringPart::normal(format!("the trait `{}` ", cand.print_trait_sugared())),
+                    StringPart::highlighted("is"),
+                    StringPart::normal(desc),
+                    StringPart::highlighted(cand.self_ty().to_string()),
+                    StringPart::normal("`"),
+                    StringPart::normal(mention_castable),
                 ]);
                 return true;
             }
diff --git a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs
index 785da11b9b2..3056ebb7575 100644
--- a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs
+++ b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs
@@ -19,6 +19,6 @@ use rustc_errors::{Applicability, MultiSpan};
 extern crate rustc_session;
 
 #[derive(Diagnostic)]
-#[diag(compiletest_example, code = 0123)]
+#[diag(compiletest_example, code = E0123)]
 //~^ ERROR diagnostic slug and crate name do not match
 struct Hello {}
diff --git a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr
index eda24a555f8..df1bad3cad0 100644
--- a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr
@@ -1,7 +1,7 @@
 error: diagnostic slug and crate name do not match
   --> $DIR/enforce_slug_naming.rs:22:8
    |
-LL | #[diag(compiletest_example, code = 0123)]
+LL | #[diag(compiletest_example, code = E0123)]
    |        ^^^^^^^^^^^^^^^^^^^
    |
    = note: slug is `compiletest_example` but the crate name is `rustc_dummy`