diff --git a/RELEASES.md b/RELEASES.md
index 3fb74b52292c1..038a83cde84d6 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,96 @@
+Version 1.76.0 (2024-02-08)
+==========================
+
+<a id="1.76.0-Language"></a>
+
+Language
+--------
+- [Document Rust ABI compatibility between various types](https://github.com/rust-lang/rust/pull/115476/)
+- [Also: guarantee that char and u32 are ABI-compatible](https://github.com/rust-lang/rust/pull/118032/)
+- [Warn against ambiguous wide pointer comparisons](https://github.com/rust-lang/rust/pull/117758/)
+
+<a id="1.76.0-Compiler"></a>
+
+Compiler
+--------
+- [Lint pinned `#[must_use]` pointers (in particular, `Box<T>` where `T` is `#[must_use]`) in `unused_must_use`.](https://github.com/rust-lang/rust/pull/118054/)
+- [Soundness fix: fix computing the offset of an unsized field in a packed struct](https://github.com/rust-lang/rust/pull/118540/)
+- [Soundness fix: fix dynamic size/align computation logic for packed types with dyn Trait tail](https://github.com/rust-lang/rust/pull/118538/)
+- [Add `$message_type` field to distinguish json diagnostic outputs](https://github.com/rust-lang/rust/pull/115691/)
+- [Enable Rust to use the EHCont security feature of Windows](https://github.com/rust-lang/rust/pull/118013/)
+- [Add tier 3 {x86_64,i686}-win7-windows-msvc targets](https://github.com/rust-lang/rust/pull/118150/)
+- [Add tier 3 aarch64-apple-watchos target](https://github.com/rust-lang/rust/pull/119074/)
+- [Add tier 3 arm64e-apple-ios & arm64e-apple-darwin targets](https://github.com/rust-lang/rust/pull/115526/)
+
+Refer to Rust's [platform support page][platform-support-doc]
+for more information on Rust's tiered platform support.
+
+<a id="1.76.0-Libraries"></a>
+
+Libraries
+---------
+- [Add a column number to `dbg!()`](https://github.com/rust-lang/rust/pull/114962/)
+- [Add `std::hash::{DefaultHasher, RandomState}` exports](https://github.com/rust-lang/rust/pull/115694/)
+- [Fix rounding issue with exponents in fmt](https://github.com/rust-lang/rust/pull/116301/)
+- [Add T: ?Sized to `RwLockReadGuard` and `RwLockWriteGuard`'s Debug impls.](https://github.com/rust-lang/rust/pull/117138/)
+- [Windows: Allow `File::create` to work on hidden files](https://github.com/rust-lang/rust/pull/116438/)
+
+<a id="1.76.0-Stabilized-APIs"></a>
+
+Stabilized APIs
+---------------
+
+- [`Arc::unwrap_or_clone`](https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#method.unwrap_or_clone)
+- [`Rc::unwrap_or_clone`](https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#method.unwrap_or_clone)
+- [`Result::inspect`](https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.inspect)
+- [`Result::inspect_err`](https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.inspect_err)
+- [`Option::inspect`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.inspect)
+- [`type_name_of_val`](https://doc.rust-lang.org/stable/std/any/fn.type_name_of_val.html)
+- [`std::hash::{DefaultHasher, RandomState}`](https://doc.rust-lang.org/stable/std/hash/index.html#structs)
+  These were previously available only through `std::collections::hash_map`.
+- [`ptr::{from_ref, from_mut}`](https://doc.rust-lang.org/stable/std/ptr/fn.from_ref.html)
+- [`ptr::addr_eq`](https://doc.rust-lang.org/stable/std/ptr/fn.addr_eq.html)
+
+<a id="1.76.0-Cargo"></a>
+
+Cargo
+-----
+
+See [Cargo release notes](https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-176-2024-02-08).
+
+<a id="1.76.0-Rustdoc"></a>
+
+Rustdoc
+-------
+
+- [Don't merge cfg and doc(cfg) attributes for re-exports](https://github.com/rust-lang/rust/pull/113091/)
+- [rustdoc: allow resizing the sidebar / hiding the top bar](https://github.com/rust-lang/rust/pull/115660/)
+- [rustdoc-search: add support for traits and associated types](https://github.com/rust-lang/rust/pull/116085/)
+- [rustdoc: Add highlighting for comments in items declaration](https://github.com/rust-lang/rust/pull/117869/)
+
+<a id="1.76.0-Compatibility-Notes"></a>
+
+Compatibility Notes
+-------------------
+- [Add allow-by-default lint for unit bindings](https://github.com/rust-lang/rust/pull/112380/)
+  This is expected to be upgraded to a warning by default in a future Rust
+  release. Some macros emit bindings with type `()` with user-provided spans,
+  which means that this lint will warn for user code.
+- [Remove x86_64-sun-solaris target.](https://github.com/rust-lang/rust/pull/118091/)
+- [Remove asmjs-unknown-emscripten target](https://github.com/rust-lang/rust/pull/117338/)
+- [Report errors in jobserver inherited through environment variables](https://github.com/rust-lang/rust/pull/113730/)
+  This [may warn](https://github.com/rust-lang/rust/issues/120515) on benign problems too.
+- [Update the minimum external LLVM to 16.](https://github.com/rust-lang/rust/pull/117947/)
+- [Improve `print_tts`](https://github.com/rust-lang/rust/pull/114571/)
+  This change can break some naive manual parsing of token trees in proc macro
+  code which expect a particular structure after `.to_string()`, rather than just arbitrary Rust code.
+- [Make `IMPLIED_BOUNDS_ENTAILMENT` into a hard error from a lint](https://github.com/rust-lang/rust/pull/117984/)
+- [Vec's allocation behavior was changed when collecting some iterators](https://github.com/rust-lang/rust/pull/110353)
+  Allocation behavior is currently not specified, nevertheless changes can be surprising.
+  See [`impl FromIterator for Vec`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#impl-FromIterator%3CT%3E-for-Vec%3CT%3E)
+  for more details.
+- [Properly reject `default` on free const items](https://github.com/rust-lang/rust/pull/117818/)
+
 Version 1.75.0 (2023-12-28)
 ==========================
 
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index dd3f7289a60b2..6b772c1295f55 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -25,7 +25,7 @@ pub(super) struct ItemLowerer<'a, 'hir> {
     pub(super) tcx: TyCtxt<'hir>,
     pub(super) resolver: &'a mut ResolverAstLowering,
     pub(super) ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
-    pub(super) owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>,
+    pub(super) owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<'hir>>,
 }
 
 /// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span
@@ -64,10 +64,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
         }
     }
 
-    pub(super) fn lower_node(
-        &mut self,
-        def_id: LocalDefId,
-    ) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> {
+    pub(super) fn lower_node(&mut self, def_id: LocalDefId) -> hir::MaybeOwner<'hir> {
         let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
         if let hir::MaybeOwner::Phantom = owner {
             let node = self.ast_index[def_id];
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 3621844efc8d2..f26b1331ef388 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -99,7 +99,7 @@ struct LoweringContext<'a, 'hir> {
     /// Attributes inside the owner being lowered.
     attrs: SortedMap<hir::ItemLocalId, &'hir [Attribute]>,
     /// Collect items that were created by lowering the current owner.
-    children: Vec<(LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>)>,
+    children: Vec<(LocalDefId, hir::MaybeOwner<'hir>)>,
 
     coroutine_kind: Option<hir::CoroutineKind>,
 
@@ -415,7 +415,7 @@ fn index_crate<'a>(
 /// This hash will then be part of the crate_hash which is stored in the metadata.
 fn compute_hir_hash(
     tcx: TyCtxt<'_>,
-    owners: &IndexSlice<LocalDefId, hir::MaybeOwner<&hir::OwnerInfo<'_>>>,
+    owners: &IndexSlice<LocalDefId, hir::MaybeOwner<'_>>,
 ) -> Fingerprint {
     let mut hir_body_nodes: Vec<_> = owners
         .iter_enumerated()
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index 8a275a8363010..6cbcda37f50b8 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -130,7 +130,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
         noun_old: &str,
         old_opt_via: &str,
         previous_end_span: Option<Span>,
-    ) -> DiagnosticBuilder<'cx> {
+    ) -> DiagnosticBuilder<'tcx> {
         let mut err = struct_span_code_err!(
             self.dcx(),
             new_loan_span,
@@ -162,7 +162,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
         old_opt_via: &str,
         previous_end_span: Option<Span>,
         second_borrow_desc: &str,
-    ) -> DiagnosticBuilder<'cx> {
+    ) -> DiagnosticBuilder<'tcx> {
         let mut err = struct_span_code_err!(
             self.dcx(),
             new_loan_span,
@@ -194,7 +194,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
         kind_old: &str,
         msg_old: &str,
         old_load_end_span: Option<Span>,
-    ) -> DiagnosticBuilder<'cx> {
+    ) -> DiagnosticBuilder<'tcx> {
         let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") };
         let mut err = struct_span_code_err!(
             self.dcx(),
@@ -235,7 +235,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
         span: Span,
         borrow_span: Span,
         desc: &str,
-    ) -> DiagnosticBuilder<'cx> {
+    ) -> DiagnosticBuilder<'tcx> {
         struct_span_code_err!(
             self.dcx(),
             span,
@@ -252,7 +252,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
         span: Span,
         desc: &str,
         is_arg: bool,
-    ) -> DiagnosticBuilder<'cx> {
+    ) -> DiagnosticBuilder<'tcx> {
         let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" };
         struct_span_code_err!(self.dcx(), span, E0384, "cannot assign {} {}", msg, desc)
     }
@@ -265,7 +265,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
         &self,
         move_from_span: Span,
         move_from_desc: &str,
-    ) -> DiagnosticBuilder<'cx> {
+    ) -> DiagnosticBuilder<'tcx> {
         struct_span_code_err!(
             self.dcx(),
             move_from_span,
@@ -283,7 +283,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
         move_from_span: Span,
         ty: Ty<'_>,
         is_index: Option<bool>,
-    ) -> DiagnosticBuilder<'cx> {
+    ) -> DiagnosticBuilder<'tcx> {
         let type_name = match (&ty.kind(), is_index) {
             (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array",
             (&ty::Slice(_), _) => "slice",
@@ -304,7 +304,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
         &self,
         move_from_span: Span,
         container_ty: Ty<'_>,
-    ) -> DiagnosticBuilder<'cx> {
+    ) -> DiagnosticBuilder<'tcx> {
         struct_span_code_err!(
             self.dcx(),
             move_from_span,
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 2e83072b8d132..b0b7cc076bab5 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -327,7 +327,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         &mut self,
         mpi: MovePathIndex,
         move_span: Span,
-        err: &mut DiagnosticBuilder<'_>,
+        err: &mut DiagnosticBuilder<'tcx>,
         in_pattern: &mut bool,
         move_spans: UseSpans<'_>,
     ) {
@@ -486,7 +486,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         desired_action: InitializationRequiringAction,
         span: Span,
         use_spans: UseSpans<'tcx>,
-    ) -> DiagnosticBuilder<'cx> {
+    ) -> DiagnosticBuilder<'tcx> {
         // We need all statements in the body where the binding was assigned to later find all
         // the branching code paths where the binding *wasn't* assigned to.
         let inits = &self.move_data.init_path_map[mpi];
@@ -880,7 +880,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         location: Location,
         (place, _span): (Place<'tcx>, Span),
         borrow: &BorrowData<'tcx>,
-    ) -> DiagnosticBuilder<'cx> {
+    ) -> DiagnosticBuilder<'tcx> {
         let borrow_spans = self.retrieve_borrow_spans(borrow);
         let borrow_span = borrow_spans.args_or_use();
 
@@ -930,7 +930,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         (place, span): (Place<'tcx>, Span),
         gen_borrow_kind: BorrowKind,
         issued_borrow: &BorrowData<'tcx>,
-    ) -> DiagnosticBuilder<'cx> {
+    ) -> DiagnosticBuilder<'tcx> {
         let issued_spans = self.retrieve_borrow_spans(issued_borrow);
         let issued_span = issued_spans.args_or_use();
 
@@ -2129,7 +2129,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         drop_span: Span,
         borrow_spans: UseSpans<'tcx>,
         explanation: BorrowExplanation<'tcx>,
-    ) -> DiagnosticBuilder<'cx> {
+    ) -> DiagnosticBuilder<'tcx> {
         debug!(
             "report_local_value_does_not_live_long_enough(\
              {:?}, {:?}, {:?}, {:?}, {:?}\
@@ -2304,7 +2304,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         &mut self,
         drop_span: Span,
         borrow_span: Span,
-    ) -> DiagnosticBuilder<'cx> {
+    ) -> DiagnosticBuilder<'tcx> {
         debug!(
             "report_thread_local_value_does_not_live_long_enough(\
              {:?}, {:?}\
@@ -2329,7 +2329,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         borrow_spans: UseSpans<'tcx>,
         proper_span: Span,
         explanation: BorrowExplanation<'tcx>,
-    ) -> DiagnosticBuilder<'cx> {
+    ) -> DiagnosticBuilder<'tcx> {
         if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } =
             explanation
         {
@@ -2440,7 +2440,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                         "consider consuming the `{ty}` when turning it into an \
                                          `Iterator`",
                                     ),
-                                    "into_iter".to_string(),
+                                    "into_iter",
                                     Applicability::MaybeIncorrect,
                                 );
                             }
@@ -2496,7 +2496,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         return_span: Span,
         category: ConstraintCategory<'tcx>,
         opt_place_desc: Option<&String>,
-    ) -> Option<DiagnosticBuilder<'cx>> {
+    ) -> Option<DiagnosticBuilder<'tcx>> {
         let return_kind = match category {
             ConstraintCategory::Return(_) => "return",
             ConstraintCategory::Yield => "yield",
@@ -2591,7 +2591,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         constraint_span: Span,
         captured_var: &str,
         scope: &str,
-    ) -> DiagnosticBuilder<'cx> {
+    ) -> DiagnosticBuilder<'tcx> {
         let tcx = self.infcx.tcx;
         let args_span = use_span.args_or_use();
 
@@ -2699,7 +2699,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         upvar_span: Span,
         upvar_name: Symbol,
         escape_span: Span,
-    ) -> DiagnosticBuilder<'cx> {
+    ) -> DiagnosticBuilder<'tcx> {
         let tcx = self.infcx.tcx;
 
         let escapes_from = tcx.def_descr(self.mir_def_id().to_def_id());
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index fb3525e8998c0..0a0bb75a2a3a6 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -288,7 +288,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         &mut self,
         place: Place<'tcx>,
         span: Span,
-    ) -> DiagnosticBuilder<'a> {
+    ) -> DiagnosticBuilder<'tcx> {
         let description = if place.projection.len() == 1 {
             format!("static item {}", self.describe_any_place(place.as_ref()))
         } else {
@@ -310,7 +310,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         deref_target_place: Place<'tcx>,
         span: Span,
         use_spans: Option<UseSpans<'tcx>>,
-    ) -> DiagnosticBuilder<'a> {
+    ) -> DiagnosticBuilder<'tcx> {
         // Inspect the type of the content behind the
         // borrow to provide feedback about why this
         // was a move rather than a copy.
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 0a6b758efa564..3fddf67f55b97 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);
@@ -924,7 +924,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                         err.span_suggestion_verbose(
                             expr.span.shrink_to_lo(),
                             "use a mutable iterator instead",
-                            "mut ".to_string(),
+                            "mut ",
                             Applicability::MachineApplicable,
                         );
                     }
diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
index ad66c677c78f5..bac1d9dd57f6b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
@@ -251,6 +251,6 @@ impl OutlivesSuggestionBuilder {
         diag.sort_span = mir_span.shrink_to_hi();
 
         // Buffer the diagnostic
-        mbcx.buffer_non_error_diag(diag);
+        mbcx.buffer_non_error(diag);
     }
 }
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index ea48e78509b7c..8b5e548345c97 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -19,7 +19,7 @@ extern crate tracing;
 
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::graph::dominators::Dominators;
-use rustc_errors::{Diagnostic, DiagnosticBuilder};
+use rustc_errors::DiagnosticBuilder;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_index::bit_set::{BitSet, ChunkedBitSet};
@@ -173,12 +173,11 @@ fn do_mir_borrowck<'tcx>(
         }
     }
 
-    let mut errors = error::BorrowckErrors::new(infcx.tcx);
+    let mut diags = diags::BorrowckDiags::new();
 
     // Gather the upvars of a closure, if any.
     if let Some(e) = input_body.tainted_by_errors {
         infcx.set_tainted_by_errors(e);
-        errors.set_tainted_by_errors(e);
     }
 
     // Replace all regions with fresh inference variables. This
@@ -244,7 +243,7 @@ fn do_mir_borrowck<'tcx>(
         &regioncx,
         &opt_closure_req,
         &opaque_type_values,
-        &mut errors,
+        &mut diags,
     );
 
     // The various `flow_*` structures can be large. We drop `flow_inits` here
@@ -305,11 +304,11 @@ fn do_mir_borrowck<'tcx>(
             next_region_name: RefCell::new(1),
             polonius_output: None,
             move_errors: Vec::new(),
-            errors,
+            diags,
         };
         MoveVisitor { ctxt: &mut promoted_mbcx }.visit_body(promoted_body);
         promoted_mbcx.report_move_errors();
-        errors = promoted_mbcx.errors;
+        diags = promoted_mbcx.diags;
 
         struct MoveVisitor<'a, 'cx, 'tcx> {
             ctxt: &'a mut MirBorrowckCtxt<'cx, 'tcx>,
@@ -346,7 +345,7 @@ fn do_mir_borrowck<'tcx>(
         next_region_name: RefCell::new(1),
         polonius_output,
         move_errors: Vec::new(),
-        errors,
+        diags,
     };
 
     // Compute and report region errors, if any.
@@ -574,7 +573,7 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
     /// Results of Polonius analysis.
     polonius_output: Option<Rc<PoloniusOutput>>,
 
-    errors: error::BorrowckErrors<'tcx>,
+    diags: diags::BorrowckDiags<'tcx>,
     move_errors: Vec<MoveError<'tcx>>,
 }
 
@@ -2125,7 +2124,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 | WriteKind::MutableBorrow(BorrowKind::Fake),
             ) => {
                 if self.is_mutable(place.as_ref(), is_local_mutation_allowed).is_err()
-                    && !self.has_buffered_errors()
+                    && !self.has_buffered_diags()
                 {
                     // rust-lang/rust#46908: In pure NLL mode this code path should be
                     // unreachable, but we use `span_delayed_bug` because we can hit this when
@@ -2383,17 +2382,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     }
 }
 
-mod error {
+mod diags {
     use rustc_errors::ErrorGuaranteed;
 
     use super::*;
 
-    pub struct BorrowckErrors<'tcx> {
-        tcx: TyCtxt<'tcx>,
+    enum BufferedDiag<'tcx> {
+        Error(DiagnosticBuilder<'tcx>),
+        NonError(DiagnosticBuilder<'tcx, ()>),
+    }
+
+    impl<'tcx> BufferedDiag<'tcx> {
+        fn sort_span(&self) -> Span {
+            match self {
+                BufferedDiag::Error(diag) => diag.sort_span,
+                BufferedDiag::NonError(diag) => diag.sort_span,
+            }
+        }
+    }
+
+    pub struct BorrowckDiags<'tcx> {
         /// This field keeps track of move errors that are to be reported for given move indices.
         ///
-        /// There are situations where many errors can be reported for a single move out (see #53807)
-        /// and we want only the best of those errors.
+        /// There are situations where many errors can be reported for a single move out (see
+        /// #53807) and we want only the best of those errors.
         ///
         /// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the
         /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of
@@ -2406,51 +2418,38 @@ mod error {
         /// same primary span come out in a consistent order.
         buffered_move_errors:
             BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)>,
+
         buffered_mut_errors: FxIndexMap<Span, (DiagnosticBuilder<'tcx>, usize)>,
-        /// Buffer of diagnostics to be reported. Uses `Diagnostic` rather than `DiagnosticBuilder`
-        /// because it has a mixture of error diagnostics and non-error diagnostics.
-        buffered: Vec<Diagnostic>,
-        /// Set to Some if we emit an error during borrowck
-        tainted_by_errors: Option<ErrorGuaranteed>,
+
+        /// Buffer of diagnostics to be reported. A mixture of error and non-error diagnostics.
+        buffered_diags: Vec<BufferedDiag<'tcx>>,
     }
 
-    impl<'tcx> BorrowckErrors<'tcx> {
-        pub fn new(tcx: TyCtxt<'tcx>) -> Self {
-            BorrowckErrors {
-                tcx,
+    impl<'tcx> BorrowckDiags<'tcx> {
+        pub fn new() -> Self {
+            BorrowckDiags {
                 buffered_move_errors: BTreeMap::new(),
                 buffered_mut_errors: Default::default(),
-                buffered: Default::default(),
-                tainted_by_errors: None,
-            }
-        }
-
-        pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) {
-            if let None = self.tainted_by_errors {
-                self.tainted_by_errors = Some(self.tcx.dcx().span_delayed_bug(
-                    t.span.clone_ignoring_labels(),
-                    "diagnostic buffered but not emitted",
-                ))
+                buffered_diags: Default::default(),
             }
-            self.buffered.push(t.into_diagnostic());
         }
 
-        pub fn buffer_non_error_diag(&mut self, t: DiagnosticBuilder<'_, ()>) {
-            self.buffered.push(t.into_diagnostic());
+        pub fn buffer_error(&mut self, t: DiagnosticBuilder<'tcx>) {
+            self.buffered_diags.push(BufferedDiag::Error(t));
         }
 
-        pub fn set_tainted_by_errors(&mut self, e: ErrorGuaranteed) {
-            self.tainted_by_errors = Some(e);
+        pub fn buffer_non_error(&mut self, t: DiagnosticBuilder<'tcx, ()>) {
+            self.buffered_diags.push(BufferedDiag::NonError(t));
         }
     }
 
     impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
-        pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) {
-            self.errors.buffer_error(t);
+        pub fn buffer_error(&mut self, t: DiagnosticBuilder<'tcx>) {
+            self.diags.buffer_error(t);
         }
 
-        pub fn buffer_non_error_diag(&mut self, t: DiagnosticBuilder<'_, ()>) {
-            self.errors.buffer_non_error_diag(t);
+        pub fn buffer_non_error(&mut self, t: DiagnosticBuilder<'tcx, ()>) {
+            self.diags.buffer_non_error(t);
         }
 
         pub fn buffer_move_error(
@@ -2459,7 +2458,7 @@ mod error {
             place_and_err: (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>),
         ) -> bool {
             if let Some((_, diag)) =
-                self.errors.buffered_move_errors.insert(move_out_indices, place_and_err)
+                self.diags.buffered_move_errors.insert(move_out_indices, place_and_err)
             {
                 // Cancel the old diagnostic so we don't ICE
                 diag.cancel();
@@ -2473,47 +2472,50 @@ mod error {
             &mut self,
             span: Span,
         ) -> Option<(DiagnosticBuilder<'tcx>, usize)> {
-            self.errors.buffered_mut_errors.remove(&span)
+            self.diags.buffered_mut_errors.remove(&span)
         }
 
         pub fn buffer_mut_error(&mut self, span: Span, t: DiagnosticBuilder<'tcx>, count: usize) {
-            self.errors.buffered_mut_errors.insert(span, (t, count));
+            self.diags.buffered_mut_errors.insert(span, (t, count));
         }
 
         pub fn emit_errors(&mut self) -> Option<ErrorGuaranteed> {
+            let mut res = None;
+
             // Buffer any move errors that we collected and de-duplicated.
-            for (_, (_, diag)) in std::mem::take(&mut self.errors.buffered_move_errors) {
+            for (_, (_, diag)) in std::mem::take(&mut self.diags.buffered_move_errors) {
                 // We have already set tainted for this error, so just buffer it.
-                self.errors.buffered.push(diag.into_diagnostic());
+                self.diags.buffered_diags.push(BufferedDiag::Error(diag));
             }
-            for (_, (mut diag, count)) in std::mem::take(&mut self.errors.buffered_mut_errors) {
+            for (_, (mut diag, count)) in std::mem::take(&mut self.diags.buffered_mut_errors) {
                 if count > 10 {
                     diag.note(format!("...and {} other attempted mutable borrows", count - 10));
                 }
-                self.errors.buffered.push(diag.into_diagnostic());
+                self.diags.buffered_diags.push(BufferedDiag::Error(diag));
             }
 
-            if !self.errors.buffered.is_empty() {
-                self.errors.buffered.sort_by_key(|diag| diag.sort_span);
-
-                let dcx = self.dcx();
-                for diag in self.errors.buffered.drain(..) {
-                    dcx.emit_diagnostic(diag);
+            if !self.diags.buffered_diags.is_empty() {
+                self.diags.buffered_diags.sort_by_key(|buffered_diag| buffered_diag.sort_span());
+                for buffered_diag in self.diags.buffered_diags.drain(..) {
+                    match buffered_diag {
+                        BufferedDiag::Error(diag) => res = Some(diag.emit()),
+                        BufferedDiag::NonError(diag) => diag.emit(),
+                    }
                 }
             }
 
-            self.errors.tainted_by_errors
+            res
         }
 
-        pub fn has_buffered_errors(&self) -> bool {
-            self.errors.buffered.is_empty()
+        pub(crate) fn has_buffered_diags(&self) -> bool {
+            self.diags.buffered_diags.is_empty()
         }
 
         pub fn has_move_error(
             &self,
             move_out_indices: &[MoveOutIndex],
-        ) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'cx>)> {
-            self.errors.buffered_move_errors.get(move_out_indices)
+        ) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)> {
+            self.diags.buffered_move_errors.get(move_out_indices)
         }
     }
 }
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index cc8208e9dc306..7ace013975e1b 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -264,7 +264,7 @@ pub(super) fn dump_annotation<'tcx>(
     regioncx: &RegionInferenceContext<'tcx>,
     closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
     opaque_type_values: &FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
-    errors: &mut crate::error::BorrowckErrors<'tcx>,
+    diags: &mut crate::diags::BorrowckDiags<'tcx>,
 ) {
     let tcx = infcx.tcx;
     let base_def_id = tcx.typeck_root_def_id(body.source.def_id());
@@ -310,7 +310,7 @@ pub(super) fn dump_annotation<'tcx>(
         err.note(format!("Inferred opaque type values:\n{opaque_type_values:#?}"));
     }
 
-    errors.buffer_non_error_diag(err);
+    diags.buffer_non_error(err);
 }
 
 fn for_each_region_constraint<'tcx>(
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 03f8f43ff1643..f8f054db65ede 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -408,7 +408,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool, target_info: &Locke
         .filter(|_feature| {
             target_info.cpu_supports(_feature)
             /*
-               adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512ifma,
+               adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma,
                avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
                bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
                sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
index d82ff6656f4d3..e839d278bea7c 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 06edb79453727..4211f875dd01a 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 dabf78ef90e5f..1ebc82ad6d4b2 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 b87eef07fd53a..8ad4925cff288 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_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index 8bfb181648628..faff7f0b52673 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -255,13 +255,8 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
     /// Stashes diagnostic for possible later improvement in a different,
     /// later stage of the compiler. The diagnostic can be accessed with
     /// the provided `span` and `key` through [`DiagCtxt::steal_diagnostic()`].
-    pub fn stash(self, span: Span, key: StashKey) {
-        self.dcx.stash_diagnostic(span, key, self.into_diagnostic());
-    }
-
-    /// Converts the builder to a `Diagnostic` for later emission.
-    pub fn into_diagnostic(mut self) -> Diagnostic {
-        self.take_diag()
+    pub fn stash(mut self, span: Span, key: StashKey) {
+        self.dcx.stash_diagnostic(span, key, self.take_diag());
     }
 
     /// Delay emission of this diagnostic as a bug.
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index faab3fc663a82..15effd3cbec9b 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 9f76c1dd248b0..4be5ed923e5e0 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 960b68196ff02..b2bd4d8eb956e 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 98eb70b5fceee..b55f78538852a 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/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 681e228a0f2ff..de1b28acb1267 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -894,34 +894,23 @@ impl<'tcx> OwnerInfo<'tcx> {
 }
 
 #[derive(Copy, Clone, Debug, HashStable_Generic)]
-pub enum MaybeOwner<T> {
-    Owner(T),
+pub enum MaybeOwner<'tcx> {
+    Owner(&'tcx OwnerInfo<'tcx>),
     NonOwner(HirId),
     /// Used as a placeholder for unused LocalDefId.
     Phantom,
 }
 
-impl<T> MaybeOwner<T> {
-    pub fn as_owner(self) -> Option<T> {
+impl<'tcx> MaybeOwner<'tcx> {
+    pub fn as_owner(self) -> Option<&'tcx OwnerInfo<'tcx>> {
         match self {
             MaybeOwner::Owner(i) => Some(i),
             MaybeOwner::NonOwner(_) | MaybeOwner::Phantom => None,
         }
     }
 
-    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> MaybeOwner<U> {
-        match self {
-            MaybeOwner::Owner(i) => MaybeOwner::Owner(f(i)),
-            MaybeOwner::NonOwner(hir_id) => MaybeOwner::NonOwner(hir_id),
-            MaybeOwner::Phantom => MaybeOwner::Phantom,
-        }
-    }
-
-    pub fn unwrap(self) -> T {
-        match self {
-            MaybeOwner::Owner(i) => i,
-            MaybeOwner::NonOwner(_) | MaybeOwner::Phantom => panic!("Not a HIR owner"),
-        }
+    pub fn unwrap(self) -> &'tcx OwnerInfo<'tcx> {
+        self.as_owner().unwrap_or_else(|| panic!("Not a HIR owner"))
     }
 }
 
@@ -933,7 +922,7 @@ impl<T> MaybeOwner<T> {
 /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
 #[derive(Debug)]
 pub struct Crate<'hir> {
-    pub owners: IndexVec<LocalDefId, MaybeOwner<&'hir OwnerInfo<'hir>>>,
+    pub owners: IndexVec<LocalDefId, MaybeOwner<'hir>>,
     // Only present when incr. comp. is enabled.
     pub opt_hir_hash: Option<Fingerprint>,
 }
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index 407517b15ef5e..e67a44d96ad43 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -247,7 +247,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         err.span_suggestion_verbose(
                             assoc_name.span,
                             fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg,
-                            suggested_name.to_string(),
+                            suggested_name,
                             Applicability::MaybeIncorrect,
                         );
                     }
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 3674a760cbf9d..5cdcc1bb860b2 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/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 2bbef11fa2450..1adde8c21b8e2 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1000,7 +1000,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             err.span_suggestion_verbose(
                 lhs.span.shrink_to_hi(),
                 "you might have meant to write a semicolon here",
-                ";".to_string(),
+                ";",
                 Applicability::MachineApplicable,
             );
             return true;
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 6c9501e93fa11..904961d9eba26 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1116,9 +1116,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                         item_name.span,
                                         format!(
                                             "you might have meant to use `{}`",
-                                            inherent_method.name.as_str()
+                                            inherent_method.name
                                         ),
-                                        inherent_method.name.as_str(),
+                                        inherent_method.name,
                                         Applicability::MaybeIncorrect,
                                     );
                                     break 'outer;
@@ -2019,7 +2019,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 diag.span_suggestion_verbose(
                     sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':').unwrap(),
                     "you may have meant to call an instance method",
-                    ".".to_string(),
+                    ".",
                     Applicability::MaybeIncorrect,
                 );
             }
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index b7f28ef958aa8..fcf4b59e93fcd 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 0e7c641e0e0b8..0452d4fe6c806 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 5ca8809099675..8a4705e0056e1 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 211da80020297..3ebbcd650302f 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/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index b54e438f6144d..94191df30a5e6 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -127,12 +127,11 @@ pub fn provide(providers: &mut Providers) {
     providers.hir_crate_items = map::hir_crate_items;
     providers.crate_hash = map::crate_hash;
     providers.hir_module_items = map::hir_module_items;
-    providers.opt_local_def_id_to_hir_id = |tcx, id| {
-        let owner = tcx.hir_crate(()).owners[id].map(|_| ());
-        Some(match owner {
-            MaybeOwner::Owner(_) => HirId::make_owner(id),
-            MaybeOwner::Phantom => bug!("No HirId for {:?}", id),
+    providers.opt_local_def_id_to_hir_id = |tcx, def_id| {
+        Some(match tcx.hir_crate(()).owners[def_id] {
+            MaybeOwner::Owner(_) => HirId::make_owner(def_id),
             MaybeOwner::NonOwner(hir_id) => hir_id,
+            MaybeOwner::Phantom => bug!("No HirId for {:?}", def_id),
         })
     };
     providers.opt_hir_owner_nodes =
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 95574aee499f2..0f69ab93452f7 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 37c5bba46a7d8..c9e69253701c5 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 0fe33e441f430..91b7952bec5e8 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_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 1b01df6a18714..a272a51f32747 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -185,8 +185,8 @@ impl EraseType for Option<ty::EarlyBinder<Ty<'_>>> {
     type Result = [u8; size_of::<Option<ty::EarlyBinder<Ty<'static>>>>()];
 }
 
-impl<T> EraseType for rustc_hir::MaybeOwner<&'_ T> {
-    type Result = [u8; size_of::<rustc_hir::MaybeOwner<&'static ()>>()];
+impl EraseType for rustc_hir::MaybeOwner<'_> {
+    type Result = [u8; size_of::<rustc_hir::MaybeOwner<'static>>()];
 }
 
 impl<T: EraseType> EraseType for ty::EarlyBinder<T> {
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index c49f92f4f859f..eba62aae60f75 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 49e036c380133..d5fa11086872f 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_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 9f748e2a3feb1..e36a648e2032e 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -3288,7 +3288,7 @@ impl<'a> Parser<'a> {
                         } else {
                             Applicability::MaybeIncorrect
                         };
-                        err.span_suggestion_verbose(sugg_sp, msg, "=> ".to_string(), applicability);
+                        err.span_suggestion_verbose(sugg_sp, msg, "=> ", applicability);
                     }
                 }
                 err
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index 48cf04f7790d0..e059e7074910a 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -148,7 +148,7 @@ impl<'a> Parser<'a> {
             .with_span_suggestion_verbose(
                 mistyped_const_ident.span,
                 "use the `const` keyword",
-                kw::Const.as_str(),
+                kw::Const,
                 Applicability::MachineApplicable,
             )
             .emit();
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 9a77643f9510f..8050b34956ce9 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1453,7 +1453,7 @@ impl<'a> Parser<'a> {
                                 err.span_suggestion_verbose(
                                     prev_span,
                                     "perhaps you meant to use `struct` here",
-                                    "struct".to_string(),
+                                    "struct",
                                     Applicability::MaybeIncorrect,
                                 );
                             }
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 9be286744351f..d19987cb33cf2 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -464,7 +464,11 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
                 self.lookup_and_handle_method(expr.hir_id);
             }
             hir::ExprKind::Field(ref lhs, ..) => {
-                self.handle_field_access(lhs, expr.hir_id);
+                if self.typeck_results().opt_field_index(expr.hir_id).is_some() {
+                    self.handle_field_access(lhs, expr.hir_id);
+                } else {
+                    self.tcx.dcx().span_delayed_bug(expr.span, "couldn't resolve index for field");
+                }
             }
             hir::ExprKind::Struct(qpath, fields, _) => {
                 let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index c8ec10cad17c4..02847a0f5f914 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -289,6 +289,9 @@ resolve_underscore_lifetime_name_cannot_be_used_here =
     `'_` cannot be used here
     .note = `'_` is a reserved lifetime name
 
+resolve_unexpected_res_change_ty_to_const_param_sugg =
+    you might have meant to write a const parameter here
+
 resolve_unreachable_label =
     use of unreachable label `{$name}`
     .label = unreachable label `{$name}`
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index 50ff09feb4d9b..655fc9812d747 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -1,4 +1,4 @@
-use rustc_errors::codes::*;
+use rustc_errors::{codes::*, Applicability};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{
     symbol::{Ident, Symbol},
@@ -787,3 +787,16 @@ pub(crate) struct IsNotDirectlyImportable {
     pub(crate) span: Span,
     pub(crate) target: Ident,
 }
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+    resolve_unexpected_res_change_ty_to_const_param_sugg,
+    code = "const ",
+    style = "verbose"
+)]
+pub(crate) struct UnexpectedResChangeTyToConstParamSugg {
+    #[primary_span]
+    pub span: Span,
+    #[applicability]
+    pub applicability: Applicability,
+}
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 9788fcb3c7d36..1f2803d4368ae 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -594,9 +594,9 @@ struct DiagnosticMetadata<'ast> {
     /// The current trait (used to suggest).
     current_item: Option<&'ast Item>,
 
-    /// When processing generics and encountering a type not found, suggest introducing a type
-    /// param.
-    currently_processing_generics: bool,
+    /// When processing generic arguments and encountering an unresolved ident not found,
+    /// suggest introducing a type or const param depending on the context.
+    currently_processing_generic_args: bool,
 
     /// The current enclosing (non-closure) function (used for better errors).
     current_function: Option<(FnKind<'ast>, Span)>,
@@ -1069,7 +1069,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
 
     fn visit_generic_arg(&mut self, arg: &'ast GenericArg) {
         debug!("visit_generic_arg({:?})", arg);
-        let prev = replace(&mut self.diagnostic_metadata.currently_processing_generics, true);
+        let prev = replace(&mut self.diagnostic_metadata.currently_processing_generic_args, true);
         match arg {
             GenericArg::Type(ref ty) => {
                 // We parse const arguments as path types as we cannot distinguish them during
@@ -1100,7 +1100,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
                                 },
                             );
 
-                            self.diagnostic_metadata.currently_processing_generics = prev;
+                            self.diagnostic_metadata.currently_processing_generic_args = prev;
                             return;
                         }
                     }
@@ -1113,7 +1113,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
                 self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::No))
             }
         }
-        self.diagnostic_metadata.currently_processing_generics = prev;
+        self.diagnostic_metadata.currently_processing_generic_args = prev;
     }
 
     fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) {
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index a4c041f1ff247..310c126213ad2 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -444,6 +444,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         }
 
         self.suggest_bare_struct_literal(&mut err);
+        self.suggest_changing_type_to_const_param(&mut err, res, source, span);
 
         if self.suggest_pattern_match_with_let(&mut err, source, span) {
             // Fallback label.
@@ -452,7 +453,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         }
 
         self.suggest_self_or_self_ref(&mut err, path, span);
-        self.detect_assoct_type_constraint_meant_as_path(&mut err, &base_error);
+        self.detect_assoc_type_constraint_meant_as_path(&mut err, &base_error);
         if self.suggest_self_ty(&mut err, source, path, span)
             || self.suggest_self_value(&mut err, source, path, span)
         {
@@ -491,7 +492,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         (err, candidates)
     }
 
-    fn detect_assoct_type_constraint_meant_as_path(
+    fn detect_assoc_type_constraint_meant_as_path(
         &self,
         err: &mut Diagnostic,
         base_error: &BaseError,
@@ -699,7 +700,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                         err.span_suggestion_verbose(
                             span.shrink_to_lo(),
                             msg,
-                            "self.".to_string(),
+                            "self.",
                             Applicability::MachineApplicable,
                         );
                     }
@@ -710,7 +711,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                         err.span_suggestion_verbose(
                             span.shrink_to_lo(),
                             format!("you might have meant to {}", candidate.action()),
-                            "Self::".to_string(),
+                            "Self::",
                             Applicability::MachineApplicable,
                         );
                     }
@@ -799,7 +800,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
             false,
         ) = (source, res, is_macro)
         {
-            if let Some(bounds @ [_, .., _]) = self.diagnostic_metadata.current_trait_object {
+            if let Some(bounds @ [first_bound, .., last_bound]) =
+                self.diagnostic_metadata.current_trait_object
+            {
                 fallback = true;
                 let spans: Vec<Span> = bounds
                     .iter()
@@ -807,9 +810,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                     .filter(|&sp| sp != base_error.span)
                     .collect();
 
-                let start_span = bounds[0].span();
+                let start_span = first_bound.span();
                 // `end_span` is the end of the poly trait ref (Foo + 'baz + Bar><)
-                let end_span = bounds.last().unwrap().span();
+                let end_span = last_bound.span();
                 // `last_bound_span` is the last bound of the poly trait ref (Foo + >'baz< + Bar)
                 let last_bound_span = spans.last().cloned().unwrap();
                 let mut multi_span: MultiSpan = spans.clone().into();
@@ -1136,6 +1139,55 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         }
     }
 
+    fn suggest_changing_type_to_const_param(
+        &mut self,
+        err: &mut Diagnostic,
+        res: Option<Res>,
+        source: PathSource<'_>,
+        span: Span,
+    ) {
+        let PathSource::Trait(_) = source else { return };
+
+        // We don't include `DefKind::Str` and `DefKind::AssocTy` as they can't be reached here anyway.
+        let applicability = match res {
+            Some(Res::PrimTy(PrimTy::Int(_) | PrimTy::Uint(_) | PrimTy::Bool | PrimTy::Char)) => {
+                Applicability::MachineApplicable
+            }
+            // FIXME(const_generics): Add `DefKind::TyParam` and `SelfTyParam` once we support generic
+            // const generics. Of course, `Struct` and `Enum` may contain ty params, too, but the
+            // benefits of including them here outweighs the small number of false positives.
+            Some(Res::Def(DefKind::Struct | DefKind::Enum, _))
+                if self.r.tcx.features().adt_const_params =>
+            {
+                Applicability::MaybeIncorrect
+            }
+            _ => return,
+        };
+
+        let Some(item) = self.diagnostic_metadata.current_item else { return };
+        let Some(generics) = item.kind.generics() else { return };
+
+        let param = generics.params.iter().find_map(|param| {
+            // Only consider type params with exactly one trait bound.
+            if let [bound] = &*param.bounds
+                && let ast::GenericBound::Trait(tref, ast::TraitBoundModifiers::NONE) = bound
+                && tref.span == span
+                && param.ident.span.eq_ctxt(span)
+            {
+                Some(param.ident.span)
+            } else {
+                None
+            }
+        });
+
+        if let Some(param) = param {
+            err.subdiagnostic(errors::UnexpectedResChangeTyToConstParamSugg {
+                span: param.shrink_to_lo(),
+                applicability,
+            });
+        }
+    }
+
     fn suggest_pattern_match_with_let(
         &mut self,
         err: &mut Diagnostic,
@@ -2419,10 +2471,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         let mut iter = ident.chars().map(|c| c.is_uppercase());
         let single_uppercase_char =
             matches!(iter.next(), Some(true)) && matches!(iter.next(), None);
-        if !self.diagnostic_metadata.currently_processing_generics && !single_uppercase_char {
+        if !self.diagnostic_metadata.currently_processing_generic_args && !single_uppercase_char {
             return None;
         }
-        match (self.diagnostic_metadata.current_item, single_uppercase_char, self.diagnostic_metadata.currently_processing_generics) {
+        match (self.diagnostic_metadata.current_item, single_uppercase_char, self.diagnostic_metadata.currently_processing_generic_args) {
             (Some(Item { kind: ItemKind::Fn(..), ident, .. }), _, _) if ident.name == sym::main => {
                 // Ignore `fn main()` as we don't want to suggest `fn main<T>()`
             }
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 1cfaa49401dac..8adb0cbcc9d76 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 3a0ae74dd9215..f6af5a4f87e07 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_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index 5f5de57dd1d87..c350a37975d23 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -201,6 +201,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability)] = &[
     ("avx512dq", Unstable(sym::avx512_target_feature)),
     ("avx512er", Unstable(sym::avx512_target_feature)),
     ("avx512f", Unstable(sym::avx512_target_feature)),
+    ("avx512fp16", Unstable(sym::avx512_target_feature)),
     ("avx512ifma", Unstable(sym::avx512_target_feature)),
     ("avx512pf", Unstable(sym::avx512_target_feature)),
     ("avx512vbmi", Unstable(sym::avx512_target_feature)),
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 5bab57ca56cb4..79dcf187519bd 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1288,7 +1288,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             err.span_suggestion_verbose(
                 obligation.cause.span.shrink_to_hi(),
                 "consider using clone here",
-                ".clone()".to_string(),
+                ".clone()",
                 Applicability::MaybeIncorrect,
             );
             return true;
@@ -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"
             ));
@@ -3245,7 +3245,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             err.span_suggestion_verbose(
                                 span,
                                 "you can use `impl Trait` as the argument type",
-                                "impl ".to_string(),
+                                "impl ",
                                 Applicability::MaybeIncorrect,
                             );
                             let sugg = if !needs_parens {
@@ -5203,7 +5203,7 @@ fn point_at_assoc_type_restriction(
                     err.span_suggestion_verbose(
                         path.span,
                         "replace the associated type with the type specified in this `impl`",
-                        tcx.type_of(new.def_id).skip_binder().to_string(),
+                        tcx.type_of(new.def_id).skip_binder(),
                         Applicability::MachineApplicable,
                     );
                 }
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 dee3e14f3c918..d9c5de17af885 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/library/core/src/lib.rs b/library/core/src/lib.rs
index 2af242d4b5071..ead8cbe0e2f43 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -200,7 +200,6 @@
 //
 // Language features:
 // tidy-alphabetical-start
-#![cfg_attr(not(bootstrap), feature(is_val_statically_known))]
 #![feature(abi_unadjusted)]
 #![feature(adt_const_params)]
 #![feature(allow_internal_unsafe)]
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index bb35b6128ea5a..d052dcc3e6ee6 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -1374,59 +1374,26 @@ macro_rules! int_impl {
         #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
-        #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
         #[inline]
         pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
-            // SAFETY: This path has the same behavior as the other.
-            if unsafe { intrinsics::is_val_statically_known(self) }
-                && self.unsigned_abs().is_power_of_two()
-            {
-                if self == 1 { // Avoid divide by zero
-                    return Some(1);
-                }
-                if self == -1 { // Avoid divide by zero
-                    return Some(if exp & 1 != 0 { -1 } else { 1 });
-                }
-                // SAFETY: We just checked this is a power of two. and above zero.
-                let power_used = unsafe { intrinsics::cttz_nonzero(self.wrapping_abs()) as u32 };
-                if exp > Self::BITS / power_used { return None; } // Division of constants is free
-
-                // SAFETY: exp <= Self::BITS / power_used
-                let res = unsafe { intrinsics::unchecked_shl(
-                    1 as Self,
-                    intrinsics::unchecked_mul(power_used, exp) as Self
-                )};
-                // LLVM doesn't always optimize out the checks
-                // at the ir level.
-
-                let sign = self.is_negative() && exp & 1 != 0;
-                if !sign && res == Self::MIN  {
-                    None
-                } else if sign {
-                    Some(res.wrapping_neg())
-                } else {
-                    Some(res)
-                }
-            } else {
-                if exp == 0 {
-                    return Some(1);
-                }
-                let mut base = self;
-                let mut acc: Self = 1;
-
-                while exp > 1 {
-                    if (exp & 1) == 1 {
-                        acc = try_opt!(acc.checked_mul(base));
-                    }
-                    exp /= 2;
-                    base = try_opt!(base.checked_mul(base));
+            if exp == 0 {
+                return Some(1);
+            }
+            let mut base = self;
+            let mut acc: Self = 1;
+
+            while exp > 1 {
+                if (exp & 1) == 1 {
+                    acc = try_opt!(acc.checked_mul(base));
                 }
-                // since exp!=0, finally the exp must be 1.
-                // Deal with the final bit of the exponent separately, since
-                // squaring the base afterwards is not necessary and may cause a
-                // needless overflow.
-                acc.checked_mul(base)
+                exp /= 2;
+                base = try_opt!(base.checked_mul(base));
             }
+            // since exp!=0, finally the exp must be 1.
+            // Deal with the final bit of the exponent separately, since
+            // squaring the base afterwards is not necessary and may cause a
+            // needless overflow.
+            acc.checked_mul(base)
         }
 
         /// Strict exponentiation. Computes `self.pow(exp)`, panicking if
@@ -2091,58 +2058,27 @@ macro_rules! int_impl {
         #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
-        #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
         #[inline]
         pub const fn wrapping_pow(self, mut exp: u32) -> Self {
-            // SAFETY: This path has the same behavior as the other.
-            if unsafe { intrinsics::is_val_statically_known(self) }
-                && self.unsigned_abs().is_power_of_two()
-            {
-                if self == 1 { // Avoid divide by zero
-                    return 1;
-                }
-                if self == -1 { // Avoid divide by zero
-                    return if exp & 1 != 0 { -1 } else { 1 };
-                }
-                // SAFETY: We just checked this is a power of two. and above zero.
-                let power_used = unsafe { intrinsics::cttz_nonzero(self.wrapping_abs()) as u32 };
-                if exp > Self::BITS / power_used { return 0; } // Division of constants is free
-
-                // SAFETY: exp <= Self::BITS / power_used
-                let res = unsafe { intrinsics::unchecked_shl(
-                    1 as Self,
-                    intrinsics::unchecked_mul(power_used, exp) as Self
-                )};
-                // LLVM doesn't always optimize out the checks
-                // at the ir level.
-
-                let sign = self.is_negative() && exp & 1 != 0;
-                if sign {
-                    res.wrapping_neg()
-                } else {
-                    res
-                }
-            } else {
-                if exp == 0 {
-                    return 1;
-                }
-                let mut base = self;
-                let mut acc: Self = 1;
-
-                while exp > 1 {
-                    if (exp & 1) == 1 {
-                        acc = acc.wrapping_mul(base);
-                    }
-                    exp /= 2;
-                    base = base.wrapping_mul(base);
-                }
+            if exp == 0 {
+                return 1;
+            }
+            let mut base = self;
+            let mut acc: Self = 1;
 
-                // since exp!=0, finally the exp must be 1.
-                // Deal with the final bit of the exponent separately, since
-                // squaring the base afterwards is not necessary and may cause a
-                // needless overflow.
-                acc.wrapping_mul(base)
+            while exp > 1 {
+                if (exp & 1) == 1 {
+                    acc = acc.wrapping_mul(base);
+                }
+                exp /= 2;
+                base = base.wrapping_mul(base);
             }
+
+            // since exp!=0, finally the exp must be 1.
+            // Deal with the final bit of the exponent separately, since
+            // squaring the base afterwards is not necessary and may cause a
+            // needless overflow.
+            acc.wrapping_mul(base)
         }
 
         /// Calculates `self` + `rhs`
@@ -2625,68 +2561,36 @@ macro_rules! int_impl {
         #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
-        #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
         #[inline]
         pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
-            // SAFETY: This path has the same behavior as the other.
-            if unsafe { intrinsics::is_val_statically_known(self) }
-                && self.unsigned_abs().is_power_of_two()
-            {
-                if self == 1 { // Avoid divide by zero
-                    return (1, false);
-                }
-                if self == -1 { // Avoid divide by zero
-                    return (if exp & 1 != 0 { -1 } else { 1 }, false);
-                }
-                // SAFETY: We just checked this is a power of two. and above zero.
-                let power_used = unsafe { intrinsics::cttz_nonzero(self.wrapping_abs()) as u32 };
-                if exp > Self::BITS / power_used { return (0, true); } // Division of constants is free
-
-                // SAFETY: exp <= Self::BITS / power_used
-                let res = unsafe { intrinsics::unchecked_shl(
-                    1 as Self,
-                    intrinsics::unchecked_mul(power_used, exp) as Self
-                )};
-                // LLVM doesn't always optimize out the checks
-                // at the ir level.
-
-                let sign = self.is_negative() && exp & 1 != 0;
-                let overflow = res == Self::MIN;
-                if sign {
-                    (res.wrapping_neg(), overflow)
-                } else {
-                    (res, overflow)
-                }
-            } else {
-                if exp == 0 {
-                    return (1,false);
-                }
-                let mut base = self;
-                let mut acc: Self = 1;
-                let mut overflown = false;
-                // Scratch space for storing results of overflowing_mul.
-                let mut r;
-
-                while exp > 1 {
-                    if (exp & 1) == 1 {
-                        r = acc.overflowing_mul(base);
-                        acc = r.0;
-                        overflown |= r.1;
-                    }
-                    exp /= 2;
-                    r = base.overflowing_mul(base);
-                    base = r.0;
+            if exp == 0 {
+                return (1,false);
+            }
+            let mut base = self;
+            let mut acc: Self = 1;
+            let mut overflown = false;
+            // Scratch space for storing results of overflowing_mul.
+            let mut r;
+
+            while exp > 1 {
+                if (exp & 1) == 1 {
+                    r = acc.overflowing_mul(base);
+                    acc = r.0;
                     overflown |= r.1;
                 }
-
-                // since exp!=0, finally the exp must be 1.
-                // Deal with the final bit of the exponent separately, since
-                // squaring the base afterwards is not necessary and may cause a
-                // needless overflow.
-                r = acc.overflowing_mul(base);
-                r.1 |= overflown;
-                r
+                exp /= 2;
+                r = base.overflowing_mul(base);
+                base = r.0;
+                overflown |= r.1;
             }
+
+            // since exp!=0, finally the exp must be 1.
+            // Deal with the final bit of the exponent separately, since
+            // squaring the base afterwards is not necessary and may cause a
+            // needless overflow.
+            r = acc.overflowing_mul(base);
+            r.1 |= overflown;
+            r
         }
 
         /// Raises self to the power of `exp`, using exponentiation by squaring.
@@ -2704,68 +2608,28 @@ macro_rules! int_impl {
         #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
-        #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
         #[inline]
         #[rustc_inherit_overflow_checks]
-        #[track_caller] // Hides the hackish overflow check for powers of two.
         pub const fn pow(self, mut exp: u32) -> Self {
-            // SAFETY: This path has the same behavior as the other.
-            if unsafe { intrinsics::is_val_statically_known(self) }
-                && self.unsigned_abs().is_power_of_two()
-            {
-                if self == 1 { // Avoid divide by zero
-                    return 1;
-                }
-                if self == -1 { // Avoid divide by zero
-                    return if exp & 1 != 0 { -1 } else { 1 };
-                }
-                // SAFETY: We just checked this is a power of two. and above zero.
-                let power_used = unsafe { intrinsics::cttz_nonzero(self.wrapping_abs()) as u32 };
-                if exp > Self::BITS / power_used { // Division of constants is free
-                    #[allow(arithmetic_overflow)]
-                    return Self::MAX * Self::MAX * 0;
-                }
+            if exp == 0 {
+                return 1;
+            }
+            let mut base = self;
+            let mut acc = 1;
 
-                // SAFETY: exp <= Self::BITS / power_used
-                let res = unsafe { intrinsics::unchecked_shl(
-                    1 as Self,
-                    intrinsics::unchecked_mul(power_used, exp) as Self
-                )};
-                // LLVM doesn't always optimize out the checks
-                // at the ir level.
-
-                let sign = self.is_negative() && exp & 1 != 0;
-                #[allow(arithmetic_overflow)]
-                if !sign && res == Self::MIN  {
-                    // So it panics.
-                    _ = Self::MAX * Self::MAX;
-                }
-                if sign {
-                    res.wrapping_neg()
-                } else {
-                    res
-                }
-            } else {
-                if exp == 0 {
-                    return 1;
-                }
-                let mut base = self;
-                let mut acc = 1;
-
-                while exp > 1 {
-                    if (exp & 1) == 1 {
-                        acc = acc * base;
-                    }
-                    exp /= 2;
-                    base = base * base;
+            while exp > 1 {
+                if (exp & 1) == 1 {
+                    acc = acc * base;
                 }
-
-                // since exp!=0, finally the exp must be 1.
-                // Deal with the final bit of the exponent separately, since
-                // squaring the base afterwards is not necessary and may cause a
-                // needless overflow.
-                acc * base
+                exp /= 2;
+                base = base * base;
             }
+
+            // since exp!=0, finally the exp must be 1.
+            // Deal with the final bit of the exponent separately, since
+            // squaring the base afterwards is not necessary and may cause a
+            // needless overflow.
+            acc * base
         }
 
         /// Returns the square root of the number, rounded down.
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index d450c68a5b230..a217c2e259d2b 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -1364,49 +1364,28 @@ macro_rules! uint_impl {
         #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
-        #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
         #[inline]
         pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
-            // SAFETY: This path has the same behavior as the other.
-            if unsafe { intrinsics::is_val_statically_known(self) }
-                && self.is_power_of_two()
-            {
-                if self == 1 { // Avoid divide by zero
-                    return Some(1);
-                }
-                // SAFETY: We just checked this is a power of two. and above zero.
-                let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 };
-                if exp > Self::BITS / power_used { return None; } // Division of constants is free
-
-                // SAFETY: exp <= Self::BITS / power_used
-                unsafe { Some(intrinsics::unchecked_shl(
-                    1 as Self,
-                    intrinsics::unchecked_mul(power_used, exp) as Self
-                )) }
-                // LLVM doesn't always optimize out the checks
-                // at the ir level.
-            } else {
-                if exp == 0 {
-                    return Some(1);
-                }
-                let mut base = self;
-                let mut acc: Self = 1;
-
-                while exp > 1 {
-                    if (exp & 1) == 1 {
-                        acc = try_opt!(acc.checked_mul(base));
-                    }
-                    exp /= 2;
-                    base = try_opt!(base.checked_mul(base));
+            if exp == 0 {
+                return Some(1);
+            }
+            let mut base = self;
+            let mut acc: Self = 1;
+
+            while exp > 1 {
+                if (exp & 1) == 1 {
+                    acc = try_opt!(acc.checked_mul(base));
                 }
+                exp /= 2;
+                base = try_opt!(base.checked_mul(base));
+            }
 
-                // since exp!=0, finally the exp must be 1.
-                // Deal with the final bit of the exponent separately, since
-                // squaring the base afterwards is not necessary and may cause a
-                // needless overflow.
+            // since exp!=0, finally the exp must be 1.
+            // Deal with the final bit of the exponent separately, since
+            // squaring the base afterwards is not necessary and may cause a
+            // needless overflow.
 
-                acc.checked_mul(base)
-            }
+            acc.checked_mul(base)
         }
 
         /// Strict exponentiation. Computes `self.pow(exp)`, panicking if
@@ -1908,48 +1887,27 @@ macro_rules! uint_impl {
         #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
-        #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
         #[inline]
         pub const fn wrapping_pow(self, mut exp: u32) -> Self {
-            // SAFETY: This path has the same behavior as the other.
-            if unsafe { intrinsics::is_val_statically_known(self) }
-                && self.is_power_of_two()
-            {
-                if self == 1 { // Avoid divide by zero
-                    return 1;
-                }
-                // SAFETY: We just checked this is a power of two. and above zero.
-                let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 };
-                if exp > Self::BITS / power_used {  return 0; } // Division of constants is free
-
-                // SAFETY: exp <= Self::BITS / power_used
-                unsafe { intrinsics::unchecked_shl(
-                    1 as Self,
-                    intrinsics::unchecked_mul(power_used, exp) as Self
-                )}
-                // LLVM doesn't always optimize out the checks
-                // at the ir level.
-            } else {
-                if exp == 0 {
-                    return 1;
-                }
-                let mut base = self;
-                let mut acc: Self = 1;
-
-                while exp > 1 {
-                    if (exp & 1) == 1 {
-                        acc = acc.wrapping_mul(base);
-                    }
-                    exp /= 2;
-                    base = base.wrapping_mul(base);
-                }
+            if exp == 0 {
+                return 1;
+            }
+            let mut base = self;
+            let mut acc: Self = 1;
 
-                // since exp!=0, finally the exp must be 1.
-                // Deal with the final bit of the exponent separately, since
-                // squaring the base afterwards is not necessary and may cause a
-                // needless overflow.
-                acc.wrapping_mul(base)
+            while exp > 1 {
+                if (exp & 1) == 1 {
+                    acc = acc.wrapping_mul(base);
+                }
+                exp /= 2;
+                base = base.wrapping_mul(base);
             }
+
+            // since exp!=0, finally the exp must be 1.
+            // Deal with the final bit of the exponent separately, since
+            // squaring the base afterwards is not necessary and may cause a
+            // needless overflow.
+            acc.wrapping_mul(base)
         }
 
         /// Calculates `self` + `rhs`
@@ -2383,58 +2341,37 @@ macro_rules! uint_impl {
         #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
-        #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
         #[inline]
         pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
-            // SAFETY: This path has the same behavior as the other.
-            if unsafe { intrinsics::is_val_statically_known(self) }
-                && self.is_power_of_two()
-            {
-                if self == 1 { // Avoid divide by zero
-                    return (1, false);
-                }
-                // SAFETY: We just checked this is a power of two. and above zero.
-                let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 };
-                if exp > Self::BITS / power_used {  return (0, true); } // Division of constants is free
-
-                // SAFETY: exp <= Self::BITS / power_used
-                unsafe { (intrinsics::unchecked_shl(
-                    1 as Self,
-                    intrinsics::unchecked_mul(power_used, exp) as Self
-                ), false) }
-                // LLVM doesn't always optimize out the checks
-                // at the ir level.
-            } else {
-                if exp == 0{
-                    return (1,false);
-                }
-                let mut base = self;
-                let mut acc: Self = 1;
-                let mut overflown = false;
-                // Scratch space for storing results of overflowing_mul.
-                let mut r;
-
-                while exp > 1 {
-                    if (exp & 1) == 1 {
-                        r = acc.overflowing_mul(base);
-                        acc = r.0;
-                        overflown |= r.1;
-                    }
-                    exp /= 2;
-                    r = base.overflowing_mul(base);
-                    base = r.0;
+            if exp == 0{
+                return (1,false);
+            }
+            let mut base = self;
+            let mut acc: Self = 1;
+            let mut overflown = false;
+            // Scratch space for storing results of overflowing_mul.
+            let mut r;
+
+            while exp > 1 {
+                if (exp & 1) == 1 {
+                    r = acc.overflowing_mul(base);
+                    acc = r.0;
                     overflown |= r.1;
                 }
+                exp /= 2;
+                r = base.overflowing_mul(base);
+                base = r.0;
+                overflown |= r.1;
+            }
 
-                // since exp!=0, finally the exp must be 1.
-                // Deal with the final bit of the exponent separately, since
-                // squaring the base afterwards is not necessary and may cause a
-                // needless overflow.
-                r = acc.overflowing_mul(base);
-                r.1 |= overflown;
+            // since exp!=0, finally the exp must be 1.
+            // Deal with the final bit of the exponent separately, since
+            // squaring the base afterwards is not necessary and may cause a
+            // needless overflow.
+            r = acc.overflowing_mul(base);
+            r.1 |= overflown;
 
-                r
-            }
+            r
         }
 
         /// Raises self to the power of `exp`, using exponentiation by squaring.
@@ -2450,64 +2387,28 @@ macro_rules! uint_impl {
         #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
-        #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
         #[inline]
         #[rustc_inherit_overflow_checks]
-        #[track_caller] // Hides the hackish overflow check for powers of two.
         pub const fn pow(self, mut exp: u32) -> Self {
-            // LLVM now knows that `self` is a constant value, but not a
-            // constant in Rust. This allows us to compute the power used at
-            // compile-time.
-            //
-            // This will likely add a branch in debug builds, but this should
-            // be ok.
-            //
-            // This is a massive performance boost in release builds as you can
-            // get the power of a power of two and the exponent through a `shl`
-            // instruction, but we must add a couple more checks for parity with
-            // our own `pow`.
-            // SAFETY: This path has the same behavior as the other.
-            if unsafe { intrinsics::is_val_statically_known(self) }
-                && self.is_power_of_two()
-            {
-                if self == 1 { // Avoid divide by zero
-                    return 1;
-                }
-                // SAFETY: We just checked this is a power of two. and above zero.
-                let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 };
-                if exp > Self::BITS / power_used { // Division of constants is free
-                    #[allow(arithmetic_overflow)]
-                    return Self::MAX * Self::MAX * 0;
-                }
+            if exp == 0 {
+                return 1;
+            }
+            let mut base = self;
+            let mut acc = 1;
 
-                // SAFETY: exp <= Self::BITS / power_used
-                unsafe { intrinsics::unchecked_shl(
-                    1 as Self,
-                    intrinsics::unchecked_mul(power_used, exp) as Self
-                )}
-                // LLVM doesn't always optimize out the checks
-                // at the ir level.
-            } else {
-                if exp == 0 {
-                    return 1;
-                }
-                let mut base = self;
-                let mut acc = 1;
-
-                while exp > 1 {
-                    if (exp & 1) == 1 {
-                        acc = acc * base;
-                    }
-                    exp /= 2;
-                    base = base * base;
+            while exp > 1 {
+                if (exp & 1) == 1 {
+                    acc = acc * base;
                 }
-
-                // since exp!=0, finally the exp must be 1.
-                // Deal with the final bit of the exponent separately, since
-                // squaring the base afterwards is not necessary and may cause a
-                // needless overflow.
-                acc * base
+                exp /= 2;
+                base = base * base;
             }
+
+            // since exp!=0, finally the exp must be 1.
+            // Deal with the final bit of the exponent separately, since
+            // squaring the base afterwards is not necessary and may cause a
+            // needless overflow.
+            acc * base
         }
 
         /// Returns the square root of the number, rounded down.
diff --git a/tests/codegen/pow_of_two.rs b/tests/codegen/pow_of_two.rs
deleted file mode 100644
index 372360dfd12c7..0000000000000
--- a/tests/codegen/pow_of_two.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-// compile-flags: --crate-type=lib -Zmerge-functions=disabled -O -C overflow-checks=false
-
-// CHECK-LABEL: @a(
-#[no_mangle]
-pub fn a(exp: u32) -> u64 {
-    // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 64
-    // CHECK: %{{[^ ]+}} = zext{{( nneg)?}} i32 %exp to i64
-    // CHECK: %{{[^ ]+}} = shl nuw i64 {{[^ ]+}}, %{{[^ ]+}}
-    // CHECK: ret i64 %{{[^ ]+}}
-    2u64.pow(exp)
-}
-
-// CHECK-LABEL: @b(
-#[no_mangle]
-pub fn b(exp: u32) -> i64 {
-    // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 64
-    // CHECK: %{{[^ ]+}} = zext{{( nneg)?}} i32 %exp to i64
-    // CHECK: %{{[^ ]+}} = shl nuw i64 {{[^ ]+}}, %{{[^ ]+}}
-    // CHECK: ret i64 %{{[^ ]+}}
-    2i64.pow(exp)
-}
-
-// CHECK-LABEL: @c(
-#[no_mangle]
-pub fn c(exp: u32) -> u32 {
-    // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 16
-    // CHECK: %{{[^ ]+}} = shl nuw nsw i32 %exp, 1
-    // CHECK: %{{[^ ]+}} = shl nuw i32 1, %{{[^ ]+}}
-    // CHECK: %{{[^ ]+}} = select i1 %{{[^ ]+}}, i32 0, i32 %{{[^ ]+}}
-    // CHECK: ret i32 %{{[^ ]+}}
-    4u32.pow(exp)
-}
-
-// CHECK-LABEL: @d(
-#[no_mangle]
-pub fn d(exp: u32) -> u32 {
-    // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 6
-    // CHECK: %{{[^ ]+}} = mul nuw nsw i32 %exp, 5
-    // CHECK: %{{[^ ]+}} = shl nuw nsw i32 1, %{{[^ ]+}}
-    // CHECK: %{{[^ ]+}} = select i1 {{[^ ]+}}, i32 0, i32 %{{[^ ]+}}
-    // CHECK: ret i32 %{{[^ ]+}}
-    32u32.pow(exp)
-}
-
-// CHECK-LABEL: @e(
-#[no_mangle]
-pub fn e(exp: u32) -> i32 {
-    // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 6
-    // CHECK: %{{[^ ]+}} = mul nuw {{(nsw )?}}i32 %exp, 5
-    // CHECK: %{{[^ ]+}} = shl nuw {{(nsw )?}}i32 1, %{{[^ ]+}}
-    // CHECK: %{{[^ ]+}} = select i1 {{[^ ]+}}, i32 0, i32 %{{[^ ]+}}
-    // CHECK: ret i32 %{{[^ ]+}}
-    32i32.pow(exp)
-}
-// note: d and e are expected to yield the same IR
diff --git a/tests/coverage/bad_counter_ids.cov-map b/tests/coverage/bad_counter_ids.cov-map
index 3b51e3ef9de66..7eff7f5f02f3c 100644
--- a/tests/coverage/bad_counter_ids.cov-map
+++ b/tests/coverage/bad_counter_ids.cov-map
@@ -1,81 +1,81 @@
 Function name: bad_counter_ids::eq_bad
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 23, 01, 02, 1f, 00, 03, 01, 00, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 24, 01, 02, 1f, 00, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 35, 1) to (start + 2, 31)
+- Code(Counter(0)) at (prev + 36, 1) to (start + 2, 31)
 - Code(Zero) at (prev + 3, 1) to (start + 0, 2)
 
 Function name: bad_counter_ids::eq_bad_message
-Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 28, 01, 02, 0f, 02, 02, 20, 00, 2b, 00, 01, 01, 00, 02]
+Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 29, 01, 02, 0f, 02, 02, 20, 00, 2b, 00, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Zero
 Number of file 0 mappings: 3
-- Code(Counter(0)) at (prev + 40, 1) to (start + 2, 15)
+- Code(Counter(0)) at (prev + 41, 1) to (start + 2, 15)
 - Code(Expression(0, Sub)) at (prev + 2, 32) to (start + 0, 43)
     = (c0 - Zero)
 - Code(Zero) at (prev + 1, 1) to (start + 0, 2)
 
 Function name: bad_counter_ids::eq_good
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 0f, 01, 02, 1f, 05, 03, 01, 00, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 02, 1f, 05, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 15, 1) to (start + 2, 31)
+- Code(Counter(0)) at (prev + 16, 1) to (start + 2, 31)
 - Code(Counter(1)) at (prev + 3, 1) to (start + 0, 2)
 
 Function name: bad_counter_ids::eq_good_message
-Raw bytes (19): 0x[01, 01, 00, 03, 01, 14, 01, 02, 0f, 00, 02, 20, 00, 2b, 05, 01, 01, 00, 02]
+Raw bytes (19): 0x[01, 01, 00, 03, 01, 15, 01, 02, 0f, 00, 02, 20, 00, 2b, 05, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 3
-- Code(Counter(0)) at (prev + 20, 1) to (start + 2, 15)
+- Code(Counter(0)) at (prev + 21, 1) to (start + 2, 15)
 - Code(Zero) at (prev + 2, 32) to (start + 0, 43)
 - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2)
 
 Function name: bad_counter_ids::ne_bad
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 2d, 01, 02, 1f, 00, 03, 01, 00, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 2e, 01, 02, 1f, 00, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 45, 1) to (start + 2, 31)
+- Code(Counter(0)) at (prev + 46, 1) to (start + 2, 31)
 - Code(Zero) at (prev + 3, 1) to (start + 0, 2)
 
 Function name: bad_counter_ids::ne_bad_message
-Raw bytes (19): 0x[01, 01, 00, 03, 01, 32, 01, 02, 0f, 05, 02, 20, 00, 2b, 00, 01, 01, 00, 02]
+Raw bytes (19): 0x[01, 01, 00, 03, 01, 33, 01, 02, 0f, 05, 02, 20, 00, 2b, 00, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 3
-- Code(Counter(0)) at (prev + 50, 1) to (start + 2, 15)
+- Code(Counter(0)) at (prev + 51, 1) to (start + 2, 15)
 - Code(Counter(1)) at (prev + 2, 32) to (start + 0, 43)
 - Code(Zero) at (prev + 1, 1) to (start + 0, 2)
 
 Function name: bad_counter_ids::ne_good
-Raw bytes (16): 0x[01, 01, 01, 01, 00, 02, 01, 19, 01, 02, 1f, 02, 03, 01, 00, 02]
+Raw bytes (16): 0x[01, 01, 01, 01, 00, 02, 01, 1a, 01, 02, 1f, 02, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Zero
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 25, 1) to (start + 2, 31)
+- Code(Counter(0)) at (prev + 26, 1) to (start + 2, 31)
 - Code(Expression(0, Sub)) at (prev + 3, 1) to (start + 0, 2)
     = (c0 - Zero)
 
 Function name: bad_counter_ids::ne_good_message
-Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 1e, 01, 02, 0f, 00, 02, 20, 00, 2b, 02, 01, 01, 00, 02]
+Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 1f, 01, 02, 0f, 00, 02, 20, 00, 2b, 02, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
 - expression 0 operands: lhs = Counter(0), rhs = Zero
 Number of file 0 mappings: 3
-- Code(Counter(0)) at (prev + 30, 1) to (start + 2, 15)
+- Code(Counter(0)) at (prev + 31, 1) to (start + 2, 15)
 - Code(Zero) at (prev + 2, 32) to (start + 0, 43)
 - Code(Expression(0, Sub)) at (prev + 1, 1) to (start + 0, 2)
     = (c0 - Zero)
diff --git a/tests/coverage/bad_counter_ids.coverage b/tests/coverage/bad_counter_ids.coverage
index 5474ec2f78552..39e6cae11ddac 100644
--- a/tests/coverage/bad_counter_ids.coverage
+++ b/tests/coverage/bad_counter_ids.coverage
@@ -1,5 +1,6 @@
    LL|       |#![feature(coverage_attribute)]
-   LL|       |// compile-flags: --edition=2021 -Copt-level=0 -Zmir-opt-level=3
+   LL|       |// edition: 2021
+   LL|       |// compile-flags: -Copt-level=0 -Zmir-opt-level=3
    LL|       |
    LL|       |// Regression test for <https://github.com/rust-lang/rust/issues/117012>.
    LL|       |//
diff --git a/tests/coverage/bad_counter_ids.rs b/tests/coverage/bad_counter_ids.rs
index ef5460102b70c..e22b96468abd3 100644
--- a/tests/coverage/bad_counter_ids.rs
+++ b/tests/coverage/bad_counter_ids.rs
@@ -1,5 +1,6 @@
 #![feature(coverage_attribute)]
-// compile-flags: --edition=2021 -Copt-level=0 -Zmir-opt-level=3
+// edition: 2021
+// compile-flags: -Copt-level=0 -Zmir-opt-level=3
 
 // Regression test for <https://github.com/rust-lang/rust/issues/117012>.
 //
diff --git a/tests/coverage/closure_macro.coverage b/tests/coverage/closure_macro.coverage
index a6eeb79a71c8f..ab152a91356a0 100644
--- a/tests/coverage/closure_macro.coverage
+++ b/tests/coverage/closure_macro.coverage
@@ -1,5 +1,5 @@
-   LL|       |// compile-flags: --edition=2018
    LL|       |#![feature(coverage_attribute)]
+   LL|       |// edition: 2018
    LL|       |
    LL|       |macro_rules! bail {
    LL|       |    ($msg:literal $(,)?) => {
diff --git a/tests/coverage/closure_macro.rs b/tests/coverage/closure_macro.rs
index c3ef916788091..38a81ea434b9b 100644
--- a/tests/coverage/closure_macro.rs
+++ b/tests/coverage/closure_macro.rs
@@ -1,5 +1,5 @@
-// compile-flags: --edition=2018
 #![feature(coverage_attribute)]
+// edition: 2018
 
 macro_rules! bail {
     ($msg:literal $(,)?) => {
diff --git a/tests/coverage/fn_sig_into_try.coverage b/tests/coverage/fn_sig_into_try.coverage
index 71e15fc11eb8a..aac5c9d9a94ee 100644
--- a/tests/coverage/fn_sig_into_try.coverage
+++ b/tests/coverage/fn_sig_into_try.coverage
@@ -1,5 +1,5 @@
    LL|       |#![feature(coverage_attribute)]
-   LL|       |// compile-flags: --edition=2021
+   LL|       |// edition: 2021
    LL|       |
    LL|       |// Regression test for inconsistent handling of function signature spans that
    LL|       |// are followed by code using the `?` operator.
diff --git a/tests/coverage/fn_sig_into_try.rs b/tests/coverage/fn_sig_into_try.rs
index 1f4cc67af8386..5d8e7929ef975 100644
--- a/tests/coverage/fn_sig_into_try.rs
+++ b/tests/coverage/fn_sig_into_try.rs
@@ -1,5 +1,5 @@
 #![feature(coverage_attribute)]
-// compile-flags: --edition=2021
+// edition: 2021
 
 // Regression test for inconsistent handling of function signature spans that
 // are followed by code using the `?` operator.
diff --git a/tests/coverage/issue-93054.cov-map b/tests/coverage/issue-93054.cov-map
index c2c6e9a651673..024ef519fcffe 100644
--- a/tests/coverage/issue-93054.cov-map
+++ b/tests/coverage/issue-93054.cov-map
@@ -1,24 +1,24 @@
 Function name: issue_93054::foo2 (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 00, 1d]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 00, 1d]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Zero) at (prev + 22, 1) to (start + 0, 29)
+- Code(Zero) at (prev + 21, 1) to (start + 0, 29)
 
 Function name: issue_93054::main
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 00, 0d]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 1d, 01, 00, 0d]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 30, 1) to (start + 0, 13)
+- Code(Counter(0)) at (prev + 29, 1) to (start + 0, 13)
 
 Function name: issue_93054::make (unused)
-Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 01, 02, 02]
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 01, 02, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Zero) at (prev + 26, 1) to (start + 2, 2)
+- Code(Zero) at (prev + 25, 1) to (start + 2, 2)
 
diff --git a/tests/coverage/issue-93054.coverage b/tests/coverage/issue-93054.coverage
index 15f225326a427..6ae8ffb5cb4f2 100644
--- a/tests/coverage/issue-93054.coverage
+++ b/tests/coverage/issue-93054.coverage
@@ -1,11 +1,10 @@
    LL|       |#![allow(dead_code, unreachable_code)]
+   LL|       |// edition: 2021
    LL|       |
    LL|       |// Regression test for #93054: Functions using uninhabited types often only have a single,
    LL|       |// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail.
    LL|       |// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them.
    LL|       |
-   LL|       |// compile-flags: --edition=2021
-   LL|       |
    LL|       |enum Never {}
    LL|       |
    LL|       |impl Never {
diff --git a/tests/coverage/issue-93054.rs b/tests/coverage/issue-93054.rs
index da546cfeef854..f16fc1e423962 100644
--- a/tests/coverage/issue-93054.rs
+++ b/tests/coverage/issue-93054.rs
@@ -1,11 +1,10 @@
 #![allow(dead_code, unreachable_code)]
+// edition: 2021
 
 // Regression test for #93054: Functions using uninhabited types often only have a single,
 // unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail.
 // Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them.
 
-// compile-flags: --edition=2021
-
 enum Never {}
 
 impl Never {
diff --git a/tests/coverage/long_and_wide.coverage b/tests/coverage/long_and_wide.coverage
index d7d29ca40cddd..cf4dd2811406c 100644
--- a/tests/coverage/long_and_wide.coverage
+++ b/tests/coverage/long_and_wide.coverage
@@ -1,4 +1,4 @@
-   LL|       |// compile-flags: --edition=2021
+   LL|       |// edition: 2021
    LL|       |// ignore-tidy-linelength
    LL|       |
    LL|       |// This file deliberately contains line and column numbers larger than 127,
diff --git a/tests/coverage/long_and_wide.rs b/tests/coverage/long_and_wide.rs
index a7cbcd4802791..87f2207bd7e67 100644
--- a/tests/coverage/long_and_wide.rs
+++ b/tests/coverage/long_and_wide.rs
@@ -1,4 +1,4 @@
-// compile-flags: --edition=2021
+// edition: 2021
 // ignore-tidy-linelength
 
 // This file deliberately contains line and column numbers larger than 127,
diff --git a/tests/coverage/sort_groups.coverage b/tests/coverage/sort_groups.coverage
index c70d7b3b28253..77cbb09c74a73 100644
--- a/tests/coverage/sort_groups.coverage
+++ b/tests/coverage/sort_groups.coverage
@@ -1,4 +1,4 @@
-   LL|       |// compile-flags: --edition=2021
+   LL|       |// edition: 2021
    LL|       |
    LL|       |// Demonstrate that `sort_subviews.py` can sort instantiation groups into a
    LL|       |// predictable order, while preserving their heterogeneous contents.
diff --git a/tests/coverage/sort_groups.rs b/tests/coverage/sort_groups.rs
index 5adbbc6a87d1f..17fd862ca2cad 100644
--- a/tests/coverage/sort_groups.rs
+++ b/tests/coverage/sort_groups.rs
@@ -1,4 +1,4 @@
-// compile-flags: --edition=2021
+// edition: 2021
 
 // Demonstrate that `sort_subviews.py` can sort instantiation groups into a
 // predictable order, while preserving their heterogeneous contents.
diff --git a/tests/coverage/trivial.coverage b/tests/coverage/trivial.coverage
index 4f417979ef97d..af4be7b8f3356 100644
--- a/tests/coverage/trivial.coverage
+++ b/tests/coverage/trivial.coverage
@@ -1,4 +1,4 @@
-   LL|       |// compile-flags: --edition=2021
+   LL|       |// edition: 2021
    LL|       |
    LL|      1|fn main() {}
 
diff --git a/tests/coverage/trivial.rs b/tests/coverage/trivial.rs
index d0a9b44fb3605..782472739a002 100644
--- a/tests/coverage/trivial.rs
+++ b/tests/coverage/trivial.rs
@@ -1,3 +1,3 @@
-// compile-flags: --edition=2021
+// edition: 2021
 
 fn main() {}
diff --git a/tests/coverage/unreachable.coverage b/tests/coverage/unreachable.coverage
index 7015bb90aa38d..a58765f688be5 100644
--- a/tests/coverage/unreachable.coverage
+++ b/tests/coverage/unreachable.coverage
@@ -1,6 +1,6 @@
    LL|       |#![feature(core_intrinsics)]
    LL|       |#![feature(coverage_attribute)]
-   LL|       |// compile-flags: --edition=2021
+   LL|       |// edition: 2021
    LL|       |
    LL|       |// <https://github.com/rust-lang/rust/issues/116171>
    LL|       |// If we instrument a function for coverage, but all of its counter-increment
diff --git a/tests/coverage/unreachable.rs b/tests/coverage/unreachable.rs
index 6385bfa160d7d..6d0c7b3ca8db5 100644
--- a/tests/coverage/unreachable.rs
+++ b/tests/coverage/unreachable.rs
@@ -1,6 +1,6 @@
 #![feature(core_intrinsics)]
 #![feature(coverage_attribute)]
-// compile-flags: --edition=2021
+// edition: 2021
 
 // <https://github.com/rust-lang/rust/issues/116171>
 // If we instrument a function for coverage, but all of its counter-increment
diff --git a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs
index 785da11b9b2e3..3056ebb7575fd 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 eda24a555f848..df1bad3cad0cf 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`
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index 814d473619777..652e573d6ef32 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -143,7 +143,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_feature = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `f`, `f16c`, `f32mm`, `f64mm`, `fast-unaligned-access`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, `zkt`
+   = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `f`, `f16c`, `f32mm`, `f64mm`, `fast-unaligned-access`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, `zkt`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
diff --git a/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.rs b/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.rs
new file mode 100644
index 0000000000000..3f1f208459d17
--- /dev/null
+++ b/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.rs
@@ -0,0 +1,5 @@
+// Regression test for issue #120615.
+
+fn main() {
+    [(); loop {}].field; //~ ERROR constant evaluation is taking a long time
+}
diff --git a/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.stderr b/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.stderr
new file mode 100644
index 0000000000000..9d62bbc2187f7
--- /dev/null
+++ b/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.stderr
@@ -0,0 +1,17 @@
+error: constant evaluation is taking a long time
+  --> $DIR/field-access-after-const-eval-fail-in-ty.rs:4:10
+   |
+LL |     [(); loop {}].field;
+   |          ^^^^^^^
+   |
+   = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval.
+           If your compilation actually takes a long time, you can safely allow the lint.
+help: the constant being evaluated
+  --> $DIR/field-access-after-const-eval-fail-in-ty.rs:4:10
+   |
+LL |     [(); loop {}].field;
+   |          ^^^^^^^
+   = note: `#[deny(long_running_const_eval)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/resolve/change-ty-to-const-param-sugg-0.rs b/tests/ui/resolve/change-ty-to-const-param-sugg-0.rs
new file mode 100644
index 0000000000000..36fe16f64ebeb
--- /dev/null
+++ b/tests/ui/resolve/change-ty-to-const-param-sugg-0.rs
@@ -0,0 +1,10 @@
+fn make<N: u32>() {}
+//~^ ERROR expected trait, found builtin type `u32`
+//~| HELP you might have meant to write a const parameter here
+
+struct Array<N: usize>([bool; N]);
+//~^ ERROR expected trait, found builtin type `usize`
+//~| HELP you might have meant to write a const parameter here
+//~| ERROR expected value, found type parameter `N`
+
+fn main() {}
diff --git a/tests/ui/resolve/change-ty-to-const-param-sugg-0.stderr b/tests/ui/resolve/change-ty-to-const-param-sugg-0.stderr
new file mode 100644
index 0000000000000..4e411eae3cbbb
--- /dev/null
+++ b/tests/ui/resolve/change-ty-to-const-param-sugg-0.stderr
@@ -0,0 +1,34 @@
+error[E0404]: expected trait, found builtin type `u32`
+  --> $DIR/change-ty-to-const-param-sugg-0.rs:1:12
+   |
+LL | fn make<N: u32>() {}
+   |            ^^^ not a trait
+   |
+help: you might have meant to write a const parameter here
+   |
+LL | fn make<const N: u32>() {}
+   |         +++++
+
+error[E0404]: expected trait, found builtin type `usize`
+  --> $DIR/change-ty-to-const-param-sugg-0.rs:5:17
+   |
+LL | struct Array<N: usize>([bool; N]);
+   |                 ^^^^^ not a trait
+   |
+help: you might have meant to write a const parameter here
+   |
+LL | struct Array<const N: usize>([bool; N]);
+   |              +++++
+
+error[E0423]: expected value, found type parameter `N`
+  --> $DIR/change-ty-to-const-param-sugg-0.rs:5:31
+   |
+LL | struct Array<N: usize>([bool; N]);
+   |              -                ^ not a value
+   |              |
+   |              found this type parameter
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0404, E0423.
+For more information about an error, try `rustc --explain E0404`.
diff --git a/tests/ui/resolve/change-ty-to-const-param-sugg-1.rs b/tests/ui/resolve/change-ty-to-const-param-sugg-1.rs
new file mode 100644
index 0000000000000..b1d2595f3790f
--- /dev/null
+++ b/tests/ui/resolve/change-ty-to-const-param-sugg-1.rs
@@ -0,0 +1,24 @@
+#![feature(adt_const_params)]
+#![allow(incomplete_features)]
+
+use std::marker::ConstParamTy;
+
+struct Tagged<T: Tag, O: Options>;
+//~^ ERROR expected trait, found enum `Tag`
+//~| HELP you might have meant to write a const parameter here
+//~| ERROR expected trait, found struct `Options`
+//~| HELP you might have meant to write a const parameter here
+
+#[derive(PartialEq, Eq, ConstParamTy)]
+enum Tag {
+    One,
+    Two,
+}
+
+#[derive(PartialEq, Eq, ConstParamTy)]
+struct Options {
+    verbose: bool,
+    safe: bool,
+}
+
+fn main() {}
diff --git a/tests/ui/resolve/change-ty-to-const-param-sugg-1.stderr b/tests/ui/resolve/change-ty-to-const-param-sugg-1.stderr
new file mode 100644
index 0000000000000..933fac27f8f4e
--- /dev/null
+++ b/tests/ui/resolve/change-ty-to-const-param-sugg-1.stderr
@@ -0,0 +1,25 @@
+error[E0404]: expected trait, found enum `Tag`
+  --> $DIR/change-ty-to-const-param-sugg-1.rs:6:18
+   |
+LL | struct Tagged<T: Tag, O: Options>;
+   |                  ^^^ not a trait
+   |
+help: you might have meant to write a const parameter here
+   |
+LL | struct Tagged<const T: Tag, O: Options>;
+   |               +++++
+
+error[E0404]: expected trait, found struct `Options`
+  --> $DIR/change-ty-to-const-param-sugg-1.rs:6:26
+   |
+LL | struct Tagged<T: Tag, O: Options>;
+   |                          ^^^^^^^ not a trait
+   |
+help: you might have meant to write a const parameter here
+   |
+LL | struct Tagged<T: Tag, const O: Options>;
+   |                       +++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0404`.