diff --git a/Cargo.lock b/Cargo.lock
index 5feb21a65b7..218fa5a6842 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -469,9 +469,9 @@ version = "0.1.0"
 
 [[package]]
 name = "cc"
-version = "1.0.79"
+version = "1.0.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
 
 [[package]]
 name = "cfg-if"
@@ -3970,6 +3970,7 @@ version = "0.0.0"
 dependencies = [
  "itertools 0.11.0",
  "rustc_ast",
+ "rustc_ast_ir",
  "rustc_attr",
  "rustc_data_structures",
  "rustc_errors",
@@ -4038,6 +4039,7 @@ dependencies = [
 name = "rustc_infer"
 version = "0.0.0"
 dependencies = [
+ "rustc_ast_ir",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_fluent_macro",
@@ -4570,6 +4572,7 @@ name = "rustc_span"
 version = "0.0.0"
 dependencies = [
  "indexmap",
+ "itoa",
  "md-5",
  "rustc_arena",
  "rustc_data_structures",
@@ -4632,6 +4635,7 @@ dependencies = [
  "bitflags 2.4.2",
  "itertools 0.11.0",
  "rustc_ast",
+ "rustc_ast_ir",
  "rustc_attr",
  "rustc_data_structures",
  "rustc_errors",
@@ -4670,6 +4674,7 @@ name = "rustc_transmute"
 version = "0.0.0"
 dependencies = [
  "itertools 0.11.0",
+ "rustc_ast_ir",
  "rustc_data_structures",
  "rustc_hir",
  "rustc_infer",
@@ -4685,6 +4690,7 @@ name = "rustc_ty_utils"
 version = "0.0.0"
 dependencies = [
  "itertools 0.11.0",
+ "rustc_ast_ir",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_fluent_macro",
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 28e148bddb2..1c6d0495ecf 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -1,6 +1,9 @@
+use std::borrow::{Borrow, Cow};
+use std::cmp;
 use std::fmt::{self, Write};
+use std::iter;
+use std::ops::Bound;
 use std::ops::Deref;
-use std::{borrow::Borrow, cmp, iter, ops::Bound};
 
 use rustc_index::Idx;
 use tracing::debug;
@@ -32,7 +35,7 @@ where
 pub trait LayoutCalculator {
     type TargetDataLayoutRef: Borrow<TargetDataLayout>;
 
-    fn delayed_bug(&self, txt: String);
+    fn delayed_bug(&self, txt: impl Into<Cow<'static, str>>);
     fn current_data_layout(&self) -> Self::TargetDataLayoutRef;
 
     fn scalar_pair<FieldIdx: Idx, VariantIdx: Idx>(
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 34529e0a086..4f2b9d0ef50 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1612,8 +1612,9 @@ pub enum PointerKind {
     SharedRef { frozen: bool },
     /// Mutable reference. `unpin` indicates the absence of any pinned data.
     MutableRef { unpin: bool },
-    /// Box. `unpin` indicates the absence of any pinned data.
-    Box { unpin: bool },
+    /// Box. `unpin` indicates the absence of any pinned data. `global` indicates whether this box
+    /// uses the global allocator or a custom one.
+    Box { unpin: bool, global: bool },
 }
 
 /// Note that this information is advisory only, and backends are free to ignore it.
@@ -1622,6 +1623,8 @@ pub enum PointerKind {
 pub struct PointeeInfo {
     pub size: Size,
     pub align: Align,
+    /// If this is `None`, then this is a raw pointer, so size and alignment are not guaranteed to
+    /// be reliable.
     pub safe: Option<PointerKind>,
 }
 
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 13b1a589d9b..d522c285e3e 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2302,6 +2302,9 @@ pub enum InlineAsmOperand {
     Sym {
         sym: InlineAsmSym,
     },
+    Label {
+        block: P<Block>,
+    },
 }
 
 impl InlineAsmOperand {
@@ -2311,7 +2314,7 @@ impl InlineAsmOperand {
             | Self::Out { reg, .. }
             | Self::InOut { reg, .. }
             | Self::SplitInOut { reg, .. } => Some(reg),
-            Self::Const { .. } | Self::Sym { .. } => None,
+            Self::Const { .. } | Self::Sym { .. } | Self::Label { .. } => None,
         }
     }
 }
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index bbbb34f7f2f..9ec92c9d4ed 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1331,6 +1331,7 @@ pub fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
             }
             InlineAsmOperand::Const { anon_const } => vis.visit_anon_const(anon_const),
             InlineAsmOperand::Sym { sym } => vis.visit_inline_asm_sym(sym),
+            InlineAsmOperand::Label { block } => vis.visit_block(block),
         }
     }
 }
@@ -1604,7 +1605,10 @@ pub fn noop_visit_capture_by<T: MutVisitor>(capture_by: &mut CaptureBy, vis: &mu
     }
 }
 
-/// Some value for the AST node that is valid but possibly meaningless.
+/// Some value for the AST node that is valid but possibly meaningless. Similar
+/// to `Default` but not intended for wide use. The value will never be used
+/// meaningfully, it exists just to support unwinding in `visit_clobber` in the
+/// case where its closure panics.
 pub trait DummyAstNode {
     fn dummy() -> Self;
 }
@@ -1679,19 +1683,6 @@ impl DummyAstNode for Stmt {
     }
 }
 
-impl DummyAstNode for Block {
-    fn dummy() -> Self {
-        Block {
-            stmts: Default::default(),
-            id: DUMMY_NODE_ID,
-            rules: BlockCheckMode::Default,
-            span: Default::default(),
-            tokens: Default::default(),
-            could_be_bare_literal: Default::default(),
-        }
-    }
-}
-
 impl DummyAstNode for Crate {
     fn dummy() -> Self {
         Crate {
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index f29022386a9..7296e29301f 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -15,11 +15,12 @@
 
 use crate::ast::*;
 
-use core::ops::ControlFlow;
-
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 
+pub use rustc_ast_ir::visit::VisitorResult;
+pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
+
 #[derive(Copy, Clone, Debug, PartialEq)]
 pub enum AssocCtxt {
     Trait,
@@ -101,51 +102,6 @@ pub enum LifetimeCtxt {
     GenericArg,
 }
 
-/// Similar to the `Try` trait, but also implemented for `()`.
-pub trait VisitorResult {
-    type Residual;
-    fn output() -> Self;
-    fn from_residual(residual: Self::Residual) -> Self;
-    fn branch(self) -> ControlFlow<Self::Residual>;
-}
-
-impl VisitorResult for () {
-    type Residual = !;
-
-    fn output() -> Self {}
-    fn from_residual(_: !) -> Self {}
-    fn branch(self) -> ControlFlow<!> {
-        ControlFlow::Continue(())
-    }
-}
-
-impl<T> VisitorResult for ControlFlow<T> {
-    type Residual = T;
-
-    fn output() -> Self {
-        ControlFlow::Continue(())
-    }
-    fn from_residual(residual: Self::Residual) -> Self {
-        ControlFlow::Break(residual)
-    }
-    fn branch(self) -> ControlFlow<T> {
-        self
-    }
-}
-
-#[macro_export]
-macro_rules! try_visit {
-    ($e:expr) => {
-        match $crate::visit::VisitorResult::branch($e) {
-            core::ops::ControlFlow::Continue(()) => (),
-            #[allow(unreachable_code)]
-            core::ops::ControlFlow::Break(r) => {
-                return $crate::visit::VisitorResult::from_residual(r);
-            }
-        }
-    };
-}
-
 /// Each method of the `Visitor` trait is a hook to be potentially
 /// overridden. Each method's default implementation recursively visits
 /// the substructure of the input via the corresponding `walk` method;
@@ -316,24 +272,6 @@ pub trait Visitor<'ast>: Sized {
     }
 }
 
-#[macro_export]
-macro_rules! walk_list {
-    ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => {
-        for elem in $list {
-            $crate::try_visit!($visitor.$method(elem $(, $($extra_args,)* )?));
-        }
-    }
-}
-
-#[macro_export]
-macro_rules! visit_opt {
-    ($visitor: expr, $method: ident, $opt: expr $(, $($extra_args: expr),* )?) => {
-        if let Some(x) = $opt {
-            $crate::try_visit!($visitor.$method(x $(, $($extra_args,)* )?));
-        }
-    }
-}
-
 pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result {
     walk_list!(visitor, visit_item, &krate.items);
     walk_list!(visitor, visit_attribute, &krate.attrs);
@@ -885,6 +823,7 @@ pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm)
                 try_visit!(visitor.visit_anon_const(anon_const))
             }
             InlineAsmOperand::Sym { sym } => try_visit!(visitor.visit_inline_asm_sym(sym)),
+            InlineAsmOperand::Label { block } => try_visit!(visitor.visit_block(block)),
         }
     }
     V::Result::output()
diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs
index 9fe13709213..ff7a1552047 100644
--- a/compiler/rustc_ast_ir/src/lib.rs
+++ b/compiler/rustc_ast_ir/src/lib.rs
@@ -1,3 +1,4 @@
+#![cfg_attr(feature = "nightly", feature(never_type))]
 #![cfg_attr(feature = "nightly", feature(rustc_attrs))]
 #![cfg_attr(feature = "nightly", allow(internal_features))]
 
@@ -5,6 +6,8 @@
 #[macro_use]
 extern crate rustc_macros;
 
+pub mod visit;
+
 /// The movability of a coroutine / closure literal:
 /// whether a coroutine contains self-references, causing it to be `!Unpin`.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
diff --git a/compiler/rustc_ast_ir/src/visit.rs b/compiler/rustc_ast_ir/src/visit.rs
new file mode 100644
index 00000000000..dec9f7a47d0
--- /dev/null
+++ b/compiler/rustc_ast_ir/src/visit.rs
@@ -0,0 +1,82 @@
+use core::ops::ControlFlow;
+
+/// Similar to the `Try` trait, but also implemented for `()`.
+pub trait VisitorResult {
+    type Residual;
+    fn output() -> Self;
+    fn from_residual(residual: Self::Residual) -> Self;
+    fn from_branch(b: ControlFlow<Self::Residual>) -> Self;
+    fn branch(self) -> ControlFlow<Self::Residual>;
+}
+
+impl VisitorResult for () {
+    #[cfg(feature = "nightly")]
+    type Residual = !;
+
+    #[cfg(not(feature = "nightly"))]
+    type Residual = core::ops::Infallible;
+
+    fn output() -> Self {}
+    fn from_residual(_: Self::Residual) -> Self {}
+    fn from_branch(_: ControlFlow<Self::Residual>) -> Self {}
+    fn branch(self) -> ControlFlow<Self::Residual> {
+        ControlFlow::Continue(())
+    }
+}
+
+impl<T> VisitorResult for ControlFlow<T> {
+    type Residual = T;
+
+    fn output() -> Self {
+        ControlFlow::Continue(())
+    }
+    fn from_residual(residual: Self::Residual) -> Self {
+        ControlFlow::Break(residual)
+    }
+    fn from_branch(b: Self) -> Self {
+        b
+    }
+    fn branch(self) -> Self {
+        self
+    }
+}
+
+#[macro_export]
+macro_rules! try_visit {
+    ($e:expr) => {
+        match $crate::visit::VisitorResult::branch($e) {
+            core::ops::ControlFlow::Continue(()) => (),
+            #[allow(unreachable_code)]
+            core::ops::ControlFlow::Break(r) => {
+                return $crate::visit::VisitorResult::from_residual(r);
+            }
+        }
+    };
+}
+
+#[macro_export]
+macro_rules! visit_opt {
+    ($visitor: expr, $method: ident, $opt: expr $(, $($extra_args: expr),* )?) => {
+        if let Some(x) = $opt {
+            $crate::try_visit!($visitor.$method(x $(, $($extra_args,)* )?));
+        }
+    }
+}
+
+#[macro_export]
+macro_rules! walk_list {
+    ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => {
+        for elem in $list {
+            $crate::try_visit!($visitor.$method(elem $(, $($extra_args,)* )?));
+        }
+    }
+}
+
+#[macro_export]
+macro_rules! walk_visitable_list {
+    ($visitor: expr, $list: expr $(, $($extra_args: expr),* )?) => {
+        for elem in $list {
+            $crate::try_visit!(elem.visit_with($visitor $(, $($extra_args,)* )?));
+        }
+    }
+}
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index e87cf05713c..d91d65497e1 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -88,6 +88,9 @@ ast_lowering_invalid_abi_suggestion = did you mean
 ast_lowering_invalid_asm_template_modifier_const =
     asm template modifiers are not allowed for `const` arguments
 
+ast_lowering_invalid_asm_template_modifier_label =
+    asm template modifiers are not allowed for `label` arguments
+
 ast_lowering_invalid_asm_template_modifier_reg_class =
     invalid asm template modifier for this register class
 
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index fd717e82d26..cef50a70534 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -3,9 +3,9 @@ use crate::{ImplTraitContext, ImplTraitPosition, ParamMode, ResolverAstLoweringE
 use super::errors::{
     AbiSpecifiedMultipleTimes, AttSyntaxOnlyX86, ClobberAbiNotSupported,
     InlineAsmUnsupportedTarget, InvalidAbiClobberAbi, InvalidAsmTemplateModifierConst,
-    InvalidAsmTemplateModifierRegClass, InvalidAsmTemplateModifierRegClassSub,
-    InvalidAsmTemplateModifierSym, InvalidRegister, InvalidRegisterClass, RegisterClassOnlyClobber,
-    RegisterConflict,
+    InvalidAsmTemplateModifierLabel, InvalidAsmTemplateModifierRegClass,
+    InvalidAsmTemplateModifierRegClassSub, InvalidAsmTemplateModifierSym, InvalidRegister,
+    InvalidRegisterClass, RegisterClassOnlyClobber, RegisterConflict,
 };
 use super::LoweringContext;
 
@@ -22,6 +22,7 @@ use std::collections::hash_map::Entry;
 use std::fmt::Write;
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     pub(crate) fn lower_inline_asm(
         &mut self,
         sp: Span,
@@ -236,6 +237,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             }
                         }
                     }
+                    InlineAsmOperand::Label { block } => {
+                        if !self.tcx.features().asm_goto {
+                            feature_err(
+                                sess,
+                                sym::asm_goto,
+                                *op_sp,
+                                "label operands for inline assembly are unstable",
+                            )
+                            .emit();
+                        }
+                        hir::InlineAsmOperand::Label { block: self.lower_block(block, false) }
+                    }
                 };
                 (op, self.lower_span(*op_sp))
             })
@@ -295,6 +308,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             op_span: op_sp,
                         });
                     }
+                    hir::InlineAsmOperand::Label { .. } => {
+                        self.dcx().emit_err(InvalidAsmTemplateModifierLabel {
+                            placeholder_span,
+                            op_span: op_sp,
+                        });
+                    }
                 }
             }
         }
@@ -334,7 +353,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
                         hir::InlineAsmOperand::Const { .. }
                         | hir::InlineAsmOperand::SymFn { .. }
-                        | hir::InlineAsmOperand::SymStatic { .. } => {
+                        | hir::InlineAsmOperand::SymStatic { .. }
+                        | hir::InlineAsmOperand::Label { .. } => {
                             unreachable!("{op:?} is not a register operand");
                         }
                     };
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index eafbe3462bb..76744ae6264 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -1,5 +1,5 @@
 use rustc_errors::{
-    codes::*, AddToDiagnostic, Diag, DiagArgFromDisplay, EmissionGuarantee, SubdiagnosticMessageOp,
+    codes::*, AddToDiagnostic, Diag, DiagArgFromDisplay, EmissionGuarantee, SubdiagMessageOp,
 };
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
@@ -41,7 +41,7 @@ pub struct InvalidAbi {
 pub struct InvalidAbiReason(pub &'static str);
 
 impl AddToDiagnostic for InvalidAbiReason {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _: F,
@@ -261,6 +261,16 @@ pub struct InvalidAsmTemplateModifierSym {
     pub op_span: Span,
 }
 
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_invalid_asm_template_modifier_label)]
+pub struct InvalidAsmTemplateModifierLabel {
+    #[primary_span]
+    #[label(ast_lowering_template_modifier)]
+    pub placeholder_span: Span,
+    #[label(ast_lowering_argument)]
+    pub op_span: Span,
+}
+
 #[derive(Diagnostic, Clone, Copy)]
 #[diag(ast_lowering_register_class_only_clobber)]
 pub struct RegisterClassOnlyClobber {
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 9950db4784b..41f7418ddde 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -125,12 +125,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     let lit_kind = match LitKind::from_token_lit(*token_lit) {
                         Ok(lit_kind) => lit_kind,
                         Err(err) => {
-                            let guar = report_lit_error(
-                                &self.tcx.sess.parse_sess,
-                                err,
-                                *token_lit,
-                                e.span,
-                            );
+                            let guar =
+                                report_lit_error(&self.tcx.sess.psess, err, *token_lit, e.span);
                             LitKind::Err(guar)
                         }
                     };
@@ -721,7 +717,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         sym::track_caller,
                         span,
                     )))),
-                    id: self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(),
+                    id: self.tcx.sess.psess.attr_id_generator.mk_attr_id(),
                     style: AttrStyle::Outer,
                     span: unstable_span,
                 }],
@@ -764,10 +760,28 @@ impl<'hir> LoweringContext<'_, 'hir> {
             Some(hir::CoroutineKind::Coroutine(_))
             | Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _))
             | None => {
-                return hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks {
-                    await_kw_span,
-                    item_span: self.current_item,
-                }));
+                // Lower to a block `{ EXPR; <error> }` so that the awaited expr
+                // is not accidentally orphaned.
+                let stmt_id = self.next_id();
+                let expr_err = self.expr(
+                    expr.span,
+                    hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks {
+                        await_kw_span,
+                        item_span: self.current_item,
+                    })),
+                );
+                return hir::ExprKind::Block(
+                    self.block_all(
+                        expr.span,
+                        arena_vec![self; hir::Stmt {
+                            hir_id: stmt_id,
+                            kind: hir::StmtKind::Semi(expr),
+                            span: expr.span,
+                        }],
+                        Some(self.arena.alloc(expr_err)),
+                    ),
+                    None,
+                );
             }
         };
 
@@ -1499,13 +1513,33 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
     }
 
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
+        let yielded =
+            opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));
+
         let is_async_gen = match self.coroutine_kind {
             Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => false,
             Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true,
             Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => {
-                return hir::ExprKind::Err(
-                    self.dcx().emit_err(AsyncCoroutinesNotSupported { span }),
+                // Lower to a block `{ EXPR; <error> }` so that the awaited expr
+                // is not accidentally orphaned.
+                let stmt_id = self.next_id();
+                let expr_err = self.expr(
+                    yielded.span,
+                    hir::ExprKind::Err(self.dcx().emit_err(AsyncCoroutinesNotSupported { span })),
+                );
+                return hir::ExprKind::Block(
+                    self.block_all(
+                        yielded.span,
+                        arena_vec![self; hir::Stmt {
+                            hir_id: stmt_id,
+                            kind: hir::StmtKind::Semi(yielded),
+                            span: yielded.span,
+                        }],
+                        Some(self.arena.alloc(expr_err)),
+                    ),
+                    None,
                 );
             }
             Some(hir::CoroutineKind::Coroutine(_)) => {
@@ -1535,9 +1569,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
         };
 
-        let yielded =
-            opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));
-
         if is_async_gen {
             // `yield $expr` is transformed into `task_context = yield async_gen_ready($expr)`.
             // This ensures that we store our resumed `ResumeContext` correctly, and also that
@@ -1756,7 +1787,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         // `#[allow(unreachable_code)]`
         let attr = attr::mk_attr_nested_word(
-            &self.tcx.sess.parse_sess.attr_id_generator,
+            &self.tcx.sess.psess.attr_id_generator,
             AttrStyle::Outer,
             sym::allow,
             sym::unreachable_code,
diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs
index 00cb09d7a54..3f84e6b100d 100644
--- a/compiler/rustc_ast_lowering/src/format.rs
+++ b/compiler/rustc_ast_lowering/src/format.rs
@@ -1,4 +1,5 @@
 use super::LoweringContext;
+use core::ops::ControlFlow;
 use rustc_ast as ast;
 use rustc_ast::visit::Visitor;
 use rustc_ast::*;
@@ -594,30 +595,32 @@ fn expand_format_args<'hir>(
 }
 
 fn may_contain_yield_point(e: &ast::Expr) -> bool {
-    struct MayContainYieldPoint(bool);
+    struct MayContainYieldPoint;
 
     impl Visitor<'_> for MayContainYieldPoint {
-        fn visit_expr(&mut self, e: &ast::Expr) {
+        type Result = ControlFlow<()>;
+
+        fn visit_expr(&mut self, e: &ast::Expr) -> ControlFlow<()> {
             if let ast::ExprKind::Await(_, _) | ast::ExprKind::Yield(_) = e.kind {
-                self.0 = true;
+                ControlFlow::Break(())
             } else {
                 visit::walk_expr(self, e);
+                ControlFlow::Continue(())
             }
         }
 
-        fn visit_mac_call(&mut self, _: &ast::MacCall) {
+        fn visit_mac_call(&mut self, _: &ast::MacCall) -> ControlFlow<()> {
             // Macros should be expanded at this point.
             unreachable!("unexpanded macro in ast lowering");
         }
 
-        fn visit_item(&mut self, _: &ast::Item) {
+        fn visit_item(&mut self, _: &ast::Item) -> ControlFlow<()> {
             // Do not recurse into nested items.
+            ControlFlow::Continue(())
         }
     }
 
-    let mut visitor = MayContainYieldPoint(false);
-    visitor.visit_expr(e);
-    visitor.0
+    MayContainYieldPoint.visit_expr(e).is_break()
 }
 
 fn for_all_argument_indexes(template: &mut [FormatArgsPiece], mut f: impl FnMut(&mut usize)) {
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 01b1e6fcaff..52300138186 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -275,7 +275,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         }
                         Some(ty) => this.lower_ty(
                             ty,
-                            ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: false },
+                            ImplTraitContext::OpaqueTy {
+                                origin: hir::OpaqueTyOrigin::TyAlias {
+                                    parent: this.local_def_id(id),
+                                    in_assoc_ty: false,
+                                },
+                                fn_kind: None,
+                            },
                         ),
                     },
                 );
@@ -936,7 +942,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         Some(ty) => {
                             let ty = this.lower_ty(
                                 ty,
-                                ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: true },
+                                ImplTraitContext::OpaqueTy {
+                                    origin: hir::OpaqueTyOrigin::TyAlias {
+                                        parent: this.local_def_id(i.id),
+                                        in_assoc_ty: true,
+                                    },
+                                    fn_kind: None,
+                                },
                             );
                             hir::ImplItemKind::Type(ty)
                         }
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 087d240b0d5..94e1e06a954 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -265,13 +265,12 @@ enum ImplTraitContext {
     /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
     /// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`.
     ///
-    ReturnPositionOpaqueTy {
-        /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn,
+    OpaqueTy {
         origin: hir::OpaqueTyOrigin,
-        fn_kind: FnDeclKind,
+        /// Only used to change the lifetime capture rules, since
+        /// RPITIT captures all in scope, RPIT does not.
+        fn_kind: Option<FnDeclKind>,
     },
-    /// Impl trait in type aliases.
-    TypeAliasesOpaqueTy { in_assoc_ty: bool },
     /// `impl Trait` is unstably accepted in this position.
     FeatureGated(ImplTraitPosition, Symbol),
     /// `impl Trait` is not accepted in this position.
@@ -427,7 +426,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> {
     tcx.ensure_with_value().early_lint_checks(());
     tcx.ensure_with_value().debugger_visualizers(LOCAL_CRATE);
     tcx.ensure_with_value().get_lang_items(());
-    let (mut resolver, krate) = tcx.resolver_for_lowering(()).steal();
+    let (mut resolver, krate) = tcx.resolver_for_lowering().steal();
 
     let ast_index = index_crate(&resolver.node_id_to_def_id, &krate);
     let mut owners = IndexVec::from_fn_n(
@@ -1075,9 +1074,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 // Disallow ATB in dyn types
                 if self.is_in_dyn_type {
                     let suggestion = match itctx {
-                        ImplTraitContext::ReturnPositionOpaqueTy { .. }
-                        | ImplTraitContext::TypeAliasesOpaqueTy { .. }
-                        | ImplTraitContext::Universal => {
+                        ImplTraitContext::OpaqueTy { .. } | ImplTraitContext::Universal => {
                             let bound_end_span = constraint
                                 .gen_args
                                 .as_ref()
@@ -1417,24 +1414,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             TyKind::ImplTrait(def_node_id, bounds) => {
                 let span = t.span;
                 match itctx {
-                    ImplTraitContext::ReturnPositionOpaqueTy { origin, fn_kind } => self
-                        .lower_opaque_impl_trait(
-                            span,
-                            origin,
-                            *def_node_id,
-                            bounds,
-                            Some(fn_kind),
-                            itctx,
-                        ),
-                    ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty } => self
-                        .lower_opaque_impl_trait(
-                            span,
-                            hir::OpaqueTyOrigin::TyAlias { in_assoc_ty },
-                            *def_node_id,
-                            bounds,
-                            None,
-                            itctx,
-                        ),
+                    ImplTraitContext::OpaqueTy { origin, fn_kind } => self.lower_opaque_impl_trait(
+                        span,
+                        origin,
+                        *def_node_id,
+                        bounds,
+                        fn_kind,
+                        itctx,
+                    ),
                     ImplTraitContext::Universal => {
                         let span = t.span;
 
@@ -1553,9 +1540,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         let captured_lifetimes_to_duplicate = match origin {
             hir::OpaqueTyOrigin::TyAlias { .. } => {
-                // in a TAIT like `type Foo<'a> = impl Foo<'a>`, we don't duplicate any
-                // lifetimes, since we don't have the issue that any are late-bound.
-                Vec::new()
+                // type alias impl trait and associated type position impl trait were
+                // decided to capture all in-scope lifetimes, which we collect for
+                // all opaques during resolution.
+                self.resolver
+                    .take_extra_lifetime_params(opaque_ty_node_id)
+                    .into_iter()
+                    .map(|(ident, id, _)| Lifetime { id, ident })
+                    .collect()
             }
             hir::OpaqueTyOrigin::FnReturn(..) => {
                 if matches!(
@@ -1823,9 +1815,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         FnDeclKind::Fn
                         | FnDeclKind::Inherent
                         | FnDeclKind::Trait
-                        | FnDeclKind::Impl => ImplTraitContext::ReturnPositionOpaqueTy {
+                        | FnDeclKind::Impl => ImplTraitContext::OpaqueTy {
                             origin: hir::OpaqueTyOrigin::FnReturn(self.local_def_id(fn_node_id)),
-                            fn_kind: kind,
+                            fn_kind: Some(kind),
                         },
                         FnDeclKind::ExternFn => {
                             ImplTraitContext::Disallowed(ImplTraitPosition::ExternFnReturn)
@@ -1919,9 +1911,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     output,
                     coro,
                     opaque_ty_span,
-                    ImplTraitContext::ReturnPositionOpaqueTy {
+                    ImplTraitContext::OpaqueTy {
                         origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
-                        fn_kind,
+                        fn_kind: Some(fn_kind),
                     },
                 );
                 arena_vec![this; bound]
@@ -2272,6 +2264,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         self.expr_block(block)
     }
 
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen {
         match c.value.kind {
             ExprKind::Underscore => {
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 48941a232c2..aeeb4bf9e76 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -423,7 +423,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             // fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug
             // //      disallowed --^^^^^^^^^^        allowed --^^^^^^^^^^
             // ```
-            FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) => {
+            FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::OpaqueTy { .. }) => {
                 if self.tcx.features().impl_trait_in_fn_trait_return {
                     self.lower_ty(ty, itctx)
                 } else {
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index b56d695c671..2bef4c91224 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -8,8 +8,7 @@
 
 use itertools::{Either, Itertools};
 use rustc_ast::ptr::P;
-use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
-use rustc_ast::walk_list;
+use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
 use rustc_ast::*;
 use rustc_ast_pretty::pprust::{self, State};
 use rustc_data_structures::fx::FxIndexMap;
@@ -18,7 +17,7 @@ use rustc_parse::validate_attr;
 use rustc_session::lint::builtin::{
     DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
 };
-use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
+use rustc_session::lint::{BuiltinLintDiag, LintBuffer};
 use rustc_session::Session;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Span;
@@ -750,7 +749,7 @@ impl<'a> AstValidator<'a> {
                 id,
                 span,
                 fluent::ast_passes_extern_without_abi,
-                BuiltinLintDiagnostics::MissingAbi(span, abi::Abi::FALLBACK),
+                BuiltinLintDiag::MissingAbi(span, abi::Abi::FALLBACK),
             )
         }
     }
@@ -835,7 +834,7 @@ fn validate_generic_param_order(
 
 impl<'a> Visitor<'a> for AstValidator<'a> {
     fn visit_attribute(&mut self, attr: &Attribute) {
-        validate_attr::check_attr(&self.session.parse_sess, attr);
+        validate_attr::check_attr(&self.session.psess, attr);
     }
 
     fn visit_ty(&mut self, ty: &'a Ty) {
@@ -930,35 +929,38 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         only_trait: only_trait.then_some(()),
                     };
 
-                self.visibility_not_permitted(
-                    &item.vis,
-                    errors::VisibilityNotPermittedNote::IndividualImplItems,
-                );
-                if let &Unsafe::Yes(span) = unsafety {
-                    self.dcx().emit_err(errors::InherentImplCannotUnsafe {
-                        span: self_ty.span,
-                        annotation_span: span,
-                        annotation: "unsafe",
-                        self_ty: self_ty.span,
-                    });
-                }
-                if let &ImplPolarity::Negative(span) = polarity {
-                    self.dcx().emit_err(error(span, "negative", false));
-                }
-                if let &Defaultness::Default(def_span) = defaultness {
-                    self.dcx().emit_err(error(def_span, "`default`", true));
-                }
-                if let &Const::Yes(span) = constness {
-                    self.dcx().emit_err(error(span, "`const`", true));
-                }
+                self.with_in_trait_impl(None, |this| {
+                    this.visibility_not_permitted(
+                        &item.vis,
+                        errors::VisibilityNotPermittedNote::IndividualImplItems,
+                    );
+                    if let &Unsafe::Yes(span) = unsafety {
+                        this.dcx().emit_err(errors::InherentImplCannotUnsafe {
+                            span: self_ty.span,
+                            annotation_span: span,
+                            annotation: "unsafe",
+                            self_ty: self_ty.span,
+                        });
+                    }
+                    if let &ImplPolarity::Negative(span) = polarity {
+                        this.dcx().emit_err(error(span, "negative", false));
+                    }
+                    if let &Defaultness::Default(def_span) = defaultness {
+                        this.dcx().emit_err(error(def_span, "`default`", true));
+                    }
+                    if let &Const::Yes(span) = constness {
+                        this.dcx().emit_err(error(span, "`const`", true));
+                    }
 
-                self.visit_vis(&item.vis);
-                self.visit_ident(item.ident);
-                self.with_tilde_const(Some(DisallowTildeConstContext::Impl(item.span)), |this| {
-                    this.visit_generics(generics)
+                    this.visit_vis(&item.vis);
+                    this.visit_ident(item.ident);
+                    this.with_tilde_const(
+                        Some(DisallowTildeConstContext::Impl(item.span)),
+                        |this| this.visit_generics(generics),
+                    );
+                    this.visit_ty(self_ty);
+                    walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl);
                 });
-                self.visit_ty(self_ty);
-                walk_list!(self, visit_assoc_item, items, AssocCtxt::Impl);
                 walk_list!(self, visit_attribute, &item.attrs);
                 return; // Avoid visiting again.
             }
@@ -1408,7 +1410,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                             FnCtxt::Foreign => fluent::ast_passes_pattern_in_foreign,
                             _ => fluent::ast_passes_pattern_in_bodiless,
                         };
-                        let diag = BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident);
+                        let diag = BuiltinLintDiag::PatternsInFnsWithoutBody(span, ident);
                         self.lint_buffer.buffer_lint_with_diagnostic(
                             PATTERNS_IN_FNS_WITHOUT_BODY,
                             id,
@@ -1491,7 +1493,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 item.id,
                 err.span,
                 fluent::ast_passes_deprecated_where_clause_location,
-                BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(sugg),
+                BuiltinLintDiag::DeprecatedWhereclauseLocation(sugg),
             );
         }
 
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 19eed070911..e225401ea37 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -2,7 +2,7 @@
 
 use rustc_ast::ParamKindOrd;
 use rustc_errors::{
-    codes::*, AddToDiagnostic, Applicability, Diag, EmissionGuarantee, SubdiagnosticMessageOp,
+    codes::*, AddToDiagnostic, Applicability, Diag, EmissionGuarantee, SubdiagMessageOp,
 };
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
@@ -374,7 +374,7 @@ pub struct EmptyLabelManySpans(pub Vec<Span>);
 
 // The derive for `Vec<Span>` does multiple calls to `span_label`, adding commas between each
 impl AddToDiagnostic for EmptyLabelManySpans {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _: F,
@@ -743,7 +743,7 @@ pub struct StableFeature {
 }
 
 impl AddToDiagnostic for StableFeature {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _: F,
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 1b0dd9acc37..2e14238f950 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -17,6 +17,7 @@ use crate::errors;
 macro_rules! gate {
     ($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
         if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
+            #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
             feature_err(&$visitor.sess, sym::$feature, $span, $explain).emit();
         }
     }};
@@ -34,6 +35,7 @@ macro_rules! gate {
 macro_rules! gate_alt {
     ($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr) => {{
         if !$has_feature && !$span.allows_unstable($name) {
+            #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
             feature_err(&$visitor.sess, $name, $span, $explain).emit();
         }
     }};
@@ -73,6 +75,7 @@ struct PostExpansionVisitor<'a> {
 }
 
 impl<'a> PostExpansionVisitor<'a> {
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn check_abi(&self, abi: ast::StrLit, constness: ast::Const) {
         let ast::StrLit { symbol_unescaped, span, .. } = abi;
 
@@ -203,14 +206,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 );
             }
         }
-        if !attr.is_doc_comment()
-            && let [seg, _] = attr.get_normal_item().path.segments.as_slice()
-            && seg.ident.name == sym::diagnostic
-            && !self.features.diagnostic_namespace
-        {
-            let msg = "`#[diagnostic]` attribute name space is experimental";
-            gate!(self, diagnostic_namespace, seg.ident.span, msg);
-        }
 
         // Emit errors for non-staged-api crates.
         if !self.features.staged_api {
@@ -507,7 +502,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
     check_incompatible_features(sess, features);
     let mut visitor = PostExpansionVisitor { sess, features };
 
-    let spans = sess.parse_sess.gated_spans.spans.borrow();
+    let spans = sess.psess.gated_spans.spans.borrow();
     macro_rules! gate_all {
         ($gate:ident, $msg:literal) => {
             if let Some(spans) = spans.get(&sym::$gate) {
@@ -579,6 +574,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
                 if let Ok(snippet) = sm.span_to_snippet(span)
                     && snippet == "!"
                 {
+                    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
                     feature_err(sess, sym::never_patterns, span, "`!` patterns are experimental")
                         .emit();
                 } else {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 6119c6c84f8..e5d7b848903 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -1452,6 +1452,10 @@ impl<'a> State<'a> {
                             s.print_path(&sym.path, true, 0);
                         }
                     }
+                    InlineAsmOperand::Label { block } => {
+                        s.head("label");
+                        s.print_block(block);
+                    }
                 }
             }
             AsmArg::ClobberAbi(abi) => {
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 3d2cf25e98b..814104ec78c 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -8,7 +8,7 @@ use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg};
 use rustc_macros::HashStable_Generic;
 use rustc_session::config::ExpectedValues;
 use rustc_session::lint::builtin::UNEXPECTED_CFGS;
-use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::parse::feature_err;
 use rustc_session::{RustcVersion, Session};
 use rustc_span::hygiene::Transparency;
@@ -516,6 +516,7 @@ pub struct Condition {
 }
 
 /// Tests if a cfg-pattern matches the cfg set
+#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
 pub fn cfg_matches(
     cfg: &ast::MetaItem,
     sess: &Session,
@@ -524,9 +525,9 @@ pub fn cfg_matches(
 ) -> bool {
     eval_condition(cfg, sess, features, &mut |cfg| {
         try_gate_cfg(cfg.name, cfg.span, sess, features);
-        match sess.parse_sess.check_config.expecteds.get(&cfg.name) {
+        match sess.psess.check_config.expecteds.get(&cfg.name) {
             Some(ExpectedValues::Some(values)) if !values.contains(&cfg.value) => {
-                sess.parse_sess.buffer_lint_with_diagnostic(
+                sess.psess.buffer_lint_with_diagnostic(
                     UNEXPECTED_CFGS,
                     cfg.span,
                     lint_node_id,
@@ -535,19 +536,19 @@ pub fn cfg_matches(
                     } else {
                         format!("unexpected `cfg` condition value: (none)")
                     },
-                    BuiltinLintDiagnostics::UnexpectedCfgValue(
+                    BuiltinLintDiag::UnexpectedCfgValue(
                         (cfg.name, cfg.name_span),
                         cfg.value.map(|v| (v, cfg.value_span.unwrap())),
                     ),
                 );
             }
-            None if sess.parse_sess.check_config.exhaustive_names => {
-                sess.parse_sess.buffer_lint_with_diagnostic(
+            None if sess.psess.check_config.exhaustive_names => {
+                sess.psess.buffer_lint_with_diagnostic(
                     UNEXPECTED_CFGS,
                     cfg.span,
                     lint_node_id,
                     format!("unexpected `cfg` condition name: `{}`", cfg.name),
-                    BuiltinLintDiagnostics::UnexpectedCfgName(
+                    BuiltinLintDiag::UnexpectedCfgName(
                         (cfg.name, cfg.name_span),
                         cfg.value.map(|v| (v, cfg.value_span.unwrap())),
                     ),
@@ -555,7 +556,7 @@ pub fn cfg_matches(
             }
             _ => { /* not unexpected */ }
         }
-        sess.parse_sess.config.contains(&(cfg.name, cfg.value))
+        sess.psess.config.contains(&(cfg.name, cfg.value))
     })
 }
 
@@ -566,6 +567,7 @@ fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Feat
     }
 }
 
+#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
 fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) {
     let (cfg, feature, has_feature) = gated_cfg;
     if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
@@ -592,13 +594,14 @@ fn parse_version(s: Symbol) -> Option<RustcVersion> {
 
 /// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
 /// evaluate individual items.
+#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
 pub fn eval_condition(
     cfg: &ast::MetaItem,
     sess: &Session,
     features: Option<&Features>,
     eval: &mut impl FnMut(Condition) -> bool,
 ) -> bool {
-    let dcx = &sess.parse_sess.dcx;
+    let dcx = &sess.psess.dcx;
     match &cfg.kind {
         ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
             try_gate_cfg(sym::version, cfg.span, sess, features);
@@ -626,7 +629,7 @@ pub fn eval_condition(
             };
 
             // See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
-            if sess.parse_sess.assume_incomplete_release {
+            if sess.psess.assume_incomplete_release {
                 RustcVersion::CURRENT > min_version
             } else {
                 RustcVersion::CURRENT >= min_version
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 53e8ac121bb..560928d3941 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -76,6 +76,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// LL |         for (key, value) in dict {
     ///    |                             ^^^^
     /// ```
+    #[allow(rustc::diagnostic_outside_of_impl)] // FIXME
     pub(super) fn add_moved_or_invoked_closure_note(
         &self,
         location: Location,
@@ -585,6 +586,7 @@ impl UseSpans<'_> {
     }
 
     /// Add a span label to the arguments of the closure, if it exists.
+    #[allow(rustc::diagnostic_outside_of_impl)]
     pub(super) fn args_subdiag(
         self,
         dcx: &rustc_errors::DiagCtxt,
@@ -598,6 +600,7 @@ impl UseSpans<'_> {
 
     /// Add a span label to the use of the captured variable, if it exists.
     /// only adds label to the `path_span`
+    #[allow(rustc::diagnostic_outside_of_impl)]
     pub(super) fn var_path_only_subdiag(
         self,
         dcx: &rustc_errors::DiagCtxt,
@@ -635,6 +638,7 @@ impl UseSpans<'_> {
     }
 
     /// Add a subdiagnostic to the use of the captured variable, if it exists.
+    #[allow(rustc::diagnostic_outside_of_impl)]
     pub(super) fn var_subdiag(
         self,
         dcx: &rustc_errors::DiagCtxt,
@@ -1008,6 +1012,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         self.borrow_spans(span, borrow.reserve_location)
     }
 
+    #[allow(rustc::diagnostic_outside_of_impl)]
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn explain_captures(
         &mut self,
         err: &mut Diag<'_>,
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index c327e591f3c..ebc9f1d109e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -1,6 +1,7 @@
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
 
+use core::ops::ControlFlow;
 use hir::ExprKind;
 use rustc_errors::{Applicability, Diag};
 use rustc_hir as hir;
@@ -727,30 +728,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             _ => local_decl.source_info.span,
         };
 
-        struct BindingFinder {
-            span: Span,
-            hir_id: Option<hir::HirId>,
-        }
-
-        impl<'tcx> Visitor<'tcx> for BindingFinder {
-            fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
-                if let hir::StmtKind::Local(local) = s.kind {
-                    if local.pat.span == self.span {
-                        self.hir_id = Some(local.hir_id);
-                    }
-                }
-                hir::intravisit::walk_stmt(self, s);
-            }
-        }
-
         let def_id = self.body.source.def_id();
         let hir_id = if let Some(local_def_id) = def_id.as_local()
             && let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
         {
             let body = self.infcx.tcx.hir().body(body_id);
-            let mut v = BindingFinder { span: pat_span, hir_id: None };
-            v.visit_body(body);
-            v.hir_id
+            BindingFinder { span: pat_span }.visit_body(body).break_value()
         } else {
             None
         };
@@ -859,17 +842,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         };
 
         let hir_map = self.infcx.tcx.hir();
-        struct Finder<'tcx> {
+        struct Finder {
             span: Span,
-            expr: Option<&'tcx Expr<'tcx>>,
         }
 
-        impl<'tcx> Visitor<'tcx> for Finder<'tcx> {
-            fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
-                if e.span == self.span && self.expr.is_none() {
-                    self.expr = Some(e);
+        impl<'tcx> Visitor<'tcx> for Finder {
+            type Result = ControlFlow<&'tcx Expr<'tcx>>;
+            fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) -> Self::Result {
+                if e.span == self.span {
+                    ControlFlow::Break(e)
+                } else {
+                    hir::intravisit::walk_expr(self, e)
                 }
-                hir::intravisit::walk_expr(self, e);
             }
         }
         if let Some(body_id) = hir_map.maybe_body_owned_by(self.mir_def_id())
@@ -878,9 +862,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             // `span` corresponds to the expression being iterated, find the `for`-loop desugared
             // expression with that span in order to identify potential fixes when encountering a
             // read-only iterator that should be mutable.
-            let mut v = Finder { span, expr: None };
-            v.visit_block(block);
-            if let Some(expr) = v.expr
+            if let ControlFlow::Break(expr) = (Finder { span }).visit_block(block)
                 && let Call(_, [expr]) = expr.kind
             {
                 match expr.kind {
@@ -1179,29 +1161,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 );
             }
             Some((false, err_label_span, message)) => {
-                struct BindingFinder {
-                    span: Span,
-                    hir_id: Option<hir::HirId>,
-                }
-
-                impl<'tcx> Visitor<'tcx> for BindingFinder {
-                    fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
-                        if let hir::StmtKind::Local(local) = s.kind {
-                            if local.pat.span == self.span {
-                                self.hir_id = Some(local.hir_id);
-                            }
-                        }
-                        hir::intravisit::walk_stmt(self, s);
-                    }
-                }
                 let def_id = self.body.source.def_id();
                 let hir_id = if let Some(local_def_id) = def_id.as_local()
                     && let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
                 {
                     let body = self.infcx.tcx.hir().body(body_id);
-                    let mut v = BindingFinder { span: err_label_span, hir_id: None };
-                    v.visit_body(body);
-                    v.hir_id
+                    BindingFinder { span: err_label_span }.visit_body(body).break_value()
                 } else {
                     None
                 };
@@ -1333,6 +1298,23 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     }
 }
 
+struct BindingFinder {
+    span: Span,
+}
+
+impl<'tcx> Visitor<'tcx> for BindingFinder {
+    type Result = ControlFlow<hir::HirId>;
+    fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) -> Self::Result {
+        if let hir::StmtKind::Local(local) = s.kind
+            && local.pat.span == self.span
+        {
+            ControlFlow::Break(local.hir_id)
+        } else {
+            hir::intravisit::walk_stmt(self, s)
+        }
+    }
+}
+
 pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool {
     debug!("local_info: {:?}, ty.kind(): {:?}", local_decl.local_info, local_decl.ty.kind());
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 3765dfe5db5..c06bf94a6fd 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -201,6 +201,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     // For generic associated types (GATs) which implied 'static requirement
     // from higher-ranked trait bounds (HRTB). Try to locate span of the trait
     // and the span which bounded to the trait for adding 'static lifetime suggestion
+    #[allow(rustc::diagnostic_outside_of_impl)]
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn suggest_static_lifetime_for_gat_from_hrtb(
         &self,
         diag: &mut Diag<'_>,
@@ -254,9 +256,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
 
         hrtb_bounds.iter().for_each(|bound| {
             let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }, _) = bound else { return; };
-            // FIXME: make this translatable
-            #[allow(rustc::diagnostic_outside_of_impl)]
-            #[allow(rustc::untranslatable_diagnostic)]
             diag.span_note(
                 *trait_span,
                 "due to current limitations in the borrow checker, this implies a `'static` lifetime"
@@ -580,6 +579,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     ///            executing...
     ///    = note: ...therefore, returned references to captured variables will escape the closure
     /// ```
+    #[allow(rustc::diagnostic_outside_of_impl)] // FIXME
     fn report_fnmut_error(
         &self,
         errci: &ErrorConstraintInfo<'tcx>,
@@ -761,6 +761,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     ///    |     ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it
     ///    |                    is returning data with lifetime `'b`
     /// ```
+    #[allow(rustc::diagnostic_outside_of_impl)] // FIXME
     fn report_general_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'tcx> {
         let ErrorConstraintInfo {
             fr,
@@ -822,6 +823,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     /// LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + 'a {
     ///    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     /// ```
+    #[allow(rustc::diagnostic_outside_of_impl)]
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn add_static_impl_trait_suggestion(
         &self,
         diag: &mut Diag<'_>,
@@ -972,6 +975,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         self.suggest_constrain_dyn_trait_in_impl(diag, &visitor.0, ident, self_ty);
     }
 
+    #[allow(rustc::diagnostic_outside_of_impl)]
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     #[instrument(skip(self, err), level = "debug")]
     fn suggest_constrain_dyn_trait_in_impl(
         &self,
@@ -1034,6 +1039,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         suggest_adding_lifetime_params(self.infcx.tcx, sub, ty_sup, ty_sub, diag);
     }
 
+    #[allow(rustc::diagnostic_outside_of_impl)]
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn suggest_move_on_borrowing_closure(&self, diag: &mut Diag<'_>) {
         let map = self.infcx.tcx.hir();
         let body_id = map.body_owned_by(self.mir_def_id());
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index ef582033c4e..8dcfe014b65 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -6,6 +6,7 @@
 #![feature(assert_matches)]
 #![feature(associated_type_bounds)]
 #![feature(box_patterns)]
+#![feature(control_flow_enum)]
 #![feature(let_chains)]
 #![feature(min_specialization)]
 #![feature(never_type)]
@@ -723,7 +724,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
                 operands,
                 options: _,
                 line_spans: _,
-                destination: _,
+                targets: _,
                 unwind: _,
             } => {
                 for op in operands {
@@ -749,7 +750,8 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
                         }
                         InlineAsmOperand::Const { value: _ }
                         | InlineAsmOperand::SymFn { value: _ }
-                        | InlineAsmOperand::SymStatic { def_id: _ } => {}
+                        | InlineAsmOperand::SymStatic { def_id: _ }
+                        | InlineAsmOperand::Label { target_index: _ } => {}
                     }
                 }
             }
diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs
index 10941cadcbb..956de1dec9b 100644
--- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs
+++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs
@@ -161,7 +161,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> {
                 operands,
                 options: _,
                 line_spans: _,
-                destination: _,
+                targets: _,
                 unwind: _,
             } => {
                 for op in operands {
@@ -182,7 +182,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> {
                         }
                         InlineAsmOperand::Const { value: _ }
                         | InlineAsmOperand::SymFn { value: _ }
-                        | InlineAsmOperand::SymStatic { def_id: _ } => {}
+                        | InlineAsmOperand::SymStatic { def_id: _ }
+                        | InlineAsmOperand::Label { target_index: _ } => {}
                     }
                 }
             }
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 4b096a59234..12b02c7fcfa 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -367,14 +367,17 @@ fn check_opaque_type_parameter_valid(
     span: Span,
 ) -> Result<(), ErrorGuaranteed> {
     let opaque_ty_hir = tcx.hir().expect_item(opaque_type_key.def_id);
-    let is_ty_alias = match opaque_ty_hir.expect_opaque_ty().origin {
-        OpaqueTyOrigin::TyAlias { .. } => true,
-        OpaqueTyOrigin::AsyncFn(..) | OpaqueTyOrigin::FnReturn(..) => false,
+    let (parent, is_ty_alias) = match opaque_ty_hir.expect_opaque_ty().origin {
+        OpaqueTyOrigin::TyAlias { parent, .. } => (parent, true),
+        OpaqueTyOrigin::AsyncFn(parent) | OpaqueTyOrigin::FnReturn(parent) => (parent, false),
     };
 
-    let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
+    let parent_generics = tcx.generics_of(parent);
     let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
-    for (i, arg) in opaque_type_key.args.iter().enumerate() {
+
+    // Only check the parent generics, which will ignore any of the
+    // duplicated lifetime args that come from reifying late-bounds.
+    for (i, arg) in opaque_type_key.args.iter().take(parent_generics.count()).enumerate() {
         if let Err(guar) = arg.error_reported() {
             return Err(guar);
         }
@@ -395,7 +398,7 @@ fn check_opaque_type_parameter_valid(
             seen_params.entry(arg).or_default().push(i);
         } else {
             // Prevent `fn foo() -> Foo<u32>` from being defining.
-            let opaque_param = opaque_generics.param_at(i, tcx);
+            let opaque_param = parent_generics.param_at(i, tcx);
             let kind = opaque_param.kind.descr();
 
             return Err(tcx.dcx().emit_err(NonGenericOpaqueTypeParam {
@@ -409,10 +412,10 @@ fn check_opaque_type_parameter_valid(
 
     for (_, indices) in seen_params {
         if indices.len() > 1 {
-            let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
+            let descr = parent_generics.param_at(indices[0], tcx).kind.descr();
             let spans: Vec<_> = indices
                 .into_iter()
-                .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
+                .map(|i| tcx.def_span(parent_generics.param_at(i, tcx).def_id))
                 .collect();
             #[allow(rustc::diagnostic_outside_of_impl)]
             #[allow(rustc::untranslatable_diagnostic)]
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 26e1e24d1a1..8d38b86fa34 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1667,7 +1667,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             // (Eventually this should use const-generics, but those are not up for the task yet:
             // https://github.com/rust-lang/rust/issues/85229.)
             if let Some(name @ (sym::simd_shuffle | sym::simd_insert | sym::simd_extract)) =
-                self.tcx().intrinsic(def_id)
+                self.tcx().intrinsic(def_id).map(|i| i.name)
             {
                 let idx = match name {
                     sym::simd_shuffle => 2,
@@ -1770,8 +1770,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 self.assert_iscleanup(body, block_data, real_target, is_cleanup);
                 self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
             }
-            TerminatorKind::InlineAsm { destination, unwind, .. } => {
-                if let Some(target) = destination {
+            TerminatorKind::InlineAsm { ref targets, unwind, .. } => {
+                for &target in targets {
                     self.assert_iscleanup(body, block_data, target, is_cleanup);
                 }
                 self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index bc2a9d5ad1e..ba8401393d7 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -19,6 +19,8 @@ builtin_macros_asm_expected_other = expected operand, {$is_global_asm ->
 
 builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names
 
+builtin_macros_asm_mayunwind = asm labels are not allowed with the `may_unwind` option
+
 builtin_macros_asm_modifier_invalid = asm template modifier must be a single character
 
 builtin_macros_asm_mutually_exclusive = the `{$opt1}` and `{$opt2}` options are mutually exclusive
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 29bf5e9f304..bc851fadc2e 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -10,7 +10,6 @@ use rustc_index::bit_set::GrowableBitSet;
 use rustc_parse::parser::Parser;
 use rustc_parse_format as parse;
 use rustc_session::lint;
-use rustc_session::parse::ParseSess;
 use rustc_span::symbol::Ident;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{ErrorGuaranteed, InnerSpan, Span};
@@ -36,19 +35,17 @@ fn parse_args<'a>(
     is_global_asm: bool,
 ) -> PResult<'a, AsmArgs> {
     let mut p = ecx.new_parser_from_tts(tts);
-    let sess = &ecx.sess.parse_sess;
-    parse_asm_args(&mut p, sess, sp, is_global_asm)
+    parse_asm_args(&mut p, sp, is_global_asm)
 }
 
 // Primarily public for rustfmt consumption.
 // Internal consumers should continue to leverage `expand_asm`/`expand__global_asm`
 pub fn parse_asm_args<'a>(
     p: &mut Parser<'a>,
-    sess: &'a ParseSess,
     sp: Span,
     is_global_asm: bool,
 ) -> PResult<'a, AsmArgs> {
-    let dcx = &sess.dcx;
+    let dcx = &p.psess.dcx;
 
     if p.token == token::Eof {
         return Err(dcx.create_err(errors::AsmRequiresTemplate { span: sp }));
@@ -167,6 +164,9 @@ pub fn parse_asm_args<'a>(
                 path: path.clone(),
             };
             ast::InlineAsmOperand::Sym { sym }
+        } else if !is_global_asm && p.eat_keyword(sym::label) {
+            let block = p.parse_block()?;
+            ast::InlineAsmOperand::Label { block }
         } else if allow_templates {
             let template = p.parse_expr()?;
             // If it can't possibly expand to a string, provide diagnostics here to include other
@@ -243,6 +243,7 @@ pub fn parse_asm_args<'a>(
     let mut have_real_output = false;
     let mut outputs_sp = vec![];
     let mut regclass_outputs = vec![];
+    let mut labels_sp = vec![];
     for (op, op_sp) in &args.operands {
         match op {
             ast::InlineAsmOperand::Out { reg, expr, .. }
@@ -260,6 +261,9 @@ pub fn parse_asm_args<'a>(
                     regclass_outputs.push(*op_sp);
                 }
             }
+            ast::InlineAsmOperand::Label { .. } => {
+                labels_sp.push(*op_sp);
+            }
             _ => {}
         }
     }
@@ -271,6 +275,9 @@ pub fn parse_asm_args<'a>(
         // Bail out now since this is likely to confuse MIR
         return Err(err);
     }
+    if args.options.contains(ast::InlineAsmOptions::MAY_UNWIND) && !labels_sp.is_empty() {
+        dcx.emit_err(errors::AsmMayUnwind { labels_sp });
+    }
 
     if args.clobber_abis.len() > 0 {
         if is_global_asm {
@@ -299,7 +306,7 @@ pub fn parse_asm_args<'a>(
 fn err_duplicate_option(p: &mut Parser<'_>, symbol: Symbol, span: Span) {
     // Tool-only output
     let full_span = if p.token.kind == token::Comma { span.to(p.token.span) } else { span };
-    p.sess.dcx.emit_err(errors::AsmOptAlreadyprovided { span, symbol, full_span });
+    p.psess.dcx.emit_err(errors::AsmOptAlreadyprovided { span, symbol, full_span });
 }
 
 /// Try to set the provided option in the provided `AsmArgs`.
@@ -371,7 +378,7 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a,
     p.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
 
     if p.eat(&token::CloseDelim(Delimiter::Parenthesis)) {
-        return Err(p.sess.dcx.create_err(errors::NonABI { span: p.token.span }));
+        return Err(p.psess.dcx.create_err(errors::NonABI { span: p.token.span }));
     }
 
     let mut new_abis = Vec::new();
@@ -382,7 +389,7 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a,
             }
             Err(opt_lit) => {
                 let span = opt_lit.map_or(p.token.span, |lit| lit.span);
-                let mut err = p.sess.dcx.struct_span_err(span, "expected string literal");
+                let mut err = p.psess.dcx.struct_span_err(span, "expected string literal");
                 err.span_label(span, "not a string literal");
                 return Err(err);
             }
@@ -498,7 +505,7 @@ fn expand_preparsed_asm(
             };
 
             if template_str.contains(".intel_syntax") {
-                ecx.parse_sess().buffer_lint(
+                ecx.psess().buffer_lint(
                     lint::builtin::BAD_ASM_STYLE,
                     find_span(".intel_syntax"),
                     ecx.current_expansion.lint_node_id,
@@ -506,7 +513,7 @@ fn expand_preparsed_asm(
                 );
             }
             if template_str.contains(".att_syntax") {
-                ecx.parse_sess().buffer_lint(
+                ecx.psess().buffer_lint(
                     lint::builtin::BAD_ASM_STYLE,
                     find_span(".att_syntax"),
                     ecx.current_expansion.lint_node_id,
diff --git a/compiler/rustc_builtin_macros/src/cfg_accessible.rs b/compiler/rustc_builtin_macros/src/cfg_accessible.rs
index ceb5f861078..1933b2e1fb7 100644
--- a/compiler/rustc_builtin_macros/src/cfg_accessible.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_accessible.rs
@@ -46,7 +46,7 @@ impl MultiItemModifier for Expander {
     ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
         let template = AttributeTemplate { list: Some("path"), ..Default::default() };
         validate_attr::check_builtin_meta_item(
-            &ecx.sess.parse_sess,
+            &ecx.sess.psess,
             meta_item,
             ast::AttrStyle::Outer,
             sym::cfg_accessible,
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index cfa94b0e780..93f7d09546b 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -1,5 +1,6 @@
 use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
 
+use core::ops::ControlFlow;
 use rustc_ast as ast;
 use rustc_ast::mut_visit::MutVisitor;
 use rustc_ast::ptr::P;
@@ -87,41 +88,40 @@ fn flat_map_annotatable(
     }
 }
 
-struct CfgFinder {
-    has_cfg_or_cfg_attr: bool,
-}
+fn has_cfg_or_cfg_attr(annotatable: &Annotatable) -> bool {
+    struct CfgFinder;
 
-impl CfgFinder {
-    fn has_cfg_or_cfg_attr(annotatable: &Annotatable) -> bool {
-        let mut finder = CfgFinder { has_cfg_or_cfg_attr: false };
-        match annotatable {
-            Annotatable::Item(item) => finder.visit_item(item),
-            Annotatable::TraitItem(item) => finder.visit_assoc_item(item, visit::AssocCtxt::Trait),
-            Annotatable::ImplItem(item) => finder.visit_assoc_item(item, visit::AssocCtxt::Impl),
-            Annotatable::ForeignItem(item) => finder.visit_foreign_item(item),
-            Annotatable::Stmt(stmt) => finder.visit_stmt(stmt),
-            Annotatable::Expr(expr) => finder.visit_expr(expr),
-            Annotatable::Arm(arm) => finder.visit_arm(arm),
-            Annotatable::ExprField(field) => finder.visit_expr_field(field),
-            Annotatable::PatField(field) => finder.visit_pat_field(field),
-            Annotatable::GenericParam(param) => finder.visit_generic_param(param),
-            Annotatable::Param(param) => finder.visit_param(param),
-            Annotatable::FieldDef(field) => finder.visit_field_def(field),
-            Annotatable::Variant(variant) => finder.visit_variant(variant),
-            Annotatable::Crate(krate) => finder.visit_crate(krate),
-        };
-        finder.has_cfg_or_cfg_attr
-    }
-}
-
-impl<'ast> visit::Visitor<'ast> for CfgFinder {
-    fn visit_attribute(&mut self, attr: &'ast Attribute) {
-        // We want short-circuiting behavior, so don't use the '|=' operator.
-        self.has_cfg_or_cfg_attr = self.has_cfg_or_cfg_attr
-            || attr
+    impl<'ast> visit::Visitor<'ast> for CfgFinder {
+        type Result = ControlFlow<()>;
+        fn visit_attribute(&mut self, attr: &'ast Attribute) -> ControlFlow<()> {
+            if attr
                 .ident()
-                .is_some_and(|ident| ident.name == sym::cfg || ident.name == sym::cfg_attr);
+                .is_some_and(|ident| ident.name == sym::cfg || ident.name == sym::cfg_attr)
+            {
+                ControlFlow::Break(())
+            } else {
+                ControlFlow::Continue(())
+            }
+        }
     }
+
+    let res = match annotatable {
+        Annotatable::Item(item) => CfgFinder.visit_item(item),
+        Annotatable::TraitItem(item) => CfgFinder.visit_assoc_item(item, visit::AssocCtxt::Trait),
+        Annotatable::ImplItem(item) => CfgFinder.visit_assoc_item(item, visit::AssocCtxt::Impl),
+        Annotatable::ForeignItem(item) => CfgFinder.visit_foreign_item(item),
+        Annotatable::Stmt(stmt) => CfgFinder.visit_stmt(stmt),
+        Annotatable::Expr(expr) => CfgFinder.visit_expr(expr),
+        Annotatable::Arm(arm) => CfgFinder.visit_arm(arm),
+        Annotatable::ExprField(field) => CfgFinder.visit_expr_field(field),
+        Annotatable::PatField(field) => CfgFinder.visit_pat_field(field),
+        Annotatable::GenericParam(param) => CfgFinder.visit_generic_param(param),
+        Annotatable::Param(param) => CfgFinder.visit_param(param),
+        Annotatable::FieldDef(field) => CfgFinder.visit_field_def(field),
+        Annotatable::Variant(variant) => CfgFinder.visit_variant(variant),
+        Annotatable::Crate(krate) => CfgFinder.visit_crate(krate),
+    };
+    res.is_break()
 }
 
 impl CfgEval<'_, '_> {
@@ -132,7 +132,7 @@ impl CfgEval<'_, '_> {
     fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Option<Annotatable> {
         // Tokenizing and re-parsing the `Annotatable` can have a significant
         // performance impact, so try to avoid it if possible
-        if !CfgFinder::has_cfg_or_cfg_attr(&annotatable) {
+        if !has_cfg_or_cfg_attr(&annotatable) {
             return Some(annotatable);
         }
 
@@ -195,8 +195,7 @@ impl CfgEval<'_, '_> {
         // Re-parse the tokens, setting the `capture_cfg` flag to save extra information
         // to the captured `AttrTokenStream` (specifically, we capture
         // `AttrTokenTree::AttributesData` for all occurrences of `#[cfg]` and `#[cfg_attr]`)
-        let mut parser =
-            rustc_parse::stream_to_parser(&self.cfg.sess.parse_sess, orig_tokens, None);
+        let mut parser = rustc_parse::stream_to_parser(&self.cfg.sess.psess, orig_tokens, None);
         parser.capture_cfg = true;
         match parse_annotatable_with(&mut parser) {
             Ok(a) => annotatable = a,
diff --git a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
index d956c096d24..ada82e45712 100644
--- a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
+++ b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
@@ -7,10 +7,10 @@ use rustc_ast::{self as ast, AttrItem, AttrStyle};
 use rustc_session::parse::ParseSess;
 use rustc_span::FileName;
 
-pub fn inject(krate: &mut ast::Crate, parse_sess: &ParseSess, attrs: &[String]) {
+pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
     for raw_attr in attrs {
         let mut parser = rustc_parse::new_parser_from_source_str(
-            parse_sess,
+            psess,
             FileName::cli_crate_attr_source_code(raw_attr),
             raw_attr.clone(),
         );
@@ -25,12 +25,12 @@ pub fn inject(krate: &mut ast::Crate, parse_sess: &ParseSess, attrs: &[String])
         };
         let end_span = parser.token.span;
         if parser.token != token::Eof {
-            parse_sess.dcx.emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) });
+            psess.dcx.emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) });
             continue;
         }
 
         krate.attrs.push(mk_attr(
-            &parse_sess.attr_id_generator,
+            &psess.attr_id_generator,
             AttrStyle::Inner,
             path,
             args,
diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs
index abfaa9b006e..0bfb848859b 100644
--- a/compiler/rustc_builtin_macros/src/concat.rs
+++ b/compiler/rustc_builtin_macros/src/concat.rs
@@ -43,7 +43,7 @@ pub fn expand_concat(
                     guar = Some(guarantee);
                 }
                 Err(err) => {
-                    guar = Some(report_lit_error(&cx.sess.parse_sess, err, token_lit, e.span));
+                    guar = Some(report_lit_error(&cx.sess.psess, err, token_lit, e.span));
                 }
             },
             // We also want to allow negative numeric literals.
@@ -52,7 +52,7 @@ pub fn expand_concat(
                     Ok(LitKind::Int(i, _)) => accumulator.push_str(&format!("-{i}")),
                     Ok(LitKind::Float(f, _)) => accumulator.push_str(&format!("-{f}")),
                     Err(err) => {
-                        guar = Some(report_lit_error(&cx.sess.parse_sess, err, token_lit, e.span));
+                        guar = Some(report_lit_error(&cx.sess.psess, err, token_lit, e.span));
                     }
                     _ => missing_literal.push(e.span),
                 }
diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs
index 3fb0b50f417..502bfb4467e 100644
--- a/compiler/rustc_builtin_macros/src/concat_bytes.rs
+++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs
@@ -55,7 +55,7 @@ fn invalid_type_err(
         Ok(LitKind::Int(_, _)) => dcx.emit_err(ConcatBytesNonU8 { span }),
         Ok(LitKind::ByteStr(..) | LitKind::Byte(_)) => unreachable!(),
         Ok(LitKind::Err(guar)) => guar,
-        Err(err) => report_lit_error(&cx.sess.parse_sess, err, token_lit, span),
+        Err(err) => report_lit_error(&cx.sess.psess, err, token_lit, span),
     }
 }
 
diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs
index 7388e133c53..4f412cf79d9 100644
--- a/compiler/rustc_builtin_macros/src/derive.rs
+++ b/compiler/rustc_builtin_macros/src/derive.rs
@@ -34,7 +34,7 @@ impl MultiItemModifier for Expander {
                 let template =
                     AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() };
                 validate_attr::check_builtin_meta_item(
-                    &sess.parse_sess,
+                    &sess.psess,
                     meta_item,
                     ast::AttrStyle::Outer,
                     sym::derive,
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs
index 386d4a54b65..292a916e2a7 100644
--- a/compiler/rustc_builtin_macros/src/deriving/default.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/default.rs
@@ -1,8 +1,10 @@
 use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::errors;
+use core::ops::ControlFlow;
 use rustc_ast as ast;
-use rustc_ast::{attr, walk_list, EnumDef, VariantData};
+use rustc_ast::visit::walk_list;
+use rustc_ast::{attr, EnumDef, VariantData};
 use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
 use rustc_span::symbol::Ident;
 use rustc_span::symbol::{kw, sym};
@@ -230,20 +232,19 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, '
 }
 
 fn has_a_default_variant(item: &Annotatable) -> bool {
-    struct HasDefaultAttrOnVariant {
-        found: bool,
-    }
+    struct HasDefaultAttrOnVariant;
 
     impl<'ast> rustc_ast::visit::Visitor<'ast> for HasDefaultAttrOnVariant {
-        fn visit_variant(&mut self, v: &'ast rustc_ast::Variant) {
+        type Result = ControlFlow<()>;
+        fn visit_variant(&mut self, v: &'ast rustc_ast::Variant) -> ControlFlow<()> {
             if v.attrs.iter().any(|attr| attr.has_name(kw::Default)) {
-                self.found = true;
+                ControlFlow::Break(())
+            } else {
+                // no need to subrecurse.
+                ControlFlow::Continue(())
             }
-            // no need to subrecurse.
         }
     }
 
-    let mut visitor = HasDefaultAttrOnVariant { found: false };
-    item.visit_with(&mut visitor);
-    visitor.found
+    item.visit_with(&mut HasDefaultAttrOnVariant).is_break()
 }
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index eb664b571ba..3cb3e30daa7 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -1603,9 +1603,10 @@ impl<'a> TraitDef<'a> {
                         // Once use of `icu4x-0.9.0` has dropped sufficiently, this
                         // exception should be removed.
                         let is_simple_path = |ty: &P<ast::Ty>, sym| {
-                            if let TyKind::Path(None, ast::Path { segments, .. }) = &ty.kind &&
-                                let [seg] = segments.as_slice() &&
-                                seg.ident.name == sym && seg.args.is_none()
+                            if let TyKind::Path(None, ast::Path { segments, .. }) = &ty.kind
+                                && let [seg] = segments.as_slice()
+                                && seg.ident.name == sym
+                                && seg.args.is_none()
                             {
                                 true
                             } else {
@@ -1613,8 +1614,8 @@ impl<'a> TraitDef<'a> {
                             }
                         };
 
-                        let exception = if let TyKind::Slice(ty) = &struct_field.ty.kind &&
-                            is_simple_path(ty, sym::u8)
+                        let exception = if let TyKind::Slice(ty) = &struct_field.ty.kind
+                            && is_simple_path(ty, sym::u8)
                         {
                             Some("byte")
                         } else if is_simple_path(&struct_field.ty, sym::str) {
@@ -1624,14 +1625,14 @@ impl<'a> TraitDef<'a> {
                         };
 
                         if let Some(ty) = exception {
-                            cx.sess.parse_sess.buffer_lint_with_diagnostic(
+                            cx.sess.psess.buffer_lint_with_diagnostic(
                                 BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
                                 sp,
                                 ast::CRATE_NODE_ID,
                                 format!(
                                     "{ty} slice in a packed struct that derives a built-in trait"
                                 ),
-                                rustc_lint_defs::BuiltinLintDiagnostics::ByteSliceInPackedStructWithDerive
+                                rustc_lint_defs::BuiltinLintDiag::ByteSliceInPackedStructWithDerive,
                             );
                         } else {
                             // Wrap the expression in `{...}`, causing a copy.
diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs
index f057d44bf71..193b38a8323 100644
--- a/compiler/rustc_builtin_macros/src/env.rs
+++ b/compiler/rustc_builtin_macros/src/env.rs
@@ -39,7 +39,7 @@ pub fn expand_option_env<'cx>(
 
     let sp = cx.with_def_site_ctxt(sp);
     let value = lookup_env(cx, var);
-    cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
+    cx.sess.psess.env_depinfo.borrow_mut().insert((var, value));
     let e = match value {
         None => {
             let lt = cx.lifetime(sp, Ident::new(kw::StaticLifetime, sp));
@@ -94,7 +94,7 @@ pub fn expand_env<'cx>(
 
     let span = cx.with_def_site_ctxt(sp);
     let value = lookup_env(cx, var);
-    cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
+    cx.sess.psess.env_depinfo.borrow_mut().insert((var, value));
     let e = match value {
         None => {
             let ExprKind::Lit(token::Lit {
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index 6546a35734c..06302ae577a 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -1,6 +1,6 @@
 use rustc_errors::{
     codes::*, AddToDiagnostic, Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic, Level, MultiSpan,
-    SingleLabelManySpans, SubdiagnosticMessageOp,
+    SingleLabelManySpans, SubdiagMessageOp,
 };
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
@@ -590,7 +590,7 @@ pub(crate) struct FormatUnusedArg {
 // Allow the singular form to be a subdiagnostic of the multiple-unused
 // form of diagnostic.
 impl AddToDiagnostic for FormatUnusedArg {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
@@ -766,6 +766,13 @@ pub(crate) struct AsmNoReturn {
     pub(crate) outputs_sp: Vec<Span>,
 }
 
+#[derive(Diagnostic)]
+#[diag(builtin_macros_asm_mayunwind)]
+pub(crate) struct AsmMayUnwind {
+    #[primary_span]
+    pub(crate) labels_sp: Vec<Span>,
+}
+
 #[derive(Diagnostic)]
 #[diag(builtin_macros_global_asm_clobber_abi)]
 pub(crate) struct GlobalAsmClobberAbi {
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 0ce9d7ead82..385c90ff14b 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -16,7 +16,7 @@ use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{BytePos, ErrorGuaranteed, InnerSpan, Span};
 
 use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY;
-use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, LintId};
+use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, LintId};
 
 // The format_args!() macro is expanded in three steps:
 //  1. First, `parse_args` will parse the `(literal, arg, arg, name=arg, name=arg)` syntax,
@@ -553,7 +553,7 @@ fn make_format_args(
                 msg: format!("named argument `{}` is not used by name", arg_name.name).into(),
                 node_id: rustc_ast::CRATE_NODE_ID,
                 lint_id: LintId::of(NAMED_ARGUMENTS_USED_POSITIONALLY),
-                diagnostic: BuiltinLintDiagnostics::NamedArgumentUsedPositionally {
+                diagnostic: BuiltinLintDiag::NamedArgumentUsedPositionally {
                     position_sp_to_replace,
                     position_sp_for_msg,
                     named_arg_sp: arg_name.span,
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs
index 8e0978de237..2da9bda19e0 100644
--- a/compiler/rustc_builtin_macros/src/source_util.rs
+++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -118,7 +118,7 @@ pub fn expand_include<'cx>(
             return DummyResult::any(sp, guar);
         }
     };
-    let p = new_parser_from_file(cx.parse_sess(), &file, Some(sp));
+    let p = new_parser_from_file(cx.psess(), &file, Some(sp));
 
     // If in the included file we have e.g., `mod bar;`,
     // then the path of `bar.rs` should be relative to the directory of `file`.
@@ -136,7 +136,7 @@ pub fn expand_include<'cx>(
         fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
             let expr = parse_expr(&mut self.p).ok()?;
             if self.p.token != token::Eof {
-                self.p.sess.buffer_lint(
+                self.p.psess.buffer_lint(
                     INCOMPLETE_INCLUDE,
                     self.p.token.span,
                     self.node_id,
diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
index 3ee3112f021..9bcd793c450 100644
--- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs
+++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
@@ -17,7 +17,7 @@ pub fn inject(
     features: &Features,
 ) -> usize {
     let orig_num_items = krate.items.len();
-    let edition = sess.parse_sess.edition;
+    let edition = sess.psess.edition;
 
     // the first name in this list is the crate name of the crate with the prelude
     let names: &[Symbol] = if attr::contains_name(pre_configured_attrs, sym::no_core) {
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index dc28cd2ea31..a2015445b42 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -159,7 +159,7 @@ struct InnerItemLinter<'a> {
 impl<'a> Visitor<'a> for InnerItemLinter<'_> {
     fn visit_item(&mut self, i: &'a ast::Item) {
         if let Some(attr) = attr::find_by_name(&i.attrs, sym::rustc_test_marker) {
-            self.sess.parse_sess.buffer_lint(
+            self.sess.psess.buffer_lint(
                 UNNAMEABLE_TEST_ITEMS,
                 attr.span,
                 i.id,
@@ -200,7 +200,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
             EntryPointType::MainNamed | EntryPointType::RustcMainAttr | EntryPointType::Start => {
                 item.map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| {
                     let allow_dead_code = attr::mk_attr_nested_word(
-                        &self.sess.parse_sess.attr_id_generator,
+                        &self.sess.psess.attr_id_generator,
                         ast::AttrStyle::Outer,
                         sym::allow,
                         sym::dead_code,
diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs
index eeaf00004e6..ad6b09ba574 100644
--- a/compiler/rustc_builtin_macros/src/util.rs
+++ b/compiler/rustc_builtin_macros/src/util.rs
@@ -9,7 +9,7 @@ pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, na
     // All the built-in macro attributes are "words" at the moment.
     let template = AttributeTemplate { word: true, ..Default::default() };
     validate_attr::check_builtin_meta_item(
-        &ecx.sess.parse_sess,
+        &ecx.sess.psess,
         meta_item,
         AttrStyle::Outer,
         name,
@@ -37,7 +37,7 @@ pub fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable, name:
     };
     if let Some(attrs) = attrs {
         if let Some(attr) = attr::find_by_name(attrs, name) {
-            ecx.parse_sess().buffer_lint(
+            ecx.psess().buffer_lint(
                 DUPLICATE_MACRO_ATTRIBUTES,
                 attr.span,
                 ecx.current_expansion.lint_node_id,
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
index cf9a105538d..5f0f3e6549c 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
@@ -44,9 +44,10 @@ jobs:
             env:
               TARGET_TRIPLE: x86_64-apple-darwin
           # cross-compile from Linux to Windows using mingw
-          - os: ubuntu-latest
-            env:
-              TARGET_TRIPLE: x86_64-pc-windows-gnu
+          # FIXME The wine version in Ubuntu 22.04 is missing ProcessPrng
+          #- os: ubuntu-latest
+          #  env:
+          #    TARGET_TRIPLE: x86_64-pc-windows-gnu
           - os: ubuntu-latest
             env:
               TARGET_TRIPLE: aarch64-unknown-linux-gnu
@@ -80,11 +81,11 @@ jobs:
       if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
       run: rustup set default-host x86_64-pc-windows-gnu
 
-    - name: Install MinGW toolchain and wine
-      if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
-      run: |
-        sudo apt-get update
-        sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable
+    #- name: Install MinGW toolchain and wine
+    #  if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
+    #  run: |
+    #    sudo apt-get update
+    #    sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable
 
     - name: Install AArch64 toolchain and qemu
       if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'aarch64-unknown-linux-gnu'
diff --git a/compiler/rustc_codegen_cranelift/.gitignore b/compiler/rustc_codegen_cranelift/.gitignore
index e6ac8c8408d..7915fa138f8 100644
--- a/compiler/rustc_codegen_cranelift/.gitignore
+++ b/compiler/rustc_codegen_cranelift/.gitignore
@@ -1,18 +1,21 @@
-/target
-/build_system/target
-**/*.rs.bk
-*.rlib
-*.o
-perf.data
-perf.data.old
-*.events
-*.string*
+# Build artifacts during normal use
 /y.bin
 /y.bin.dSYM
 /y.exe
 /y.pdb
+/download
 /build
 /dist
+/target
+/build_system/target
+
+# Downloaded by certain scripts
 /rust
-/download
 /git-fixed-subtree.sh
+
+# Various things that can be created during development
+*.rlib
+*.o
+perf.data
+perf.data.old
+*.mm_profdata
diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock
index b70a1234af3..e308cf80284 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/Cargo.lock
@@ -46,18 +46,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.104.0"
+version = "0.105.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d819feeda4c420a18f1e28236ca0ce1177b22bf7c8a44ddee92dfe40de15bcf0"
+checksum = "9515fcc42b6cb5137f76b84c1a6f819782d0cf12473d145d3bc5cd67eedc8bc2"
 dependencies = [
  "cranelift-entity",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.104.0"
+version = "0.105.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9b8d03d5bdbca7e5f72b0e0a0f69933ed1f09e24be6c075aa6fe3f802b0cc0c"
+checksum = "1ad827c6071bfe6d22de1bc331296a29f9ddc506ff926d8415b435ec6a6efce0"
 dependencies = [
  "bumpalo",
  "cranelift-bforest",
@@ -76,39 +76,39 @@ dependencies = [
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.104.0"
+version = "0.105.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3fd3664e38e51649b17dc30cfdd561273fe2f590dcd013fb75d9eabc6272dfb"
+checksum = "10e6b36237a9ca2ce2fb4cc7741d418a080afa1327402138412ef85d5367bef1"
 dependencies = [
  "cranelift-codegen-shared",
 ]
 
 [[package]]
 name = "cranelift-codegen-shared"
-version = "0.104.0"
+version = "0.105.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b031ec5e605828975952622b5a77d49126f20ffe88d33719a0af66b23a0fc36"
+checksum = "c36bf4bfb86898a94ccfa773a1f86e8a5346b1983ff72059bdd2db4600325251"
 
 [[package]]
 name = "cranelift-control"
-version = "0.104.0"
+version = "0.105.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fada054d017cf2ed8f7ed2336e0517fc1b19e6825be1790de9eb00c94788362b"
+checksum = "7cbf36560e7a6bd1409ca91e7b43b2cc7ed8429f343d7605eadf9046e8fac0d0"
 dependencies = [
  "arbitrary",
 ]
 
 [[package]]
 name = "cranelift-entity"
-version = "0.104.0"
+version = "0.105.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "177b6f94ae8de6348eb45bf977c79ab9e3c40fc3ac8cb7ed8109560ea39bee7d"
+checksum = "a71e11061a75b1184c09bea97c026a88f08b59ade96a7bb1f259d4ea0df2e942"
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.104.0"
+version = "0.105.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebebd23a69a23e3ddea78e98ff3a2de222e88c8e045d81ef4a72f042e0d79dbd"
+checksum = "af5d4da63143ee3485c7bcedde0a818727d737d1083484a0ceedb8950c89e495"
 dependencies = [
  "cranelift-codegen",
  "log",
@@ -118,15 +118,15 @@ dependencies = [
 
 [[package]]
 name = "cranelift-isle"
-version = "0.104.0"
+version = "0.105.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1571bfc14df8966d12c6121b5325026591a4b4009e22fea0fe3765ab7cd33b96"
+checksum = "457a9832b089e26f5eea70dcf49bed8ec6edafed630ce7c83161f24d46ab8085"
 
 [[package]]
 name = "cranelift-jit"
-version = "0.104.0"
+version = "0.105.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f61e236d7622c3c43016e8b0f3ba27136e21ac7de328c7fda902e61db1de851"
+checksum = "0af95fe68d5a10919012c8db82b1d59820405b8001c8c6d05f94b08031334fa9"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -144,9 +144,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-module"
-version = "0.104.0"
+version = "0.105.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f30c6820342015c5009070e3e48d1da7b13521399de904663f1c84f5ee839657"
+checksum = "11b0b201fa10a4014062d4c56c307c8d18fdf9a84cb5279efe6080241f42c7a7"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -155,9 +155,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-native"
-version = "0.104.0"
+version = "0.105.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35a69c37e0c10b46fe5527f2397ac821046efbf5f7ec112c8b84df25712f465b"
+checksum = "9b490d579df1ce365e1ea359e24ed86d82289fa785153327c2f6a69a59a731e4"
 dependencies = [
  "cranelift-codegen",
  "libc",
@@ -166,9 +166,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-object"
-version = "0.104.0"
+version = "0.105.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24425a329b4343177d5f1852243841dcec17f929d72c0e7f41262140155e55e7"
+checksum = "fb7e821ac6db471bcdbd004e5a4fa0d374f1046bd3a2ce278c332e0b0c01ca63"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -241,9 +241,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.148"
+version = "0.2.153"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
 
 [[package]]
 name = "libloading"
@@ -410,9 +410,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
 [[package]]
 name = "wasmtime-jit-icache-coherence"
-version = "17.0.0"
+version = "18.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdc26415bb89e9ccd3bdc498fef63aabf665c4c0dd710c107691deb9694955da"
+checksum = "33f4121cb29dda08139b2824a734dd095d83ce843f2d613a84eb580b9cfc17ac"
 dependencies = [
  "cfg-if",
  "libc",
diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml
index 586ce2286f9..c0b9e27b179 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.toml
+++ b/compiler/rustc_codegen_cranelift/Cargo.toml
@@ -8,12 +8,12 @@ crate-type = ["dylib"]
 
 [dependencies]
 # These have to be in sync with each other
-cranelift-codegen = { version = "0.104", default-features = false, features = ["std", "unwind", "all-arch"] }
-cranelift-frontend = { version = "0.104" }
-cranelift-module = { version = "0.104" }
-cranelift-native = { version = "0.104" }
-cranelift-jit = { version = "0.104", optional = true }
-cranelift-object = { version = "0.104" }
+cranelift-codegen = { version = "0.105.2", default-features = false, features = ["std", "unwind", "all-arch"] }
+cranelift-frontend = { version = "0.105.2" }
+cranelift-module = { version = "0.105.2" }
+cranelift-native = { version = "0.105.2" }
+cranelift-jit = { version = "0.105.2", optional = true }
+cranelift-object = { version = "0.105.2" }
 target-lexicon = "0.12.0"
 gimli = { version = "0.28", default-features = false, features = ["write"]}
 object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md
index 4f455261963..a297b22326f 100644
--- a/compiler/rustc_codegen_cranelift/Readme.md
+++ b/compiler/rustc_codegen_cranelift/Readme.md
@@ -123,11 +123,6 @@ You need to do this steps to successfully compile and use the cranelift backend
 
 You can also set `rust-analyzer.rustc.source` to your rust workspace to get rust-analyzer to understand your changes.
 
-## Configuration
-
-See the documentation on the `BackendConfig` struct in [config.rs](src/config.rs) for all
-configuration options.
-
 ## Not yet supported
 
 * SIMD ([tracked here](https://github.com/rust-lang/rustc_codegen_cranelift/issues/171), `std::simd` fully works, `std::arch` is partially supported)
diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
index c68968b4fde..3677d0a7d36 100644
--- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
@@ -1,5 +1,6 @@
 use std::ffi::OsStr;
 use std::fs;
+use std::hash::{Hash, Hasher};
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
@@ -71,7 +72,11 @@ fn hash_file(file: &std::path::Path) -> u64 {
     let contents = std::fs::read(file).unwrap();
     #[allow(deprecated)]
     let mut hasher = std::hash::SipHasher::new();
-    std::hash::Hash::hash(&contents, &mut hasher);
+    // The following is equivalent to
+    //   std::hash::Hash::hash(&contents, &mut hasher);
+    // but gives the same result independent of host byte order.
+    hasher.write_usize(contents.len().to_le());
+    Hash::hash_slice(&contents, &mut hasher);
     std::hash::Hasher::finish(&hasher)
 }
 
@@ -80,16 +85,26 @@ fn hash_dir(dir: &std::path::Path) -> u64 {
     for entry in std::fs::read_dir(dir).unwrap() {
         let entry = entry.unwrap();
         if entry.file_type().unwrap().is_dir() {
-            sub_hashes
-                .insert(entry.file_name().to_str().unwrap().to_owned(), hash_dir(&entry.path()));
+            sub_hashes.insert(
+                entry.file_name().to_str().unwrap().to_owned(),
+                hash_dir(&entry.path()).to_le(),
+            );
         } else {
-            sub_hashes
-                .insert(entry.file_name().to_str().unwrap().to_owned(), hash_file(&entry.path()));
+            sub_hashes.insert(
+                entry.file_name().to_str().unwrap().to_owned(),
+                hash_file(&entry.path()).to_le(),
+            );
         }
     }
     #[allow(deprecated)]
     let mut hasher = std::hash::SipHasher::new();
-    std::hash::Hash::hash(&sub_hashes, &mut hasher);
+    // The following is equivalent to
+    //   std::hash::Hash::hash(&sub_hashes, &mut hasher);
+    // but gives the same result independent of host byte order.
+    hasher.write_usize(sub_hashes.len().to_le());
+    for elt in sub_hashes {
+        elt.hash(&mut hasher);
+    }
     std::hash::Hasher::finish(&hasher)
 }
 
diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs
index 818f3d6f08d..1c3e615c7ab 100644
--- a/compiler/rustc_codegen_cranelift/build_system/tests.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs
@@ -133,8 +133,8 @@ pub(crate) static REGEX: CargoProject = CargoProject::new(&REGEX_REPO.source_dir
 pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github(
     "rust-lang",
     "portable-simd",
-    "97007cc2e70df8c97326ce896a79e2f0ce4dd98b",
-    "e54a16035cedf205",
+    "5794c837bc605c4cd9dbb884285976dfdb293cce",
+    "a64d8fdd0ed0d9c4",
     "portable-simd",
 );
 
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs
index a79909ce0c8..67a0d0dabea 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs
@@ -525,8 +525,11 @@ pub struct Unique<T: ?Sized> {
 impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}
 impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
 
+#[lang = "global_alloc_ty"]
+pub struct Global;
+
 #[lang = "owned_box"]
-pub struct Box<T: ?Sized, A = ()>(Unique<T>, A);
+pub struct Box<T: ?Sized, A = Global>(Unique<T>, A);
 
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
 
@@ -536,7 +539,7 @@ impl<T> Box<T> {
             let size = intrinsics::size_of::<T>();
             let ptr = libc::malloc(size);
             intrinsics::copy(&val as *const T as *const u8, ptr, size);
-            Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, ())
+            Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, Global)
         }
     }
 }
diff --git a/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch
index 6afa5c71fe5..5442c3cef9e 100644
--- a/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch
@@ -39,6 +39,6 @@ index 42a26ae..5ac1042 100644
 +#![cfg(test)]
  #![feature(alloc_layout_extra)]
  #![feature(array_chunks)]
- #![feature(array_methods)]
+ #![feature(array_windows)]
 --
 2.21.0 (Apple Git-122)
diff --git a/compiler/rustc_codegen_cranelift/patches/0023-coretests-Ignore-failing-tests.patch b/compiler/rustc_codegen_cranelift/patches/0023-coretests-Ignore-failing-tests.patch
deleted file mode 100644
index 385f5a8a2e0..00000000000
--- a/compiler/rustc_codegen_cranelift/patches/0023-coretests-Ignore-failing-tests.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From dd82e95c9de212524e14fc60155de1ae40156dfc Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Sun, 24 Nov 2019 15:34:06 +0100
-Subject: [PATCH] [core] Ignore failing tests
-
----
- library/core/tests/iter.rs       |  4 ++++
- library/core/tests/num/bignum.rs | 10 ++++++++++
- library/core/tests/num/mod.rs    |  5 +++--
- library/core/tests/time.rs       |  1 +
- 4 files changed, 18 insertions(+), 2 deletions(-)
-
-diff --git a/atomic.rs b/atomic.rs
-index 13b12db..96fe4b9 100644
---- a/atomic.rs
-+++ b/atomic.rs
-@@ -185,6 +185,7 @@ fn ptr_bitops() {
- }
- 
- #[test]
-+#[cfg_attr(target_arch = "s390x", ignore)] // s390x backend doesn't support stack alignment >8 bytes
- #[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins
- fn ptr_bitops_tagging() {
-     #[repr(align(16))]
--- 
-2.21.0 (Apple Git-122)
diff --git a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml b/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml
index ad63b0768d3..369f9c88be1 100644
--- a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml
+++ b/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml
@@ -150,9 +150,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.3.3"
+version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-alloc",
@@ -161,9 +161,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.150"
+version = "0.2.153"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -398,6 +398,7 @@ version = "0.0.0"
 dependencies = [
  "core",
  "getopts",
+ "libc",
  "panic_abort",
  "panic_unwind",
  "std",
diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain
index ccd7edbc2a9..e9f225b4e9e 100644
--- a/compiler/rustc_codegen_cranelift/rust-toolchain
+++ b/compiler/rustc_codegen_cranelift/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2024-01-26"
+channel = "nightly-2024-03-08"
 components = ["rust-src", "rustc-dev", "llvm-tools"]
diff --git a/compiler/rustc_codegen_cranelift/rustfmt.toml b/compiler/rustc_codegen_cranelift/rustfmt.toml
index 0f884187add..6f4d4413c25 100644
--- a/compiler/rustc_codegen_cranelift/rustfmt.toml
+++ b/compiler/rustc_codegen_cranelift/rustfmt.toml
@@ -1,5 +1,4 @@
 ignore = [
-    "y.rs",
     "example/gen_block_iterate.rs", # uses edition 2024
 ]
 
diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
index 636f2875a68..e884577d519 100755
--- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
@@ -10,12 +10,26 @@ pushd rust
 
 command -v rg >/dev/null 2>&1 || cargo install ripgrep
 
+# FIXME(rust-lang/rust#122196) fix stage0 rmake.rs run-make tests and remove
+# this workaround
+for test in $(ls tests/run-make); do
+  if [[ -e "tests/run-make/$test/rmake.rs" ]]; then
+    rm -r "tests/run-make/$test"
+  fi
+done
+
+# FIXME remove this workaround once ICE tests no longer emit an outdated nightly message
+for test in $(rg -i --files-with-matches "//@(\[.*\])? failure-status: 101" tests/ui); do
+  echo "rm $test"
+  rm $test
+done
+
 rm -r tests/ui/{unsized-locals/,lto/,linkage*} || true
 for test in $(rg --files-with-matches "lto" tests/{codegen-units,ui,incremental}); do
   rm $test
 done
 
-for test in $(rg -i --files-with-matches "//(\[\w+\])?~[^\|]*\s*ERR|// error-pattern:|// build-fail|// run-fail|-Cllvm-args" tests/ui); do
+for test in $(rg -i --files-with-matches "//(\[\w+\])?~[^\|]*\s*ERR|//@ error-pattern:|//@(\[.*\])? build-fail|//@(\[.*\])? run-fail|-Cllvm-args" tests/ui); do
   rm $test
 done
 
@@ -43,8 +57,8 @@ rm tests/ui/proc-macro/allowed-signatures.rs
 rm tests/ui/proc-macro/no-mangle-in-proc-macro-issue-111888.rs
 
 # vendor intrinsics
-rm tests/ui/sse2.rs # CodegenBackend::target_features not yet implemented
 rm tests/ui/simd/array-type.rs # "Index argument for `simd_insert` is not a constant"
+rm tests/ui/asm/x86_64/evex512-implicit-feature.rs # unimplemented AVX512 x86 vendor intrinsic
 
 # exotic linkages
 rm tests/ui/issues/issue-33992.rs # unsupported linkages
@@ -62,14 +76,12 @@ rm -r tests/run-pass-valgrind/unsized-locals
 # misc unimplemented things
 rm tests/ui/intrinsics/intrinsic-nearby.rs # unimplemented nearbyintf32 and nearbyintf64 intrinsics
 rm tests/ui/target-feature/missing-plusminus.rs # error not implemented
-rm tests/ui/fn/dyn-fn-alignment.rs # wants a 256 byte alignment
 rm -r tests/run-make/emit-named-files # requires full --emit support
 rm -r tests/run-make/repr128-dwarf # debuginfo test
 rm -r tests/run-make/split-debuginfo # same
 rm -r tests/run-make/symbols-include-type-name # --emit=asm not supported
 rm -r tests/run-make/target-specs # i686 not supported by Cranelift
 rm -r tests/run-make/mismatching-target-triples # same
-rm tests/ui/asm/x86_64/issue-82869.rs # vector regs in inline asm not yet supported
 rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly
 
 # requires LTO
@@ -109,8 +121,6 @@ rm -r tests/run-make/optimization-remarks-dir # remarks are LLVM specific
 rm tests/ui/mir/mir_misc_casts.rs # depends on deduplication of constants
 rm tests/ui/mir/mir_raw_fat_ptr.rs # same
 rm tests/ui/consts/issue-33537.rs # same
-rm tests/ui/layout/valid_range_oob.rs # different ICE message
-rm tests/ui/const-generics/generic_const_exprs/issue-80742.rs # gives error instead of ICE with cg_clif
 
 # rustdoc-clif passes extra args, suppressing the help message when no args are passed
 rm -r tests/run-make/issue-88756-default-output
@@ -119,15 +129,12 @@ rm -r tests/run-make/issue-88756-default-output
 # should work when using ./x.py test the way it is intended
 # ============================================================
 rm -r tests/run-make/remap-path-prefix-dwarf # requires llvm-dwarfdump
-rm -r tests/ui/consts/missing_span_in_backtrace.rs # expects sysroot source to be elsewhere
 
 # genuine bugs
 # ============
 rm tests/incremental/spike-neg1.rs # errors out for some reason
 rm tests/incremental/spike-neg2.rs # same
 
-rm tests/ui/simd/simd-bitmask.rs # simd_bitmask doesn't implement [u*; N] return type
-
 rm -r tests/run-make/issue-51671 # wrong filename given in case of --emit=obj
 rm -r tests/run-make/issue-30063 # same
 rm -r tests/run-make/multiple-emits # same
@@ -145,6 +152,7 @@ rm tests/ui/codegen/subtyping-enforces-type-equality.rs # assert_assignable bug
 # ======================
 rm tests/ui/backtrace.rs # TODO warning
 rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue
+rm tests/ui/async-await/async-closures/once.rs # FIXME bug in the rustc FnAbi calculation code
 
 rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd
 
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index a7e76fbc128..1ce920f3bdb 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -445,7 +445,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                 template,
                 operands,
                 options,
-                destination,
+                targets,
                 line_spans: _,
                 unwind: _,
             } => {
@@ -456,13 +456,25 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                     );
                 }
 
+                let have_labels = if options.contains(InlineAsmOptions::NORETURN) {
+                    !targets.is_empty()
+                } else {
+                    targets.len() > 1
+                };
+                if have_labels {
+                    fx.tcx.dcx().span_fatal(
+                        source_info.span,
+                        "cranelift doesn't support labels in inline assembly.",
+                    );
+                }
+
                 crate::inline_asm::codegen_inline_asm_terminator(
                     fx,
                     source_info.span,
                     template,
                     operands,
                     *options,
-                    *destination,
+                    targets.get(0).copied(),
                 );
             }
             TerminatorKind::UnwindTerminate(reason) => {
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs
index e35ec4fe1c7..7e29d407a1f 100644
--- a/compiler/rustc_codegen_cranelift/src/common.rs
+++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -392,18 +392,25 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
     }
 
     pub(crate) fn create_stack_slot(&mut self, size: u32, align: u32) -> Pointer {
-        if align <= 16 {
+        let abi_align = if self.tcx.sess.target.arch == "s390x" { 8 } else { 16 };
+        if align <= abi_align {
             let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData {
                 kind: StackSlotKind::ExplicitSlot,
-                // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to
-                // specify stack slot alignment.
-                size: (size + 15) / 16 * 16,
+                // FIXME Don't force the size to a multiple of <abi_align> bytes once Cranelift gets
+                // a way to specify stack slot alignment.
+                size: (size + abi_align - 1) / abi_align * abi_align,
             });
             Pointer::stack_slot(stack_slot)
         } else {
             // Alignment is too big to handle using the above hack. Dynamically realign a stack slot
             // instead. This wastes some space for the realignment.
-            let base_ptr = self.create_stack_slot(size + align, 16).get_addr(self);
+            let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData {
+                kind: StackSlotKind::ExplicitSlot,
+                // FIXME Don't force the size to a multiple of <abi_align> bytes once Cranelift gets
+                // a way to specify stack slot alignment.
+                size: (size + align) / abi_align * abi_align,
+            });
+            let base_ptr = self.bcx.ins().stack_addr(self.pointer_type, stack_slot, 0);
             let misalign_offset = self.bcx.ins().urem_imm(base_ptr, i64::from(align));
             let realign_offset = self.bcx.ins().irsub_imm(misalign_offset, i64::from(align));
             Pointer::new(self.bcx.ins().iadd(base_ptr, realign_offset))
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index b6de688130c..18c5960ffc6 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -372,7 +372,13 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
         }
 
         let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()).to_vec();
-        data.define(bytes.into_boxed_slice());
+        if bytes.is_empty() {
+            // FIXME(bytecodealliance/wasmtime#7918) cranelift-jit has a bug where it causes UB on
+            // empty data objects
+            data.define(Box::new([0]));
+        } else {
+            data.define(bytes.into_boxed_slice());
+        }
 
         for &(offset, prov) in alloc.provenance().ptrs().iter() {
             let alloc_id = prov.alloc_id();
diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs
index da07b66c762..44650898de8 100644
--- a/compiler/rustc_codegen_cranelift/src/global_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs
@@ -78,7 +78,8 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
                         InlineAsmOperand::In { .. }
                         | InlineAsmOperand::Out { .. }
                         | InlineAsmOperand::InOut { .. }
-                        | InlineAsmOperand::SplitInOut { .. } => {
+                        | InlineAsmOperand::SplitInOut { .. }
+                        | InlineAsmOperand::Label { .. } => {
                             span_bug!(op_sp, "invalid operand type for global_asm!")
                         }
                     }
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index 7793b1b7092..171ee88a11c 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -129,6 +129,9 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
                 let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
                 CInlineAsmOperand::Symbol { symbol: fx.tcx.symbol_name(instance).name.to_owned() }
             }
+            InlineAsmOperand::Label { .. } => {
+                span_bug!(span, "asm! label operands are not yet supported");
+            }
         })
         .collect::<Vec<_>>();
 
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
index 2e3e7ce986b..1615dc5de69 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
@@ -170,6 +170,65 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
             }
         }
 
+        "llvm.x86.sse.add.ss" => {
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_add_ss&ig_expand=171
+            intrinsic_args!(fx, args => (a, b); intrinsic);
+
+            assert_eq!(a.layout(), b.layout());
+            assert_eq!(a.layout(), ret.layout());
+            let layout = a.layout();
+
+            let (_, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
+            assert!(lane_ty.is_floating_point());
+            let ret_lane_layout = fx.layout_of(lane_ty);
+
+            ret.write_cvalue(fx, a);
+
+            let a_lane = a.value_lane(fx, 0).load_scalar(fx);
+            let b_lane = b.value_lane(fx, 0).load_scalar(fx);
+
+            let res = fx.bcx.ins().fadd(a_lane, b_lane);
+
+            let res_lane = CValue::by_val(res, ret_lane_layout);
+            ret.place_lane(fx, 0).write_cvalue(fx, res_lane);
+        }
+
+        "llvm.x86.sse.sqrt.ps" => {
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sqrt_ps&ig_expand=6245
+            intrinsic_args!(fx, args => (a); intrinsic);
+
+            // FIXME use vector instructions when possible
+            simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
+                fx.bcx.ins().sqrt(lane)
+            });
+        }
+
+        "llvm.x86.sse.max.ps" => {
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_max_ps&ig_expand=4357
+            intrinsic_args!(fx, args => (a, b); intrinsic);
+
+            simd_pair_for_each_lane(
+                fx,
+                a,
+                b,
+                ret,
+                &|fx, _lane_ty, _res_lane_ty, a_lane, b_lane| fx.bcx.ins().fmax(a_lane, b_lane),
+            );
+        }
+
+        "llvm.x86.sse.min.ps" => {
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_min_ps&ig_expand=4489
+            intrinsic_args!(fx, args => (a, b); intrinsic);
+
+            simd_pair_for_each_lane(
+                fx,
+                a,
+                b,
+                ret,
+                &|fx, _lane_ty, _res_lane_ty, a_lane, b_lane| fx.bcx.ins().fmin(a_lane, b_lane),
+            );
+        }
+
         "llvm.x86.sse.cmp.ps" | "llvm.x86.sse2.cmp.pd" => {
             let (x, y, kind) = match args {
                 [x, y, kind] => (x, y, kind),
@@ -1067,6 +1126,122 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
             );
         }
 
+        "llvm.x86.sha1rnds4" => {
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha1rnds4_epu32&ig_expand=5877
+            intrinsic_args!(fx, args => (a, b, _func); intrinsic);
+
+            let a = a.load_scalar(fx);
+            let b = b.load_scalar(fx);
+
+            let func = if let Some(func) =
+                crate::constant::mir_operand_get_const_val(fx, &args[2].node)
+            {
+                func
+            } else {
+                fx.tcx
+                    .dcx()
+                    .span_fatal(span, "Func argument for `_mm_sha1rnds4_epu32` is not a constant");
+            };
+
+            let func = func.try_to_u8().unwrap_or_else(|_| panic!("kind not scalar: {:?}", func));
+
+            codegen_inline_asm_inner(
+                fx,
+                &[InlineAsmTemplatePiece::String(format!("sha1rnds4 xmm1, xmm2, {func}"))],
+                &[
+                    CInlineAsmOperand::InOut {
+                        reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
+                        _late: true,
+                        in_value: a,
+                        out_place: Some(ret),
+                    },
+                    CInlineAsmOperand::In {
+                        reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm2)),
+                        value: b,
+                    },
+                ],
+                InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM,
+            );
+        }
+
+        "llvm.x86.sha1msg1" => {
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha1msg1_epu32&ig_expand=5874
+            intrinsic_args!(fx, args => (a, b); intrinsic);
+
+            let a = a.load_scalar(fx);
+            let b = b.load_scalar(fx);
+
+            codegen_inline_asm_inner(
+                fx,
+                &[InlineAsmTemplatePiece::String("sha1msg1 xmm1, xmm2".to_string())],
+                &[
+                    CInlineAsmOperand::InOut {
+                        reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
+                        _late: true,
+                        in_value: a,
+                        out_place: Some(ret),
+                    },
+                    CInlineAsmOperand::In {
+                        reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm2)),
+                        value: b,
+                    },
+                ],
+                InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM,
+            );
+        }
+
+        "llvm.x86.sha1msg2" => {
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha1msg2_epu32&ig_expand=5875
+            intrinsic_args!(fx, args => (a, b); intrinsic);
+
+            let a = a.load_scalar(fx);
+            let b = b.load_scalar(fx);
+
+            codegen_inline_asm_inner(
+                fx,
+                &[InlineAsmTemplatePiece::String("sha1msg2 xmm1, xmm2".to_string())],
+                &[
+                    CInlineAsmOperand::InOut {
+                        reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
+                        _late: true,
+                        in_value: a,
+                        out_place: Some(ret),
+                    },
+                    CInlineAsmOperand::In {
+                        reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm2)),
+                        value: b,
+                    },
+                ],
+                InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM,
+            );
+        }
+
+        "llvm.x86.sha1nexte" => {
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha1nexte_epu32&ig_expand=5876
+            intrinsic_args!(fx, args => (a, b); intrinsic);
+
+            let a = a.load_scalar(fx);
+            let b = b.load_scalar(fx);
+
+            codegen_inline_asm_inner(
+                fx,
+                &[InlineAsmTemplatePiece::String("sha1nexte xmm1, xmm2".to_string())],
+                &[
+                    CInlineAsmOperand::InOut {
+                        reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
+                        _late: true,
+                        in_value: a,
+                        out_place: Some(ret),
+                    },
+                    CInlineAsmOperand::In {
+                        reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm2)),
+                        value: b,
+                    },
+                ],
+                InlineAsmOptions::NOSTACK | InlineAsmOptions::PURE | InlineAsmOptions::NOMEM,
+            );
+        }
+
         "llvm.x86.sha256rnds2" => {
             // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sha256rnds2_epu32&ig_expand=5977
             intrinsic_args!(fx, args => (a, b, k); intrinsic);
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 84269ec2942..8b86a116df1 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -391,12 +391,15 @@ fn codegen_float_intrinsic_call<'tcx>(
         | sym::ceilf32
         | sym::ceilf64
         | sym::truncf32
-        | sym::truncf64 => {
+        | sym::truncf64
+        | sym::sqrtf32
+        | sym::sqrtf64 => {
             let val = match intrinsic {
                 sym::fabsf32 | sym::fabsf64 => fx.bcx.ins().fabs(args[0]),
                 sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]),
                 sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]),
                 sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]),
+                sym::sqrtf32 | sym::sqrtf64 => fx.bcx.ins().sqrt(args[0]),
                 _ => unreachable!(),
             };
 
@@ -1255,7 +1258,17 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
         // Unimplemented intrinsics must have a fallback body. The fallback body is obtained
         // by converting the `InstanceDef::Intrinsic` to an `InstanceDef::Item`.
-        _ => return Err(Instance::new(instance.def_id(), instance.args)),
+        _ => {
+            let intrinsic = fx.tcx.intrinsic(instance.def_id()).unwrap();
+            if intrinsic.must_be_overridden {
+                span_bug!(
+                    source_info.span,
+                    "intrinsic {} must be overridden by codegen_cranelift, but isn't",
+                    intrinsic.name,
+                );
+            }
+            return Err(Instance::new(instance.def_id(), instance.args));
+        }
     }
 
     let ret_block = fx.get_block(destination.unwrap());
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
index 8f662808522..79da970a58e 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
@@ -853,7 +853,13 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
             };
 
             for lane in 0..lane_count {
-                let m_lane = fx.bcx.ins().ushr_imm(m, u64::from(lane) as i64);
+                // The bit order of the mask depends on the byte endianness, LSB-first for
+                // little endian and MSB-first for big endian.
+                let mask_lane = match fx.tcx.sess.target.endian {
+                    Endian::Big => lane_count - 1 - lane,
+                    Endian::Little => lane,
+                };
+                let m_lane = fx.bcx.ins().ushr_imm(m, u64::from(mask_lane) as i64);
                 let m_lane = fx.bcx.ins().band_imm(m_lane, 1);
                 let a_lane = a.value_lane(fx, lane).load_scalar(fx);
                 let b_lane = b.value_lane(fx, lane).load_scalar(fx);
diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs
index acfa461a6f3..7b61dc64cb1 100644
--- a/compiler/rustc_codegen_cranelift/src/unsize.rs
+++ b/compiler/rustc_codegen_cranelift/src/unsize.rs
@@ -74,10 +74,6 @@ fn unsize_ptr<'tcx>(
         | (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }), &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => {
             (src, unsized_info(fx, *a, *b, old_info))
         }
-        (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
-            let (a, b) = (src_layout.ty.boxed_ty(), dst_layout.ty.boxed_ty());
-            (src, unsized_info(fx, a, b, old_info))
-        }
         (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
             assert_eq!(def_a, def_b);
 
diff --git a/compiler/rustc_codegen_cranelift/y.rs b/compiler/rustc_codegen_cranelift/y.rs
deleted file mode 100755
index e806a64d943..00000000000
--- a/compiler/rustc_codegen_cranelift/y.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/env bash
-#![deny(unsafe_code)] /*This line is ignored by bash
-# This block is ignored by rustc
-echo "Warning: y.rs is a deprecated alias for y.sh" 1>&2
-exec ./y.sh "$@"
-*/
diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs
index 230009741dc..cc3d647c8c8 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core.rs
@@ -472,6 +472,7 @@ pub trait Allocator {
 
 impl Allocator for () {}
 
+#[lang = "global_alloc_ty"]
 pub struct Global;
 
 impl Allocator for Global {}
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index a237f3e6490..f8afc5c3eb4 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -114,7 +114,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
         options: InlineAsmOptions,
         span: &[Span],
         instance: Instance<'_>,
-        _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>,
+        _catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>,
     ) {
         if options.contains(InlineAsmOptions::MAY_UNWIND) {
             self.sess().dcx().create_err(UnwindingInlineAsm { span: span[0] }).emit();
@@ -132,6 +132,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
         // added to `outputs.len()`
         let mut inputs = vec![];
 
+        // GCC index of a label equals its position in the array added to
+        // `outputs.len() + inputs.len()`.
+        let mut labels = vec![];
+
         // Clobbers collected from `out("explicit register") _` and `inout("expl_reg") var => _`
         let mut clobbers = vec![];
 
@@ -283,6 +287,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                     constants_len +=
                         self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name.len();
                 }
+
+                InlineAsmOperandRef::Label { label } => {
+                    labels.push(label);
+                }
             }
         }
 
@@ -381,6 +389,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                 InlineAsmOperandRef::Const { .. } => {
                     // processed in the previous pass
                 }
+
+                InlineAsmOperandRef::Label { .. } => {
+                    // processed in the previous pass
+                }
             }
         }
 
@@ -470,6 +482,14 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                         InlineAsmOperandRef::Const { ref string } => {
                             template_str.push_str(string);
                         }
+
+                        InlineAsmOperandRef::Label { label } => {
+                            let label_gcc_index = labels.iter()
+                                .position(|&l| l == label)
+                                .expect("wrong rust index");
+                            let gcc_index = label_gcc_index + outputs.len() + inputs.len();
+                            push_to_template(Some('l'), gcc_index);
+                        }
                     }
                 }
             }
@@ -482,7 +502,12 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
         // 4. Generate Extended Asm block
 
         let block = self.llbb();
-        let extended_asm = block.add_extended_asm(None, &template_str);
+        let extended_asm = if let Some(dest) = dest {
+            assert!(!labels.is_empty());
+            block.end_with_extended_asm_goto(None, &template_str, &labels, Some(dest))
+        } else {
+            block.add_extended_asm(None, &template_str)
+        };
 
         for op in &outputs {
             extended_asm.add_output_operand(None, &op.to_constraint(), op.tmp_var);
@@ -510,7 +535,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
         if !options.contains(InlineAsmOptions::NOSTACK) {
             // TODO(@Commeownist): figure out how to align stack
         }
-        if options.contains(InlineAsmOptions::NORETURN) {
+        if dest.is_none() && options.contains(InlineAsmOptions::NORETURN) {
             let builtin_unreachable = self.context.get_builtin_function("__builtin_unreachable");
             let builtin_unreachable: RValue<'gcc> =
                 unsafe { std::mem::transmute(builtin_unreachable) };
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index a413466093b..74539d4d495 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -28,7 +28,8 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
         options: InlineAsmOptions,
         line_spans: &[Span],
         instance: Instance<'_>,
-        dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>,
+        dest: Option<Self::BasicBlock>,
+        catch_funclet: Option<(Self::BasicBlock, Option<&Self::Funclet>)>,
     ) {
         let asm_arch = self.tcx.sess.asm_arch.unwrap();
 
@@ -165,6 +166,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
         }
 
         // Build the template string
+        let mut labels = vec![];
         let mut template_str = String::new();
         for piece in template {
             match *piece {
@@ -205,6 +207,11 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                             // Only emit the raw symbol name
                             template_str.push_str(&format!("${{{}:c}}", op_idx[&operand_idx]));
                         }
+                        InlineAsmOperandRef::Label { label } => {
+                            template_str.push_str(&format!("${{{}:l}}", constraints.len()));
+                            constraints.push("!i".to_owned());
+                            labels.push(label);
+                        }
                     }
                 }
             }
@@ -292,12 +299,14 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
             &constraints.join(","),
             &inputs,
             output_type,
+            &labels,
             volatile,
             alignstack,
             dialect,
             line_spans,
             options.contains(InlineAsmOptions::MAY_UNWIND),
-            dest_catch_funclet,
+            dest,
+            catch_funclet,
         )
         .unwrap_or_else(|| span_bug!(line_spans[0], "LLVM asm constraint validation failed"));
 
@@ -317,7 +326,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
         attributes::apply_to_callsite(result, llvm::AttributePlace::Function, &{ attrs });
 
         // Switch to the 'normal' basic block if we did an `invoke` instead of a `call`
-        if let Some((dest, _, _)) = dest_catch_funclet {
+        if let Some(dest) = dest {
             self.switch_to_block(dest);
         }
 
@@ -415,16 +424,14 @@ pub(crate) fn inline_asm_call<'ll>(
     cons: &str,
     inputs: &[&'ll Value],
     output: &'ll llvm::Type,
+    labels: &[&'ll llvm::BasicBlock],
     volatile: bool,
     alignstack: bool,
     dia: llvm::AsmDialect,
     line_spans: &[Span],
     unwind: bool,
-    dest_catch_funclet: Option<(
-        &'ll llvm::BasicBlock,
-        &'ll llvm::BasicBlock,
-        Option<&Funclet<'ll>>,
-    )>,
+    dest: Option<&'ll llvm::BasicBlock>,
+    catch_funclet: Option<(&'ll llvm::BasicBlock, Option<&Funclet<'ll>>)>,
 ) -> Option<&'ll Value> {
     let volatile = if volatile { llvm::True } else { llvm::False };
     let alignstack = if alignstack { llvm::True } else { llvm::False };
@@ -457,8 +464,11 @@ pub(crate) fn inline_asm_call<'ll>(
                 can_throw,
             );
 
-            let call = if let Some((dest, catch, funclet)) = dest_catch_funclet {
-                bx.invoke(fty, None, None, v, inputs, dest, catch, funclet)
+            let call = if !labels.is_empty() {
+                assert!(catch_funclet.is_none());
+                bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None)
+            } else if let Some((catch, funclet)) = catch_funclet {
+                bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet)
             } else {
                 bx.call(fty, None, None, v, inputs, None)
             };
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index ca43ac4b0e7..0619000364b 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -55,6 +55,7 @@ fn llvm_machine_type(cpu: &str) -> LLVMMachineType {
         "x86_64" => LLVMMachineType::AMD64,
         "x86" => LLVMMachineType::I386,
         "aarch64" => LLVMMachineType::ARM64,
+        "arm64ec" => LLVMMachineType::ARM64EC,
         "arm" => LLVMMachineType::ARM,
         _ => panic!("unsupported cpu type {cpu}"),
     }
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index eaedaec635f..ca2e2b57580 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -1538,6 +1538,58 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
         }
     }
 
+    pub(crate) fn callbr(
+        &mut self,
+        llty: &'ll Type,
+        fn_attrs: Option<&CodegenFnAttrs>,
+        fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
+        llfn: &'ll Value,
+        args: &[&'ll Value],
+        default_dest: &'ll BasicBlock,
+        indirect_dest: &[&'ll BasicBlock],
+        funclet: Option<&Funclet<'ll>>,
+    ) -> &'ll Value {
+        debug!("invoke {:?} with args ({:?})", llfn, args);
+
+        let args = self.check_call("callbr", llty, llfn, args);
+        let funclet_bundle = funclet.map(|funclet| funclet.bundle());
+        let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
+        let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
+        if let Some(funclet_bundle) = funclet_bundle {
+            bundles.push(funclet_bundle);
+        }
+
+        // Emit CFI pointer type membership test
+        self.cfi_type_test(fn_attrs, fn_abi, llfn);
+
+        // Emit KCFI operand bundle
+        let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn);
+        let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
+        if let Some(kcfi_bundle) = kcfi_bundle {
+            bundles.push(kcfi_bundle);
+        }
+
+        let callbr = unsafe {
+            llvm::LLVMRustBuildCallBr(
+                self.llbuilder,
+                llty,
+                llfn,
+                default_dest,
+                indirect_dest.as_ptr(),
+                indirect_dest.len() as c_uint,
+                args.as_ptr(),
+                args.len() as c_uint,
+                bundles.as_ptr(),
+                bundles.len() as c_uint,
+                UNNAMED,
+            )
+        };
+        if let Some(fn_abi) = fn_abi {
+            fn_abi.apply_attrs_callsite(self, callbr);
+        }
+        callbr
+    }
+
     // Emits CFI pointer type membership tests.
     fn cfi_type_test(
         &mut self,
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 16122e5557e..d1f32087908 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -260,35 +260,29 @@ pub unsafe fn create_module<'ll>(
     }
 
     if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
-        let behavior = if llvm_version >= (15, 0, 0) {
-            llvm::LLVMModFlagBehavior::Min
-        } else {
-            llvm::LLVMModFlagBehavior::Error
-        };
-
         if sess.target.arch == "aarch64" {
             llvm::LLVMRustAddModuleFlag(
                 llmod,
-                behavior,
+                llvm::LLVMModFlagBehavior::Min,
                 c"branch-target-enforcement".as_ptr().cast(),
                 bti.into(),
             );
             llvm::LLVMRustAddModuleFlag(
                 llmod,
-                behavior,
+                llvm::LLVMModFlagBehavior::Min,
                 c"sign-return-address".as_ptr().cast(),
                 pac_ret.is_some().into(),
             );
             let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
             llvm::LLVMRustAddModuleFlag(
                 llmod,
-                behavior,
+                llvm::LLVMModFlagBehavior::Min,
                 c"sign-return-address-all".as_ptr().cast(),
                 pac_opts.leaf.into(),
             );
             llvm::LLVMRustAddModuleFlag(
                 llmod,
-                behavior,
+                llvm::LLVMModFlagBehavior::Min,
                 c"sign-return-address-with-bkey".as_ptr().cast(),
                 u32::from(pac_opts.key == PAuthKey::B),
             );
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 1a5f9b42947..660f1647367 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -454,9 +454,13 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D
         ty::RawPtr(ty::TypeAndMut { ty: pointee_type, .. }) | ty::Ref(_, pointee_type, _) => {
             build_pointer_or_reference_di_node(cx, t, pointee_type, unique_type_id)
         }
-        // Box<T, A> may have a non-1-ZST allocator A. In that case, we
-        // cannot treat Box<T, A> as just an owned alias of `*mut T`.
-        ty::Adt(def, args) if def.is_box() && cx.layout_of(args.type_at(1)).is_1zst() => {
+        // Some `Box` are newtyped pointers, make debuginfo aware of that.
+        // Only works if the allocator argument is a 1-ZST and hence irrelevant for layout
+        // (or if there is no allocator argument).
+        ty::Adt(def, args)
+            if def.is_box()
+                && args.get(1).map_or(true, |arg| cx.layout_of(arg.expect_ty()).is_1zst()) =>
+        {
             build_pointer_or_reference_di_node(cx, t, t.boxed_ty(), unique_type_id)
         }
         ty::FnDef(..) | ty::FnPtr(_) => build_subroutine_type_di_node(cx, unique_type_id),
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index f33a672aff0..467e02d55e3 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -448,12 +448,14 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                     constraint,
                     inputs,
                     self.type_void(),
+                    &[],
                     true,
                     false,
                     llvm::AsmDialect::Att,
                     &[span],
                     false,
                     None,
+                    None,
                 )
                 .unwrap_or_else(|| bug!("failed to generate inline asm call for `black_box`"));
 
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 952f41fbd90..58e98037067 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -56,6 +56,7 @@ pub enum LLVMMachineType {
     AMD64 = 0x8664,
     I386 = 0x14c,
     ARM64 = 0xaa64,
+    ARM64EC = 0xa641,
     ARM = 0x01c0,
 }
 
@@ -1615,6 +1616,20 @@ extern "C" {
         Name: *const c_char,
     ) -> &'a Value;
 
+    pub fn LLVMRustBuildCallBr<'a>(
+        B: &Builder<'a>,
+        Ty: &'a Type,
+        Fn: &'a Value,
+        DefaultDest: &'a BasicBlock,
+        IndirectDests: *const &'a BasicBlock,
+        NumIndirectDests: c_uint,
+        Args: *const &'a Value,
+        NumArgs: c_uint,
+        OpBundles: *const &OperandBundleDef<'a>,
+        NumOpBundles: c_uint,
+        Name: *const c_char,
+    ) -> &'a Value;
+
     pub fn LLVMRustSetFastMath(Instr: &Value);
     pub fn LLVMRustSetAlgebraicMath(Instr: &Value);
     pub fn LLVMRustSetAllowReassoc(Instr: &Value);
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 75a189aa87c..78d47f36f91 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -201,7 +201,13 @@ impl<'a> IntoIterator for LLVMFeature<'a> {
 // which might lead to failures if the oldest tested / supported LLVM version
 // doesn't yet support the relevant intrinsics
 pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> {
-    let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch };
+    let arch = if sess.target.arch == "x86_64" {
+        "x86"
+    } else if sess.target.arch == "arm64ec" {
+        "aarch64"
+    } else {
+        &*sess.target.arch
+    };
     match (arch, s) {
         ("x86", "sse4.2") => {
             LLVMFeature::with_dependency("sse4.2", TargetFeatureFoldStrength::EnableOnly("crc32"))
diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs
index b406a04af74..220bb77d3fd 100644
--- a/compiler/rustc_codegen_llvm/src/va_arg.rs
+++ b/compiler/rustc_codegen_llvm/src/va_arg.rs
@@ -288,7 +288,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
         // Generic x86
         "x86" => emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), true),
         // Windows AArch64
-        "aarch64" if target.is_like_windows => {
+        "aarch64" | "arm64ec" if target.is_like_windows => {
             emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), false)
         }
         // macOS / iOS AArch64
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 9359df5de6a..81ca42e1ad8 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -7,7 +7,7 @@ edition = "2021"
 # tidy-alphabetical-start
 ar_archive_writer = "0.1.5"
 bitflags = "2.4.1"
-cc = "1.0.69"
+cc = "1.0.90"
 itertools = "0.11"
 jobserver = "0.1.28"
 pathdiff = "0.2.0"
diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
index cbee4877122..7ecc3864347 100644
--- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
+++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
@@ -176,7 +176,7 @@ impl<'tcx> AssertModuleSource<'tcx> {
     /// Scan for a `cfg="foo"` attribute and check whether we have a
     /// cfg flag called `foo`.
     fn check_config(&self, attr: &ast::Attribute) -> bool {
-        let config = &self.tcx.sess.parse_sess.config;
+        let config = &self.tcx.sess.psess.config;
         let value = self.field(attr, sym::cfg);
         debug!("check_config(config={:?}, value={:?})", config, value);
         if config.iter().any(|&(name, _)| name == value) {
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 158b8fb8727..ab1bc0b6cd2 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -8,7 +8,7 @@ use std::path::Path;
 use object::write::{self, StandardSegment, Symbol, SymbolSection};
 use object::{
     elf, pe, xcoff, Architecture, BinaryFormat, Endianness, FileFlags, Object, ObjectSection,
-    ObjectSymbol, SectionFlags, SectionKind, SymbolFlags, SymbolKind, SymbolScope,
+    ObjectSymbol, SectionFlags, SectionKind, SubArchitecture, SymbolFlags, SymbolKind, SymbolScope,
 };
 
 use rustc_data_structures::memmap::Mmap;
@@ -182,37 +182,40 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
         Endian::Little => Endianness::Little,
         Endian::Big => Endianness::Big,
     };
-    let architecture = match &sess.target.arch[..] {
-        "arm" => Architecture::Arm,
-        "aarch64" => {
+    let (architecture, sub_architecture) = match &sess.target.arch[..] {
+        "arm" => (Architecture::Arm, None),
+        "aarch64" => (
             if sess.target.pointer_width == 32 {
                 Architecture::Aarch64_Ilp32
             } else {
                 Architecture::Aarch64
-            }
-        }
-        "x86" => Architecture::I386,
-        "s390x" => Architecture::S390x,
-        "mips" | "mips32r6" => Architecture::Mips,
-        "mips64" | "mips64r6" => Architecture::Mips64,
-        "x86_64" => {
+            },
+            None,
+        ),
+        "x86" => (Architecture::I386, None),
+        "s390x" => (Architecture::S390x, None),
+        "mips" | "mips32r6" => (Architecture::Mips, None),
+        "mips64" | "mips64r6" => (Architecture::Mips64, None),
+        "x86_64" => (
             if sess.target.pointer_width == 32 {
                 Architecture::X86_64_X32
             } else {
                 Architecture::X86_64
-            }
-        }
-        "powerpc" => Architecture::PowerPc,
-        "powerpc64" => Architecture::PowerPc64,
-        "riscv32" => Architecture::Riscv32,
-        "riscv64" => Architecture::Riscv64,
-        "sparc64" => Architecture::Sparc64,
-        "avr" => Architecture::Avr,
-        "msp430" => Architecture::Msp430,
-        "hexagon" => Architecture::Hexagon,
-        "bpf" => Architecture::Bpf,
-        "loongarch64" => Architecture::LoongArch64,
-        "csky" => Architecture::Csky,
+            },
+            None,
+        ),
+        "powerpc" => (Architecture::PowerPc, None),
+        "powerpc64" => (Architecture::PowerPc64, None),
+        "riscv32" => (Architecture::Riscv32, None),
+        "riscv64" => (Architecture::Riscv64, None),
+        "sparc64" => (Architecture::Sparc64, None),
+        "avr" => (Architecture::Avr, None),
+        "msp430" => (Architecture::Msp430, None),
+        "hexagon" => (Architecture::Hexagon, None),
+        "bpf" => (Architecture::Bpf, None),
+        "loongarch64" => (Architecture::LoongArch64, None),
+        "csky" => (Architecture::Csky, None),
+        "arm64ec" => (Architecture::Aarch64, Some(SubArchitecture::Arm64EC)),
         // Unsupported architecture.
         _ => return None,
     };
@@ -227,6 +230,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
     };
 
     let mut file = write::Object::new(binary_format, architecture, endianness);
+    file.set_sub_architecture(sub_architecture);
     if sess.target.is_like_osx {
         if macho_is_arm64e(&sess.target) {
             file.set_macho_cpu_subtype(object::macho::CPU_SUBTYPE_ARM64E);
@@ -335,7 +339,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
                 "ilp32s" | "lp64s" => e_flags |= elf::EF_LARCH_ABI_SOFT_FLOAT,
                 "ilp32f" | "lp64f" => e_flags |= elf::EF_LARCH_ABI_SINGLE_FLOAT,
                 "ilp32d" | "lp64d" => e_flags |= elf::EF_LARCH_ABI_DOUBLE_FLOAT,
-                _ => bug!("unknown RISC-V ABI name"),
+                _ => bug!("unknown LoongArch ABI name"),
             }
 
             e_flags
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 2dba04e0bb7..72648e5ade4 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -81,6 +81,10 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
                 return library.kind.is_statically_included().then_some(def_id);
             }
 
+            if tcx.intrinsic(def_id).is_some_and(|i| i.must_be_overridden) {
+                return None;
+            }
+
             // Only consider nodes that actually have exported symbols.
             match tcx.def_kind(def_id) {
                 DefKind::Fn | DefKind::Static(_) => {}
@@ -563,9 +567,10 @@ pub fn linking_symbol_name_for_instance_in_crate<'tcx>(
         return undecorated;
     }
 
-    let x86 = match &target.arch[..] {
-        "x86" => true,
-        "x86_64" => false,
+    let prefix = match &target.arch[..] {
+        "x86" => Some('_'),
+        "x86_64" => None,
+        "arm64ec" => Some('#'),
         // Only x86/64 use symbol decorations.
         _ => return undecorated,
     };
@@ -602,8 +607,8 @@ pub fn linking_symbol_name_for_instance_in_crate<'tcx>(
         Conv::X86Stdcall => ("_", "@"),
         Conv::X86VectorCall => ("", "@@"),
         _ => {
-            if x86 {
-                undecorated.insert(0, '_');
+            if let Some(prefix) = prefix {
+                undecorated.insert(0, prefix);
             }
             return undecorated;
         }
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 60865d06ab9..bbb04652119 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -16,8 +16,8 @@ use rustc_data_structures::sync::Lrc;
 use rustc_errors::emitter::Emitter;
 use rustc_errors::translation::Translate;
 use rustc_errors::{
-    Diag, DiagArgMap, DiagCtxt, DiagnosticMessage, ErrCode, FatalError, FluentBundle, Level,
-    MultiSpan, Style,
+    Diag, DiagArgMap, DiagCtxt, DiagMessage, ErrCode, FatalError, FluentBundle, Level, MultiSpan,
+    Style,
 };
 use rustc_fs_util::link_or_copy;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
@@ -1004,9 +1004,9 @@ pub(crate) enum Message<B: WriteBackendMethods> {
 /// process another codegen unit.
 pub struct CguMessage;
 
-// A cut-down version of `rustc_errors::Diagnostic` that impls `Send`, which
+// A cut-down version of `rustc_errors::DiagInner` that impls `Send`, which
 // can be used to send diagnostics from codegen threads to the main thread.
-// It's missing the following fields from `rustc_errors::Diagnostic`.
+// It's missing the following fields from `rustc_errors::DiagInner`.
 // - `span`: it doesn't impl `Send`.
 // - `suggestions`: it doesn't impl `Send`, and isn't used for codegen
 //   diagnostics.
@@ -1015,18 +1015,18 @@ pub struct CguMessage;
 // - `emitted_at`: not used for codegen diagnostics.
 struct Diagnostic {
     level: Level,
-    messages: Vec<(DiagnosticMessage, Style)>,
+    messages: Vec<(DiagMessage, Style)>,
     code: Option<ErrCode>,
     children: Vec<Subdiagnostic>,
     args: DiagArgMap,
 }
 
-// A cut-down version of `rustc_errors::SubDiagnostic` that impls `Send`. It's
-// missing the following fields from `rustc_errors::SubDiagnostic`.
+// A cut-down version of `rustc_errors::Subdiag` that impls `Send`. It's
+// missing the following fields from `rustc_errors::Subdiag`.
 // - `span`: it doesn't impl `Send`.
 pub struct Subdiagnostic {
     level: Level,
-    messages: Vec<(DiagnosticMessage, Style)>,
+    messages: Vec<(DiagMessage, Style)>,
 }
 
 #[derive(PartialEq, Clone, Copy, Debug)]
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index f7afd22a48c..1a3c70cedd0 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -510,11 +510,13 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         // Params for UEFI
         let param_handle = bx.get_param(0);
         let param_system_table = bx.get_param(1);
+        let ptr_size = bx.tcx().data_layout.pointer_size;
+        let ptr_align = bx.tcx().data_layout.pointer_align.abi;
         let arg_argc = bx.const_int(cx.type_isize(), 2);
-        let arg_argv = bx.alloca(cx.type_array(cx.type_ptr(), 2), Align::ONE);
-        bx.store(param_handle, arg_argv, Align::ONE);
-        let arg_argv_el1 = bx.gep(cx.type_ptr(), arg_argv, &[bx.const_int(cx.type_int(), 1)]);
-        bx.store(param_system_table, arg_argv_el1, Align::ONE);
+        let arg_argv = bx.alloca(cx.type_array(cx.type_ptr(), 2), ptr_align);
+        bx.store(param_handle, arg_argv, ptr_align);
+        let arg_argv_el1 = bx.inbounds_ptradd(arg_argv, bx.const_usize(ptr_size.bytes()));
+        bx.store(param_system_table, arg_argv_el1, ptr_align);
         (arg_argc, arg_argv)
     } else if cx.sess().target.main_needs_argc_argv {
         // Params from native `main()` used as args for rust start function
@@ -907,7 +909,11 @@ impl CrateInfo {
                     lang_items::required(tcx, l).then_some(name)
                 })
                 .collect();
-            let prefix = if target.is_like_windows && target.arch == "x86" { "_" } else { "" };
+            let prefix = match (target.is_like_windows, target.arch.as_ref()) {
+                (true, "x86") => "_",
+                (true, "arm64ec") => "#",
+                _ => "",
+            };
 
             // This loop only adds new items to values of the hash map, so the order in which we
             // iterate over the values is not important.
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 9c7aadb81f8..89a44d2897a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -12,12 +12,12 @@ use crate::MemFlags;
 use rustc_ast as ast;
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_hir::lang_items::LangItem;
-use rustc_middle::mir::{self, AssertKind, SwitchTargets, UnwindTerminateReason};
+use rustc_middle::mir::{self, AssertKind, BasicBlock, SwitchTargets, UnwindTerminateReason};
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
 use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_session::config::OptLevel;
-use rustc_span::{source_map::Spanned, sym, Span, Symbol};
+use rustc_span::{source_map::Spanned, sym, Span};
 use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg};
 use rustc_target::abi::{self, HasDataLayout, WrappingRange};
 use rustc_target::spec::abi::Abi;
@@ -264,7 +264,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
             mir::UnwindAction::Unreachable => None,
         };
 
-        if let Some(cleanup) = unwind_target {
+        if operands.iter().any(|x| matches!(x, InlineAsmOperandRef::Label { .. })) {
+            assert!(unwind_target.is_none());
             let ret_llbb = if let Some(target) = destination {
                 fx.llbb(target)
             } else {
@@ -277,11 +278,29 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
                 options,
                 line_spans,
                 instance,
-                Some((ret_llbb, cleanup, self.funclet(fx))),
+                Some(ret_llbb),
+                None,
+            );
+            MergingSucc::False
+        } else if let Some(cleanup) = unwind_target {
+            let ret_llbb = if let Some(target) = destination {
+                fx.llbb(target)
+            } else {
+                fx.unreachable_block()
+            };
+
+            bx.codegen_inline_asm(
+                template,
+                operands,
+                options,
+                line_spans,
+                instance,
+                Some(ret_llbb),
+                Some((cleanup, self.funclet(fx))),
             );
             MergingSucc::False
         } else {
-            bx.codegen_inline_asm(template, operands, options, line_spans, instance, None);
+            bx.codegen_inline_asm(template, operands, options, line_spans, instance, None, None);
 
             if let Some(target) = destination {
                 self.funclet_br(fx, bx, target, mergeable_succ)
@@ -680,7 +699,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         &mut self,
         helper: &TerminatorCodegenHelper<'tcx>,
         bx: &mut Bx,
-        intrinsic: Option<Symbol>,
+        intrinsic: Option<ty::IntrinsicDef>,
         instance: Option<Instance<'tcx>>,
         source_info: mir::SourceInfo,
         target: Option<mir::BasicBlock>,
@@ -690,7 +709,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         // Emit a panic or a no-op for `assert_*` intrinsics.
         // These are intrinsics that compile to panics so that we can get a message
         // which mentions the offending type, even from a const context.
-        let panic_intrinsic = intrinsic.and_then(|s| ValidityRequirement::from_intrinsic(s));
+        let panic_intrinsic = intrinsic.and_then(|i| ValidityRequirement::from_intrinsic(i.name));
         if let Some(requirement) = panic_intrinsic {
             let ty = instance.unwrap().args.type_at(0);
 
@@ -826,14 +845,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         // The arguments we'll be passing. Plus one to account for outptr, if used.
         let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize;
 
-        if intrinsic == Some(sym::caller_location) {
+        if matches!(intrinsic, Some(ty::IntrinsicDef { name: sym::caller_location, .. })) {
             return if let Some(target) = target {
                 let location =
                     self.get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info });
 
                 let mut llargs = Vec::with_capacity(arg_count);
-                let ret_dest =
-                    self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, true, true);
+                let ret_dest = self.make_return_dest(
+                    bx,
+                    destination,
+                    &fn_abi.ret,
+                    &mut llargs,
+                    intrinsic,
+                    Some(target),
+                );
                 assert_eq!(llargs, []);
                 if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
                     location.val.store(bx, tmp);
@@ -846,7 +871,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         }
 
         let instance = match intrinsic {
-            None | Some(sym::drop_in_place) => instance,
+            None => instance,
             Some(intrinsic) => {
                 let mut llargs = Vec::with_capacity(1);
                 let ret_dest = self.make_return_dest(
@@ -854,8 +879,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     destination,
                     &fn_abi.ret,
                     &mut llargs,
-                    true,
-                    target.is_some(),
+                    Some(intrinsic),
+                    target,
                 );
                 let dest = match ret_dest {
                     _ if fn_abi.ret.is_indirect() => llargs[0],
@@ -873,7 +898,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         // The indices passed to simd_shuffle in the
                         // third argument must be constant. This is
                         // checked by the type-checker.
-                        if i == 2 && intrinsic == sym::simd_shuffle {
+                        if i == 2 && intrinsic.name == sym::simd_shuffle {
                             if let mir::Operand::Constant(constant) = &arg.node {
                                 let (llval, ty) = self.simd_shuffle_indices(bx, constant);
                                 return OperandRef {
@@ -903,14 +928,33 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             MergingSucc::False
                         };
                     }
-                    Err(instance) => Some(instance),
+                    Err(instance) => {
+                        if intrinsic.must_be_overridden {
+                            span_bug!(
+                                span,
+                                "intrinsic {} must be overridden by codegen backend, but isn't",
+                                intrinsic.name,
+                            );
+                        }
+                        Some(instance)
+                    }
                 }
             }
         };
 
         let mut llargs = Vec::with_capacity(arg_count);
         let destination = target.as_ref().map(|&target| {
-            (self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, false, true), target)
+            (
+                self.make_return_dest(
+                    bx,
+                    destination,
+                    &fn_abi.ret,
+                    &mut llargs,
+                    None,
+                    Some(target),
+                ),
+                target,
+            )
         });
 
         // Split the rust-call tupled arguments off.
@@ -1075,7 +1119,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         operands: &[mir::InlineAsmOperand<'tcx>],
         options: ast::InlineAsmOptions,
         line_spans: &[Span],
-        destination: Option<mir::BasicBlock>,
+        targets: &[mir::BasicBlock],
         unwind: mir::UnwindAction,
         instance: Instance<'_>,
         mergeable_succ: bool,
@@ -1127,6 +1171,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 mir::InlineAsmOperand::SymStatic { def_id } => {
                     InlineAsmOperandRef::SymStatic { def_id }
                 }
+                mir::InlineAsmOperand::Label { target_index } => {
+                    InlineAsmOperandRef::Label { label: self.llbb(targets[target_index]) }
+                }
             })
             .collect();
 
@@ -1137,7 +1184,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             &operands,
             options,
             line_spans,
-            destination,
+            if options.contains(InlineAsmOptions::NORETURN) {
+                None
+            } else {
+                targets.get(0).copied()
+            },
             unwind,
             instance,
             mergeable_succ,
@@ -1293,7 +1344,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 ref operands,
                 options,
                 line_spans,
-                destination,
+                ref targets,
                 unwind,
             } => self.codegen_asm_terminator(
                 helper,
@@ -1303,7 +1354,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 operands,
                 options,
                 line_spans,
-                destination,
+                targets,
                 unwind,
                 self.instance,
                 mergeable_succ(),
@@ -1643,10 +1694,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         dest: mir::Place<'tcx>,
         fn_ret: &ArgAbi<'tcx, Ty<'tcx>>,
         llargs: &mut Vec<Bx::Value>,
-        is_intrinsic: bool,
-        has_target: bool,
+        intrinsic: Option<ty::IntrinsicDef>,
+        target: Option<BasicBlock>,
     ) -> ReturnDest<'tcx, Bx::Value> {
-        if !has_target {
+        if target.is_none() {
             return ReturnDest::Nothing;
         }
         // If the return is ignored, we can just return a do-nothing `ReturnDest`.
@@ -1667,7 +1718,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         tmp.storage_live(bx);
                         llargs.push(tmp.llval);
                         ReturnDest::IndirectOperand(tmp, index)
-                    } else if is_intrinsic {
+                    } else if intrinsic.is_some() {
                         // Currently, intrinsics always need a location to store
                         // the result, so we create a temporary `alloca` for the
                         // result.
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 94eb37e78e0..932926976b5 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -204,6 +204,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
 
     pub fn deref<Cx: LayoutTypeMethods<'tcx>>(self, cx: &Cx) -> PlaceRef<'tcx, V> {
         if self.layout.ty.is_box() {
+            // Derefer should have removed all Box derefs
             bug!("dereferencing {:?} in codegen", self.layout.ty);
         }
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 725d3bf4431..1ec6c351e25 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -104,10 +104,6 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         let mut simple = || {
             let llval = if offset.bytes() == 0 {
                 self.llval
-            } else if field.is_zst() {
-                // FIXME(erikdesjardins): it should be fine to use inbounds for ZSTs too;
-                // keeping this logic for now to preserve previous behavior.
-                bx.ptradd(self.llval, bx.const_usize(offset.bytes()))
             } else {
                 bx.inbounds_ptradd(self.llval, bx.const_usize(offset.bytes()))
             };
@@ -168,8 +164,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         debug!("struct_field_ptr: DST field offset: {:?}", offset);
 
         // Adjust pointer.
-        // FIXME(erikdesjardins): should be able to use inbounds here too.
-        let ptr = bx.ptradd(self.llval, offset);
+        let ptr = bx.inbounds_ptradd(self.llval, offset);
 
         PlaceRef { llval: ptr, llextra: self.llextra, layout: field, align: effective_field_align }
     }
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index f7ff36c0467..9ae82d4845e 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -94,8 +94,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 }
 
                 if let OperandValue::Immediate(v) = cg_elem.val {
-                    let zero = bx.const_usize(0);
-                    let start = dest.project_index(bx, zero).llval;
+                    let start = dest.llval;
                     let size = bx.const_usize(dest.layout.size.bytes());
 
                     // Use llvm.memset.p0i8.* to initialize all zero arrays
diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs
index 295e2769109..1a4795c0213 100644
--- a/compiler/rustc_codegen_ssa/src/mono_item.rs
+++ b/compiler/rustc_codegen_ssa/src/mono_item.rs
@@ -76,7 +76,8 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
                             hir::InlineAsmOperand::In { .. }
                             | hir::InlineAsmOperand::Out { .. }
                             | hir::InlineAsmOperand::InOut { .. }
-                            | hir::InlineAsmOperand::SplitInOut { .. } => {
+                            | hir::InlineAsmOperand::SplitInOut { .. }
+                            | hir::InlineAsmOperand::Label { .. } => {
                                 span_bug!(*op_sp, "invalid operand type for global_asm!")
                             }
                         })
diff --git a/compiler/rustc_codegen_ssa/src/traits/asm.rs b/compiler/rustc_codegen_ssa/src/traits/asm.rs
index c2ae74b18d8..8d67b626bbd 100644
--- a/compiler/rustc_codegen_ssa/src/traits/asm.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/asm.rs
@@ -33,6 +33,9 @@ pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> {
     SymStatic {
         def_id: DefId,
     },
+    Label {
+        label: B::BasicBlock,
+    },
 }
 
 #[derive(Debug)]
@@ -51,7 +54,8 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes {
         options: InlineAsmOptions,
         line_spans: &[Span],
         instance: Instance<'_>,
-        dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>,
+        dest: Option<Self::BasicBlock>,
+        catch_funclet: Option<(Self::BasicBlock, Option<&Self::Funclet>)>,
     );
 }
 
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index 2805ca360ad..81c9e02e2ee 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -232,9 +232,6 @@ const_eval_non_const_fn_call =
 const_eval_non_const_impl =
     impl defined here, but it is not `const`
 
-const_eval_noreturn_asm_returned =
-    returned from noreturn inline assembly
-
 const_eval_not_enough_caller_args =
     calling a function with fewer arguments than it requires
 
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index 62bc68b1a20..e5b4fc3a574 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -1,8 +1,6 @@
 use std::mem;
 
-use rustc_errors::{
-    DiagArgName, DiagArgValue, DiagnosticMessage, IntoDiagnostic, IntoDiagnosticArg,
-};
+use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, IntoDiagnostic, IntoDiagnosticArg};
 use rustc_hir::CRATE_HIR_ID;
 use rustc_middle::mir::AssertKind;
 use rustc_middle::query::TyCtxtAt;
@@ -25,7 +23,7 @@ pub enum ConstEvalErrKind {
 }
 
 impl MachineStopType for ConstEvalErrKind {
-    fn diagnostic_message(&self) -> DiagnosticMessage {
+    fn diagnostic_message(&self) -> DiagMessage {
         use crate::fluent_generated::*;
         use ConstEvalErrKind::*;
         match self {
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 946ffc05cc1..6736fc749c0 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -24,7 +24,7 @@ use crate::errors::{LongRunning, LongRunningWarn};
 use crate::fluent_generated as fluent;
 use crate::interpret::{
     self, compile_time_machine, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, FnVal,
-    Frame, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, PointerArithmetic, Scalar,
+    Frame, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, Scalar,
 };
 
 use super::error::*;
@@ -219,7 +219,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
         &mut self,
         instance: ty::Instance<'tcx>,
         args: &[FnArg<'tcx>],
-        dest: &PlaceTy<'tcx>,
+        dest: &MPlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
         let def_id = instance.def_id();
@@ -227,7 +227,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
         if self.tcx.has_attr(def_id, sym::rustc_const_panic_str)
             || Some(def_id) == self.tcx.lang_items().begin_panic_fn()
         {
-            let args = self.copy_fn_args(args)?;
+            let args = self.copy_fn_args(args);
             // &str or &&str
             assert!(args.len() == 1);
 
@@ -254,7 +254,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
 
             return Ok(Some(new_instance));
         } else if Some(def_id) == self.tcx.lang_items().align_offset_fn() {
-            let args = self.copy_fn_args(args)?;
+            let args = self.copy_fn_args(args);
             // For align_offset, we replace the function call if the pointer has no address.
             match self.align_offset(instance, &args, dest, ret)? {
                 ControlFlow::Continue(()) => return Ok(Some(instance)),
@@ -280,7 +280,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
         &mut self,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx>],
-        dest: &PlaceTy<'tcx>,
+        dest: &MPlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx, ControlFlow<()>> {
         assert_eq!(args.len(), 2);
@@ -410,7 +410,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         orig_instance: ty::Instance<'tcx>,
         _abi: CallAbi,
         args: &[FnArg<'tcx>],
-        dest: &PlaceTy<'tcx>,
+        dest: &MPlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         _unwind: mir::UnwindAction, // unwinding is not supported in consts
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
@@ -455,7 +455,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx>],
-        dest: &PlaceTy<'tcx, Self::Provenance>,
+        dest: &MPlaceTy<'tcx, Self::Provenance>,
         target: Option<mir::BasicBlock>,
         _unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index c59e0a0df9f..afabd9689c6 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -1,8 +1,7 @@
 use std::borrow::Cow;
 
 use rustc_errors::{
-    codes::*, Diag, DiagArgValue, DiagCtxt, DiagnosticMessage, EmissionGuarantee, IntoDiagnostic,
-    Level,
+    codes::*, Diag, DiagArgValue, DiagCtxt, DiagMessage, EmissionGuarantee, IntoDiagnostic, Level,
 };
 use rustc_hir::ConstContext;
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@@ -424,7 +423,7 @@ pub struct UndefinedBehavior {
 
 pub trait ReportErrorExt {
     /// Returns the diagnostic message for this error.
-    fn diagnostic_message(&self) -> DiagnosticMessage;
+    fn diagnostic_message(&self) -> DiagMessage;
     fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>);
 
     fn debug(self) -> String
@@ -433,7 +432,7 @@ pub trait ReportErrorExt {
     {
         ty::tls::with(move |tcx| {
             let dcx = tcx.dcx();
-            let mut diag = dcx.struct_allow(DiagnosticMessage::Str(String::new().into()));
+            let mut diag = dcx.struct_allow(DiagMessage::Str(String::new().into()));
             let message = self.diagnostic_message();
             self.add_args(&mut diag);
             let s = dcx.eagerly_translate_to_string(message, diag.args.iter());
@@ -457,7 +456,7 @@ fn bad_pointer_message(msg: CheckInAllocMsg, dcx: &DiagCtxt) -> String {
 }
 
 impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
-    fn diagnostic_message(&self) -> DiagnosticMessage {
+    fn diagnostic_message(&self) -> DiagMessage {
         use crate::fluent_generated::*;
         use UndefinedBehaviorInfo::*;
         match self {
@@ -595,7 +594,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
 }
 
 impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
-    fn diagnostic_message(&self) -> DiagnosticMessage {
+    fn diagnostic_message(&self) -> DiagMessage {
         use crate::fluent_generated::*;
         use rustc_middle::mir::interpret::ValidationErrorKind::*;
         match self.kind {
@@ -783,7 +782,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
 }
 
 impl ReportErrorExt for UnsupportedOpInfo {
-    fn diagnostic_message(&self) -> DiagnosticMessage {
+    fn diagnostic_message(&self) -> DiagMessage {
         use crate::fluent_generated::*;
         match self {
             UnsupportedOpInfo::Unsupported(s) => s.clone().into(),
@@ -819,7 +818,7 @@ impl ReportErrorExt for UnsupportedOpInfo {
 }
 
 impl<'tcx> ReportErrorExt for InterpError<'tcx> {
-    fn diagnostic_message(&self) -> DiagnosticMessage {
+    fn diagnostic_message(&self) -> DiagMessage {
         match self {
             InterpError::UndefinedBehavior(ub) => ub.diagnostic_message(),
             InterpError::Unsupported(e) => e.diagnostic_message(),
@@ -842,7 +841,7 @@ impl<'tcx> ReportErrorExt for InterpError<'tcx> {
 }
 
 impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> {
-    fn diagnostic_message(&self) -> DiagnosticMessage {
+    fn diagnostic_message(&self) -> DiagMessage {
         use crate::fluent_generated::*;
         match self {
             InvalidProgramInfo::TooGeneric => const_eval_too_generic,
@@ -877,7 +876,7 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> {
 }
 
 impl ReportErrorExt for ResourceExhaustionInfo {
-    fn diagnostic_message(&self) -> DiagnosticMessage {
+    fn diagnostic_message(&self) -> DiagMessage {
         use crate::fluent_generated::*;
         match self {
             ResourceExhaustionInfo::StackFrameLimitReached => const_eval_stack_frame_limit_reached,
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index a88e130cd4b..2cebea9d145 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -182,13 +182,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
         use rustc_type_ir::TyKind::*;
 
-        let val = match src.layout.ty.kind() {
-            // Floating point
-            Float(FloatTy::F32) => self.cast_from_float(src.to_scalar().to_f32()?, cast_to.ty),
-            Float(FloatTy::F64) => self.cast_from_float(src.to_scalar().to_f64()?, cast_to.ty),
-            _ => {
-                bug!("Can't cast 'Float' type into {}", cast_to.ty);
-            }
+        let Float(fty) = src.layout.ty.kind() else {
+            bug!("FloatToFloat/FloatToInt cast: source type {} is not a float type", src.layout.ty)
+        };
+        let val = match fty {
+            FloatTy::F16 => unimplemented!("f16_f128"),
+            FloatTy::F32 => self.cast_from_float(src.to_scalar().to_f32()?, cast_to.ty),
+            FloatTy::F64 => self.cast_from_float(src.to_scalar().to_f64()?, cast_to.ty),
+            FloatTy::F128 => unimplemented!("f16_f128"),
         };
         Ok(ImmTy::from_scalar(val, cast_to))
     }
@@ -275,6 +276,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         trace!("cast_from_scalar: {}, {} -> {}", v, src_layout.ty, cast_ty);
 
         Ok(match *cast_ty.kind() {
+            // int -> int
             Int(_) | Uint(_) => {
                 let size = match *cast_ty.kind() {
                     Int(t) => Integer::from_int_ty(self, t).size(),
@@ -285,15 +287,26 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 Scalar::from_uint(v, size)
             }
 
-            Float(FloatTy::F32) if signed => Scalar::from_f32(Single::from_i128(v as i128).value),
-            Float(FloatTy::F64) if signed => Scalar::from_f64(Double::from_i128(v as i128).value),
-            Float(FloatTy::F32) => Scalar::from_f32(Single::from_u128(v).value),
-            Float(FloatTy::F64) => Scalar::from_f64(Double::from_u128(v).value),
-
-            Char => {
-                // `u8` to `char` cast
-                Scalar::from_u32(u8::try_from(v).unwrap().into())
+            // signed int -> float
+            Float(fty) if signed => {
+                let v = v as i128;
+                match fty {
+                    FloatTy::F16 => unimplemented!("f16_f128"),
+                    FloatTy::F32 => Scalar::from_f32(Single::from_i128(v).value),
+                    FloatTy::F64 => Scalar::from_f64(Double::from_i128(v).value),
+                    FloatTy::F128 => unimplemented!("f16_f128"),
+                }
             }
+            // unsigned int -> float
+            Float(fty) => match fty {
+                FloatTy::F16 => unimplemented!("f16_f128"),
+                FloatTy::F32 => Scalar::from_f32(Single::from_u128(v).value),
+                FloatTy::F64 => Scalar::from_f64(Double::from_u128(v).value),
+                FloatTy::F128 => unimplemented!("f16_f128"),
+            },
+
+            // u8 -> char
+            Char => Scalar::from_u32(u8::try_from(v).unwrap().into()),
 
             // Casts to bool are not permitted by rustc, no need to handle them here.
             _ => span_bug!(self.cur_span(), "invalid int to {} cast", cast_ty),
@@ -339,14 +352,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let v = f.to_i128(size.bits_usize()).value;
                 Scalar::from_int(v, size)
             }
-            // float -> f32
-            Float(FloatTy::F32) => {
-                Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value))
-            }
-            // float -> f64
-            Float(FloatTy::F64) => {
-                Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value))
-            }
+            // float -> float
+            Float(fty) => match fty {
+                FloatTy::F16 => unimplemented!("f16_f128"),
+                FloatTy::F32 => Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value)),
+                FloatTy::F64 => Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value)),
+                FloatTy::F128 => unimplemented!("f16_f128"),
+            },
             // That's it.
             _ => span_bug!(self.cur_span(), "invalid float to {} cast", dest_ty),
         }
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index e951a77611c..6d4f6d0cb3c 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -10,6 +10,8 @@ use super::{ImmTy, InterpCx, InterpResult, Machine, Readable, Scalar, Writeable}
 
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Writes the discriminant of the given variant.
+    ///
+    /// If the variant is uninhabited, this is UB.
     #[instrument(skip(self), level = "trace")]
     pub fn write_discriminant(
         &mut self,
@@ -102,6 +104,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
     /// Read discriminant, return the runtime value as well as the variant index.
     /// Can also legally be called on non-enums (e.g. through the discriminant_value intrinsic)!
+    ///
+    /// Will never return an uninhabited variant.
     #[instrument(skip(self), level = "trace")]
     pub fn read_discriminant(
         &self,
@@ -244,7 +248,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 variant
             }
         };
-        // For consistency with `write_discriminant`, and to make sure that `project_downcast` cannot fail due to strange layouts, we declare immediate UB for uninhabited variants.
+        // Reading the discriminant of an uninhabited variant is UB. This is the basis for the
+        // `uninhabited_enum_branching` MIR pass. It also ensures consistency with
+        // `write_discriminant`.
         if op.layout().for_variant(self, index).abi.is_uninhabited() {
             throw_ub!(UninhabitedEnumVariantRead(index))
         }
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index cb308ab53ec..a484fbd892c 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -108,7 +108,7 @@ pub struct Frame<'mir, 'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> {
 
     /// The location where the result of the current stack frame should be written to,
     /// and its layout in the caller.
-    pub return_place: PlaceTy<'tcx, Prov>,
+    pub return_place: MPlaceTy<'tcx, Prov>,
 
     /// The list of locals for this stack frame, stored in order as
     /// `[return_ptr, arguments..., variables..., temporaries...]`.
@@ -771,7 +771,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         &mut self,
         instance: ty::Instance<'tcx>,
         body: &'mir mir::Body<'tcx>,
-        return_place: &PlaceTy<'tcx, M::Provenance>,
+        return_place: &MPlaceTy<'tcx, M::Provenance>,
         return_to_block: StackPopCleanup,
     ) -> InterpResult<'tcx> {
         trace!("body: {:#?}", body);
@@ -912,7 +912,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             } else {
                 self.copy_op_allow_transmute(&op, &dest)
             };
-            trace!("return value: {:?}", self.dump_place(&dest));
+            trace!("return value: {:?}", self.dump_place(&dest.into()));
             // We delay actually short-circuiting on this error until *after* the stack frame is
             // popped, since we want this error to be attributed to the caller, whose type defines
             // this transmute.
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 1cb991b38f7..b68bfb4211d 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -21,7 +21,7 @@ use rustc_span::symbol::{sym, Symbol};
 use rustc_target::abi::Size;
 
 use super::{
-    util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy,
+    util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, MPlaceTy, Machine, OpTy,
     Pointer,
 };
 
@@ -104,7 +104,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         &mut self,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx, M::Provenance>],
-        dest: &PlaceTy<'tcx, M::Provenance>,
+        dest: &MPlaceTy<'tcx, M::Provenance>,
         ret: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx, bool> {
         let instance_args = instance.args;
@@ -377,7 +377,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let index = u64::from(self.read_scalar(&args[1])?.to_u32()?);
                 let elem = &args[2];
                 let (input, input_len) = self.operand_to_simd(&args[0])?;
-                let (dest, dest_len) = self.place_to_simd(dest)?;
+                let (dest, dest_len) = self.mplace_to_simd(dest)?;
                 assert_eq!(input_len, dest_len, "Return vector length must match input length");
                 // Bounds are not checked by typeck so we have to do it ourselves.
                 if index >= input_len {
@@ -430,7 +430,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             _ => return Ok(false),
         }
 
-        trace!("{:?}", self.dump_place(dest));
+        trace!("{:?}", self.dump_place(&dest.clone().into()));
         self.go_to_block(ret);
         Ok(true)
     }
@@ -488,7 +488,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         &mut self,
         a: &ImmTy<'tcx, M::Provenance>,
         b: &ImmTy<'tcx, M::Provenance>,
-        dest: &PlaceTy<'tcx, M::Provenance>,
+        dest: &MPlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
         assert_eq!(a.layout.ty, b.layout.ty);
         assert!(matches!(a.layout.ty.kind(), ty::Int(..) | ty::Uint(..)));
@@ -506,7 +506,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             )
         }
         // `Rem` says this is all right, so we can let `Div` do its job.
-        self.binop_ignore_overflow(BinOp::Div, a, b, dest)
+        self.binop_ignore_overflow(BinOp::Div, a, b, &dest.clone().into())
     }
 
     pub fn saturating_arith(
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 0106ec425bc..90a654a1229 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -196,7 +196,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
         instance: ty::Instance<'tcx>,
         abi: CallAbi,
         args: &[FnArg<'tcx, Self::Provenance>],
-        destination: &PlaceTy<'tcx, Self::Provenance>,
+        destination: &MPlaceTy<'tcx, Self::Provenance>,
         target: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>>;
@@ -208,7 +208,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
         fn_val: Self::ExtraFnVal,
         abi: CallAbi,
         args: &[FnArg<'tcx, Self::Provenance>],
-        destination: &PlaceTy<'tcx, Self::Provenance>,
+        destination: &MPlaceTy<'tcx, Self::Provenance>,
         target: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx>;
@@ -219,7 +219,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx, Self::Provenance>],
-        destination: &PlaceTy<'tcx, Self::Provenance>,
+        destination: &MPlaceTy<'tcx, Self::Provenance>,
         target: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx>;
@@ -374,11 +374,17 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
         kind: Option<MemoryKind<Self::MemoryKind>>,
     ) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>>>;
 
+    /// Evaluate the inline assembly.
+    ///
+    /// This should take care of jumping to the next block (one of `targets`) when asm goto
+    /// is triggered, `targets[0]` when the assembly falls through, or diverge in case of
+    /// `InlineAsmOptions::NORETURN` being set.
     fn eval_inline_asm(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _template: &'tcx [InlineAsmTemplatePiece],
         _operands: &[mir::InlineAsmOperand<'tcx>],
         _options: InlineAsmOptions,
+        _targets: &[mir::BasicBlock],
     ) -> InterpResult<'tcx> {
         throw_unsup_format!("inline assembly is not supported")
     }
@@ -466,11 +472,11 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
     /// argument/return value was actually copied or passed in-place..
     fn protect_in_place_function_argument(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        place: &PlaceTy<'tcx, Self::Provenance>,
+        mplace: &MPlaceTy<'tcx, Self::Provenance>,
     ) -> InterpResult<'tcx> {
         // Without an aliasing model, all we can do is put `Uninit` into the place.
         // Conveniently this also ensures that the place actually points to suitable memory.
-        ecx.write_uninit(place)
+        ecx.write_uninit(mplace)
     }
 
     /// Called immediately before a new stack frame gets pushed.
@@ -584,7 +590,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
         fn_val: !,
         _abi: CallAbi,
         _args: &[FnArg<$tcx>],
-        _destination: &PlaceTy<$tcx, Self::Provenance>,
+        _destination: &MPlaceTy<$tcx, Self::Provenance>,
         _target: Option<mir::BasicBlock>,
         _unwind: mir::UnwindAction,
     ) -> InterpResult<$tcx> {
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 6e987784ff9..60f7710c11d 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -194,6 +194,12 @@ pub(super) enum Place<Prov: Provenance = CtfeProvenance> {
     Local { frame: usize, local: mir::Local, offset: Option<Size> },
 }
 
+/// An evaluated place, together with its type.
+///
+/// This may reference a stack frame by its index, so `PlaceTy` should generally not be kept around
+/// for longer than a single operation. Popping and then pushing a stack frame can make `PlaceTy`
+/// point to the wrong destination. If the interpreter has multiple stacks, stack switching will
+/// also invalidate a `PlaceTy`.
 #[derive(Clone)]
 pub struct PlaceTy<'tcx, Prov: Provenance = CtfeProvenance> {
     place: Place<Prov>, // Keep this private; it helps enforce invariants.
@@ -437,6 +443,7 @@ where
         trace!("deref to {} on {:?}", val.layout.ty, *val);
 
         if val.layout.ty.is_box() {
+            // Derefer should have removed all Box derefs
             bug!("dereferencing {}", val.layout.ty);
         }
 
@@ -494,16 +501,6 @@ where
         Ok((mplace, len))
     }
 
-    /// Converts a repr(simd) place into a place where `place_index` accesses the SIMD elements.
-    /// Also returns the number of elements.
-    pub fn place_to_simd(
-        &mut self,
-        place: &PlaceTy<'tcx, M::Provenance>,
-    ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::Provenance>, u64)> {
-        let mplace = self.force_allocation(place)?;
-        self.mplace_to_simd(&mplace)
-    }
-
     pub fn local_to_place(
         &self,
         frame: usize,
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index e72ace8be35..bafb8cb0018 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -1,6 +1,7 @@
 use std::borrow::Cow;
 
-use rustc_ast::ast::InlineAsmOptions;
+use either::Either;
+
 use rustc_middle::{
     mir,
     ty::{
@@ -30,14 +31,14 @@ pub enum FnArg<'tcx, Prov: Provenance = CtfeProvenance> {
     Copy(OpTy<'tcx, Prov>),
     /// Allow for the argument to be passed in-place: destroy the value originally stored at that place and
     /// make the place inaccessible for the duration of the function call.
-    InPlace(PlaceTy<'tcx, Prov>),
+    InPlace(MPlaceTy<'tcx, Prov>),
 }
 
 impl<'tcx, Prov: Provenance> FnArg<'tcx, Prov> {
     pub fn layout(&self) -> &TyAndLayout<'tcx> {
         match self {
             FnArg::Copy(op) => &op.layout,
-            FnArg::InPlace(place) => &place.layout,
+            FnArg::InPlace(mplace) => &mplace.layout,
         }
     }
 }
@@ -45,13 +46,10 @@ impl<'tcx, Prov: Provenance> FnArg<'tcx, Prov> {
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Make a copy of the given fn_arg. Any `InPlace` are degenerated to copies, no protection of the
     /// original memory occurs.
-    pub fn copy_fn_arg(
-        &self,
-        arg: &FnArg<'tcx, M::Provenance>,
-    ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
+    pub fn copy_fn_arg(&self, arg: &FnArg<'tcx, M::Provenance>) -> OpTy<'tcx, M::Provenance> {
         match arg {
-            FnArg::Copy(op) => Ok(op.clone()),
-            FnArg::InPlace(place) => self.place_to_op(place),
+            FnArg::Copy(op) => op.clone(),
+            FnArg::InPlace(mplace) => mplace.clone().into(),
         }
     }
 
@@ -60,7 +58,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     pub fn copy_fn_args(
         &self,
         args: &[FnArg<'tcx, M::Provenance>],
-    ) -> InterpResult<'tcx, Vec<OpTy<'tcx, M::Provenance>>> {
+    ) -> Vec<OpTy<'tcx, M::Provenance>> {
         args.iter().map(|fn_arg| self.copy_fn_arg(fn_arg)).collect()
     }
 
@@ -71,7 +69,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, FnArg<'tcx, M::Provenance>> {
         Ok(match arg {
             FnArg::Copy(op) => FnArg::Copy(self.project_field(op, field)?),
-            FnArg::InPlace(place) => FnArg::InPlace(self.project_field(place, field)?),
+            FnArg::InPlace(mplace) => FnArg::InPlace(self.project_field(mplace, field)?),
         })
     }
 
@@ -153,7 +151,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     ),
                 };
 
-                let destination = self.eval_place(destination)?;
+                let destination = self.force_allocation(&self.eval_place(destination)?)?;
                 self.eval_fn_call(
                     fn_val,
                     (fn_sig.abi, fn_abi),
@@ -224,15 +222,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 terminator.kind
             ),
 
-            InlineAsm { template, ref operands, options, destination, .. } => {
-                M::eval_inline_asm(self, template, operands, options)?;
-                if options.contains(InlineAsmOptions::NORETURN) {
-                    throw_ub_custom!(fluent::const_eval_noreturn_asm_returned);
-                }
-                self.go_to_block(
-                    destination
-                        .expect("InlineAsm terminators without noreturn must have a destination"),
-                )
+            InlineAsm { template, ref operands, options, ref targets, .. } => {
+                M::eval_inline_asm(self, template, operands, options, targets)?;
             }
         }
 
@@ -246,10 +237,36 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, Vec<FnArg<'tcx, M::Provenance>>> {
         ops.iter()
             .map(|op| {
-                Ok(match &op.node {
-                    mir::Operand::Move(place) => FnArg::InPlace(self.eval_place(*place)?),
-                    _ => FnArg::Copy(self.eval_operand(&op.node, None)?),
-                })
+                let arg = match &op.node {
+                    mir::Operand::Copy(_) | mir::Operand::Constant(_) => {
+                        // Make a regular copy.
+                        let op = self.eval_operand(&op.node, None)?;
+                        FnArg::Copy(op)
+                    }
+                    mir::Operand::Move(place) => {
+                        // If this place lives in memory, preserve its location.
+                        // We call `place_to_op` which will be an `MPlaceTy` whenever there exists
+                        // an mplace for this place. (This is in contrast to `PlaceTy::as_mplace_or_local`
+                        // which can return a local even if that has an mplace.)
+                        let place = self.eval_place(*place)?;
+                        let op = self.place_to_op(&place)?;
+
+                        match op.as_mplace_or_imm() {
+                            Either::Left(mplace) => FnArg::InPlace(mplace),
+                            Either::Right(_imm) => {
+                                // This argument doesn't live in memory, so there's no place
+                                // to make inaccessible during the call.
+                                // We rely on there not being any stray `PlaceTy` that would let the
+                                // caller directly access this local!
+                                // This is also crucial for tail calls, where we want the `FnArg` to
+                                // stay valid when the old stack frame gets popped.
+                                FnArg::Copy(op)
+                            }
+                        }
+                    }
+                };
+
+                Ok(arg)
             })
             .collect()
     }
@@ -359,14 +376,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             Ok(Some(match ty.kind() {
                 ty::Ref(_, ty, _) => *ty,
                 ty::RawPtr(mt) => mt.ty,
-                // We should only accept `Box` with the default allocator.
-                // It's hard to test for that though so we accept every 1-ZST allocator.
-                ty::Adt(def, args)
-                    if def.is_box()
-                        && self.layout_of(args[1].expect_ty()).is_ok_and(|l| l.is_1zst()) =>
-                {
-                    args[0].expect_ty()
-                }
+                // We only accept `Box` with the default allocator.
+                _ if ty.is_box_global(*self.tcx) => ty.boxed_ty(),
                 _ => return Ok(None),
             }))
         };
@@ -465,7 +476,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // We work with a copy of the argument for now; if this is in-place argument passing, we
         // will later protect the source it comes from. This means the callee cannot observe if we
         // did in-place of by-copy argument passing, except for pointer equality tests.
-        let caller_arg_copy = self.copy_fn_arg(caller_arg)?;
+        let caller_arg_copy = self.copy_fn_arg(caller_arg);
         if !already_live {
             let local = callee_arg.as_local().unwrap();
             let meta = caller_arg_copy.meta();
@@ -483,8 +494,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // specifically.)
         self.copy_op_allow_transmute(&caller_arg_copy, &callee_arg)?;
         // If this was an in-place pass, protect the place it comes from for the duration of the call.
-        if let FnArg::InPlace(place) = caller_arg {
-            M::protect_in_place_function_argument(self, place)?;
+        if let FnArg::InPlace(mplace) = caller_arg {
+            M::protect_in_place_function_argument(self, mplace)?;
         }
         Ok(())
     }
@@ -503,7 +514,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         (caller_abi, caller_fn_abi): (Abi, &FnAbi<'tcx, Ty<'tcx>>),
         args: &[FnArg<'tcx, M::Provenance>],
         with_caller_location: bool,
-        destination: &PlaceTy<'tcx, M::Provenance>,
+        destination: &MPlaceTy<'tcx, M::Provenance>,
         target: Option<mir::BasicBlock>,
         mut unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
@@ -531,7 +542,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 M::call_intrinsic(
                     self,
                     instance,
-                    &self.copy_fn_args(args)?,
+                    &self.copy_fn_args(args),
                     destination,
                     target,
                     unwind,
@@ -608,8 +619,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                             .map(|arg| (
                                 arg.layout().ty,
                                 match arg {
-                                    FnArg::Copy(op) => format!("copy({:?})", *op),
-                                    FnArg::InPlace(place) => format!("in-place({:?})", *place),
+                                    FnArg::Copy(op) => format!("copy({op:?})"),
+                                    FnArg::InPlace(mplace) => format!("in-place({mplace:?})"),
                                 }
                             ))
                             .collect::<Vec<_>>()
@@ -731,8 +742,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                             callee_ty: callee_fn_abi.ret.layout.ty
                         });
                     }
+
                     // Protect return place for in-place return value passing.
-                    M::protect_in_place_function_argument(self, destination)?;
+                    M::protect_in_place_function_argument(self, &destination)?;
 
                     // Don't forget to mark "initially live" locals as live.
                     self.storage_live_for_always_live_locals()?;
@@ -755,7 +767,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // An `InPlace` does nothing here, we keep the original receiver intact. We can't
                 // really pass the argument in-place anyway, and we are constructing a new
                 // `Immediate` receiver.
-                let mut receiver = self.copy_fn_arg(&args[0])?;
+                let mut receiver = self.copy_fn_arg(&args[0]);
                 let receiver_place = loop {
                     match receiver.layout.ty.kind() {
                         ty::Ref(..) | ty::RawPtr(..) => {
diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs
index 2a13671a829..3427368421f 100644
--- a/compiler/rustc_const_eval/src/interpret/util.rs
+++ b/compiler/rustc_const_eval/src/interpret/util.rs
@@ -30,9 +30,9 @@ where
     }
 
     impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedInstantiationVisitor<'tcx> {
-        type BreakTy = FoundParam;
+        type Result = ControlFlow<FoundParam>;
 
-        fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
             if !ty.has_param() {
                 return ControlFlow::Continue(());
             }
@@ -64,7 +64,7 @@ where
             }
         }
 
-        fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+        fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {
             match c.kind() {
                 ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam),
                 _ => c.super_visit_with(self),
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index c98dc4deb75..7ec78e7b9cf 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -17,7 +17,7 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
 use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor};
 
 use std::mem;
-use std::ops::{ControlFlow, Deref};
+use std::ops::Deref;
 
 use super::ops::{self, NonConstOp, Status};
 use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
@@ -164,9 +164,9 @@ struct LocalReturnTyVisitor<'ck, 'mir, 'tcx> {
 }
 
 impl<'ck, 'mir, 'tcx> TypeVisitor<TyCtxt<'tcx>> for LocalReturnTyVisitor<'ck, 'mir, 'tcx> {
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, t: Ty<'tcx>) {
         match t.kind() {
-            ty::FnPtr(_) => ControlFlow::Continue(()),
+            ty::FnPtr(_) => {}
             ty::Ref(_, _, hir::Mutability::Mut) => {
                 self.checker.check_op(ops::ty::MutRef(self.kind));
                 t.super_visit_with(self)
@@ -581,7 +581,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                 if is_int_bool_or_char(lhs_ty) && is_int_bool_or_char(rhs_ty) {
                     // Int, bool, and char operations are fine.
                 } else if lhs_ty.is_fn_ptr() || lhs_ty.is_unsafe_ptr() {
-                    assert_eq!(lhs_ty, rhs_ty);
                     assert!(matches!(
                         op,
                         BinOp::Eq
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 1107b894ab3..15720f25c5c 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -62,6 +62,7 @@ impl<'tcx> NonConstOp<'tcx> for FloatingPointOp {
         }
     }
 
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
         feature_err(
             &ccx.tcx.sess,
@@ -556,6 +557,7 @@ impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref {
         Status::Unstable(sym::const_mut_refs)
     }
 
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
         feature_err(
             &ccx.tcx.sess,
@@ -589,6 +591,7 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess {
         }
     }
 
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
         let mut err = feature_err(
             &ccx.tcx.sess,
@@ -632,6 +635,7 @@ pub mod ty {
             }
         }
 
+        #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
         fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
             feature_err(
                 &ccx.tcx.sess,
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index cc49e8ea247..74ba2f6039e 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -471,9 +471,9 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
                 self.check_edge(location, *real_target, EdgeKind::Normal);
                 self.check_unwind_edge(location, *unwind);
             }
-            TerminatorKind::InlineAsm { destination, unwind, .. } => {
-                if let Some(destination) = destination {
-                    self.check_edge(location, *destination, EdgeKind::Normal);
+            TerminatorKind::InlineAsm { targets, unwind, .. } => {
+                for &target in targets {
+                    self.check_edge(location, target, EdgeKind::Normal);
                 }
                 self.check_unwind_edge(location, *unwind);
             }
diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs
index 50a614a1b02..07a361ba260 100644
--- a/compiler/rustc_data_structures/src/sync/worker_local.rs
+++ b/compiler/rustc_data_structures/src/sync/worker_local.rs
@@ -42,7 +42,7 @@ pub struct Registry(Arc<RegistryData>);
 thread_local! {
     /// The registry associated with the thread.
     /// This allows the `WorkerLocal` type to clone the registry in its constructor.
-    static REGISTRY: OnceCell<Registry> = OnceCell::new();
+    static REGISTRY: OnceCell<Registry> = const { OnceCell::new() };
 }
 
 struct ThreadData {
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index 242aa06fe3e..fcc0afd3488 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -50,7 +50,7 @@ rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_ty_utils = { path = "../rustc_ty_utils" }
 serde_json = "1.0.59"
 shlex = "1.0"
-time = { version = "0.3", default-features = false, features = ["alloc", "formatting"] }
+time = { version = "0.3", default-features = false, features = ["alloc", "formatting", "parsing", "macros"] }
 tracing = { version = "0.1.35" }
 # tidy-alphabetical-end
 
diff --git a/compiler/rustc_driver_impl/messages.ftl b/compiler/rustc_driver_impl/messages.ftl
index 39462112dc2..1b69a6e2fbe 100644
--- a/compiler/rustc_driver_impl/messages.ftl
+++ b/compiler/rustc_driver_impl/messages.ftl
@@ -1,6 +1,10 @@
 driver_impl_ice = the compiler unexpectedly panicked. this is a bug.
 driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
 driver_impl_ice_bug_report_internal_feature = using internal features is not supported and expected to cause internal compiler errors when used incorrectly
+driver_impl_ice_bug_report_outdated =
+    it seems that this compiler `{$version}` is outdated, a newer nightly should have been released in the mean time
+    .update = please consider running `rustup update nightly` to update the nightly channel and check if this problem still persists
+    .url = if the problem still persists, we would appreciate a bug report: {$bug_report_url}
 driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
 
 driver_impl_ice_flags = compiler flags: {$flags}
diff --git a/compiler/rustc_driver_impl/src/args.rs b/compiler/rustc_driver_impl/src/args.rs
index 5dfd37a6da4..28574457389 100644
--- a/compiler/rustc_driver_impl/src/args.rs
+++ b/compiler/rustc_driver_impl/src/args.rs
@@ -1,9 +1,7 @@
-use std::error;
-use std::fmt;
-use std::fs;
-use std::io;
+use std::{env, error, fmt, fs, io};
 
 use rustc_session::EarlyDiagCtxt;
+use rustc_span::ErrorGuaranteed;
 
 /// Expands argfiles in command line arguments.
 #[derive(Default)]
@@ -86,7 +84,7 @@ impl Expander {
     fn read_file(path: &str) -> Result<String, Error> {
         fs::read_to_string(path).map_err(|e| {
             if e.kind() == io::ErrorKind::InvalidData {
-                Error::Utf8Error(Some(path.to_string()))
+                Error::Utf8Error(path.to_string())
             } else {
                 Error::IOError(path.to_string(), e)
             }
@@ -94,22 +92,53 @@ impl Expander {
     }
 }
 
+/// Replaces any `@file` arguments with the contents of `file`, with each line of `file` as a
+/// separate argument.
+///
 /// **Note:** This function doesn't interpret argument 0 in any special way.
 /// If this function is intended to be used with command line arguments,
 /// `argv[0]` must be removed prior to calling it manually.
-pub fn arg_expand_all(early_dcx: &EarlyDiagCtxt, at_args: &[String]) -> Vec<String> {
+#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
+pub fn arg_expand_all(
+    early_dcx: &EarlyDiagCtxt,
+    at_args: &[String],
+) -> Result<Vec<String>, ErrorGuaranteed> {
     let mut expander = Expander::default();
+    let mut result = Ok(());
     for arg in at_args {
         if let Err(err) = expander.arg(arg) {
-            early_dcx.early_fatal(format!("Failed to load argument file: {err}"));
+            result = Err(early_dcx.early_err(format!("failed to load argument file: {err}")));
         }
     }
-    expander.finish()
+    result.map(|()| expander.finish())
+}
+
+/// Gets the raw unprocessed command-line arguments as Unicode strings, without doing any further
+/// processing (e.g., without `@file` expansion).
+///
+/// This function is identical to [`env::args()`] except that it emits an error when it encounters
+/// non-Unicode arguments instead of panicking.
+pub fn raw_args(early_dcx: &EarlyDiagCtxt) -> Result<Vec<String>, ErrorGuaranteed> {
+    let mut res = Ok(Vec::new());
+    for (i, arg) in env::args_os().enumerate() {
+        match arg.into_string() {
+            Ok(arg) => {
+                if let Ok(args) = &mut res {
+                    args.push(arg);
+                }
+            }
+            Err(arg) => {
+                res =
+                    Err(early_dcx.early_err(format!("argument {i} is not valid Unicode: {arg:?}")))
+            }
+        }
+    }
+    res
 }
 
 #[derive(Debug)]
-pub enum Error {
-    Utf8Error(Option<String>),
+enum Error {
+    Utf8Error(String),
     IOError(String, io::Error),
     ShellParseError(String),
 }
@@ -117,10 +146,9 @@ pub enum Error {
 impl fmt::Display for Error {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
-            Error::Utf8Error(None) => write!(fmt, "Utf8 error"),
-            Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {path}"),
-            Error::IOError(path, err) => write!(fmt, "IO Error: {path}: {err}"),
-            Error::ShellParseError(path) => write!(fmt, "Invalid shell-style arguments in {path}"),
+            Error::Utf8Error(path) => write!(fmt, "UTF-8 error in {path}"),
+            Error::IOError(path, err) => write!(fmt, "IO error: {path}: {err}"),
+            Error::ShellParseError(path) => write!(fmt, "invalid shell-style arguments in {path}"),
         }
     }
 }
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 410e7eba30a..e06d1d245b2 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -4,6 +4,7 @@
 //!
 //! This API is completely unstable and subject to change.
 
+#![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(rustdoc_internals)]
@@ -58,7 +59,7 @@ use std::str;
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::{Arc, OnceLock};
 use std::time::{Instant, SystemTime};
-use time::OffsetDateTime;
+use time::{Date, OffsetDateTime, Time};
 
 #[allow(unused_macros)]
 macro do_not_use_print($($t:tt)*) {
@@ -291,7 +292,7 @@ fn run_compiler(
     // the compiler with @empty_file as argv[0] and no more arguments.
     let at_args = at_args.get(1..).unwrap_or_default();
 
-    let args = args::arg_expand_all(&default_early_dcx, at_args);
+    let args = args::arg_expand_all(&default_early_dcx, at_args)?;
 
     let Some(matches) = handle_options(&default_early_dcx, &args) else { return Ok(()) };
 
@@ -314,7 +315,7 @@ fn run_compiler(
         file_loader,
         locale_resources: DEFAULT_LOCALE_RESOURCES,
         lint_caps: Default::default(),
-        parse_sess_created: None,
+        psess_created: None,
         hash_untracked_state: None,
         register_lints: None,
         override_queries: None,
@@ -417,7 +418,7 @@ fn run_compiler(
             }
 
             // Make sure name resolution and macro expansion is run.
-            queries.global_ctxt()?.enter(|tcx| tcx.resolver_for_lowering(()));
+            queries.global_ctxt()?.enter(|tcx| tcx.resolver_for_lowering());
 
             if callbacks.after_expansion(compiler, queries) == Compilation::Stop {
                 return early_exit();
@@ -768,7 +769,7 @@ fn print_crate_info(
             }
             Cfg => {
                 let mut cfgs = sess
-                    .parse_sess
+                    .psess
                     .config
                     .iter()
                     .filter_map(|&(name, value)| {
@@ -1215,12 +1216,10 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option<geto
 
 fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
     match &sess.io.input {
-        Input::File(ifile) => rustc_parse::parse_crate_attrs_from_file(ifile, &sess.parse_sess),
-        Input::Str { name, input } => rustc_parse::parse_crate_attrs_from_source_str(
-            name.clone(),
-            input.clone(),
-            &sess.parse_sess,
-        ),
+        Input::File(ifile) => rustc_parse::parse_crate_attrs_from_file(ifile, &sess.psess),
+        Input::Str { name, input } => {
+            rustc_parse::parse_crate_attrs_from_source_str(name.clone(), input.clone(), &sess.psess)
+        }
     }
 }
 
@@ -1371,6 +1370,9 @@ pub fn install_ice_hook(
     using_internal_features
 }
 
+const DATE_FORMAT: &[time::format_description::FormatItem<'static>] =
+    &time::macros::format_description!("[year]-[month]-[day]");
+
 /// Prints the ICE message, including query stack, but without backtrace.
 ///
 /// The message will point the user at `bug_report_url` to report the ICE.
@@ -1399,10 +1401,34 @@ fn report_ice(
         dcx.emit_err(session_diagnostics::Ice);
     }
 
-    if using_internal_features.load(std::sync::atomic::Ordering::Relaxed) {
-        dcx.emit_note(session_diagnostics::IceBugReportInternalFeature);
+    use time::ext::NumericalDuration;
+
+    // Try to hint user to update nightly if applicable when reporting an ICE.
+    // Attempt to calculate when current version was released, and add 12 hours
+    // as buffer. If the current version's release timestamp is older than
+    // the system's current time + 24 hours + 12 hours buffer if we're on
+    // nightly.
+    if let Some("nightly") = option_env!("CFG_RELEASE_CHANNEL")
+        && let Some(version) = option_env!("CFG_VERSION")
+        && let Some(ver_date_str) = option_env!("CFG_VER_DATE")
+        && let Ok(ver_date) = Date::parse(&ver_date_str, DATE_FORMAT)
+        && let ver_datetime = OffsetDateTime::new_utc(ver_date, Time::MIDNIGHT)
+        && let system_datetime = OffsetDateTime::from(SystemTime::now())
+        && system_datetime.checked_sub(36.hours()).is_some_and(|d| d > ver_datetime)
+        && !using_internal_features.load(std::sync::atomic::Ordering::Relaxed)
+    {
+        dcx.emit_note(session_diagnostics::IceBugReportOutdated {
+            version,
+            bug_report_url,
+            note_update: (),
+            note_url: (),
+        });
     } else {
-        dcx.emit_note(session_diagnostics::IceBugReport { bug_report_url });
+        if using_internal_features.load(std::sync::atomic::Ordering::Relaxed) {
+            dcx.emit_note(session_diagnostics::IceBugReportInternalFeature);
+        } else {
+            dcx.emit_note(session_diagnostics::IceBugReport { bug_report_url });
+        }
     }
 
     let version = util::version_str!().unwrap_or("unknown_version");
@@ -1489,15 +1515,7 @@ pub fn main() -> ! {
     let mut callbacks = TimePassesCallbacks::default();
     let using_internal_features = install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ());
     let exit_code = catch_with_exit_code(|| {
-        let args = env::args_os()
-            .enumerate()
-            .map(|(i, arg)| {
-                arg.into_string().unwrap_or_else(|arg| {
-                    early_dcx.early_fatal(format!("argument {i} is not valid Unicode: {arg:?}"))
-                })
-            })
-            .collect::<Vec<_>>();
-        RunCompiler::new(&args, &mut callbacks)
+        RunCompiler::new(&args::raw_args(&early_dcx)?, &mut callbacks)
             .set_using_internal_features(using_internal_features)
             .run()
     });
diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index ff5ffd2454a..c9bbe45b212 100644
--- a/compiler/rustc_driver_impl/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -229,7 +229,7 @@ impl<'tcx> PrintExtra<'tcx> {
     {
         match self {
             PrintExtra::AfterParsing { krate, .. } => f(krate),
-            PrintExtra::NeedsAstMap { tcx } => f(&tcx.resolver_for_lowering(()).borrow().1),
+            PrintExtra::NeedsAstMap { tcx } => f(&tcx.resolver_for_lowering().borrow().1),
         }
     }
 
@@ -260,7 +260,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
                 ExpandedIdentified => Box::new(AstIdentifiedAnn),
                 ExpandedHygiene => Box::new(AstHygieneAnn { sess }),
             };
-            let parse = &sess.parse_sess;
+            let psess = &sess.psess;
             let is_expanded = ppm.needs_ast_map();
             ex.with_krate(|krate| {
                 pprust_ast::print_crate(
@@ -270,8 +270,8 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
                     src,
                     &*annotation,
                     is_expanded,
-                    parse.edition,
-                    &sess.parse_sess.attr_id_generator,
+                    psess.edition,
+                    &sess.psess.attr_id_generator,
                 )
             })
         }
@@ -281,7 +281,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
         }
         AstTreeExpanded => {
             debug!("pretty-printing expanded AST");
-            format!("{:#?}", ex.tcx().resolver_for_lowering(()).borrow().1)
+            format!("{:#?}", ex.tcx().resolver_for_lowering().borrow().1)
         }
         Hir(s) => {
             debug!("pretty printing HIR {:?}", s);
diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs
index 2b31fdd77cc..62d0da62d2a 100644
--- a/compiler/rustc_driver_impl/src/session_diagnostics.rs
+++ b/compiler/rustc_driver_impl/src/session_diagnostics.rs
@@ -46,6 +46,17 @@ pub(crate) struct IceBugReport<'a> {
 #[diag(driver_impl_ice_bug_report_internal_feature)]
 pub(crate) struct IceBugReportInternalFeature;
 
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice_bug_report_outdated)]
+pub(crate) struct IceBugReportOutdated<'a> {
+    pub version: &'a str,
+    pub bug_report_url: &'a str,
+    #[note(driver_impl_update)]
+    pub note_update: (),
+    #[note(driver_impl_url)]
+    pub note_url: (),
+}
+
 #[derive(Diagnostic)]
 #[diag(driver_impl_ice_version)]
 pub(crate) struct IceVersion<'a> {
diff --git a/compiler/rustc_error_codes/src/error_codes/E0657.md b/compiler/rustc_error_codes/src/error_codes/E0657.md
index 7fe48c51147..477d8e8bb6d 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0657.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0657.md
@@ -1,57 +1,26 @@
-A lifetime bound on a trait implementation was captured at an incorrect place.
+An `impl Trait` captured a higher-ranked lifetime, which is not supported.
+
+Currently, `impl Trait` types are only allowed to capture lifetimes from
+their parent items, and not from any `for<'a>` binders in scope.
 
 Erroneous code example:
 
 ```compile_fail,E0657
-trait Id<T> {}
-trait Lt<'a> {}
+trait BorrowInto<'a> {
+    type Target;
 
-impl<'a> Lt<'a> for () {}
-impl<T> Id<T> for T {}
-
-fn free_fn_capture_hrtb_in_impl_trait()
-    -> Box<for<'a> Id<impl Lt<'a>>> // error!
-{
-    Box::new(())
+    fn borrow_into(&'a self) -> Self::Target;
 }
 
-struct Foo;
-impl Foo {
-    fn impl_fn_capture_hrtb_in_impl_trait()
-        -> Box<for<'a> Id<impl Lt<'a>>> // error!
-    {
-        Box::new(())
+impl<'a> BorrowInto<'a> for () {
+    type Target = &'a ();
+
+    fn borrow_into(&'a self) -> Self::Target {
+        self
     }
 }
-```
 
-Here, you have used the inappropriate lifetime in the `impl Trait`,
-The `impl Trait` can only capture lifetimes bound at the fn or impl
-level.
-
-To fix this we have to define the lifetime at the function or impl
-level and use that lifetime in the `impl Trait`. For example you can
-define the lifetime at the function:
-
-```
-trait Id<T> {}
-trait Lt<'a> {}
-
-impl<'a> Lt<'a> for () {}
-impl<T> Id<T> for T {}
-
-fn free_fn_capture_hrtb_in_impl_trait<'b>()
-    -> Box<for<'a> Id<impl Lt<'b>>> // ok!
-{
-    Box::new(())
-}
-
-struct Foo;
-impl Foo {
-    fn impl_fn_capture_hrtb_in_impl_trait<'b>()
-        -> Box<for<'a> Id<impl Lt<'b>>> // ok!
-    {
-        Box::new(())
-    }
+fn opaque() -> impl for<'a> BorrowInto<'a, Target = impl Sized + 'a> {
+    ()
 }
 ```
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index f91b6655f63..ad82c2d96e7 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -253,11 +253,11 @@ type FluentId = Cow<'static, str>;
 /// translatable and non-translatable diagnostic messages.
 ///
 /// Translatable messages for subdiagnostics are typically attributes attached to a larger Fluent
-/// message so messages of this type must be combined with a `DiagnosticMessage` (using
-/// `DiagnosticMessage::with_subdiagnostic_message`) before rendering. However, subdiagnostics from
+/// message so messages of this type must be combined with a `DiagMessage` (using
+/// `DiagMessage::with_subdiagnostic_message`) before rendering. However, subdiagnostics from
 /// the `Subdiagnostic` derive refer to Fluent identifiers directly.
-#[rustc_diagnostic_item = "SubdiagnosticMessage"]
-pub enum SubdiagnosticMessage {
+#[rustc_diagnostic_item = "SubdiagMessage"]
+pub enum SubdiagMessage {
     /// Non-translatable diagnostic message.
     Str(Cow<'static, str>),
     /// Translatable message which has already been translated eagerly.
@@ -265,7 +265,7 @@ pub enum SubdiagnosticMessage {
     /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
     /// be instantiated multiple times with different values. These subdiagnostics' messages
     /// are translated when they are added to the parent diagnostic, producing this variant of
-    /// `DiagnosticMessage`.
+    /// `DiagMessage`.
     Translated(Cow<'static, str>),
     /// Identifier of a Fluent message. Instances of this variant are generated by the
     /// `Subdiagnostic` derive.
@@ -278,19 +278,19 @@ pub enum SubdiagnosticMessage {
     FluentAttr(FluentId),
 }
 
-impl From<String> for SubdiagnosticMessage {
+impl From<String> for SubdiagMessage {
     fn from(s: String) -> Self {
-        SubdiagnosticMessage::Str(Cow::Owned(s))
+        SubdiagMessage::Str(Cow::Owned(s))
     }
 }
-impl From<&'static str> for SubdiagnosticMessage {
+impl From<&'static str> for SubdiagMessage {
     fn from(s: &'static str) -> Self {
-        SubdiagnosticMessage::Str(Cow::Borrowed(s))
+        SubdiagMessage::Str(Cow::Borrowed(s))
     }
 }
-impl From<Cow<'static, str>> for SubdiagnosticMessage {
+impl From<Cow<'static, str>> for SubdiagMessage {
     fn from(s: Cow<'static, str>) -> Self {
-        SubdiagnosticMessage::Str(s)
+        SubdiagMessage::Str(s)
     }
 }
 
@@ -299,8 +299,8 @@ impl From<Cow<'static, str>> for SubdiagnosticMessage {
 ///
 /// Intended to be removed once diagnostics are entirely translatable.
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
-#[rustc_diagnostic_item = "DiagnosticMessage"]
-pub enum DiagnosticMessage {
+#[rustc_diagnostic_item = "DiagMessage"]
+pub enum DiagMessage {
     /// Non-translatable diagnostic message.
     Str(Cow<'static, str>),
     /// Translatable message which has been already translated.
@@ -308,7 +308,7 @@ pub enum DiagnosticMessage {
     /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
     /// be instantiated multiple times with different values. These subdiagnostics' messages
     /// are translated when they are added to the parent diagnostic, producing this variant of
-    /// `DiagnosticMessage`.
+    /// `DiagMessage`.
     Translated(Cow<'static, str>),
     /// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic
     /// message. Yet to be translated.
@@ -318,85 +318,80 @@ pub enum DiagnosticMessage {
     FluentIdentifier(FluentId, Option<FluentId>),
 }
 
-impl DiagnosticMessage {
-    /// Given a `SubdiagnosticMessage` which may contain a Fluent attribute, create a new
-    /// `DiagnosticMessage` that combines that attribute with the Fluent identifier of `self`.
+impl DiagMessage {
+    /// Given a `SubdiagMessage` which may contain a Fluent attribute, create a new
+    /// `DiagMessage` that combines that attribute with the Fluent identifier of `self`.
     ///
-    /// - If the `SubdiagnosticMessage` is non-translatable then return the message as a
-    /// `DiagnosticMessage`.
+    /// - If the `SubdiagMessage` is non-translatable then return the message as a `DiagMessage`.
     /// - If `self` is non-translatable then return `self`'s message.
-    pub fn with_subdiagnostic_message(&self, sub: SubdiagnosticMessage) -> Self {
+    pub fn with_subdiagnostic_message(&self, sub: SubdiagMessage) -> Self {
         let attr = match sub {
-            SubdiagnosticMessage::Str(s) => return DiagnosticMessage::Str(s),
-            SubdiagnosticMessage::Translated(s) => return DiagnosticMessage::Translated(s),
-            SubdiagnosticMessage::FluentIdentifier(id) => {
-                return DiagnosticMessage::FluentIdentifier(id, None);
+            SubdiagMessage::Str(s) => return DiagMessage::Str(s),
+            SubdiagMessage::Translated(s) => return DiagMessage::Translated(s),
+            SubdiagMessage::FluentIdentifier(id) => {
+                return DiagMessage::FluentIdentifier(id, None);
             }
-            SubdiagnosticMessage::FluentAttr(attr) => attr,
+            SubdiagMessage::FluentAttr(attr) => attr,
         };
 
         match self {
-            DiagnosticMessage::Str(s) => DiagnosticMessage::Str(s.clone()),
-            DiagnosticMessage::Translated(s) => DiagnosticMessage::Translated(s.clone()),
-            DiagnosticMessage::FluentIdentifier(id, _) => {
-                DiagnosticMessage::FluentIdentifier(id.clone(), Some(attr))
+            DiagMessage::Str(s) => DiagMessage::Str(s.clone()),
+            DiagMessage::Translated(s) => DiagMessage::Translated(s.clone()),
+            DiagMessage::FluentIdentifier(id, _) => {
+                DiagMessage::FluentIdentifier(id.clone(), Some(attr))
             }
         }
     }
 
     pub fn as_str(&self) -> Option<&str> {
         match self {
-            DiagnosticMessage::Translated(s) | DiagnosticMessage::Str(s) => Some(s),
-            DiagnosticMessage::FluentIdentifier(_, _) => None,
+            DiagMessage::Translated(s) | DiagMessage::Str(s) => Some(s),
+            DiagMessage::FluentIdentifier(_, _) => None,
         }
     }
 }
 
-impl From<String> for DiagnosticMessage {
+impl From<String> for DiagMessage {
     fn from(s: String) -> Self {
-        DiagnosticMessage::Str(Cow::Owned(s))
+        DiagMessage::Str(Cow::Owned(s))
     }
 }
-impl From<&'static str> for DiagnosticMessage {
+impl From<&'static str> for DiagMessage {
     fn from(s: &'static str) -> Self {
-        DiagnosticMessage::Str(Cow::Borrowed(s))
+        DiagMessage::Str(Cow::Borrowed(s))
     }
 }
-impl From<Cow<'static, str>> for DiagnosticMessage {
+impl From<Cow<'static, str>> for DiagMessage {
     fn from(s: Cow<'static, str>) -> Self {
-        DiagnosticMessage::Str(s)
+        DiagMessage::Str(s)
     }
 }
 
 /// A workaround for must_produce_diag ICEs when formatting types in disabled lints.
 ///
-/// Delays formatting until `.into(): DiagnosticMessage` is used.
+/// Delays formatting until `.into(): DiagMessage` is used.
 pub struct DelayDm<F>(pub F);
 
-impl<F: FnOnce() -> String> From<DelayDm<F>> for DiagnosticMessage {
+impl<F: FnOnce() -> String> From<DelayDm<F>> for DiagMessage {
     fn from(DelayDm(f): DelayDm<F>) -> Self {
-        DiagnosticMessage::from(f())
+        DiagMessage::from(f())
     }
 }
 
 /// Translating *into* a subdiagnostic message from a diagnostic message is a little strange - but
-/// the subdiagnostic functions (e.g. `span_label`) take a `SubdiagnosticMessage` and the
-/// subdiagnostic derive refers to typed identifiers that are `DiagnosticMessage`s, so need to be
-/// able to convert between these, as much as they'll be converted back into `DiagnosticMessage`
+/// the subdiagnostic functions (e.g. `span_label`) take a `SubdiagMessage` and the
+/// subdiagnostic derive refers to typed identifiers that are `DiagMessage`s, so need to be
+/// able to convert between these, as much as they'll be converted back into `DiagMessage`
 /// using `with_subdiagnostic_message` eventually. Don't use this other than for the derive.
-impl Into<SubdiagnosticMessage> for DiagnosticMessage {
-    fn into(self) -> SubdiagnosticMessage {
+impl Into<SubdiagMessage> for DiagMessage {
+    fn into(self) -> SubdiagMessage {
         match self {
-            DiagnosticMessage::Str(s) => SubdiagnosticMessage::Str(s),
-            DiagnosticMessage::Translated(s) => SubdiagnosticMessage::Translated(s),
-            DiagnosticMessage::FluentIdentifier(id, None) => {
-                SubdiagnosticMessage::FluentIdentifier(id)
-            }
+            DiagMessage::Str(s) => SubdiagMessage::Str(s),
+            DiagMessage::Translated(s) => SubdiagMessage::Translated(s),
+            DiagMessage::FluentIdentifier(id, None) => SubdiagMessage::FluentIdentifier(id),
             // There isn't really a sensible behaviour for this because it loses information but
             // this is the most sensible of the behaviours.
-            DiagnosticMessage::FluentIdentifier(_, Some(attr)) => {
-                SubdiagnosticMessage::FluentAttr(attr)
-            }
+            DiagMessage::FluentIdentifier(_, Some(attr)) => SubdiagMessage::FluentAttr(attr),
         }
     }
 }
@@ -412,7 +407,7 @@ pub struct SpanLabel {
     pub is_primary: bool,
 
     /// What label should we attach to this span (if any)?
-    pub label: Option<DiagnosticMessage>,
+    pub label: Option<DiagMessage>,
 }
 
 /// A collection of `Span`s.
@@ -426,7 +421,7 @@ pub struct SpanLabel {
 #[derive(Clone, Debug, Hash, PartialEq, Eq, Encodable, Decodable)]
 pub struct MultiSpan {
     primary_spans: Vec<Span>,
-    span_labels: Vec<(Span, DiagnosticMessage)>,
+    span_labels: Vec<(Span, DiagMessage)>,
 }
 
 impl MultiSpan {
@@ -444,7 +439,7 @@ impl MultiSpan {
         MultiSpan { primary_spans: vec, span_labels: vec![] }
     }
 
-    pub fn push_span_label(&mut self, span: Span, label: impl Into<DiagnosticMessage>) {
+    pub fn push_span_label(&mut self, span: Span, label: impl Into<DiagMessage>) {
         self.span_labels.push((span, label.into()));
     }
 
@@ -487,7 +482,7 @@ impl MultiSpan {
         replacements_occurred
     }
 
-    pub fn pop_span_label(&mut self) -> Option<(Span, DiagnosticMessage)> {
+    pub fn pop_span_label(&mut self) -> Option<(Span, DiagMessage)> {
         self.span_labels.pop()
     }
 
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
index e6668769b95..b71b93cc67c 100644
--- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
+++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
@@ -9,8 +9,8 @@ use crate::emitter::FileWithAnnotatedLines;
 use crate::snippet::Line;
 use crate::translation::{to_fluent_args, Translate};
 use crate::{
-    CodeSuggestion, DiagInner, DiagnosticMessage, Emitter, ErrCode, FluentBundle,
-    LazyFallbackBundle, Level, MultiSpan, Style, Subdiag,
+    CodeSuggestion, DiagInner, DiagMessage, Emitter, ErrCode, FluentBundle, LazyFallbackBundle,
+    Level, MultiSpan, Style, Subdiag,
 };
 use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation};
 use rustc_data_structures::sync::Lrc;
@@ -125,7 +125,7 @@ impl AnnotateSnippetEmitter {
     fn emit_messages_default(
         &mut self,
         level: &Level,
-        messages: &[(DiagnosticMessage, Style)],
+        messages: &[(DiagMessage, Style)],
         args: &FluentArgs<'_>,
         code: &Option<ErrCode>,
         msp: &MultiSpan,
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 1c820bfd01f..c186d5b284f 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -1,7 +1,7 @@
 use crate::snippet::Style;
 use crate::{
-    CodeSuggestion, DiagCtxt, DiagnosticMessage, ErrCode, ErrorGuaranteed, ExplicitBug, Level,
-    MultiSpan, StashKey, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
+    CodeSuggestion, DiagCtxt, DiagMessage, ErrCode, ErrorGuaranteed, ExplicitBug, Level, MultiSpan,
+    StashKey, SubdiagMessage, Substitution, SubstitutionPart, SuggestionStyle,
 };
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_error_messages::fluent_value_from_str_list_sep_by_and;
@@ -182,15 +182,14 @@ where
 
     /// Add a subdiagnostic to an existing diagnostic where `f` is invoked on every message used
     /// (to optionally perform eager translation).
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
     );
 }
 
-pub trait SubdiagnosticMessageOp<G> =
-    Fn(&mut Diag<'_, G>, SubdiagnosticMessage) -> SubdiagnosticMessage;
+pub trait SubdiagMessageOp<G> = Fn(&mut Diag<'_, G>, SubdiagMessage) -> SubdiagMessage;
 
 /// Trait implemented by lint types. This should not be implemented manually. Instead, use
 /// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic].
@@ -199,7 +198,7 @@ pub trait DecorateLint<'a, G: EmissionGuarantee> {
     /// Decorate and emit a lint.
     fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>);
 
-    fn msg(&self) -> DiagnosticMessage;
+    fn msg(&self) -> DiagMessage;
 }
 
 #[derive(Clone, Debug, Encodable, Decodable)]
@@ -291,7 +290,7 @@ pub struct DiagInner {
     // outside of what methods in this crate themselves allow.
     pub(crate) level: Level,
 
-    pub messages: Vec<(DiagnosticMessage, Style)>,
+    pub messages: Vec<(DiagMessage, Style)>,
     pub code: Option<ErrCode>,
     pub span: MultiSpan,
     pub children: Vec<Subdiag>,
@@ -312,12 +311,12 @@ pub struct DiagInner {
 
 impl DiagInner {
     #[track_caller]
-    pub fn new<M: Into<DiagnosticMessage>>(level: Level, message: M) -> Self {
+    pub fn new<M: Into<DiagMessage>>(level: Level, message: M) -> Self {
         DiagInner::new_with_messages(level, vec![(message.into(), Style::NoStyle)])
     }
 
     #[track_caller]
-    pub fn new_with_messages(level: Level, messages: Vec<(DiagnosticMessage, Style)>) -> Self {
+    pub fn new_with_messages(level: Level, messages: Vec<(DiagMessage, Style)>) -> Self {
         DiagInner {
             level,
             messages,
@@ -396,8 +395,8 @@ impl DiagInner {
     // See comment on `Diag::subdiagnostic_message_to_diagnostic_message`.
     pub(crate) fn subdiagnostic_message_to_diagnostic_message(
         &self,
-        attr: impl Into<SubdiagnosticMessage>,
-    ) -> DiagnosticMessage {
+        attr: impl Into<SubdiagMessage>,
+    ) -> DiagMessage {
         let msg =
             self.messages.iter().map(|(msg, _)| msg).next().expect("diagnostic with no messages");
         msg.with_subdiagnostic_message(attr.into())
@@ -406,7 +405,7 @@ impl DiagInner {
     pub(crate) fn sub(
         &mut self,
         level: Level,
-        message: impl Into<SubdiagnosticMessage>,
+        message: impl Into<SubdiagMessage>,
         span: MultiSpan,
     ) {
         let sub = Subdiag {
@@ -429,7 +428,7 @@ impl DiagInner {
         &self,
     ) -> (
         &Level,
-        &[(DiagnosticMessage, Style)],
+        &[(DiagMessage, Style)],
         &Option<ErrCode>,
         &MultiSpan,
         &[Subdiag],
@@ -472,7 +471,7 @@ impl PartialEq for DiagInner {
 #[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
 pub struct Subdiag {
     pub level: Level,
-    pub messages: Vec<(DiagnosticMessage, Style)>,
+    pub messages: Vec<(DiagMessage, Style)>,
     pub span: MultiSpan,
 }
 
@@ -578,7 +577,7 @@ macro_rules! with_fn {
 impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn new<M: Into<DiagnosticMessage>>(dcx: &'a DiagCtxt, level: Level, message: M) -> Self {
+    pub fn new(dcx: &'a DiagCtxt, level: Level, message: impl Into<DiagMessage>) -> Self {
         Self::new_diagnostic(dcx, DiagInner::new(level, message))
     }
 
@@ -599,6 +598,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     ///
     /// In the meantime, though, callsites are required to deal with the "bug"
     /// locally in whichever way makes the most sense.
+    #[rustc_lint_diagnostics]
     #[track_caller]
     pub fn downgrade_to_delayed_bug(&mut self) {
         assert!(
@@ -623,7 +623,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     /// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is
     /// primary.
     #[rustc_lint_diagnostics]
-    pub fn span_label(&mut self, span: Span, label: impl Into<SubdiagnosticMessage>) -> &mut Self {
+    pub fn span_label(&mut self, span: Span, label: impl Into<SubdiagMessage>) -> &mut Self {
         let msg = self.subdiagnostic_message_to_diagnostic_message(label);
         self.span.push_span_label(span, msg);
         self
@@ -632,6 +632,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     with_fn! { with_span_labels,
     /// Labels all the given spans with the provided label.
     /// See [`Self::span_label()`] for more information.
+    #[rustc_lint_diagnostics]
     pub fn span_labels(&mut self, spans: impl IntoIterator<Item = Span>, label: &str) -> &mut Self {
         for span in spans {
             self.span_label(span, label.to_string());
@@ -639,6 +640,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
         self
     } }
 
+    #[rustc_lint_diagnostics]
     pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self {
         let before = self.span.clone();
         self.span(after);
@@ -654,6 +656,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
         self
     }
 
+    #[rustc_lint_diagnostics]
     pub fn note_expected_found(
         &mut self,
         expected_label: &dyn fmt::Display,
@@ -664,6 +667,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
         self.note_expected_found_extra(expected_label, expected, found_label, found, &"", &"")
     }
 
+    #[rustc_lint_diagnostics]
     pub fn note_expected_found_extra(
         &mut self,
         expected_label: &dyn fmt::Display,
@@ -706,6 +710,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
         self
     }
 
+    #[rustc_lint_diagnostics]
     pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self {
         self.highlighted_note(vec![
             StringPart::normal(format!("`{name}` from trait: `")),
@@ -718,18 +723,20 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     with_fn! { with_note,
     /// Add a note attached to this diagnostic.
     #[rustc_lint_diagnostics]
-    pub fn note(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self {
+    pub fn note(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
         self.sub(Level::Note, msg, MultiSpan::new());
         self
     } }
 
+    #[rustc_lint_diagnostics]
     fn highlighted_note(&mut self, msg: Vec<StringPart>) -> &mut Self {
         self.sub_with_highlights(Level::Note, msg, MultiSpan::new());
         self
     }
 
     /// This is like [`Diag::note()`], but it's only printed once.
-    pub fn note_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self {
+    #[rustc_lint_diagnostics]
+    pub fn note_once(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
         self.sub(Level::OnceNote, msg, MultiSpan::new());
         self
     }
@@ -741,7 +748,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     pub fn span_note(
         &mut self,
         sp: impl Into<MultiSpan>,
-        msg: impl Into<SubdiagnosticMessage>,
+        msg: impl Into<SubdiagMessage>,
     ) -> &mut Self {
         self.sub(Level::Note, msg, sp.into());
         self
@@ -749,10 +756,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
 
     /// Prints the span with a note above it.
     /// This is like [`Diag::note_once()`], but it gets its own span.
+    #[rustc_lint_diagnostics]
     pub fn span_note_once<S: Into<MultiSpan>>(
         &mut self,
         sp: S,
-        msg: impl Into<SubdiagnosticMessage>,
+        msg: impl Into<SubdiagMessage>,
     ) -> &mut Self {
         self.sub(Level::OnceNote, msg, sp.into());
         self
@@ -761,7 +769,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     with_fn! { with_warn,
     /// Add a warning attached to this diagnostic.
     #[rustc_lint_diagnostics]
-    pub fn warn(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self {
+    pub fn warn(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
         self.sub(Level::Warning, msg, MultiSpan::new());
         self
     } }
@@ -772,7 +780,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     pub fn span_warn<S: Into<MultiSpan>>(
         &mut self,
         sp: S,
-        msg: impl Into<SubdiagnosticMessage>,
+        msg: impl Into<SubdiagMessage>,
     ) -> &mut Self {
         self.sub(Level::Warning, msg, sp.into());
         self
@@ -781,18 +789,20 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     with_fn! { with_help,
     /// Add a help message attached to this diagnostic.
     #[rustc_lint_diagnostics]
-    pub fn help(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self {
+    pub fn help(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
         self.sub(Level::Help, msg, MultiSpan::new());
         self
     } }
 
     /// This is like [`Diag::help()`], but it's only printed once.
-    pub fn help_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self {
+    #[rustc_lint_diagnostics]
+    pub fn help_once(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
         self.sub(Level::OnceHelp, msg, MultiSpan::new());
         self
     }
 
     /// Add a help message attached to this diagnostic with a customizable highlighted message.
+    #[rustc_lint_diagnostics]
     pub fn highlighted_help(&mut self, msg: Vec<StringPart>) -> &mut Self {
         self.sub_with_highlights(Level::Help, msg, MultiSpan::new());
         self
@@ -804,7 +814,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     pub fn span_help<S: Into<MultiSpan>>(
         &mut self,
         sp: S,
-        msg: impl Into<SubdiagnosticMessage>,
+        msg: impl Into<SubdiagMessage>,
     ) -> &mut Self {
         self.sub(Level::Help, msg, sp.into());
         self
@@ -813,12 +823,14 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     /// Disallow attaching suggestions this diagnostic.
     /// Any suggestions attached e.g. with the `span_suggestion_*` methods
     /// (before and after the call to `disable_suggestions`) will be ignored.
+    #[rustc_lint_diagnostics]
     pub fn disable_suggestions(&mut self) -> &mut Self {
         self.suggestions = Err(SuggestionsDisabled);
         self
     }
 
     /// Helper for pushing to `self.suggestions`, if available (not disable).
+    #[rustc_lint_diagnostics]
     fn push_suggestion(&mut self, suggestion: CodeSuggestion) {
         for subst in &suggestion.substitutions {
             for part in &subst.parts {
@@ -839,9 +851,10 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     with_fn! { with_multipart_suggestion,
     /// Show a suggestion that has multiple parts to it.
     /// In other words, multiple changes need to be applied as part of this suggestion.
+    #[rustc_lint_diagnostics]
     pub fn multipart_suggestion(
         &mut self,
-        msg: impl Into<SubdiagnosticMessage>,
+        msg: impl Into<SubdiagMessage>,
         suggestion: Vec<(Span, String)>,
         applicability: Applicability,
     ) -> &mut Self {
@@ -855,9 +868,10 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
 
     /// Show a suggestion that has multiple parts to it, always as it's own subdiagnostic.
     /// In other words, multiple changes need to be applied as part of this suggestion.
+    #[rustc_lint_diagnostics]
     pub fn multipart_suggestion_verbose(
         &mut self,
-        msg: impl Into<SubdiagnosticMessage>,
+        msg: impl Into<SubdiagMessage>,
         suggestion: Vec<(Span, String)>,
         applicability: Applicability,
     ) -> &mut Self {
@@ -870,9 +884,10 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     }
 
     /// [`Diag::multipart_suggestion()`] but you can set the [`SuggestionStyle`].
+    #[rustc_lint_diagnostics]
     pub fn multipart_suggestion_with_style(
         &mut self,
-        msg: impl Into<SubdiagnosticMessage>,
+        msg: impl Into<SubdiagMessage>,
         mut suggestion: Vec<(Span, String)>,
         applicability: Applicability,
         style: SuggestionStyle,
@@ -912,9 +927,10 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     /// be from the message, showing the span label inline would be visually unpleasant
     /// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't
     /// improve understandability.
+    #[rustc_lint_diagnostics]
     pub fn tool_only_multipart_suggestion(
         &mut self,
-        msg: impl Into<SubdiagnosticMessage>,
+        msg: impl Into<SubdiagMessage>,
         suggestion: Vec<(Span, String)>,
         applicability: Applicability,
     ) -> &mut Self {
@@ -944,10 +960,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     /// * may contain a name of a function, variable, or type, but not whole expressions
     ///
     /// See `CodeSuggestion` for more information.
+    #[rustc_lint_diagnostics]
     pub fn span_suggestion(
         &mut self,
         sp: Span,
-        msg: impl Into<SubdiagnosticMessage>,
+        msg: impl Into<SubdiagMessage>,
         suggestion: impl ToString,
         applicability: Applicability,
     ) -> &mut Self {
@@ -962,10 +979,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     } }
 
     /// [`Diag::span_suggestion()`] but you can set the [`SuggestionStyle`].
+    #[rustc_lint_diagnostics]
     pub fn span_suggestion_with_style(
         &mut self,
         sp: Span,
-        msg: impl Into<SubdiagnosticMessage>,
+        msg: impl Into<SubdiagMessage>,
         suggestion: impl ToString,
         applicability: Applicability,
         style: SuggestionStyle,
@@ -987,10 +1005,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
 
     with_fn! { with_span_suggestion_verbose,
     /// Always show the suggested change.
+    #[rustc_lint_diagnostics]
     pub fn span_suggestion_verbose(
         &mut self,
         sp: Span,
-        msg: impl Into<SubdiagnosticMessage>,
+        msg: impl Into<SubdiagMessage>,
         suggestion: impl ToString,
         applicability: Applicability,
     ) -> &mut Self {
@@ -1007,10 +1026,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     with_fn! { with_span_suggestions,
     /// Prints out a message with multiple suggested edits of the code.
     /// See also [`Diag::span_suggestion()`].
+    #[rustc_lint_diagnostics]
     pub fn span_suggestions(
         &mut self,
         sp: Span,
-        msg: impl Into<SubdiagnosticMessage>,
+        msg: impl Into<SubdiagMessage>,
         suggestions: impl IntoIterator<Item = String>,
         applicability: Applicability,
     ) -> &mut Self {
@@ -1023,10 +1043,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
         )
     } }
 
+    #[rustc_lint_diagnostics]
     pub fn span_suggestions_with_style(
         &mut self,
         sp: Span,
-        msg: impl Into<SubdiagnosticMessage>,
+        msg: impl Into<SubdiagMessage>,
         suggestions: impl IntoIterator<Item = String>,
         applicability: Applicability,
         style: SuggestionStyle,
@@ -1053,9 +1074,10 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     /// Prints out a message with multiple suggested edits of the code, where each edit consists of
     /// multiple parts.
     /// See also [`Diag::multipart_suggestion()`].
+    #[rustc_lint_diagnostics]
     pub fn multipart_suggestions(
         &mut self,
-        msg: impl Into<SubdiagnosticMessage>,
+        msg: impl Into<SubdiagMessage>,
         suggestions: impl IntoIterator<Item = Vec<(Span, String)>>,
         applicability: Applicability,
     ) -> &mut Self {
@@ -1099,10 +1121,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     /// inline, it will only show the message and not the suggestion.
     ///
     /// See `CodeSuggestion` for more information.
+    #[rustc_lint_diagnostics]
     pub fn span_suggestion_short(
         &mut self,
         sp: Span,
-        msg: impl Into<SubdiagnosticMessage>,
+        msg: impl Into<SubdiagMessage>,
         suggestion: impl ToString,
         applicability: Applicability,
     ) -> &mut Self {
@@ -1122,10 +1145,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     /// be from the message, showing the span label inline would be visually unpleasant
     /// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't
     /// improve understandability.
+    #[rustc_lint_diagnostics]
     pub fn span_suggestion_hidden(
         &mut self,
         sp: Span,
-        msg: impl Into<SubdiagnosticMessage>,
+        msg: impl Into<SubdiagMessage>,
         suggestion: impl ToString,
         applicability: Applicability,
     ) -> &mut Self {
@@ -1148,7 +1172,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     pub fn tool_only_span_suggestion(
         &mut self,
         sp: Span,
-        msg: impl Into<SubdiagnosticMessage>,
+        msg: impl Into<SubdiagMessage>,
         suggestion: impl ToString,
         applicability: Applicability,
     ) -> &mut Self {
@@ -1166,6 +1190,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     /// [rustc_macros::Subdiagnostic]). Performs eager translation of any translatable messages
     /// used in the subdiagnostic, so suitable for use with repeated messages (i.e. re-use of
     /// interpolated variables).
+    #[rustc_lint_diagnostics]
     pub fn subdiagnostic(
         &mut self,
         dcx: &crate::DiagCtxt,
@@ -1181,6 +1206,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
 
     with_fn! { with_span,
     /// Add a span.
+    #[rustc_lint_diagnostics]
     pub fn span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self {
         self.span = sp.into();
         if let Some(span) = self.span.primary_span() {
@@ -1189,6 +1215,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
         self
     } }
 
+    #[rustc_lint_diagnostics]
     pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self {
         self.is_lint = Some(IsLint { name, has_future_breakage });
         self
@@ -1196,6 +1223,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
 
     with_fn! { with_code,
     /// Add an error code.
+    #[rustc_lint_diagnostics]
     pub fn code(&mut self, code: ErrCode) -> &mut Self {
         self.code = Some(code);
         self
@@ -1203,13 +1231,15 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
 
     with_fn! { with_primary_message,
     /// Add a primary message.
-    pub fn primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self {
+    #[rustc_lint_diagnostics]
+    pub fn primary_message(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
         self.messages[0] = (msg.into(), Style::NoStyle);
         self
     } }
 
     with_fn! { with_arg,
     /// Add an argument.
+    #[rustc_lint_diagnostics]
     pub fn arg(
         &mut self,
         name: impl Into<DiagArgName>,
@@ -1219,13 +1249,13 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
         self
     } }
 
-    /// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by
+    /// Helper function that takes a `SubdiagMessage` and returns a `DiagMessage` by
     /// combining it with the primary message of the diagnostic (if translatable, otherwise it just
     /// passes the user's string along).
     pub(crate) fn subdiagnostic_message_to_diagnostic_message(
         &self,
-        attr: impl Into<SubdiagnosticMessage>,
-    ) -> DiagnosticMessage {
+        attr: impl Into<SubdiagMessage>,
+    ) -> DiagMessage {
         self.deref().subdiagnostic_message_to_diagnostic_message(attr)
     }
 
@@ -1233,7 +1263,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     /// public methods above.
     ///
     /// Used by `proc_macro_server` for implementing `server::Diagnostic`.
-    pub fn sub(&mut self, level: Level, message: impl Into<SubdiagnosticMessage>, span: MultiSpan) {
+    pub fn sub(&mut self, level: Level, message: impl Into<SubdiagMessage>, span: MultiSpan) {
         self.deref_mut().sub(level, message, span);
     }
 
@@ -1338,7 +1368,7 @@ impl<G: EmissionGuarantee> Drop for Diag<'_, G> {
             Some(diag) if !panicking() => {
                 self.dcx.emit_diagnostic(DiagInner::new(
                     Level::Bug,
-                    DiagnosticMessage::from("the following error was constructed but not emitted"),
+                    DiagMessage::from("the following error was constructed but not emitted"),
                 ));
                 self.dcx.emit_diagnostic(*diag);
                 panic!("error was constructed but not emitted");
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 70c8d971868..839bd65e4a6 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -2,7 +2,7 @@ use crate::diagnostic::DiagLocation;
 use crate::{fluent_generated as fluent, AddToDiagnostic};
 use crate::{
     Diag, DiagArgValue, DiagCtxt, EmissionGuarantee, ErrCode, IntoDiagnostic, IntoDiagnosticArg,
-    Level, SubdiagnosticMessageOp,
+    Level, SubdiagMessageOp,
 };
 use rustc_ast as ast;
 use rustc_ast_pretty::pprust;
@@ -298,7 +298,7 @@ pub struct SingleLabelManySpans {
     pub label: &'static str,
 }
 impl AddToDiagnostic for SingleLabelManySpans {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _: F,
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 5637c05d04c..57b8df52f4b 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -10,14 +10,13 @@
 use rustc_span::source_map::SourceMap;
 use rustc_span::{FileLines, FileName, SourceFile, Span};
 
-use crate::error::TranslateError;
 use crate::snippet::{
     Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString,
 };
 use crate::styled_buffer::StyledBuffer;
 use crate::translation::{to_fluent_args, Translate};
 use crate::{
-    diagnostic::DiagLocation, CodeSuggestion, DiagCtxt, DiagInner, DiagnosticMessage, ErrCode,
+    diagnostic::DiagLocation, CodeSuggestion, DiagCtxt, DiagInner, DiagMessage, ErrCode,
     FluentBundle, LazyFallbackBundle, Level, MultiSpan, Subdiag, SubstitutionHighlight,
     SuggestionStyle, TerminalUrl,
 };
@@ -339,7 +338,7 @@ pub trait Emitter: Translate {
 
                 children.push(Subdiag {
                     level: Level::Note,
-                    messages: vec![(DiagnosticMessage::from(msg), Style::NoStyle)],
+                    messages: vec![(DiagMessage::from(msg), Style::NoStyle)],
                     span: MultiSpan::new(),
                 });
             }
@@ -539,20 +538,9 @@ impl Emitter for HumanEmitter {
 /// Fatal diagnostics are forwarded to `fatal_dcx` to avoid silent
 /// failures of rustc, as witnessed e.g. in issue #89358.
 pub struct SilentEmitter {
+    pub fallback_bundle: LazyFallbackBundle,
     pub fatal_dcx: DiagCtxt,
-    pub fatal_note: String,
-}
-
-pub fn silent_translate<'a>(
-    message: &'a DiagnosticMessage,
-) -> Result<Cow<'_, str>, TranslateError<'_>> {
-    match message {
-        DiagnosticMessage::Str(msg) | DiagnosticMessage::Translated(msg) => Ok(Cow::Borrowed(msg)),
-        DiagnosticMessage::FluentIdentifier(identifier, _) => {
-            // Any value works here.
-            Ok(identifier.clone())
-        }
-    }
+    pub fatal_note: Option<String>,
 }
 
 impl Translate for SilentEmitter {
@@ -561,17 +549,9 @@ impl Translate for SilentEmitter {
     }
 
     fn fallback_fluent_bundle(&self) -> &FluentBundle {
-        panic!("silent emitter attempted to translate message")
-    }
-
-    // Override `translate_message` for the silent emitter because eager translation of
-    // subdiagnostics result in a call to this.
-    fn translate_message<'a>(
-        &'a self,
-        message: &'a DiagnosticMessage,
-        _: &'a FluentArgs<'_>,
-    ) -> Result<Cow<'_, str>, TranslateError<'_>> {
-        silent_translate(message)
+        // Ideally this field wouldn't be necessary and the fallback bundle in `fatal_dcx` would be
+        // used but the lock prevents this.
+        &self.fallback_bundle
     }
 }
 
@@ -582,7 +562,9 @@ impl Emitter for SilentEmitter {
 
     fn emit_diagnostic(&mut self, mut diag: DiagInner) {
         if diag.level == Level::Fatal {
-            diag.sub(Level::Note, self.fatal_note.clone(), MultiSpan::new());
+            if let Some(fatal_note) = &self.fatal_note {
+                diag.sub(Level::Note, fatal_note.clone(), MultiSpan::new());
+            }
             self.fatal_dcx.emit_diagnostic(diag);
         }
     }
@@ -1216,7 +1198,7 @@ impl HumanEmitter {
     fn msgs_to_buffer(
         &self,
         buffer: &mut StyledBuffer,
-        msgs: &[(DiagnosticMessage, Style)],
+        msgs: &[(DiagMessage, Style)],
         args: &FluentArgs<'_>,
         padding: usize,
         label: &str,
@@ -1291,7 +1273,7 @@ impl HumanEmitter {
     fn emit_messages_default_inner(
         &mut self,
         msp: &MultiSpan,
-        msgs: &[(DiagnosticMessage, Style)],
+        msgs: &[(DiagMessage, Style)],
         args: &FluentArgs<'_>,
         code: &Option<ErrCode>,
         level: &Level,
@@ -2060,7 +2042,7 @@ impl HumanEmitter {
     fn emit_messages_default(
         &mut self,
         level: &Level,
-        messages: &[(DiagnosticMessage, Style)],
+        messages: &[(DiagMessage, Style)],
         args: &FluentArgs<'_>,
         code: &Option<ErrCode>,
         span: &MultiSpan,
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 6b1ccbc5f7c..76b44f73f47 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -39,7 +39,7 @@ pub use codes::*;
 pub use diagnostic::{
     AddToDiagnostic, BugAbort, DecorateLint, Diag, DiagArg, DiagArgMap, DiagArgName, DiagArgValue,
     DiagInner, DiagStyledString, EmissionGuarantee, FatalAbort, IntoDiagnostic, IntoDiagnosticArg,
-    StringPart, Subdiag, SubdiagnosticMessageOp,
+    StringPart, Subdiag, SubdiagMessageOp,
 };
 pub use diagnostic_impls::{
     DiagArgFromDisplay, DiagSymbolList, ExpectedLifetimeParameter, IndicateAnonymousLifetime,
@@ -47,8 +47,8 @@ pub use diagnostic_impls::{
 };
 pub use emitter::ColorConfig;
 pub use rustc_error_messages::{
-    fallback_fluent_bundle, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle,
-    LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage,
+    fallback_fluent_bundle, fluent_bundle, DelayDm, DiagMessage, FluentBundle, LanguageIdentifier,
+    LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagMessage,
 };
 pub use rustc_lint_defs::{pluralize, Applicability};
 pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker};
@@ -63,7 +63,7 @@ use emitter::{is_case_difference, DynEmitter, Emitter};
 use registry::Registry;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::stable_hasher::{Hash128, StableHasher};
-use rustc_data_structures::sync::Lock;
+use rustc_data_structures::sync::{Lock, Lrc};
 use rustc_data_structures::AtomicRef;
 use rustc_lint_defs::LintExpectationId;
 use rustc_span::source_map::SourceMap;
@@ -154,7 +154,7 @@ pub struct CodeSuggestion {
     /// ]
     /// ```
     pub substitutions: Vec<Substitution>,
-    pub msg: DiagnosticMessage,
+    pub msg: DiagMessage,
     /// Visual representation of this suggestion.
     pub style: SuggestionStyle,
     /// Whether or not the suggestion is approximate
@@ -606,37 +606,62 @@ impl DiagCtxt {
     }
 
     pub fn new(emitter: Box<DynEmitter>) -> Self {
-        Self {
-            inner: Lock::new(DiagCtxtInner {
-                flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
-                err_guars: Vec::new(),
-                lint_err_guars: Vec::new(),
-                delayed_bugs: Vec::new(),
-                deduplicated_err_count: 0,
-                deduplicated_warn_count: 0,
-                emitter,
-                must_produce_diag: false,
-                has_printed: false,
-                suppressed_expected_diag: false,
-                taught_diagnostics: Default::default(),
-                emitted_diagnostic_codes: Default::default(),
-                emitted_diagnostics: Default::default(),
-                stashed_diagnostics: Default::default(),
-                future_breakage_diagnostics: Vec::new(),
-                check_unstable_expect_diagnostics: false,
-                unstable_expect_diagnostics: Vec::new(),
-                fulfilled_expectations: Default::default(),
-                ice_file: None,
-            }),
-        }
+        Self { inner: Lock::new(DiagCtxtInner::new(emitter)) }
     }
 
-    /// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`.
+    pub fn make_silent(&mut self, fallback_bundle: LazyFallbackBundle, fatal_note: Option<String>) {
+        self.wrap_emitter(|old_dcx| {
+            Box::new(emitter::SilentEmitter {
+                fallback_bundle,
+                fatal_dcx: DiagCtxt { inner: Lock::new(old_dcx) },
+                fatal_note,
+            })
+        });
+    }
+
+    fn wrap_emitter<F>(&mut self, f: F)
+    where
+        F: FnOnce(DiagCtxtInner) -> Box<DynEmitter>,
+    {
+        // A empty type that implements `Emitter` so that a `DiagCtxtInner` can be constructed
+        // to temporarily swap in place of the real one, which will be used in constructing
+        // its replacement.
+        struct FalseEmitter;
+
+        impl Emitter for FalseEmitter {
+            fn emit_diagnostic(&mut self, _: DiagInner) {
+                unimplemented!("false emitter must only used during `wrap_emitter`")
+            }
+
+            fn source_map(&self) -> Option<&Lrc<SourceMap>> {
+                unimplemented!("false emitter must only used during `wrap_emitter`")
+            }
+        }
+
+        impl translation::Translate for FalseEmitter {
+            fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
+                unimplemented!("false emitter must only used during `wrap_emitter`")
+            }
+
+            fn fallback_fluent_bundle(&self) -> &FluentBundle {
+                unimplemented!("false emitter must only used during `wrap_emitter`")
+            }
+        }
+
+        let mut inner = self.inner.borrow_mut();
+        let mut prev_dcx = DiagCtxtInner::new(Box::new(FalseEmitter));
+        std::mem::swap(&mut *inner, &mut prev_dcx);
+        let new_emitter = f(prev_dcx);
+        let mut new_dcx = DiagCtxtInner::new(new_emitter);
+        std::mem::swap(&mut *inner, &mut new_dcx);
+    }
+
+    /// Translate `message` eagerly with `args` to `SubdiagMessage::Eager`.
     pub fn eagerly_translate<'a>(
         &self,
-        message: DiagnosticMessage,
+        message: DiagMessage,
         args: impl Iterator<Item = DiagArg<'a>>,
-    ) -> SubdiagnosticMessage {
+    ) -> SubdiagMessage {
         let inner = self.inner.borrow();
         inner.eagerly_translate(message, args)
     }
@@ -644,7 +669,7 @@ impl DiagCtxt {
     /// Translate `message` eagerly with `args` to `String`.
     pub fn eagerly_translate_to_string<'a>(
         &self,
-        message: DiagnosticMessage,
+        message: DiagMessage,
         args: impl Iterator<Item = DiagArg<'a>>,
     ) -> String {
         let inner = self.inner.borrow();
@@ -904,7 +929,7 @@ impl DiagCtxt {
                 // configuration like `--cap-lints allow --force-warn bare_trait_objects`.
                 inner.emit_diagnostic(DiagInner::new(
                     ForceWarning(None),
-                    DiagnosticMessage::Str(warnings),
+                    DiagMessage::Str(warnings),
                 ));
             }
             (_, 0) => {
@@ -1076,32 +1101,36 @@ impl DiagCtxt {
 // Functions beginning with `struct_`/`create_` create a diagnostic. Other
 // functions create and emit a diagnostic all in one go.
 impl DiagCtxt {
-    // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing.
+    // No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't
+    // user-facing.
     #[track_caller]
-    pub fn struct_bug(&self, msg: impl Into<DiagnosticMessage>) -> Diag<'_, BugAbort> {
-        Diag::new(self, Bug, msg)
+    pub fn struct_bug(&self, msg: impl Into<Cow<'static, str>>) -> Diag<'_, BugAbort> {
+        Diag::new(self, Bug, msg.into())
     }
 
-    // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing.
+    // No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't
+    // user-facing.
     #[track_caller]
-    pub fn bug(&self, msg: impl Into<DiagnosticMessage>) -> ! {
+    pub fn bug(&self, msg: impl Into<Cow<'static, str>>) -> ! {
         self.struct_bug(msg).emit()
     }
 
-    // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing.
+    // No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't
+    // user-facing.
     #[track_caller]
     pub fn struct_span_bug(
         &self,
         span: impl Into<MultiSpan>,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<Cow<'static, str>>,
     ) -> Diag<'_, BugAbort> {
         self.struct_bug(msg).with_span(span)
     }
 
-    // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing.
+    // No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't
+    // user-facing.
     #[track_caller]
-    pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! {
-        self.struct_span_bug(span, msg).emit()
+    pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<Cow<'static, str>>) -> ! {
+        self.struct_span_bug(span, msg.into()).emit()
     }
 
     #[track_caller]
@@ -1116,13 +1145,13 @@ impl DiagCtxt {
 
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> Diag<'_, FatalAbort> {
+    pub fn struct_fatal(&self, msg: impl Into<DiagMessage>) -> Diag<'_, FatalAbort> {
         Diag::new(self, Fatal, msg)
     }
 
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn fatal(&self, msg: impl Into<DiagnosticMessage>) -> ! {
+    pub fn fatal(&self, msg: impl Into<DiagMessage>) -> ! {
         self.struct_fatal(msg).emit()
     }
 
@@ -1131,14 +1160,14 @@ impl DiagCtxt {
     pub fn struct_span_fatal(
         &self,
         span: impl Into<MultiSpan>,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
     ) -> Diag<'_, FatalAbort> {
         self.struct_fatal(msg).with_span(span)
     }
 
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn span_fatal(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! {
+    pub fn span_fatal(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) -> ! {
         self.struct_span_fatal(span, msg).emit()
     }
 
@@ -1174,13 +1203,13 @@ impl DiagCtxt {
     // FIXME: This method should be removed (every error should have an associated error code).
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn struct_err(&self, msg: impl Into<DiagnosticMessage>) -> Diag<'_> {
+    pub fn struct_err(&self, msg: impl Into<DiagMessage>) -> Diag<'_> {
         Diag::new(self, Error, msg)
     }
 
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
+    pub fn err(&self, msg: impl Into<DiagMessage>) -> ErrorGuaranteed {
         self.struct_err(msg).emit()
     }
 
@@ -1189,7 +1218,7 @@ impl DiagCtxt {
     pub fn struct_span_err(
         &self,
         span: impl Into<MultiSpan>,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
     ) -> Diag<'_> {
         self.struct_err(msg).with_span(span)
     }
@@ -1199,7 +1228,7 @@ impl DiagCtxt {
     pub fn span_err(
         &self,
         span: impl Into<MultiSpan>,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
     ) -> ErrorGuaranteed {
         self.struct_span_err(span, msg).emit()
     }
@@ -1215,35 +1244,39 @@ impl DiagCtxt {
     }
 
     /// Ensures that an error is printed. See `Level::DelayedBug`.
-    // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing.
+    //
+    // No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't
+    // user-facing.
     #[track_caller]
-    pub fn delayed_bug(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
-        Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg).emit()
+    pub fn delayed_bug(&self, msg: impl Into<Cow<'static, str>>) -> ErrorGuaranteed {
+        Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).emit()
     }
 
     /// Ensures that an error is printed. See `Level::DelayedBug`.
     ///
     /// Note: this function used to be called `delay_span_bug`. It was renamed
     /// to match similar functions like `span_err`, `span_warn`, etc.
-    // No `#[rustc_lint_diagnostics]` because bug messages aren't user-facing.
+    //
+    // No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't
+    // user-facing.
     #[track_caller]
     pub fn span_delayed_bug(
         &self,
         sp: impl Into<MultiSpan>,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<Cow<'static, str>>,
     ) -> ErrorGuaranteed {
-        Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg).with_span(sp).emit()
+        Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).with_span(sp).emit()
     }
 
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> Diag<'_, ()> {
+    pub fn struct_warn(&self, msg: impl Into<DiagMessage>) -> Diag<'_, ()> {
         Diag::new(self, Warning, msg)
     }
 
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn warn(&self, msg: impl Into<DiagnosticMessage>) {
+    pub fn warn(&self, msg: impl Into<DiagMessage>) {
         self.struct_warn(msg).emit()
     }
 
@@ -1252,14 +1285,14 @@ impl DiagCtxt {
     pub fn struct_span_warn(
         &self,
         span: impl Into<MultiSpan>,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
     ) -> Diag<'_, ()> {
         self.struct_warn(msg).with_span(span)
     }
 
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn span_warn(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) {
+    pub fn span_warn(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
         self.struct_span_warn(span, msg).emit()
     }
 
@@ -1275,13 +1308,13 @@ impl DiagCtxt {
 
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn struct_note(&self, msg: impl Into<DiagnosticMessage>) -> Diag<'_, ()> {
+    pub fn struct_note(&self, msg: impl Into<DiagMessage>) -> Diag<'_, ()> {
         Diag::new(self, Note, msg)
     }
 
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn note(&self, msg: impl Into<DiagnosticMessage>) {
+    pub fn note(&self, msg: impl Into<DiagMessage>) {
         self.struct_note(msg).emit()
     }
 
@@ -1290,14 +1323,14 @@ impl DiagCtxt {
     pub fn struct_span_note(
         &self,
         span: impl Into<MultiSpan>,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
     ) -> Diag<'_, ()> {
         self.struct_note(msg).with_span(span)
     }
 
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn span_note(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) {
+    pub fn span_note(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
         self.struct_span_note(span, msg).emit()
     }
 
@@ -1313,19 +1346,19 @@ impl DiagCtxt {
 
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn struct_help(&self, msg: impl Into<DiagnosticMessage>) -> Diag<'_, ()> {
+    pub fn struct_help(&self, msg: impl Into<DiagMessage>) -> Diag<'_, ()> {
         Diag::new(self, Help, msg)
     }
 
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn struct_failure_note(&self, msg: impl Into<DiagnosticMessage>) -> Diag<'_, ()> {
+    pub fn struct_failure_note(&self, msg: impl Into<DiagMessage>) -> Diag<'_, ()> {
         Diag::new(self, FailureNote, msg)
     }
 
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> Diag<'_, ()> {
+    pub fn struct_allow(&self, msg: impl Into<DiagMessage>) -> Diag<'_, ()> {
         Diag::new(self, Allow, msg)
     }
 
@@ -1333,7 +1366,7 @@ impl DiagCtxt {
     #[track_caller]
     pub fn struct_expect(
         &self,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
         id: LintExpectationId,
     ) -> Diag<'_, ()> {
         Diag::new(self, Expect(id), msg)
@@ -1345,6 +1378,30 @@ impl DiagCtxt {
 // `DiagCtxt::foo()` just borrows `inner` and forwards a call to
 // `DiagCtxtInner::foo`.
 impl DiagCtxtInner {
+    fn new(emitter: Box<DynEmitter>) -> Self {
+        Self {
+            flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
+            err_guars: Vec::new(),
+            lint_err_guars: Vec::new(),
+            delayed_bugs: Vec::new(),
+            deduplicated_err_count: 0,
+            deduplicated_warn_count: 0,
+            emitter,
+            must_produce_diag: false,
+            has_printed: false,
+            suppressed_expected_diag: false,
+            taught_diagnostics: Default::default(),
+            emitted_diagnostic_codes: Default::default(),
+            emitted_diagnostics: Default::default(),
+            stashed_diagnostics: Default::default(),
+            future_breakage_diagnostics: Vec::new(),
+            check_unstable_expect_diagnostics: false,
+            unstable_expect_diagnostics: Vec::new(),
+            fulfilled_expectations: Default::default(),
+            ice_file: None,
+        }
+    }
+
     /// Emit all stashed diagnostics.
     fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
         let mut guar = None;
@@ -1553,19 +1610,19 @@ impl DiagCtxtInner {
         self.has_errors().or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
     }
 
-    /// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`.
+    /// Translate `message` eagerly with `args` to `SubdiagMessage::Eager`.
     pub fn eagerly_translate<'a>(
         &self,
-        message: DiagnosticMessage,
+        message: DiagMessage,
         args: impl Iterator<Item = DiagArg<'a>>,
-    ) -> SubdiagnosticMessage {
-        SubdiagnosticMessage::Translated(Cow::from(self.eagerly_translate_to_string(message, args)))
+    ) -> SubdiagMessage {
+        SubdiagMessage::Translated(Cow::from(self.eagerly_translate_to_string(message, args)))
     }
 
     /// Translate `message` eagerly with `args` to `String`.
     pub fn eagerly_translate_to_string<'a>(
         &self,
-        message: DiagnosticMessage,
+        message: DiagMessage,
         args: impl Iterator<Item = DiagArg<'a>>,
     ) -> String {
         let args = crate::translation::to_fluent_args(args);
@@ -1575,8 +1632,8 @@ impl DiagCtxtInner {
     fn eagerly_translate_for_subdiag(
         &self,
         diag: &DiagInner,
-        msg: impl Into<SubdiagnosticMessage>,
-    ) -> SubdiagnosticMessage {
+        msg: impl Into<SubdiagMessage>,
+    ) -> SubdiagMessage {
         let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
         self.eagerly_translate(msg, diag.args.iter())
     }
diff --git a/compiler/rustc_errors/src/markdown/term.rs b/compiler/rustc_errors/src/markdown/term.rs
index 88c3c8b9ff2..06c1333d93d 100644
--- a/compiler/rustc_errors/src/markdown/term.rs
+++ b/compiler/rustc_errors/src/markdown/term.rs
@@ -9,9 +9,9 @@ const DEFAULT_COLUMN_WIDTH: usize = 140;
 
 thread_local! {
     /// Track the position of viewable characters in our buffer
-    static CURSOR: Cell<usize> = Cell::new(0);
+    static CURSOR: Cell<usize> = const { Cell::new(0) };
     /// Width of the terminal
-    static WIDTH: Cell<usize> = Cell::new(DEFAULT_COLUMN_WIDTH);
+    static WIDTH: Cell<usize> = const { Cell::new(DEFAULT_COLUMN_WIDTH) };
 }
 
 /// Print to terminal output to a buffer
diff --git a/compiler/rustc_errors/src/tests.rs b/compiler/rustc_errors/src/tests.rs
index 79a2af7f38f..50d58aec36a 100644
--- a/compiler/rustc_errors/src/tests.rs
+++ b/compiler/rustc_errors/src/tests.rs
@@ -5,7 +5,7 @@ use crate::FluentBundle;
 use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
 use rustc_error_messages::fluent_bundle::resolver::errors::{ReferenceKind, ResolverError};
 use rustc_error_messages::langid;
-use rustc_error_messages::DiagnosticMessage;
+use rustc_error_messages::DiagMessage;
 
 struct Dummy {
     bundle: FluentBundle,
@@ -53,7 +53,7 @@ fn wellformed_fluent() {
     args.set("name", "Foo");
     args.set("ty", "std::string::String");
     {
-        let message = DiagnosticMessage::FluentIdentifier(
+        let message = DiagMessage::FluentIdentifier(
             "mir_build_borrow_of_moved_value".into(),
             Some("suggestion".into()),
         );
@@ -65,7 +65,7 @@ fn wellformed_fluent() {
     }
 
     {
-        let message = DiagnosticMessage::FluentIdentifier(
+        let message = DiagMessage::FluentIdentifier(
             "mir_build_borrow_of_moved_value".into(),
             Some("value_borrowed_label".into()),
         );
@@ -77,7 +77,7 @@ fn wellformed_fluent() {
     }
 
     {
-        let message = DiagnosticMessage::FluentIdentifier(
+        let message = DiagMessage::FluentIdentifier(
             "mir_build_borrow_of_moved_value".into(),
             Some("occurs_because_label".into()),
         );
@@ -88,7 +88,7 @@ fn wellformed_fluent() {
         );
 
         {
-            let message = DiagnosticMessage::FluentIdentifier(
+            let message = DiagMessage::FluentIdentifier(
                 "mir_build_borrow_of_moved_value".into(),
                 Some("label".into()),
             );
@@ -112,7 +112,7 @@ fn misformed_fluent() {
     args.set("name", "Foo");
     args.set("ty", "std::string::String");
     {
-        let message = DiagnosticMessage::FluentIdentifier(
+        let message = DiagMessage::FluentIdentifier(
             "mir_build_borrow_of_moved_value".into(),
             Some("value_borrowed_label".into()),
         );
@@ -141,7 +141,7 @@ fn misformed_fluent() {
     }
 
     {
-        let message = DiagnosticMessage::FluentIdentifier(
+        let message = DiagMessage::FluentIdentifier(
             "mir_build_borrow_of_moved_value".into(),
             Some("label".into()),
         );
@@ -168,7 +168,7 @@ fn misformed_fluent() {
     }
 
     {
-        let message = DiagnosticMessage::FluentIdentifier(
+        let message = DiagMessage::FluentIdentifier(
             "mir_build_borrow_of_moved_value".into(),
             Some("occurs_because_label".into()),
         );
diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs
index 1f98ba4c3b9..bf0026568ce 100644
--- a/compiler/rustc_errors/src/translation.rs
+++ b/compiler/rustc_errors/src/translation.rs
@@ -1,6 +1,6 @@
 use crate::error::{TranslateError, TranslateErrorKind};
 use crate::snippet::Style;
-use crate::{DiagArg, DiagnosticMessage, FluentBundle};
+use crate::{DiagArg, DiagMessage, FluentBundle};
 use rustc_data_structures::sync::Lrc;
 pub use rustc_error_messages::FluentArgs;
 use std::borrow::Cow;
@@ -37,10 +37,10 @@ pub trait Translate {
     /// unavailable for the requested locale.
     fn fallback_fluent_bundle(&self) -> &FluentBundle;
 
-    /// Convert `DiagnosticMessage`s to a string, performing translation if necessary.
+    /// Convert `DiagMessage`s to a string, performing translation if necessary.
     fn translate_messages(
         &self,
-        messages: &[(DiagnosticMessage, Style)],
+        messages: &[(DiagMessage, Style)],
         args: &FluentArgs<'_>,
     ) -> Cow<'_, str> {
         Cow::Owned(
@@ -51,18 +51,18 @@ pub trait Translate {
         )
     }
 
-    /// Convert a `DiagnosticMessage` to a string, performing translation if necessary.
+    /// Convert a `DiagMessage` to a string, performing translation if necessary.
     fn translate_message<'a>(
         &'a self,
-        message: &'a DiagnosticMessage,
+        message: &'a DiagMessage,
         args: &'a FluentArgs<'_>,
     ) -> Result<Cow<'_, str>, TranslateError<'_>> {
         trace!(?message, ?args);
         let (identifier, attr) = match message {
-            DiagnosticMessage::Str(msg) | DiagnosticMessage::Translated(msg) => {
+            DiagMessage::Str(msg) | DiagMessage::Translated(msg) => {
                 return Ok(Cow::Borrowed(msg));
             }
-            DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
+            DiagMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
         };
         let translate_with_bundle =
             |bundle: &'a FluentBundle| -> Result<Cow<'_, str>, TranslateError<'_>> {
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 485f0e7e46d..69dfb48919c 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -4,7 +4,6 @@ use crate::expand::{self, AstFragment, Invocation};
 use crate::module::DirOwnership;
 
 use rustc_ast::attr::MarkedAttrs;
-use rustc_ast::mut_visit::DummyAstNode;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Nonterminal};
 use rustc_ast::tokenstream::TokenStream;
@@ -16,7 +15,7 @@ use rustc_data_structures::sync::{self, Lrc};
 use rustc_errors::{Applicability, Diag, DiagCtxt, ErrorGuaranteed, PResult};
 use rustc_feature::Features;
 use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
-use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, RegisteredTools};
+use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, RegisteredTools};
 use rustc_parse::{parser, MACRO_ARGUMENTS};
 use rustc_session::config::CollapseMacroDebuginfo;
 use rustc_session::errors::report_lit_error;
@@ -582,6 +581,17 @@ impl DummyResult {
             tokens: None,
         })
     }
+
+    /// A plain dummy crate.
+    pub fn raw_crate() -> ast::Crate {
+        ast::Crate {
+            attrs: Default::default(),
+            items: Default::default(),
+            spans: Default::default(),
+            id: ast::DUMMY_NODE_ID,
+            is_placeholder: Default::default(),
+        }
+    }
 }
 
 impl MacResult for DummyResult {
@@ -650,7 +660,7 @@ impl MacResult for DummyResult {
     }
 
     fn make_crate(self: Box<DummyResult>) -> Option<ast::Crate> {
-        Some(DummyAstNode::dummy())
+        Some(DummyResult::raw_crate())
     }
 }
 
@@ -1135,13 +1145,13 @@ impl<'a> ExtCtxt<'a> {
         expand::MacroExpander::new(self, true)
     }
     pub fn new_parser_from_tts(&self, stream: TokenStream) -> parser::Parser<'a> {
-        rustc_parse::stream_to_parser(&self.sess.parse_sess, stream, MACRO_ARGUMENTS)
+        rustc_parse::stream_to_parser(&self.sess.psess, stream, MACRO_ARGUMENTS)
     }
     pub fn source_map(&self) -> &'a SourceMap {
-        self.sess.parse_sess.source_map()
+        self.sess.psess.source_map()
     }
-    pub fn parse_sess(&self) -> &'a ParseSess {
-        &self.sess.parse_sess
+    pub fn psess(&self) -> &'a ParseSess {
+        &self.sess.psess
     }
     pub fn call_site(&self) -> Span {
         self.current_expansion.id.expn_data().call_site
@@ -1216,26 +1226,22 @@ impl<'a> ExtCtxt<'a> {
 /// Resolves a `path` mentioned inside Rust code, returning an absolute path.
 ///
 /// This unifies the logic used for resolving `include_X!`.
-pub fn resolve_path(
-    parse_sess: &Session,
-    path: impl Into<PathBuf>,
-    span: Span,
-) -> PResult<'_, PathBuf> {
+pub fn resolve_path(sess: &Session, path: impl Into<PathBuf>, span: Span) -> PResult<'_, PathBuf> {
     let path = path.into();
 
     // Relative paths are resolved relative to the file in which they are found
     // after macro expansion (that is, they are unhygienic).
     if !path.is_absolute() {
         let callsite = span.source_callsite();
-        let mut result = match parse_sess.source_map().span_to_filename(callsite) {
+        let mut result = match sess.source_map().span_to_filename(callsite) {
             FileName::Real(name) => name
                 .into_local_path()
                 .expect("attempting to resolve a file path in an external file"),
             FileName::DocTest(path, _) => path,
             other => {
-                return Err(parse_sess.dcx().create_err(errors::ResolveRelativePath {
+                return Err(sess.dcx().create_err(errors::ResolveRelativePath {
                     span,
-                    path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(),
+                    path: sess.source_map().filename_for_diagnostics(&other).to_string(),
                 }));
             }
         };
@@ -1281,7 +1287,7 @@ pub fn expr_to_spanned_string<'a>(
                 Ok((err, true))
             }
             Ok(ast::LitKind::Err(guar)) => Err(guar),
-            Err(err) => Err(report_lit_error(&cx.sess.parse_sess, err, token_lit, expr.span)),
+            Err(err) => Err(report_lit_error(&cx.sess.psess, err, token_lit, expr.span)),
             _ => Ok((cx.dcx().struct_span_err(expr.span, err_msg), false)),
         },
         ast::ExprKind::Err(guar) => Err(guar),
@@ -1487,12 +1493,14 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) -> bool {
                             };
 
                             if crate_matches {
-                                sess.parse_sess.buffer_lint_with_diagnostic(
+                                // FIXME: make this translatable
+                                #[allow(rustc::untranslatable_diagnostic)]
+                                sess.psess.buffer_lint_with_diagnostic(
                                         PROC_MACRO_BACK_COMPAT,
                                         item.ident.span,
                                         ast::CRATE_NODE_ID,
                                         "using an old version of `rental`",
-                                        BuiltinLintDiagnostics::ProcMacroBackCompat(
+                                        BuiltinLintDiag::ProcMacroBackCompat(
                                         "older versions of the `rental` crate will stop compiling in future versions of Rust; \
                                         please update to `rental` v0.5.6, or switch to one of the `rental` alternatives".to_string()
                                         )
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index 9ce2084c847..989b7b485c9 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -665,7 +665,7 @@ impl<'a> ExtCtxt<'a> {
 
     // Builds `#[name]`.
     pub fn attr_word(&self, name: Symbol, span: Span) -> ast::Attribute {
-        let g = &self.sess.parse_sess.attr_id_generator;
+        let g = &self.sess.psess.attr_id_generator;
         attr::mk_attr_word(g, ast::AttrStyle::Outer, name, span)
     }
 
@@ -673,13 +673,13 @@ impl<'a> ExtCtxt<'a> {
     //
     // Note: `span` is used for both the identifier and the value.
     pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute {
-        let g = &self.sess.parse_sess.attr_id_generator;
+        let g = &self.sess.psess.attr_id_generator;
         attr::mk_attr_name_value_str(g, ast::AttrStyle::Outer, name, val, span)
     }
 
     // Builds `#[outer(inner)]`.
     pub fn attr_nested_word(&self, outer: Symbol, inner: Symbol, span: Span) -> ast::Attribute {
-        let g = &self.sess.parse_sess.attr_id_generator;
+        let g = &self.sess.psess.attr_id_generator;
         attr::mk_attr_nested_word(g, ast::AttrStyle::Outer, outer, inner, span)
     }
 }
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 435135d1959..c95d7cdeb73 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -239,16 +239,17 @@ impl<'a> StripUnconfigured<'a> {
     /// Gives a compiler warning when the `cfg_attr` contains no attributes and
     /// is in the original source file. Gives a compiler error if the syntax of
     /// the attribute is incorrect.
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     pub(crate) fn expand_cfg_attr(&self, attr: &Attribute, recursive: bool) -> Vec<Attribute> {
         let Some((cfg_predicate, expanded_attrs)) =
-            rustc_parse::parse_cfg_attr(attr, &self.sess.parse_sess)
+            rustc_parse::parse_cfg_attr(attr, &self.sess.psess)
         else {
             return vec![];
         };
 
         // Lint on zero attributes in source.
         if expanded_attrs.is_empty() {
-            self.sess.parse_sess.buffer_lint(
+            self.sess.psess.buffer_lint(
                 rustc_lint_defs::builtin::UNUSED_ATTRIBUTES,
                 attr.span,
                 ast::CRATE_NODE_ID,
@@ -273,6 +274,7 @@ impl<'a> StripUnconfigured<'a> {
         }
     }
 
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn expand_cfg_attr_item(
         &self,
         attr: &Attribute,
@@ -324,14 +326,14 @@ impl<'a> StripUnconfigured<'a> {
         };
         let tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::new(trees)));
         let attr = attr::mk_attr_from_item(
-            &self.sess.parse_sess.attr_id_generator,
+            &self.sess.psess.attr_id_generator,
             item,
             tokens,
             attr.style,
             item_span,
         );
         if attr.has_name(sym::crate_type) {
-            self.sess.parse_sess.buffer_lint(
+            self.sess.psess.buffer_lint(
                 rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
                 attr.span,
                 ast::CRATE_NODE_ID,
@@ -339,7 +341,7 @@ impl<'a> StripUnconfigured<'a> {
             );
         }
         if attr.has_name(sym::crate_name) {
-            self.sess.parse_sess.buffer_lint(
+            self.sess.psess.buffer_lint(
                 rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
                 attr.span,
                 ast::CRATE_NODE_ID,
@@ -355,7 +357,7 @@ impl<'a> StripUnconfigured<'a> {
     }
 
     pub(crate) fn cfg_true(&self, attr: &Attribute) -> (bool, Option<MetaItem>) {
-        let meta_item = match validate_attr::parse_meta(&self.sess.parse_sess, attr) {
+        let meta_item = match validate_attr::parse_meta(&self.sess.psess, attr) {
             Ok(meta_item) => meta_item,
             Err(err) => {
                 err.emit();
@@ -371,6 +373,7 @@ impl<'a> StripUnconfigured<'a> {
     }
 
     /// If attributes are not allowed on expressions, emit an error for `attr`
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     #[instrument(level = "trace", skip(self))]
     pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
         if self.features.is_some_and(|features| !features.stmt_expr_attributes)
@@ -384,7 +387,6 @@ impl<'a> StripUnconfigured<'a> {
             );
 
             if attr.is_doc_comment() {
-                #[allow(rustc::untranslatable_diagnostic)]
                 err.help("`///` is for documentation comments. For a plain comment, use `//`.");
             }
 
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 9bc7b4bdd1e..fcc439e71f9 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -14,8 +14,7 @@ use rustc_ast::mut_visit::*;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter};
 use rustc_ast::tokenstream::TokenStream;
-use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult};
-use rustc_ast::{try_visit, walk_list};
+use rustc_ast::visit::{self, try_visit, walk_list, AssocCtxt, Visitor, VisitorResult};
 use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, ExprKind};
 use rustc_ast::{ForeignItemKind, HasAttrs, HasNodeId};
 use rustc_ast::{Inline, ItemKind, MacStmtStyle, MetaItemKind, ModKind};
@@ -30,7 +29,7 @@ use rustc_parse::parser::{
 };
 use rustc_parse::validate_attr;
 use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
-use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::parse::feature_err;
 use rustc_session::{Limit, Session};
 use rustc_span::symbol::{sym, Ident};
@@ -691,10 +690,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                         // fixed prior to stabilization
                         // Fake tokens when we are invoking an inner attribute, and
                         // we are invoking it on an out-of-line module or crate.
-                        Annotatable::Crate(krate) => rustc_parse::fake_token_stream_for_crate(
-                            &self.cx.sess.parse_sess,
-                            krate,
-                        ),
+                        Annotatable::Crate(krate) => {
+                            rustc_parse::fake_token_stream_for_crate(&self.cx.sess.psess, krate)
+                        }
                         Annotatable::Item(item_inner)
                             if matches!(attr.style, AttrStyle::Inner)
                                 && matches!(
@@ -705,10 +703,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                                     )
                                 ) =>
                         {
-                            rustc_parse::fake_token_stream_for_item(
-                                &self.cx.sess.parse_sess,
-                                item_inner,
-                            )
+                            rustc_parse::fake_token_stream_for_item(&self.cx.sess.psess, item_inner)
                         }
                         _ => item.to_tokens(),
                     };
@@ -728,7 +723,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                     }
                 }
                 SyntaxExtensionKind::LegacyAttr(expander) => {
-                    match validate_attr::parse_meta(&self.cx.sess.parse_sess, &attr) {
+                    match validate_attr::parse_meta(&self.cx.sess.psess, &attr) {
                         Ok(meta) => {
                             let items = match expander.expand(self.cx, span, &meta, item, false) {
                                 ExpandResult::Ready(items) => items,
@@ -788,6 +783,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         })
     }
 
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
         let kind = match item {
             Annotatable::Item(_)
@@ -830,6 +826,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         }
 
         impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
+            #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
             fn visit_item(&mut self, item: &'ast ast::Item) {
                 match &item.kind {
                     ItemKind::Mod(_, mod_kind)
@@ -962,8 +959,8 @@ pub fn ensure_complete_parse<'a>(
         // Avoid emitting backtrace info twice.
         let def_site_span = parser.token.span.with_ctxt(SyntaxContext::root());
 
-        let semi_span = parser.sess.source_map().next_point(span);
-        let add_semicolon = match &parser.sess.source_map().span_to_snippet(semi_span) {
+        let semi_span = parser.psess.source_map().next_point(span);
+        let add_semicolon = match &parser.psess.source_map().span_to_snippet(semi_span) {
             Ok(snippet) if &snippet[..] != ";" && kind_name == "expression" => {
                 Some(span.shrink_to_hi())
             }
@@ -1694,13 +1691,14 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
 
     // Detect use of feature-gated or invalid attributes on macro invocations
     // since they will not be detected after macro expansion.
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall) {
         let features = self.cx.ecfg.features;
         let mut attrs = attrs.iter().peekable();
         let mut span: Option<Span> = None;
         while let Some(attr) = attrs.next() {
             rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features);
-            validate_attr::check_attr(&self.cx.sess.parse_sess, attr);
+            validate_attr::check_attr(&self.cx.sess.psess, attr);
 
             let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
             span = Some(current_span);
@@ -1710,24 +1708,24 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
             }
 
             if attr.is_doc_comment() {
-                self.cx.sess.parse_sess.buffer_lint_with_diagnostic(
+                self.cx.sess.psess.buffer_lint_with_diagnostic(
                     UNUSED_DOC_COMMENTS,
                     current_span,
                     self.cx.current_expansion.lint_node_id,
                     "unused doc comment",
-                    BuiltinLintDiagnostics::UnusedDocComment(attr.span),
+                    BuiltinLintDiag::UnusedDocComment(attr.span),
                 );
             } else if rustc_attr::is_builtin_attr(attr) {
                 let attr_name = attr.ident().unwrap().name;
                 // `#[cfg]` and `#[cfg_attr]` are special - they are
                 // eagerly evaluated.
                 if attr_name != sym::cfg && attr_name != sym::cfg_attr {
-                    self.cx.sess.parse_sess.buffer_lint_with_diagnostic(
+                    self.cx.sess.psess.buffer_lint_with_diagnostic(
                         UNUSED_ATTRIBUTES,
                         attr.span,
                         self.cx.current_expansion.lint_node_id,
                         format!("unused attribute `{attr_name}`"),
-                        BuiltinLintDiagnostics::UnusedBuiltinAttribute {
+                        BuiltinLintDiag::UnusedBuiltinAttribute {
                             attr_name,
                             macro_name: pprust::path_to_string(&call.path),
                             invoc_span: call.path.span,
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index 0e73abc9ed8..e550f7242c3 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -5,6 +5,7 @@
 #![feature(associated_type_defaults)]
 #![feature(if_let_guard)]
 #![feature(let_chains)]
+#![feature(lint_reasons)]
 #![feature(macro_metavar_expr)]
 #![feature(map_try_insert)]
 #![feature(proc_macro_diagnostic)]
diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs
index 053063b690e..15193298cca 100644
--- a/compiler/rustc_expand/src/mbe/diagnostics.rs
+++ b/compiler/rustc_expand/src/mbe/diagnostics.rs
@@ -7,7 +7,7 @@ use crate::mbe::{
 use rustc_ast::token::{self, Token, TokenKind};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast_pretty::pprust;
-use rustc_errors::{Applicability, Diag, DiagCtxt, DiagnosticMessage};
+use rustc_errors::{Applicability, Diag, DiagCtxt, DiagMessage};
 use rustc_parse::parser::{Parser, Recovery};
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Ident;
@@ -24,12 +24,12 @@ pub(super) fn failed_to_match_macro<'cx>(
     arg: TokenStream,
     lhses: &[Vec<MatcherLoc>],
 ) -> Box<dyn MacResult + 'cx> {
-    let sess = &cx.sess.parse_sess;
+    let psess = &cx.sess.psess;
 
     // An error occurred, try the expansion again, tracking the expansion closely for better diagnostics.
     let mut tracker = CollectTrackerAndEmitter::new(cx, sp);
 
-    let try_success_result = try_match_macro(sess, name, &arg, lhses, &mut tracker);
+    let try_success_result = try_match_macro(psess, name, &arg, lhses, &mut tracker);
 
     if try_success_result.is_ok() {
         // Nonterminal parser recovery might turn failed matches into successful ones,
@@ -58,7 +58,7 @@ pub(super) fn failed_to_match_macro<'cx>(
         err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro");
     }
 
-    annotate_doc_comment(cx.sess.dcx(), &mut err, sess.source_map(), span);
+    annotate_doc_comment(cx.sess.dcx(), &mut err, psess.source_map(), span);
 
     if let Some(span) = remaining_matcher.span() {
         err.span_note(span, format!("while trying to match {remaining_matcher}"));
@@ -87,7 +87,7 @@ pub(super) fn failed_to_match_macro<'cx>(
     // Check whether there's a missing comma in this macro call, like `println!("{}" a);`
     if let Some((arg, comma_span)) = arg.add_comma() {
         for lhs in lhses {
-            let parser = parser_from_cx(sess, arg.clone(), Recovery::Allowed);
+            let parser = parser_from_cx(psess, arg.clone(), Recovery::Allowed);
             let mut tt_parser = TtParser::new(name);
 
             if let Success(_) =
@@ -227,12 +227,12 @@ pub(super) fn emit_frag_parse_err(
 ) -> ErrorGuaranteed {
     // FIXME(davidtwco): avoid depending on the error message text
     if parser.token == token::Eof
-        && let DiagnosticMessage::Str(message) = &e.messages[0].0
+        && let DiagMessage::Str(message) = &e.messages[0].0
         && message.ends_with(", found `<eof>`")
     {
         let msg = &e.messages[0];
         e.messages[0] = (
-            DiagnosticMessage::from(format!(
+            DiagMessage::from(format!(
                 "macro expansion ends with an incomplete expression: {}",
                 message.replace(", found `<eof>`", ""),
             )),
@@ -246,10 +246,10 @@ pub(super) fn emit_frag_parse_err(
     if e.span.is_dummy() {
         // Get around lack of span in error (#30128)
         e.replace_span_with(site_span, true);
-        if !parser.sess.source_map().is_imported(arm_span) {
+        if !parser.psess.source_map().is_imported(arm_span) {
             e.span_label(arm_span, "in this macro arm");
         }
-    } else if parser.sess.source_map().is_imported(parser.token.span) {
+    } else if parser.psess.source_map().is_imported(parser.token.span) {
         e.span_label(site_span, "in this macro invocation");
     }
     match kind {
@@ -262,7 +262,7 @@ pub(super) fn emit_frag_parse_err(
                 );
 
                 if parser.token == token::Semi {
-                    if let Ok(snippet) = parser.sess.source_map().span_to_snippet(site_span) {
+                    if let Ok(snippet) = parser.psess.source_map().span_to_snippet(site_span) {
                         e.span_suggestion_verbose(
                             site_span,
                             "surround the macro invocation with `{}` to interpret the expansion as a statement",
diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs
index 8174cb03d33..dce8e0c36ed 100644
--- a/compiler/rustc_expand/src/mbe/macro_check.rs
+++ b/compiler/rustc_expand/src/mbe/macro_check.rs
@@ -110,7 +110,7 @@ use crate::mbe::{KleeneToken, TokenTree};
 use rustc_ast::token::{Delimiter, IdentIsRaw, Token, TokenKind};
 use rustc_ast::{NodeId, DUMMY_NODE_ID};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{DiagnosticMessage, MultiSpan};
+use rustc_errors::{DiagMessage, MultiSpan};
 use rustc_session::lint::builtin::{META_VARIABLE_MISUSE, MISSING_FRAGMENT_SPECIFIER};
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::kw;
@@ -193,25 +193,25 @@ struct MacroState<'a> {
 /// Checks that meta-variables are used correctly in a macro definition.
 ///
 /// Arguments:
-/// - `sess` is used to emit diagnostics and lints
+/// - `psess` is used to emit diagnostics and lints
 /// - `node_id` is used to emit lints
 /// - `span` is used when no spans are available
 /// - `lhses` and `rhses` should have the same length and represent the macro definition
 pub(super) fn check_meta_variables(
-    sess: &ParseSess,
+    psess: &ParseSess,
     node_id: NodeId,
     span: Span,
     lhses: &[TokenTree],
     rhses: &[TokenTree],
 ) -> Result<(), ErrorGuaranteed> {
     if lhses.len() != rhses.len() {
-        sess.dcx.span_bug(span, "length mismatch between LHSes and RHSes")
+        psess.dcx.span_bug(span, "length mismatch between LHSes and RHSes")
     }
     let mut guar = None;
     for (lhs, rhs) in iter::zip(lhses, rhses) {
         let mut binders = Binders::default();
-        check_binders(sess, node_id, lhs, &Stack::Empty, &mut binders, &Stack::Empty, &mut guar);
-        check_occurrences(sess, node_id, rhs, &Stack::Empty, &binders, &Stack::Empty, &mut guar);
+        check_binders(psess, node_id, lhs, &Stack::Empty, &mut binders, &Stack::Empty, &mut guar);
+        check_occurrences(psess, node_id, rhs, &Stack::Empty, &binders, &Stack::Empty, &mut guar);
     }
     guar.map_or(Ok(()), Err)
 }
@@ -220,7 +220,7 @@ pub(super) fn check_meta_variables(
 /// sets `valid` to false in case of errors.
 ///
 /// Arguments:
-/// - `sess` is used to emit diagnostics and lints
+/// - `psess` is used to emit diagnostics and lints
 /// - `node_id` is used to emit lints
 /// - `lhs` is checked as part of a LHS
 /// - `macros` is the stack of possible outer macros
@@ -228,7 +228,7 @@ pub(super) fn check_meta_variables(
 /// - `ops` is the stack of Kleene operators from the LHS
 /// - `guar` is set in case of errors
 fn check_binders(
-    sess: &ParseSess,
+    psess: &ParseSess,
     node_id: NodeId,
     lhs: &TokenTree,
     macros: &Stack<'_, MacroState<'_>>,
@@ -244,7 +244,7 @@ fn check_binders(
         // MetaVar(fragment) and not as MetaVarDecl(y, fragment).
         TokenTree::MetaVar(span, name) => {
             if macros.is_empty() {
-                sess.dcx.span_bug(span, "unexpected MetaVar in lhs");
+                psess.dcx.span_bug(span, "unexpected MetaVar in lhs");
             }
             let name = MacroRulesNormalizedIdent::new(name);
             // There are 3 possibilities:
@@ -252,13 +252,13 @@ fn check_binders(
                 // 1. The meta-variable is already bound in the current LHS: This is an error.
                 let mut span = MultiSpan::from_span(span);
                 span.push_span_label(prev_info.span, "previous declaration");
-                buffer_lint(sess, span, node_id, "duplicate matcher binding");
+                buffer_lint(psess, span, node_id, "duplicate matcher binding");
             } else if get_binder_info(macros, binders, name).is_none() {
                 // 2. The meta-variable is free: This is a binder.
                 binders.insert(name, BinderInfo { span, ops: ops.into() });
             } else {
                 // 3. The meta-variable is bound: This is an occurrence.
-                check_occurrences(sess, node_id, lhs, macros, binders, ops, guar);
+                check_occurrences(psess, node_id, lhs, macros, binders, ops, guar);
             }
         }
         // Similarly, this can only happen when checking a toplevel macro.
@@ -267,7 +267,7 @@ fn check_binders(
                 // FIXME: Report this as a hard error eventually and remove equivalent errors from
                 // `parse_tt_inner` and `nameize`. Until then the error may be reported twice, once
                 // as a hard error and then once as a buffered lint.
-                sess.buffer_lint(
+                psess.buffer_lint(
                     MISSING_FRAGMENT_SPECIFIER,
                     span,
                     node_id,
@@ -275,14 +275,15 @@ fn check_binders(
                 );
             }
             if !macros.is_empty() {
-                sess.dcx.span_bug(span, "unexpected MetaVarDecl in nested lhs");
+                psess.dcx.span_bug(span, "unexpected MetaVarDecl in nested lhs");
             }
             let name = MacroRulesNormalizedIdent::new(name);
             if let Some(prev_info) = get_binder_info(macros, binders, name) {
                 // Duplicate binders at the top-level macro definition are errors. The lint is only
                 // for nested macro definitions.
                 *guar = Some(
-                    sess.dcx
+                    psess
+                        .dcx
                         .emit_err(errors::DuplicateMatcherBinding { span, prev: prev_info.span }),
                 );
             } else {
@@ -293,13 +294,13 @@ fn check_binders(
         TokenTree::MetaVarExpr(..) => {}
         TokenTree::Delimited(.., ref del) => {
             for tt in &del.tts {
-                check_binders(sess, node_id, tt, macros, binders, ops, guar);
+                check_binders(psess, node_id, tt, macros, binders, ops, guar);
             }
         }
         TokenTree::Sequence(_, ref seq) => {
             let ops = ops.push(seq.kleene);
             for tt in &seq.tts {
-                check_binders(sess, node_id, tt, macros, binders, &ops, guar);
+                check_binders(psess, node_id, tt, macros, binders, &ops, guar);
             }
         }
     }
@@ -323,7 +324,7 @@ fn get_binder_info<'a>(
 /// errors.
 ///
 /// Arguments:
-/// - `sess` is used to emit diagnostics and lints
+/// - `psess` is used to emit diagnostics and lints
 /// - `node_id` is used to emit lints
 /// - `rhs` is checked as part of a RHS
 /// - `macros` is the stack of possible outer macros
@@ -331,7 +332,7 @@ fn get_binder_info<'a>(
 /// - `ops` is the stack of Kleene operators from the RHS
 /// - `guar` is set in case of errors
 fn check_occurrences(
-    sess: &ParseSess,
+    psess: &ParseSess,
     node_id: NodeId,
     rhs: &TokenTree,
     macros: &Stack<'_, MacroState<'_>>,
@@ -342,24 +343,24 @@ fn check_occurrences(
     match *rhs {
         TokenTree::Token(..) => {}
         TokenTree::MetaVarDecl(span, _name, _kind) => {
-            sess.dcx.span_bug(span, "unexpected MetaVarDecl in rhs")
+            psess.dcx.span_bug(span, "unexpected MetaVarDecl in rhs")
         }
         TokenTree::MetaVar(span, name) => {
             let name = MacroRulesNormalizedIdent::new(name);
-            check_ops_is_prefix(sess, node_id, macros, binders, ops, span, name);
+            check_ops_is_prefix(psess, node_id, macros, binders, ops, span, name);
         }
         TokenTree::MetaVarExpr(dl, ref mve) => {
             let Some(name) = mve.ident().map(MacroRulesNormalizedIdent::new) else {
                 return;
             };
-            check_ops_is_prefix(sess, node_id, macros, binders, ops, dl.entire(), name);
+            check_ops_is_prefix(psess, node_id, macros, binders, ops, dl.entire(), name);
         }
         TokenTree::Delimited(.., ref del) => {
-            check_nested_occurrences(sess, node_id, &del.tts, macros, binders, ops, guar);
+            check_nested_occurrences(psess, node_id, &del.tts, macros, binders, ops, guar);
         }
         TokenTree::Sequence(_, ref seq) => {
             let ops = ops.push(seq.kleene);
-            check_nested_occurrences(sess, node_id, &seq.tts, macros, binders, &ops, guar);
+            check_nested_occurrences(psess, node_id, &seq.tts, macros, binders, &ops, guar);
         }
     }
 }
@@ -388,7 +389,7 @@ enum NestedMacroState {
 /// definitions, and sets `valid` to false in case of errors.
 ///
 /// Arguments:
-/// - `sess` is used to emit diagnostics and lints
+/// - `psess` is used to emit diagnostics and lints
 /// - `node_id` is used to emit lints
 /// - `tts` is checked as part of a RHS and may contain macro definitions
 /// - `macros` is the stack of possible outer macros
@@ -396,7 +397,7 @@ enum NestedMacroState {
 /// - `ops` is the stack of Kleene operators from the RHS
 /// - `guar` is set in case of errors
 fn check_nested_occurrences(
-    sess: &ParseSess,
+    psess: &ParseSess,
     node_id: NodeId,
     tts: &[TokenTree],
     macros: &Stack<'_, MacroState<'_>>,
@@ -434,7 +435,7 @@ fn check_nested_occurrences(
             (NestedMacroState::MacroRulesNot, &TokenTree::MetaVar(..)) => {
                 state = NestedMacroState::MacroRulesNotName;
                 // We check that the meta-variable is correctly used.
-                check_occurrences(sess, node_id, tt, macros, binders, ops, guar);
+                check_occurrences(psess, node_id, tt, macros, binders, ops, guar);
             }
             (NestedMacroState::MacroRulesNotName, TokenTree::Delimited(.., del))
             | (NestedMacroState::MacroName, TokenTree::Delimited(.., del))
@@ -443,11 +444,11 @@ fn check_nested_occurrences(
                 let macro_rules = state == NestedMacroState::MacroRulesNotName;
                 state = NestedMacroState::Empty;
                 let rest =
-                    check_nested_macro(sess, node_id, macro_rules, &del.tts, &nested_macros, guar);
+                    check_nested_macro(psess, node_id, macro_rules, &del.tts, &nested_macros, guar);
                 // If we did not check the whole macro definition, then check the rest as if outside
                 // the macro definition.
                 check_nested_occurrences(
-                    sess,
+                    psess,
                     node_id,
                     &del.tts[rest..],
                     macros,
@@ -465,7 +466,7 @@ fn check_nested_occurrences(
             (NestedMacroState::Macro, &TokenTree::MetaVar(..)) => {
                 state = NestedMacroState::MacroName;
                 // We check that the meta-variable is correctly used.
-                check_occurrences(sess, node_id, tt, macros, binders, ops, guar);
+                check_occurrences(psess, node_id, tt, macros, binders, ops, guar);
             }
             (NestedMacroState::MacroName, TokenTree::Delimited(.., del))
                 if del.delim == Delimiter::Parenthesis =>
@@ -473,7 +474,7 @@ fn check_nested_occurrences(
                 state = NestedMacroState::MacroNameParen;
                 nested_binders = Binders::default();
                 check_binders(
-                    sess,
+                    psess,
                     node_id,
                     tt,
                     &nested_macros,
@@ -487,7 +488,7 @@ fn check_nested_occurrences(
             {
                 state = NestedMacroState::Empty;
                 check_occurrences(
-                    sess,
+                    psess,
                     node_id,
                     tt,
                     &nested_macros,
@@ -498,7 +499,7 @@ fn check_nested_occurrences(
             }
             (_, tt) => {
                 state = NestedMacroState::Empty;
-                check_occurrences(sess, node_id, tt, macros, binders, ops, guar);
+                check_occurrences(psess, node_id, tt, macros, binders, ops, guar);
             }
         }
     }
@@ -512,14 +513,14 @@ fn check_nested_occurrences(
 /// stopped checking because we detected we were not in a macro definition anymore.
 ///
 /// Arguments:
-/// - `sess` is used to emit diagnostics and lints
+/// - `psess` is used to emit diagnostics and lints
 /// - `node_id` is used to emit lints
 /// - `macro_rules` specifies whether the macro is `macro_rules`
 /// - `tts` is checked as a list of (LHS) => {RHS}
 /// - `macros` is the stack of outer macros
 /// - `guar` is set in case of errors
 fn check_nested_macro(
-    sess: &ParseSess,
+    psess: &ParseSess,
     node_id: NodeId,
     macro_rules: bool,
     tts: &[TokenTree],
@@ -541,8 +542,8 @@ fn check_nested_macro(
         let lhs = &tts[i];
         let rhs = &tts[i + 2];
         let mut binders = Binders::default();
-        check_binders(sess, node_id, lhs, macros, &mut binders, &Stack::Empty, guar);
-        check_occurrences(sess, node_id, rhs, macros, &binders, &Stack::Empty, guar);
+        check_binders(psess, node_id, lhs, macros, &mut binders, &Stack::Empty, guar);
+        check_occurrences(psess, node_id, rhs, macros, &binders, &Stack::Empty, guar);
         // Since the last semicolon is optional for `macro_rules` macros and decl_macro are not terminated,
         // we increment our checked position by how many token trees we already checked (the 3
         // above) before checking for the separator.
@@ -559,7 +560,7 @@ fn check_nested_macro(
 /// Checks that a meta-variable occurrence is valid.
 ///
 /// Arguments:
-/// - `sess` is used to emit diagnostics and lints
+/// - `psess` is used to emit diagnostics and lints
 /// - `node_id` is used to emit lints
 /// - `macros` is the stack of possible outer macros
 /// - `binders` contains the binders of the associated LHS
@@ -567,7 +568,7 @@ fn check_nested_macro(
 /// - `span` is the span of the meta-variable to check
 /// - `name` is the name of the meta-variable to check
 fn check_ops_is_prefix(
-    sess: &ParseSess,
+    psess: &ParseSess,
     node_id: NodeId,
     macros: &Stack<'_, MacroState<'_>>,
     binders: &Binders,
@@ -590,11 +591,11 @@ fn check_ops_is_prefix(
             for ops in acc.iter().rev() {
                 occurrence_ops.extend_from_slice(ops);
             }
-            ops_is_prefix(sess, node_id, span, name, &binder.ops, &occurrence_ops);
+            ops_is_prefix(psess, node_id, span, name, &binder.ops, &occurrence_ops);
             return;
         }
     }
-    buffer_lint(sess, span.into(), node_id, format!("unknown macro variable `{name}`"));
+    buffer_lint(psess, span.into(), node_id, format!("unknown macro variable `{name}`"));
 }
 
 /// Returns whether `binder_ops` is a prefix of `occurrence_ops`.
@@ -609,14 +610,14 @@ fn check_ops_is_prefix(
 /// It occurs under the Kleene stack ["*", "+"] and is bound under ["*"] only.
 ///
 /// Arguments:
-/// - `sess` is used to emit diagnostics and lints
+/// - `psess` is used to emit diagnostics and lints
 /// - `node_id` is used to emit lints
 /// - `span` is the span of the meta-variable being check
 /// - `name` is the name of the meta-variable being check
 /// - `binder_ops` is the stack of Kleene operators for the binder
 /// - `occurrence_ops` is the stack of Kleene operators for the occurrence
 fn ops_is_prefix(
-    sess: &ParseSess,
+    psess: &ParseSess,
     node_id: NodeId,
     span: Span,
     name: MacroRulesNormalizedIdent,
@@ -628,7 +629,7 @@ fn ops_is_prefix(
             let mut span = MultiSpan::from_span(span);
             span.push_span_label(binder.span, "expected repetition");
             let message = format!("variable '{name}' is still repeating at this depth");
-            buffer_lint(sess, span, node_id, message);
+            buffer_lint(psess, span, node_id, message);
             return;
         }
         let occurrence = &occurrence_ops[i];
@@ -637,20 +638,20 @@ fn ops_is_prefix(
             span.push_span_label(binder.span, "expected repetition");
             span.push_span_label(occurrence.span, "conflicting repetition");
             let message = "meta-variable repeats with different Kleene operator";
-            buffer_lint(sess, span, node_id, message);
+            buffer_lint(psess, span, node_id, message);
             return;
         }
     }
 }
 
 fn buffer_lint(
-    sess: &ParseSess,
+    psess: &ParseSess,
     span: MultiSpan,
     node_id: NodeId,
-    message: impl Into<DiagnosticMessage>,
+    message: impl Into<DiagMessage>,
 ) {
     // Macros loaded from other crates have dummy node ids.
     if node_id != DUMMY_NODE_ID {
-        sess.buffer_lint(META_VARIABLE_MISUSE, span, node_id, message);
+        psess.buffer_lint(META_VARIABLE_MISUSE, span, node_id, message);
     }
 }
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index c11d538048a..8903fc45def 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -21,7 +21,7 @@ use rustc_feature::Features;
 use rustc_lint_defs::builtin::{
     RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
 };
-use rustc_lint_defs::BuiltinLintDiagnostics;
+use rustc_lint_defs::BuiltinLintDiag;
 use rustc_parse::parser::{Parser, Recovery};
 use rustc_session::parse::ParseSess;
 use rustc_session::Session;
@@ -78,12 +78,12 @@ impl<'a> ParserAnyMacro<'a> {
         // but `m!()` is allowed in expression positions (cf. issue #34706).
         if kind == AstFragmentKind::Expr && parser.token == token::Semi {
             if is_local {
-                parser.sess.buffer_lint_with_diagnostic(
+                parser.psess.buffer_lint_with_diagnostic(
                     SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
                     parser.token.span,
                     lint_node_id,
                     "trailing semicolon in macro used in expression position",
-                    BuiltinLintDiagnostics::TrailingMacro(is_trailing_mac, macro_ident),
+                    BuiltinLintDiag::TrailingMacro(is_trailing_mac, macro_ident),
                 );
             }
             parser.bump();
@@ -195,7 +195,7 @@ fn expand_macro<'cx>(
     lhses: &[Vec<MatcherLoc>],
     rhses: &[mbe::TokenTree],
 ) -> Box<dyn MacResult + 'cx> {
-    let sess = &cx.sess.parse_sess;
+    let psess = &cx.sess.psess;
     // Macros defined in the current crate have a real node id,
     // whereas macros from an external crate have a dummy id.
     let is_local = node_id != DUMMY_NODE_ID;
@@ -206,7 +206,7 @@ fn expand_macro<'cx>(
     }
 
     // Track nothing for the best performance.
-    let try_success_result = try_match_macro(sess, name, &arg, lhses, &mut NoopTracker);
+    let try_success_result = try_match_macro(psess, name, &arg, lhses, &mut NoopTracker);
 
     match try_success_result {
         Ok((i, named_matches)) => {
@@ -230,7 +230,7 @@ fn expand_macro<'cx>(
                 trace_macros_note(&mut cx.expansions, sp, msg);
             }
 
-            let p = Parser::new(sess, tts, None);
+            let p = Parser::new(psess, tts, None);
 
             if is_local {
                 cx.resolver.record_macro_rule_usage(node_id, i);
@@ -272,9 +272,9 @@ pub(super) enum CanRetry {
 /// Try expanding the macro. Returns the index of the successful arm and its named_matches if it was successful,
 /// and nothing if it failed. On failure, it's the callers job to use `track` accordingly to record all errors
 /// correctly.
-#[instrument(level = "debug", skip(sess, arg, lhses, track), fields(tracking = %T::description()))]
+#[instrument(level = "debug", skip(psess, arg, lhses, track), fields(tracking = %T::description()))]
 pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
-    sess: &ParseSess,
+    psess: &ParseSess,
     name: Ident,
     arg: &TokenStream,
     lhses: &'matcher [Vec<MatcherLoc>],
@@ -299,7 +299,7 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
     // hacky, but speeds up the `html5ever` benchmark significantly. (Issue
     // 68836 suggests a more comprehensive but more complex change to deal with
     // this situation.)
-    let parser = parser_from_cx(sess, arg.clone(), T::recovery());
+    let parser = parser_from_cx(psess, arg.clone(), T::recovery());
     // Try each arm's matchers.
     let mut tt_parser = TtParser::new(name);
     for (i, lhs) in lhses.iter().enumerate() {
@@ -309,7 +309,7 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
         // This is used so that if a matcher is not `Success(..)`ful,
         // then the spans which became gated when parsing the unsuccessful matcher
         // are not recorded. On the first `Success(..)`ful matcher, the spans are merged.
-        let mut gated_spans_snapshot = mem::take(&mut *sess.gated_spans.spans.borrow_mut());
+        let mut gated_spans_snapshot = mem::take(&mut *psess.gated_spans.spans.borrow_mut());
 
         let result = tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs, track);
 
@@ -320,7 +320,7 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
                 debug!("Parsed arm successfully");
                 // The matcher was `Success(..)`ful.
                 // Merge the gated spans from parsing the matcher with the preexisting ones.
-                sess.gated_spans.merge(gated_spans_snapshot);
+                psess.gated_spans.merge(gated_spans_snapshot);
 
                 return Ok((i, named_matches));
             }
@@ -342,7 +342,7 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
 
         // The matcher was not `Success(..)`ful.
         // Restore to the state before snapshotting and maybe try again.
-        mem::swap(&mut gated_spans_snapshot, &mut sess.gated_spans.spans.borrow_mut());
+        mem::swap(&mut gated_spans_snapshot, &mut psess.gated_spans.spans.borrow_mut());
     }
 
     Err(CanRetry::Yes)
@@ -376,7 +376,7 @@ pub fn compile_declarative_macro(
     };
     let dummy_syn_ext = |guar| (mk_syn_ext(Box::new(DummyExpander(guar))), Vec::new());
 
-    let dcx = &sess.parse_sess.dcx;
+    let dcx = &sess.psess.dcx;
     let lhs_nm = Ident::new(sym::lhs, def.span);
     let rhs_nm = Ident::new(sym::rhs, def.span);
     let tt_spec = Some(NonterminalKind::TT);
@@ -430,7 +430,7 @@ pub fn compile_declarative_macro(
 
     let create_parser = || {
         let body = macro_def.body.tokens.clone();
-        Parser::new(&sess.parse_sess, body, rustc_parse::MACRO_ARGUMENTS)
+        Parser::new(&sess.psess, body, rustc_parse::MACRO_ARGUMENTS)
     };
 
     let parser = create_parser();
@@ -533,7 +533,7 @@ pub fn compile_declarative_macro(
     }
 
     check_emission(macro_check::check_meta_variables(
-        &sess.parse_sess,
+        &sess.psess,
         def.id,
         def.span,
         &lhses,
@@ -1149,12 +1149,12 @@ fn check_matcher_core<'tt>(
                             name,
                             Some(NonterminalKind::PatParam { inferred: false }),
                         ));
-                        sess.parse_sess.buffer_lint_with_diagnostic(
+                        sess.psess.buffer_lint_with_diagnostic(
                             RUST_2021_INCOMPATIBLE_OR_PATTERNS,
                             span,
                             ast::CRATE_NODE_ID,
                             "the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro",
-                            BuiltinLintDiagnostics::OrPatternsBackCompat(span, suggestion),
+                            BuiltinLintDiag::OrPatternsBackCompat(span, suggestion),
                         );
                     }
                     match is_in_follow(next_token, kind) {
@@ -1182,7 +1182,7 @@ fn check_matcher_core<'tt>(
                             err.span_label(sp, format!("not allowed after `{kind}` fragments"));
 
                             if kind == NonterminalKind::PatWithOr
-                                && sess.parse_sess.edition.at_least_rust_2021()
+                                && sess.psess.edition.at_least_rust_2021()
                                 && next_token.is_token(&BinOp(token::BinOpToken::Or))
                             {
                                 let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
@@ -1406,10 +1406,10 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String {
 }
 
 pub(super) fn parser_from_cx(
-    sess: &ParseSess,
+    psess: &ParseSess,
     mut tts: TokenStream,
     recovery: Recovery,
 ) -> Parser<'_> {
     tts.desugar_doc_comments();
-    Parser::new(sess, tts, rustc_parse::MACRO_ARGUMENTS).recovery(recovery)
+    Parser::new(psess, tts, rustc_parse::MACRO_ARGUMENTS).recovery(recovery)
 }
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index 84f7dc4771a..81e1de5b095 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -27,30 +27,30 @@ pub(crate) enum MetaVarExpr {
 
 impl MetaVarExpr {
     /// Attempt to parse a meta-variable expression from a token stream.
-    pub(crate) fn parse<'sess>(
+    pub(crate) fn parse<'psess>(
         input: &TokenStream,
         outer_span: Span,
-        sess: &'sess ParseSess,
-    ) -> PResult<'sess, MetaVarExpr> {
+        psess: &'psess ParseSess,
+    ) -> PResult<'psess, MetaVarExpr> {
         let mut tts = input.trees();
-        let ident = parse_ident(&mut tts, sess, outer_span)?;
+        let ident = parse_ident(&mut tts, psess, outer_span)?;
         let Some(TokenTree::Delimited(.., Delimiter::Parenthesis, args)) = tts.next() else {
             let msg = "meta-variable expression parameter must be wrapped in parentheses";
-            return Err(sess.dcx.struct_span_err(ident.span, msg));
+            return Err(psess.dcx.struct_span_err(ident.span, msg));
         };
-        check_trailing_token(&mut tts, sess)?;
+        check_trailing_token(&mut tts, psess)?;
         let mut iter = args.trees();
         let rslt = match ident.as_str() {
-            "count" => parse_count(&mut iter, sess, ident.span)?,
+            "count" => parse_count(&mut iter, psess, ident.span)?,
             "ignore" => {
-                eat_dollar(&mut iter, sess, ident.span)?;
-                MetaVarExpr::Ignore(parse_ident(&mut iter, sess, ident.span)?)
+                eat_dollar(&mut iter, psess, ident.span)?;
+                MetaVarExpr::Ignore(parse_ident(&mut iter, psess, ident.span)?)
             }
-            "index" => MetaVarExpr::Index(parse_depth(&mut iter, sess, ident.span)?),
-            "length" => MetaVarExpr::Length(parse_depth(&mut iter, sess, ident.span)?),
+            "index" => MetaVarExpr::Index(parse_depth(&mut iter, psess, ident.span)?),
+            "length" => MetaVarExpr::Length(parse_depth(&mut iter, psess, ident.span)?),
             _ => {
                 let err_msg = "unrecognized meta-variable expression";
-                let mut err = sess.dcx.struct_span_err(ident.span, err_msg);
+                let mut err = psess.dcx.struct_span_err(ident.span, err_msg);
                 err.span_suggestion(
                     ident.span,
                     "supported expressions are count, ignore, index and length",
@@ -60,7 +60,7 @@ impl MetaVarExpr {
                 return Err(err);
             }
         };
-        check_trailing_token(&mut iter, sess)?;
+        check_trailing_token(&mut iter, psess)?;
         Ok(rslt)
     }
 
@@ -73,12 +73,12 @@ impl MetaVarExpr {
 }
 
 // Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}`
-fn check_trailing_token<'sess>(
+fn check_trailing_token<'psess>(
     iter: &mut RefTokenTreeCursor<'_>,
-    sess: &'sess ParseSess,
-) -> PResult<'sess, ()> {
+    psess: &'psess ParseSess,
+) -> PResult<'psess, ()> {
     if let Some(tt) = iter.next() {
-        let mut diag = sess
+        let mut diag = psess
             .dcx
             .struct_span_err(tt.span(), format!("unexpected token: {}", pprust::tt_to_string(tt)));
         diag.span_note(tt.span(), "meta-variable expression must not have trailing tokens");
@@ -89,21 +89,21 @@ fn check_trailing_token<'sess>(
 }
 
 /// Parse a meta-variable `count` expression: `count(ident[, depth])`
-fn parse_count<'sess>(
+fn parse_count<'psess>(
     iter: &mut RefTokenTreeCursor<'_>,
-    sess: &'sess ParseSess,
+    psess: &'psess ParseSess,
     span: Span,
-) -> PResult<'sess, MetaVarExpr> {
-    eat_dollar(iter, sess, span)?;
-    let ident = parse_ident(iter, sess, span)?;
+) -> PResult<'psess, MetaVarExpr> {
+    eat_dollar(iter, psess, span)?;
+    let ident = parse_ident(iter, psess, span)?;
     let depth = if try_eat_comma(iter) {
         if iter.look_ahead(0).is_none() {
-            return Err(sess.dcx.struct_span_err(
+            return Err(psess.dcx.struct_span_err(
                 span,
                 "`count` followed by a comma must have an associated index indicating its depth",
             ));
         }
-        parse_depth(iter, sess, span)?
+        parse_depth(iter, psess, span)?
     } else {
         0
     };
@@ -111,14 +111,14 @@ fn parse_count<'sess>(
 }
 
 /// Parses the depth used by index(depth) and length(depth).
-fn parse_depth<'sess>(
+fn parse_depth<'psess>(
     iter: &mut RefTokenTreeCursor<'_>,
-    sess: &'sess ParseSess,
+    psess: &'psess ParseSess,
     span: Span,
-) -> PResult<'sess, usize> {
+) -> PResult<'psess, usize> {
     let Some(tt) = iter.next() else { return Ok(0) };
     let TokenTree::Token(token::Token { kind: token::TokenKind::Literal(lit), .. }, _) = tt else {
-        return Err(sess
+        return Err(psess
             .dcx
             .struct_span_err(span, "meta-variable expression depth must be a literal"));
     };
@@ -129,16 +129,16 @@ fn parse_depth<'sess>(
         Ok(n_usize)
     } else {
         let msg = "only unsuffixes integer literals are supported in meta-variable expressions";
-        Err(sess.dcx.struct_span_err(span, msg))
+        Err(psess.dcx.struct_span_err(span, msg))
     }
 }
 
 /// Parses an generic ident
-fn parse_ident<'sess>(
+fn parse_ident<'psess>(
     iter: &mut RefTokenTreeCursor<'_>,
-    sess: &'sess ParseSess,
+    psess: &'psess ParseSess,
     span: Span,
-) -> PResult<'sess, Ident> {
+) -> PResult<'psess, Ident> {
     if let Some(tt) = iter.next()
         && let TokenTree::Token(token, _) = tt
     {
@@ -147,7 +147,7 @@ fn parse_ident<'sess>(
         }
         let token_str = pprust::token_to_string(token);
         let mut err =
-            sess.dcx.struct_span_err(span, format!("expected identifier, found `{}`", &token_str));
+            psess.dcx.struct_span_err(span, format!("expected identifier, found `{}`", &token_str));
         err.span_suggestion(
             token.span,
             format!("try removing `{}`", &token_str),
@@ -156,7 +156,7 @@ fn parse_ident<'sess>(
         );
         return Err(err);
     }
-    Err(sess.dcx.struct_span_err(span, "expected identifier"))
+    Err(psess.dcx.struct_span_err(span, "expected identifier"))
 }
 
 /// Tries to move the iterator forward returning `true` if there is a comma. If not, then the
@@ -170,17 +170,17 @@ fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool {
 }
 
 /// Expects that the next item is a dollar sign.
-fn eat_dollar<'sess>(
+fn eat_dollar<'psess>(
     iter: &mut RefTokenTreeCursor<'_>,
-    sess: &'sess ParseSess,
+    psess: &'psess ParseSess,
     span: Span,
-) -> PResult<'sess, ()> {
+) -> PResult<'psess, ()> {
     if let Some(TokenTree::Token(token::Token { kind: token::Dollar, .. }, _)) = iter.look_ahead(0)
     {
         let _ = iter.next();
         return Ok(());
     }
-    Err(sess.dcx.struct_span_err(
+    Err(psess.dcx.struct_span_err(
         span,
         "meta-variables within meta-variable expressions must be referenced using a dollar sign",
     ))
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index ec1dd807d1a..5fd3716743b 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -175,8 +175,7 @@ fn parse_tree<'a>(
                                 // The delimiter is `{`. This indicates the beginning
                                 // of a meta-variable expression (e.g. `${count(ident)}`).
                                 // Try to parse the meta-variable expression.
-                                match MetaVarExpr::parse(tts, delim_span.entire(), &sess.parse_sess)
-                                {
+                                match MetaVarExpr::parse(tts, delim_span.entire(), &sess.psess) {
                                     Err(err) => {
                                         err.emit();
                                         // Returns early the same read `$` to avoid spanning
diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs
index 1282cf2c03a..8a68b39e496 100644
--- a/compiler/rustc_expand/src/module.rs
+++ b/compiler/rustc_expand/src/module.rs
@@ -66,7 +66,7 @@ pub(crate) fn parse_external_mod(
         }
 
         // Actually parse the external file as a module.
-        let mut parser = new_parser_from_file(&sess.parse_sess, &mp.file_path, Some(span));
+        let mut parser = new_parser_from_file(&sess.psess, &mp.file_path, Some(span));
         let (inner_attrs, items, inner_span) =
             parser.parse_mod(&token::Eof).map_err(|err| ModError::ParserError(err))?;
         attrs.extend(inner_attrs);
@@ -157,7 +157,7 @@ fn mod_file_path<'a>(
         DirOwnership::Owned { relative } => relative,
         DirOwnership::UnownedViaBlock => None,
     };
-    let result = default_submod_path(&sess.parse_sess, ident, relative, dir_path);
+    let result = default_submod_path(&sess.psess, ident, relative, dir_path);
     match dir_ownership {
         DirOwnership::Owned { .. } => result,
         DirOwnership::UnownedViaBlock => Err(ModError::ModInBlock(match result {
@@ -185,11 +185,7 @@ fn mod_file_path_from_attr(
         // complexity). Usually bad forms are checked in AstValidator (via
         // `check_builtin_attribute`), but by the time that runs the macro
         // is expanded, and it doesn't give an error.
-        validate_attr::emit_fatal_malformed_builtin_attribute(
-            &sess.parse_sess,
-            first_path,
-            sym::path,
-        );
+        validate_attr::emit_fatal_malformed_builtin_attribute(&sess.psess, first_path, sym::path);
     };
 
     let path_str = path_sym.as_str();
@@ -207,7 +203,7 @@ fn mod_file_path_from_attr(
 /// Returns a path to a module.
 // Public for rustfmt usage.
 pub fn default_submod_path<'a>(
-    sess: &'a ParseSess,
+    psess: &'a ParseSess,
     ident: Ident,
     relative: Option<Ident>,
     dir_path: &Path,
@@ -229,8 +225,8 @@ pub fn default_submod_path<'a>(
         format!("{}{}{}mod.rs", relative_prefix, ident.name, path::MAIN_SEPARATOR);
     let default_path = dir_path.join(&default_path_str);
     let secondary_path = dir_path.join(&secondary_path_str);
-    let default_exists = sess.source_map().file_exists(&default_path);
-    let secondary_exists = sess.source_map().file_exists(&secondary_path);
+    let default_exists = psess.source_map().file_exists(&default_path);
+    let secondary_exists = psess.source_map().file_exists(&secondary_path);
 
     match (default_exists, secondary_exists) {
         (true, false) => Ok(ModulePathSuccess {
diff --git a/compiler/rustc_expand/src/parse/tests.rs b/compiler/rustc_expand/src/parse/tests.rs
index 0e07b41b43c..066afd7a41d 100644
--- a/compiler/rustc_expand/src/parse/tests.rs
+++ b/compiler/rustc_expand/src/parse/tests.rs
@@ -1,5 +1,6 @@
 use crate::tests::{
-    matches_codepattern, string_to_stream, with_error_checking_parse, with_expected_parse_error,
+    matches_codepattern, psess, string_to_stream, with_error_checking_parse,
+    with_expected_parse_error,
 };
 
 use ast::token::IdentIsRaw;
@@ -14,19 +15,10 @@ use rustc_parse::new_parser_from_source_str;
 use rustc_parse::parser::ForceCollect;
 use rustc_session::parse::ParseSess;
 use rustc_span::create_default_session_globals_then;
-use rustc_span::source_map::FilePathMapping;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{BytePos, FileName, Pos, Span};
-
 use std::path::PathBuf;
 
-fn sess() -> ParseSess {
-    ParseSess::new(
-        vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
-        FilePathMapping::empty(),
-    )
-}
-
 /// Parses an item.
 ///
 /// Returns `Ok(Some(item))` when successful, `Ok(None)` when no item was found, and `Err`
@@ -34,9 +26,9 @@ fn sess() -> ParseSess {
 fn parse_item_from_source_str(
     name: FileName,
     source: String,
-    sess: &ParseSess,
+    psess: &ParseSess,
 ) -> PResult<'_, Option<P<ast::Item>>> {
-    new_parser_from_source_str(sess, name, source).parse_item(ForceCollect::No)
+    new_parser_from_source_str(psess, name, source).parse_item(ForceCollect::No)
 }
 
 // Produces a `rustc_span::span`.
@@ -46,12 +38,12 @@ fn sp(a: u32, b: u32) -> Span {
 
 /// Parses a string, return an expression.
 fn string_to_expr(source_str: String) -> P<ast::Expr> {
-    with_error_checking_parse(source_str, &sess(), |p| p.parse_expr())
+    with_error_checking_parse(source_str, &psess(), |p| p.parse_expr())
 }
 
 /// Parses a string, returns an item.
 fn string_to_item(source_str: String) -> Option<P<ast::Item>> {
-    with_error_checking_parse(source_str, &sess(), |p| p.parse_item(ForceCollect::No))
+    with_error_checking_parse(source_str, &psess(), |p| p.parse_item(ForceCollect::No))
 }
 
 #[test]
@@ -287,24 +279,24 @@ let mut fflags: c_int = wb();
 #[test]
 fn crlf_doc_comments() {
     create_default_session_globals_then(|| {
-        let sess = sess();
+        let psess = psess();
 
         let name_1 = FileName::Custom("crlf_source_1".to_string());
         let source = "/// doc comment\r\nfn foo() {}".to_string();
-        let item = parse_item_from_source_str(name_1, source, &sess).unwrap().unwrap();
+        let item = parse_item_from_source_str(name_1, source, &psess).unwrap().unwrap();
         let doc = item.attrs.iter().filter_map(|at| at.doc_str()).next().unwrap();
         assert_eq!(doc.as_str(), " doc comment");
 
         let name_2 = FileName::Custom("crlf_source_2".to_string());
         let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string();
-        let item = parse_item_from_source_str(name_2, source, &sess).unwrap().unwrap();
+        let item = parse_item_from_source_str(name_2, source, &psess).unwrap().unwrap();
         let docs = item.attrs.iter().filter_map(|at| at.doc_str()).collect::<Vec<_>>();
         let b: &[_] = &[Symbol::intern(" doc comment"), Symbol::intern(" line 2")];
         assert_eq!(&docs[..], b);
 
         let name_3 = FileName::Custom("clrf_source_3".to_string());
         let source = "/** doc comment\r\n *  with CRLF */\r\nfn foo() {}".to_string();
-        let item = parse_item_from_source_str(name_3, source, &sess).unwrap().unwrap();
+        let item = parse_item_from_source_str(name_3, source, &psess).unwrap().unwrap();
         let doc = item.attrs.iter().filter_map(|at| at.doc_str()).next().unwrap();
         assert_eq!(doc.as_str(), " doc comment\n *  with CRLF ");
     });
@@ -315,24 +307,24 @@ fn ttdelim_span() {
     fn parse_expr_from_source_str(
         name: FileName,
         source: String,
-        sess: &ParseSess,
+        psess: &ParseSess,
     ) -> PResult<'_, P<ast::Expr>> {
-        new_parser_from_source_str(sess, name, source).parse_expr()
+        new_parser_from_source_str(psess, name, source).parse_expr()
     }
 
     create_default_session_globals_then(|| {
-        let sess = sess();
+        let psess = psess();
         let expr = parse_expr_from_source_str(
             PathBuf::from("foo").into(),
             "foo!( fn main() { body } )".to_string(),
-            &sess,
+            &psess,
         )
         .unwrap();
 
         let ast::ExprKind::MacCall(mac) = &expr.kind else { panic!("not a macro") };
         let span = mac.args.tokens.trees().last().unwrap().span();
 
-        match sess.source_map().span_to_snippet(span) {
+        match psess.source_map().span_to_snippet(span) {
             Ok(s) => assert_eq!(&s[..], "{ body }"),
             Err(_) => panic!("could not get snippet"),
         }
@@ -348,7 +340,7 @@ fn out_of_line_mod() {
         let item = parse_item_from_source_str(
             PathBuf::from("foo").into(),
             "mod foo { struct S; mod this_does_not_exist; }".to_owned(),
-            &sess(),
+            &psess(),
         )
         .unwrap()
         .unwrap();
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index 23caf2f193a..4b5c148cb55 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -162,7 +162,7 @@ impl MultiItemModifier for DeriveProcMacro {
 
         let error_count_before = ecx.dcx().err_count();
         let mut parser =
-            rustc_parse::stream_to_parser(&ecx.sess.parse_sess, stream, Some("proc-macro derive"));
+            rustc_parse::stream_to_parser(&ecx.sess.psess, stream, Some("proc-macro derive"));
         let mut items = vec![];
 
         loop {
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 6fe0d611363..ddc685c9d07 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -354,7 +354,7 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>>
                 )]
             }
             TokenTree::Ident(self::Ident { sym, is_raw, span }) => {
-                rustc.sess().symbol_gallery.insert(sym, span);
+                rustc.psess().symbol_gallery.insert(sym, span);
                 smallvec![tokenstream::TokenTree::token_alone(Ident(sym, is_raw.into()), span)]
             }
             TokenTree::Literal(self::Literal {
@@ -429,8 +429,8 @@ impl<'a, 'b> Rustc<'a, 'b> {
         }
     }
 
-    fn sess(&self) -> &ParseSess {
-        self.ecx.parse_sess()
+    fn psess(&self) -> &ParseSess {
+        self.ecx.psess()
     }
 }
 
@@ -448,19 +448,19 @@ impl server::FreeFunctions for Rustc<'_, '_> {
     }
 
     fn track_env_var(&mut self, var: &str, value: Option<&str>) {
-        self.sess()
+        self.psess()
             .env_depinfo
             .borrow_mut()
             .insert((Symbol::intern(var), value.map(Symbol::intern)));
     }
 
     fn track_path(&mut self, path: &str) {
-        self.sess().file_depinfo.borrow_mut().insert(Symbol::intern(path));
+        self.psess().file_depinfo.borrow_mut().insert(Symbol::intern(path));
     }
 
     fn literal_from_str(&mut self, s: &str) -> Result<Literal<Self::Span, Self::Symbol>, ()> {
         let name = FileName::proc_macro_source_code(s);
-        let mut parser = rustc_parse::new_parser_from_source_str(self.sess(), name, s.to_owned());
+        let mut parser = rustc_parse::new_parser_from_source_str(self.psess(), name, s.to_owned());
 
         let first_span = parser.token.span.data();
         let minus_present = parser.eat(&token::BinOp(token::Minus));
@@ -512,11 +512,14 @@ impl server::FreeFunctions for Rustc<'_, '_> {
     }
 
     fn emit_diagnostic(&mut self, diagnostic: Diagnostic<Self::Span>) {
-        let message = rustc_errors::DiagnosticMessage::from(diagnostic.message);
+        let message = rustc_errors::DiagMessage::from(diagnostic.message);
         let mut diag: Diag<'_, ()> =
-            Diag::new(&self.sess().dcx, diagnostic.level.to_internal(), message);
+            Diag::new(&self.psess().dcx, diagnostic.level.to_internal(), message);
         diag.span(MultiSpan::from_spans(diagnostic.spans));
         for child in diagnostic.children {
+            // This message comes from another diagnostic, and we are just reconstructing the
+            // diagnostic, so there's no need for translation.
+            #[allow(rustc::untranslatable_diagnostic)]
             diag.sub(child.level.to_internal(), child.message, MultiSpan::from_spans(child.spans));
         }
         diag.emit();
@@ -532,7 +535,7 @@ impl server::TokenStream for Rustc<'_, '_> {
         parse_stream_from_source_str(
             FileName::proc_macro_source_code(src),
             src.to_string(),
-            self.sess(),
+            self.psess(),
             Some(self.call_site),
         )
     }
@@ -545,7 +548,7 @@ impl server::TokenStream for Rustc<'_, '_> {
         // Parse the expression from our tokenstream.
         let expr: PResult<'_, _> = try {
             let mut p = rustc_parse::stream_to_parser(
-                self.sess(),
+                self.psess(),
                 stream.clone(),
                 Some("proc_macro expand expr"),
             );
@@ -680,7 +683,7 @@ impl server::Span for Rustc<'_, '_> {
     }
 
     fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
-        self.sess().source_map().lookup_char_pos(span.lo()).file
+        self.psess().source_map().lookup_char_pos(span.lo()).file
     }
 
     fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
@@ -692,7 +695,7 @@ impl server::Span for Rustc<'_, '_> {
     }
 
     fn byte_range(&mut self, span: Self::Span) -> Range<usize> {
-        let source_map = self.sess().source_map();
+        let source_map = self.psess().source_map();
 
         let relative_start_pos = source_map.lookup_byte_offset(span.lo()).pos;
         let relative_end_pos = source_map.lookup_byte_offset(span.hi()).pos;
@@ -708,18 +711,18 @@ impl server::Span for Rustc<'_, '_> {
     }
 
     fn line(&mut self, span: Self::Span) -> usize {
-        let loc = self.sess().source_map().lookup_char_pos(span.lo());
+        let loc = self.psess().source_map().lookup_char_pos(span.lo());
         loc.line
     }
 
     fn column(&mut self, span: Self::Span) -> usize {
-        let loc = self.sess().source_map().lookup_char_pos(span.lo());
+        let loc = self.psess().source_map().lookup_char_pos(span.lo());
         loc.col.to_usize() + 1
     }
 
     fn join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span> {
-        let self_loc = self.sess().source_map().lookup_char_pos(first.lo());
-        let other_loc = self.sess().source_map().lookup_char_pos(second.lo());
+        let self_loc = self.psess().source_map().lookup_char_pos(first.lo());
+        let other_loc = self.psess().source_map().lookup_char_pos(second.lo());
 
         if self_loc.file.name != other_loc.file.name {
             return None;
@@ -769,7 +772,7 @@ impl server::Span for Rustc<'_, '_> {
     }
 
     fn source_text(&mut self, span: Self::Span) -> Option<String> {
-        self.sess().source_map().span_to_snippet(span).ok()
+        self.psess().source_map().span_to_snippet(span).ok()
     }
 
     /// Saves the provided span into the metadata of
@@ -797,7 +800,7 @@ impl server::Span for Rustc<'_, '_> {
     /// since we've loaded `my_proc_macro` from disk in order to execute it).
     /// In this way, we have obtained a span pointing into `my_proc_macro`
     fn save_span(&mut self, span: Self::Span) -> usize {
-        self.sess().save_proc_macro_span(span)
+        self.psess().save_proc_macro_span(span)
     }
 
     fn recover_proc_macro_span(&mut self, id: usize) -> Self::Span {
diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs
index b242ce795fd..a3510dc9bff 100644
--- a/compiler/rustc_expand/src/tests.rs
+++ b/compiler/rustc_expand/src/tests.rs
@@ -18,9 +18,13 @@ use std::path::{Path, PathBuf};
 use std::str;
 use std::sync::{Arc, Mutex};
 
+pub(crate) fn psess() -> ParseSess {
+    ParseSess::new(vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE])
+}
+
 /// Map string to parser (via tts).
-fn string_to_parser(ps: &ParseSess, source_str: String) -> Parser<'_> {
-    new_parser_from_source_str(ps, PathBuf::from("bogofile").into(), source_str)
+fn string_to_parser(psess: &ParseSess, source_str: String) -> Parser<'_> {
+    new_parser_from_source_str(psess, PathBuf::from("bogofile").into(), source_str)
 }
 
 fn create_test_handler() -> (DiagCtxt, Lrc<SourceMap>, Arc<Mutex<Vec<u8>>>) {
@@ -40,13 +44,13 @@ fn create_test_handler() -> (DiagCtxt, Lrc<SourceMap>, Arc<Mutex<Vec<u8>>>) {
 /// Returns the result of parsing the given string via the given callback.
 ///
 /// If there are any errors, this will panic.
-pub(crate) fn with_error_checking_parse<'a, T, F>(s: String, ps: &'a ParseSess, f: F) -> T
+pub(crate) fn with_error_checking_parse<'a, T, F>(s: String, psess: &'a ParseSess, f: F) -> T
 where
     F: FnOnce(&mut Parser<'a>) -> PResult<'a, T>,
 {
-    let mut p = string_to_parser(&ps, s);
+    let mut p = string_to_parser(&psess, s);
     let x = f(&mut p).unwrap();
-    p.sess.dcx.abort_if_errors();
+    p.psess.dcx.abort_if_errors();
     x
 }
 
@@ -57,8 +61,8 @@ where
     F: for<'a> FnOnce(&mut Parser<'a>) -> PResult<'a, T>,
 {
     let (handler, source_map, output) = create_test_handler();
-    let ps = ParseSess::with_dcx(handler, source_map);
-    let mut p = string_to_parser(&ps, source_str.to_string());
+    let psess = ParseSess::with_dcx(handler, source_map);
+    let mut p = string_to_parser(&psess, source_str.to_string());
     let result = f(&mut p);
     assert!(result.is_ok());
 
@@ -72,24 +76,18 @@ where
 
 /// Maps a string to tts, using a made-up filename.
 pub(crate) fn string_to_stream(source_str: String) -> TokenStream {
-    let ps = ParseSess::new(
-        vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
-        FilePathMapping::empty(),
-    );
+    let psess = psess();
     source_file_to_stream(
-        &ps,
-        ps.source_map().new_source_file(PathBuf::from("bogofile").into(), source_str),
+        &psess,
+        psess.source_map().new_source_file(PathBuf::from("bogofile").into(), source_str),
         None,
     )
 }
 
 /// Parses a string, returns a crate.
 pub(crate) fn string_to_crate(source_str: String) -> ast::Crate {
-    let ps = ParseSess::new(
-        vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
-        FilePathMapping::empty(),
-    );
-    with_error_checking_parse(source_str, &ps, |p| p.parse_crate_mod())
+    let psess = psess();
+    with_error_checking_parse(source_str, &psess, |p| p.parse_crate_mod())
 }
 
 /// Does the given string match the pattern? whitespace in the first string
@@ -180,6 +178,7 @@ impl<T: Write> Write for Shared<T> {
     }
 }
 
+#[allow(rustc::untranslatable_diagnostic)] // no translation needed for tests
 fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &str) {
     create_default_session_globals_then(|| {
         let (handler, source_map, output) = create_test_handler();
@@ -194,7 +193,6 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
             println!("text: {:?}", source_map.span_to_snippet(span));
         }
 
-        #[allow(rustc::untranslatable_diagnostic)]
         handler.span_err(msp, "foo");
 
         assert!(
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 1b2993dabdb..7e5197f16f9 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -146,6 +146,8 @@ declare_features! (
     (accepted, derive_default_enum, "1.62.0", Some(86985)),
     /// Allows the use of destructuring assignments.
     (accepted, destructuring_assignment, "1.59.0", Some(71126)),
+    /// Allows using the `#[diagnostic]` attribute tool namespace
+    (accepted, diagnostic_namespace, "CURRENT_RUSTC_VERSION", Some(111996)),
     /// Allows `#[doc(alias = "...")]`.
     (accepted, doc_alias, "1.48.0", Some(50146)),
     /// Allows `..` in tuple (struct) patterns.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 10867ae230a..0d51e1e46e0 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -695,8 +695,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // Used by the `rustc::potential_query_instability` lint to warn methods which
     // might not be stable during incremental compilation.
     rustc_attr!(rustc_lint_query_instability, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
-    // Used by the `rustc::untranslatable_diagnostic` and `rustc::diagnostic_outside_of_impl` lints
-    // to assist in changes to diagnostic APIs.
+    // Used by the `rustc::diagnostic_outside_of_impl` lints to assist in changes to diagnostic
+    // APIs. Any function with this attribute will be checked by that lint.
     rustc_attr!(rustc_lint_diagnostics, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
     // Used by the `rustc::bad_opt_access` lint to identify `DebuggingOptions` and `CodegenOptions`
     // types (as well as any others in future).
@@ -709,7 +709,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // Internal attributes, Const related:
     // ==========================================================================
 
-    rustc_attr!(rustc_promotable, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
+    rustc_attr!(
+        rustc_promotable, Normal, template!(Word), WarnFollowing,
+        @only_local: true, IMPL_DETAIL),
     rustc_attr!(
         rustc_legacy_const_generics, Normal, template!(List: "N"), ErrorFollowing,
         INTERNAL_UNSTABLE
@@ -784,7 +786,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
          the given type by annotating all impl items with #[rustc_allow_incoherent_impl]."
     ),
     rustc_attr!(
-        rustc_box, AttributeType::Normal, template!(Word), ErrorFollowing,
+        rustc_box, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true,
         "#[rustc_box] allows creating boxes \
         and it is only intended to be used in `alloc`."
     ),
@@ -806,11 +808,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     gated!(
         // Used in resolve:
         prelude_import, Normal, template!(Word), WarnFollowing,
-        "`#[prelude_import]` is for use by rustc only",
+        @only_local: true, "`#[prelude_import]` is for use by rustc only",
     ),
     gated!(
-        rustc_paren_sugar, Normal, template!(Word), WarnFollowing, unboxed_closures,
-        "unboxed_closures are still evolving",
+        rustc_paren_sugar, Normal, template!(Word), WarnFollowing, @only_local: true,
+        unboxed_closures, "unboxed_closures are still evolving",
     ),
     rustc_attr!(
         rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing, @only_local: true,
@@ -826,27 +828,31 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
     rustc_attr!(
         rustc_test_marker, Normal, template!(NameValueStr: "name"), WarnFollowing,
-        "the `#[rustc_test_marker]` attribute is used internally to track tests",
+        @only_local: true, "the `#[rustc_test_marker]` attribute is used internally to track tests",
     ),
     rustc_attr!(
-        rustc_unsafe_specialization_marker, Normal, template!(Word), WarnFollowing,
+        rustc_unsafe_specialization_marker, Normal, template!(Word),
+        WarnFollowing, @only_local: true,
         "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations"
     ),
     rustc_attr!(
-        rustc_specialization_trait, Normal, template!(Word), WarnFollowing,
+        rustc_specialization_trait, Normal, template!(Word),
+        WarnFollowing, @only_local: true,
         "the `#[rustc_specialization_trait]` attribute is used to check specializations"
     ),
     rustc_attr!(
-        rustc_main, Normal, template!(Word), WarnFollowing,
+        rustc_main, Normal, template!(Word), WarnFollowing, @only_local: true,
         "the `#[rustc_main]` attribute is used internally to specify test entry point function",
     ),
     rustc_attr!(
-        rustc_skip_array_during_method_dispatch, Normal, template!(Word), WarnFollowing,
+        rustc_skip_array_during_method_dispatch, Normal, template!(Word),
+        WarnFollowing, @only_local: true,
         "the `#[rustc_skip_array_during_method_dispatch]` attribute is used to exclude a trait \
         from method dispatch when the receiver is an array, for compatibility in editions < 2021."
     ),
     rustc_attr!(
-        rustc_must_implement_one_of, Normal, template!(List: "function1, function2, ..."), ErrorFollowing,
+        rustc_must_implement_one_of, Normal, template!(List: "function1, function2, ..."),
+        ErrorFollowing, @only_local: true,
         "the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete \
         definition of a trait, it's currently in experimental form and should be changed before \
         being exposed outside of the std"
@@ -857,6 +863,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
     rustc_attr!(
         rustc_safe_intrinsic, Normal, template!(Word), WarnFollowing,
+        @only_local: true,
         "the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe"
     ),
     rustc_attr!(
@@ -867,14 +874,24 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         rustc_no_mir_inline, Normal, template!(Word), WarnFollowing,
         "#[rustc_no_mir_inline] prevents the MIR inliner from inlining a function while not affecting codegen"
     ),
+    rustc_attr!(
+        rustc_intrinsic_must_be_overridden, Normal, template!(Word), ErrorFollowing,
+        "the `#[rustc_intrinsic_must_be_overridden]` attribute is used to declare intrinsics without real bodies",
+    ),
 
     // ==========================================================================
     // Internal attributes, Testing:
     // ==========================================================================
 
     rustc_attr!(TEST, rustc_effective_visibility, Normal, template!(Word), WarnFollowing),
-    rustc_attr!(TEST, rustc_outlives, Normal, template!(Word), WarnFollowing),
-    rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word), WarnFollowing),
+    rustc_attr!(
+        TEST, rustc_outlives, Normal, template!(Word),
+        WarnFollowing, @only_local: true
+    ),
+    rustc_attr!(
+        TEST, rustc_capture_analysis, Normal, template!(Word),
+        WarnFollowing, @only_local: true
+    ),
     rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word), WarnFollowing),
     rustc_attr!(TEST, rustc_strict_coherence, Normal, template!(Word), WarnFollowing),
     rustc_attr!(TEST, rustc_variance, Normal, template!(Word), WarnFollowing),
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 17c4d81474e..a10f4b934ea 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -345,6 +345,8 @@ declare_features! (
     (unstable, asm_const, "1.58.0", Some(93332)),
     /// Enables experimental inline assembly support for additional architectures.
     (unstable, asm_experimental_arch, "1.58.0", Some(93335)),
+    /// Allows using `label` operands in inline assembly.
+    (unstable, asm_goto, "CURRENT_RUSTC_VERSION", Some(119364)),
     /// Allows the `may_unwind` option in inline assembly.
     (unstable, asm_unwind, "1.58.0", Some(93334)),
     /// Allows users to enforce equality of associated constants `TraitImpl<AssocConst=3>`.
@@ -436,8 +438,6 @@ declare_features! (
     (unstable, deprecated_safe, "1.61.0", Some(94978)),
     /// Allows having using `suggestion` in the `#[deprecated]` attribute.
     (unstable, deprecated_suggestion, "1.61.0", Some(94785)),
-    /// Allows using the `#[diagnostic]` attribute tool namespace
-    (unstable, diagnostic_namespace, "1.73.0", Some(111996)),
     /// Controls errors in trait implementations.
     (unstable, do_not_recommend, "1.67.0", Some(51992)),
     /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs
index 520a64aaf5e..214b6587af3 100644
--- a/compiler/rustc_fluent_macro/src/fluent.rs
+++ b/compiler/rustc_fluent_macro/src/fluent.rs
@@ -54,20 +54,20 @@ fn finish(body: TokenStream, resource: TokenStream) -> proc_macro::TokenStream {
             /// identifiers for different subdiagnostic kinds.
             pub mod _subdiag {
                 /// Default for `#[help]`
-                pub const help: rustc_errors::SubdiagnosticMessage =
-                    rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("help"));
+                pub const help: rustc_errors::SubdiagMessage =
+                    rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("help"));
                 /// Default for `#[note]`
-                pub const note: rustc_errors::SubdiagnosticMessage =
-                    rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("note"));
+                pub const note: rustc_errors::SubdiagMessage =
+                    rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("note"));
                 /// Default for `#[warn]`
-                pub const warn: rustc_errors::SubdiagnosticMessage =
-                    rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("warn"));
+                pub const warn: rustc_errors::SubdiagMessage =
+                    rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("warn"));
                 /// Default for `#[label]`
-                pub const label: rustc_errors::SubdiagnosticMessage =
-                    rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("label"));
+                pub const label: rustc_errors::SubdiagMessage =
+                    rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("label"));
                 /// Default for `#[suggestion]`
-                pub const suggestion: rustc_errors::SubdiagnosticMessage =
-                    rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion"));
+                pub const suggestion: rustc_errors::SubdiagMessage =
+                    rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion"));
             }
         }
     }
@@ -244,8 +244,11 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
                 format!("Constant referring to Fluent message `{name}` from `{crate_name}`");
             constants.extend(quote! {
                 #[doc = #docstr]
-                pub const #snake_name: rustc_errors::DiagnosticMessage =
-                    rustc_errors::DiagnosticMessage::FluentIdentifier(std::borrow::Cow::Borrowed(#name), None);
+                pub const #snake_name: rustc_errors::DiagMessage =
+                    rustc_errors::DiagMessage::FluentIdentifier(
+                        std::borrow::Cow::Borrowed(#name),
+                        None
+                    );
             });
 
             for Attribute { id: Identifier { name: attr_name }, .. } in attributes {
@@ -272,8 +275,8 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
                 );
                 constants.extend(quote! {
                     #[doc = #msg]
-                    pub const #snake_name: rustc_errors::SubdiagnosticMessage =
-                        rustc_errors::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed(#attr_name));
+                    pub const #snake_name: rustc_errors::SubdiagMessage =
+                        rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed(#attr_name));
                 });
             }
 
diff --git a/compiler/rustc_fluent_macro/src/lib.rs b/compiler/rustc_fluent_macro/src/lib.rs
index e3784409af8..2303785f94e 100644
--- a/compiler/rustc_fluent_macro/src/lib.rs
+++ b/compiler/rustc_fluent_macro/src/lib.rs
@@ -35,10 +35,10 @@ mod fluent;
 ///
 /// mod fluent_generated {
 ///     mod typeck {
-///         pub const field_multiply_specified_in_initializer: DiagnosticMessage =
-///             DiagnosticMessage::fluent("typeck_field_multiply_specified_in_initializer");
-///         pub const field_multiply_specified_in_initializer_label_previous_use: DiagnosticMessage =
-///             DiagnosticMessage::fluent_attr(
+///         pub const field_multiply_specified_in_initializer: DiagMessage =
+///             DiagMessage::fluent("typeck_field_multiply_specified_in_initializer");
+///         pub const field_multiply_specified_in_initializer_label_previous_use: DiagMessage =
+///             DiagMessage::fluent_attr(
 ///                 "typeck_field_multiply_specified_in_initializer",
 ///                 "previous_use_label"
 ///             );
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 3dac6880f17..7d5b4c0f06d 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2562,6 +2562,8 @@ pub enum OpaqueTyOrigin {
     AsyncFn(LocalDefId),
     /// type aliases: `type Foo = impl Trait;`
     TyAlias {
+        /// The type alias or associated type parent of the TAIT/ATPIT
+        parent: LocalDefId,
         /// associated types in impl blocks for traits.
         in_assoc_ty: bool,
     },
@@ -2650,6 +2652,9 @@ pub enum InlineAsmOperand<'hir> {
         path: QPath<'hir>,
         def_id: DefId,
     },
+    Label {
+        block: &'hir Block<'hir>,
+    },
 }
 
 impl<'hir> InlineAsmOperand<'hir> {
@@ -2659,7 +2664,10 @@ impl<'hir> InlineAsmOperand<'hir> {
             | Self::Out { reg, .. }
             | Self::InOut { reg, .. }
             | Self::SplitInOut { reg, .. } => Some(reg),
-            Self::Const { .. } | Self::SymFn { .. } | Self::SymStatic { .. } => None,
+            Self::Const { .. }
+            | Self::SymFn { .. }
+            | Self::SymStatic { .. }
+            | Self::Label { .. } => None,
         }
     }
 
@@ -2680,6 +2688,12 @@ pub struct InlineAsm<'hir> {
     pub line_spans: &'hir [Span],
 }
 
+impl InlineAsm<'_> {
+    pub fn contains_label(&self) -> bool {
+        self.operands.iter().any(|x| matches!(x.0, InlineAsmOperand::Label { .. }))
+    }
+}
+
 /// Represents a parameter in a function header.
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub struct Param<'hir> {
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 1c38a45d3a3..32b4bf38fa9 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -65,8 +65,7 @@
 //! example coroutine inference, and possibly also HIR borrowck.
 
 use crate::hir::*;
-use rustc_ast::visit::VisitorResult;
-use rustc_ast::{try_visit, visit_opt, walk_list};
+use rustc_ast::visit::{try_visit, visit_opt, walk_list, VisitorResult};
 use rustc_ast::{Attribute, Label};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::{Ident, Symbol};
@@ -1290,6 +1289,7 @@ pub fn walk_inline_asm<'v, V: Visitor<'v>>(
             InlineAsmOperand::SymStatic { path, .. } => {
                 try_visit!(visitor.visit_qpath(path, id, *op_sp));
             }
+            InlineAsmOperand::Label { block } => try_visit!(visitor.visit_block(block)),
         }
     }
     V::Result::output()
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 8a89a3b5faa..5118bf5c3b7 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -267,6 +267,8 @@ language_item_table! {
     EhCatchTypeinfo,         sym::eh_catch_typeinfo,   eh_catch_typeinfo,          Target::Static,         GenericRequirement::None;
 
     OwnedBox,                sym::owned_box,           owned_box,                  Target::Struct,         GenericRequirement::Minimum(1);
+    GlobalAlloc,             sym::global_alloc_ty,     global_alloc_ty,            Target::Struct,         GenericRequirement::None;
+
     // Experimental language item for Miri
     PtrUnique,               sym::ptr_unique,          ptr_unique,                 Target::Struct,         GenericRequirement::Exact(1);
 
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index e376411cd95..bad472dcb5c 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -312,6 +312,10 @@ hir_analysis_only_current_traits_primitive = only traits defined in the current
 
 hir_analysis_only_current_traits_ty = `{$ty}` is not defined in the current crate
 
+hir_analysis_opaque_captures_higher_ranked_lifetime = `impl Trait` cannot capture {$bad_place}
+    .label = `impl Trait` implicitly captures all lifetimes in scope
+    .note = lifetime declared here
+
 hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
     .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
 
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index ce4c4609bc8..63afa4f7e82 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -3,7 +3,7 @@ use crate::astconv::{
     errors::prohibit_assoc_ty_binding, CreateInstantiationsForGenericArgsCtxt, ExplicitLateBound,
     GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition,
 };
-use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs};
+use crate::structured_errors::{GenericArgsInfo, StructuredDiag, WrongNumberOfGenericArgs};
 use rustc_ast::ast::ParamKindOrd;
 use rustc_errors::{
     codes::*, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan,
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index b8cf72c2c73..325342d653d 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -1612,10 +1612,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         .any(|impl_def_id| {
                             let impl_header = tcx.impl_trait_header(impl_def_id);
                             impl_header.is_some_and(|header| {
-                                let header = header.instantiate(
+                                let trait_ref = header.trait_ref.instantiate(
                                     tcx,
                                     infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
                                 );
+
                                 let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased);
                                 // FIXME: Don't bother dealing with non-lifetime binders here...
                                 if value.has_escaping_bound_vars() {
@@ -1624,7 +1625,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                 infcx
                                     .can_eq(
                                         ty::ParamEnv::empty(),
-                                        header.trait_ref.self_ty(),
+                                        trait_ref.self_ty(),
                                         value,
                                     ) && header.polarity != ty::ImplPolarity::Negative
                             })
@@ -1677,9 +1678,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     .filter(|header| {
                         // Consider only accessible traits
                         tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx)
-                            && header.skip_binder().polarity != ty::ImplPolarity::Negative
+                            && header.polarity != ty::ImplPolarity::Negative
                     })
-                    .map(|header| header.instantiate_identity().trait_ref.self_ty())
+                    .map(|header| header.trait_ref.instantiate_identity().self_ty())
                     // We don't care about blanket impls.
                     .filter(|self_ty| !self_ty.has_non_region_param())
                     .map(|self_ty| tcx.erase_regions(self_ty).to_string())
diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
index 7705445ffaa..b9543c7a29b 100644
--- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
@@ -45,10 +45,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 dummy_self,
                 &mut bounds,
                 false,
-                // FIXME: This should be `true`, but we don't really handle
-                // associated type bounds or type aliases in objects in a way
-                // that makes this meaningful, I think.
-                OnlySelfBounds(false),
+                // True so we don't populate `bounds` with associated type bounds, even
+                // though they're disallowed from object types.
+                OnlySelfBounds(true),
             ) {
                 potential_assoc_types.extend(cur_potential_assoc_types);
             }
@@ -83,9 +82,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let expanded_traits =
             traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b)));
 
-        let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits
-            .filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self)
-            .partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
+        let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
+            expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
         if regular_traits.len() > 1 {
             let first_trait = &regular_traits[0];
             let additional_trait = &regular_traits[1];
@@ -158,7 +156,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         for (base_trait_ref, span) in regular_traits_refs_spans {
             let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx);
-            for pred in traits::elaborate(tcx, [base_pred]) {
+            for pred in traits::elaborate(tcx, [base_pred]).filter_only_self() {
                 debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred);
 
                 let bound_predicate = pred.kind();
@@ -312,45 +310,39 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             })
         });
 
-        let existential_projections = projection_bounds
-            .iter()
-            // We filter out traits that don't have `Self` as their self type above,
-            // we need to do the same for projections.
-            .filter(|(bound, _)| bound.skip_binder().self_ty() == dummy_self)
-            .map(|(bound, _)| {
-                bound.map_bound(|mut b| {
-                    assert_eq!(b.projection_ty.self_ty(), dummy_self);
+        let existential_projections = projection_bounds.iter().map(|(bound, _)| {
+            bound.map_bound(|mut b| {
+                assert_eq!(b.projection_ty.self_ty(), dummy_self);
 
-                    // Like for trait refs, verify that `dummy_self` did not leak inside default type
-                    // parameters.
-                    let references_self = b.projection_ty.args.iter().skip(1).any(|arg| {
-                        if arg.walk().any(|arg| arg == dummy_self.into()) {
-                            return true;
-                        }
-                        false
-                    });
-                    if references_self {
-                        let guar = tcx.dcx().span_delayed_bug(
-                            span,
-                            "trait object projection bounds reference `Self`",
-                        );
-                        let args: Vec<_> = b
-                            .projection_ty
-                            .args
-                            .iter()
-                            .map(|arg| {
-                                if arg.walk().any(|arg| arg == dummy_self.into()) {
-                                    return Ty::new_error(tcx, guar).into();
-                                }
-                                arg
-                            })
-                            .collect();
-                        b.projection_ty.args = tcx.mk_args(&args);
+                // Like for trait refs, verify that `dummy_self` did not leak inside default type
+                // parameters.
+                let references_self = b.projection_ty.args.iter().skip(1).any(|arg| {
+                    if arg.walk().any(|arg| arg == dummy_self.into()) {
+                        return true;
                     }
+                    false
+                });
+                if references_self {
+                    let guar = tcx
+                        .dcx()
+                        .span_delayed_bug(span, "trait object projection bounds reference `Self`");
+                    let args: Vec<_> = b
+                        .projection_ty
+                        .args
+                        .iter()
+                        .map(|arg| {
+                            if arg.walk().any(|arg| arg == dummy_self.into()) {
+                                return Ty::new_error(tcx, guar).into();
+                            }
+                            arg
+                        })
+                        .collect();
+                    b.projection_ty.args = tcx.mk_args(&args);
+                }
 
-                    ty::ExistentialProjection::erase_self_ty(tcx, b)
-                })
-            });
+                ty::ExistentialProjection::erase_self_ty(tcx, b)
+            })
+        });
 
         let regular_trait_predicates = existential_trait_refs
             .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait));
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 96bebda5828..1b24c2b61fd 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -339,8 +339,9 @@ fn check_opaque_meets_bounds<'tcx>(
     origin: &hir::OpaqueTyOrigin,
 ) -> Result<(), ErrorGuaranteed> {
     let defining_use_anchor = match *origin {
-        hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did,
-        hir::OpaqueTyOrigin::TyAlias { .. } => tcx.impl_trait_parent(def_id),
+        hir::OpaqueTyOrigin::FnReturn(did)
+        | hir::OpaqueTyOrigin::AsyncFn(did)
+        | hir::OpaqueTyOrigin::TyAlias { parent: did, .. } => did,
     };
     let param_env = tcx.param_env(defining_use_anchor);
 
@@ -351,14 +352,14 @@ fn check_opaque_meets_bounds<'tcx>(
     let ocx = ObligationCtxt::new(&infcx);
 
     let args = match *origin {
-        hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => {
-            GenericArgs::identity_for_item(tcx, parent).extend_to(
-                tcx,
-                def_id.to_def_id(),
-                |param, _| tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local()).into(),
-            )
-        }
-        hir::OpaqueTyOrigin::TyAlias { .. } => GenericArgs::identity_for_item(tcx, def_id),
+        hir::OpaqueTyOrigin::FnReturn(parent)
+        | hir::OpaqueTyOrigin::AsyncFn(parent)
+        | hir::OpaqueTyOrigin::TyAlias { parent, .. } => GenericArgs::identity_for_item(
+            tcx, parent,
+        )
+        .extend_to(tcx, def_id.to_def_id(), |param, _| {
+            tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()).into()
+        }),
     };
 
     let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
@@ -402,39 +403,29 @@ fn check_opaque_meets_bounds<'tcx>(
         let guar = infcx.err_ctxt().report_fulfillment_errors(errors);
         return Err(guar);
     }
-    match origin {
-        // Checked when type checking the function containing them.
-        hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {
-            // HACK: this should also fall through to the hidden type check below, but the original
-            // implementation had a bug where equivalent lifetimes are not identical. This caused us
-            // to reject existing stable code that is otherwise completely fine. The real fix is to
-            // compare the hidden types via our type equivalence/relation infra instead of doing an
-            // identity check.
-            let _ = infcx.take_opaque_types();
-            return Ok(());
-        }
-        // Nested opaque types occur only in associated types:
-        // ` type Opaque<T> = impl Trait<&'static T, AssocTy = impl Nested>; `
-        // They can only be referenced as `<Opaque<T> as Trait<&'static T>>::AssocTy`.
-        // We don't have to check them here because their well-formedness follows from the WF of
-        // the projection input types in the defining- and use-sites.
-        hir::OpaqueTyOrigin::TyAlias { .. }
-            if tcx.def_kind(tcx.parent(def_id.to_def_id())) == DefKind::OpaqueTy => {}
-        // Can have different predicates to their defining use
-        hir::OpaqueTyOrigin::TyAlias { .. } => {
-            let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, def_id)?;
-            let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, &wf_tys);
-            let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
-            ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?;
+
+    let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, defining_use_anchor)?;
+    let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, &wf_tys);
+    let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
+    ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?;
+
+    if let hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) = origin {
+        // HACK: this should also fall through to the hidden type check below, but the original
+        // implementation had a bug where equivalent lifetimes are not identical. This caused us
+        // to reject existing stable code that is otherwise completely fine. The real fix is to
+        // compare the hidden types via our type equivalence/relation infra instead of doing an
+        // identity check.
+        let _ = infcx.take_opaque_types();
+        Ok(())
+    } else {
+        // Check that any hidden types found during wf checking match the hidden types that `type_of` sees.
+        for (mut key, mut ty) in infcx.take_opaque_types() {
+            ty.hidden_type.ty = infcx.resolve_vars_if_possible(ty.hidden_type.ty);
+            key = infcx.resolve_vars_if_possible(key);
+            sanity_check_found_hidden_type(tcx, key, ty.hidden_type)?;
         }
+        Ok(())
     }
-    // Check that any hidden types found during wf checking match the hidden types that `type_of` sees.
-    for (mut key, mut ty) in infcx.take_opaque_types() {
-        ty.hidden_type.ty = infcx.resolve_vars_if_possible(ty.hidden_type.ty);
-        key = infcx.resolve_vars_if_possible(key);
-        sanity_check_found_hidden_type(tcx, key, ty.hidden_type)?;
-    }
-    Ok(())
 }
 
 fn sanity_check_found_hidden_type<'tcx>(
@@ -527,12 +518,12 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
             check_enum(tcx, def_id);
         }
         DefKind::Fn => {
-            if let Some(name) = tcx.intrinsic(def_id) {
+            if let Some(i) = tcx.intrinsic(def_id) {
                 intrinsic::check_intrinsic_type(
                     tcx,
                     def_id,
                     tcx.def_ident_span(def_id).unwrap(),
-                    name,
+                    i.name,
                     Abi::Rust,
                 )
             }
@@ -540,11 +531,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         }
         DefKind::Impl { of_trait } => {
             if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) {
-                check_impl_items_against_trait(
-                    tcx,
-                    def_id,
-                    impl_trait_header.instantiate_identity(),
-                );
+                check_impl_items_against_trait(tcx, def_id, impl_trait_header);
                 check_on_unimplemented(tcx, def_id);
             }
         }
@@ -735,10 +722,11 @@ fn check_impl_items_against_trait<'tcx>(
     impl_id: LocalDefId,
     impl_trait_header: ty::ImplTraitHeader<'tcx>,
 ) {
+    let trait_ref = impl_trait_header.trait_ref.instantiate_identity();
     // If the trait reference itself is erroneous (so the compilation is going
     // to fail), skip checking the items here -- the `impl_item` table in `tcx`
     // isn't populated for such impls.
-    if impl_trait_header.references_error() {
+    if trait_ref.references_error() {
         return;
     }
 
@@ -762,7 +750,7 @@ fn check_impl_items_against_trait<'tcx>(
         }
     }
 
-    let trait_def = tcx.trait_def(impl_trait_header.trait_ref.def_id);
+    let trait_def = tcx.trait_def(trait_ref.def_id);
 
     for &impl_item in impl_item_refs {
         let ty_impl_item = tcx.associated_item(impl_item);
@@ -781,10 +769,10 @@ fn check_impl_items_against_trait<'tcx>(
                 ));
             }
             ty::AssocKind::Fn => {
-                compare_impl_method(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref);
+                compare_impl_method(tcx, ty_impl_item, ty_trait_item, trait_ref);
             }
             ty::AssocKind::Type => {
-                compare_impl_ty(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref);
+                compare_impl_ty(tcx, ty_impl_item, ty_trait_item, trait_ref);
             }
         }
 
@@ -804,7 +792,7 @@ fn check_impl_items_against_trait<'tcx>(
         let mut must_implement_one_of: Option<&[Ident]> =
             trait_def.must_implement_one_of.as_deref();
 
-        for &trait_item_id in tcx.associated_item_def_ids(impl_trait_header.trait_ref.def_id) {
+        for &trait_item_id in tcx.associated_item_def_ids(trait_ref.def_id) {
             let leaf_def = ancestors.leaf_def(tcx, trait_item_id);
 
             let is_implemented = leaf_def
@@ -882,7 +870,7 @@ fn check_impl_items_against_trait<'tcx>(
 
         if let Some(missing_items) = must_implement_one_of {
             let attr_span = tcx
-                .get_attr(impl_trait_header.trait_ref.def_id, sym::rustc_must_implement_one_of)
+                .get_attr(trait_ref.def_id, sym::rustc_must_implement_one_of)
                 .map(|attr| attr.span);
 
             missing_items_must_implement_one_of_err(
@@ -1474,15 +1462,14 @@ fn opaque_type_cycle_error(
                     closures: Vec<DefId>,
                 }
                 impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector {
-                    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+                    fn visit_ty(&mut self, t: Ty<'tcx>) {
                         match *t.kind() {
                             ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
                                 self.opaques.push(def);
-                                ControlFlow::Continue(())
                             }
                             ty::Closure(def_id, ..) | ty::Coroutine(def_id, ..) => {
                                 self.closures.push(def_id);
-                                t.super_visit_with(self)
+                                t.super_visit_with(self);
                             }
                             _ => t.super_visit_with(self),
                         }
@@ -1550,6 +1537,8 @@ fn opaque_type_cycle_error(
     err.emit()
 }
 
+// FIXME(@lcnr): This should not be computed per coroutine, but instead once for
+// each typeck root.
 pub(super) fn check_coroutine_obligations(
     tcx: TyCtxt<'_>,
     def_id: LocalDefId,
@@ -1557,7 +1546,7 @@ pub(super) fn check_coroutine_obligations(
     debug_assert!(tcx.is_coroutine(def_id.to_def_id()));
 
     let typeck = tcx.typeck(def_id);
-    let param_env = tcx.param_env(def_id);
+    let param_env = tcx.param_env(typeck.hir_owner.def_id);
 
     let coroutine_interior_predicates = &typeck.coroutine_interior_predicates[&def_id];
     debug!(?coroutine_interior_predicates);
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 435e251b130..ec9e928ce59 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1,5 +1,6 @@
 use super::potentially_plural_count;
 use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture};
+use core::ops::ControlFlow;
 use hir::def_id::{DefId, DefIdMap, LocalDefId};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
@@ -520,14 +521,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
         )
         .fold_with(&mut collector);
 
-    if !unnormalized_trait_sig.output().references_error() {
-        debug_assert_ne!(
-            collector.types.len(),
-            0,
-            "expect >1 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`"
-        );
-    }
-
     let trait_sig = ocx.normalize(&misc_cause, param_env, unnormalized_trait_sig);
     trait_sig.error_reported()?;
     let trait_return_ty = trait_sig.output();
@@ -646,6 +639,13 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
         }
     }
 
+    if !unnormalized_trait_sig.output().references_error() {
+        debug_assert!(
+            !collector.types.is_empty(),
+            "expect >0 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`"
+        );
+    }
+
     // FIXME: This has the same issue as #108544, but since this isn't breaking
     // existing code, I'm not particularly inclined to do the same hack as above
     // where we process wf obligations manually. This can be fixed in a forward-
@@ -1565,24 +1565,24 @@ fn compare_synthetic_generics<'tcx>(
                     let (sig, _) = impl_m.expect_fn();
                     let input_tys = sig.decl.inputs;
 
-                    struct Visitor(Option<Span>, hir::def_id::LocalDefId);
+                    struct Visitor(hir::def_id::LocalDefId);
                     impl<'v> intravisit::Visitor<'v> for Visitor {
-                        fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
-                            intravisit::walk_ty(self, ty);
+                        type Result = ControlFlow<Span>;
+                        fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) -> Self::Result {
                             if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ty.kind
                                 && let Res::Def(DefKind::TyParam, def_id) = path.res
-                                && def_id == self.1.to_def_id()
+                                && def_id == self.0.to_def_id()
                             {
-                                self.0 = Some(ty.span);
+                                ControlFlow::Break(ty.span)
+                            } else {
+                                intravisit::walk_ty(self, ty)
                             }
                         }
                     }
 
-                    let mut visitor = Visitor(None, impl_def_id);
-                    for ty in input_tys {
-                        intravisit::Visitor::visit_ty(&mut visitor, ty);
-                    }
-                    let span = visitor.0?;
+                    let span = input_tys.iter().find_map(|ty| {
+                        intravisit::Visitor::visit_ty(&mut Visitor(impl_def_id), ty).break_value()
+                    })?;
 
                     let bounds = impl_m.generics.bounds_for_param(impl_def_id).next()?.bounds;
                     let bounds = bounds.first()?.span().to(bounds.last()?.span());
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
index 29dc434ab45..8c4c4fc774e 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
@@ -12,7 +12,6 @@ use rustc_trait_selection::regions::InferCtxtRegionExt;
 use rustc_trait_selection::traits::{
     elaborate, normalize_param_env_or_error, outlives_bounds::InferCtxtExt, ObligationCtxt,
 };
-use std::ops::ControlFlow;
 
 /// Check that an implementation does not refine an RPITIT from a trait method signature.
 pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
@@ -211,9 +210,7 @@ struct ImplTraitInTraitCollector<'tcx> {
 }
 
 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'tcx> {
-    type BreakTy = !;
-
-    fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, ty: Ty<'tcx>) {
         if let ty::Alias(ty::Projection, proj) = *ty.kind()
             && self.tcx.is_impl_trait_in_trait(proj.def_id)
         {
@@ -223,12 +220,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'tcx> {
                     .explicit_item_bounds(proj.def_id)
                     .iter_instantiated_copied(self.tcx, proj.args)
                 {
-                    pred.visit_with(self)?;
+                    pred.visit_with(self);
                 }
             }
-            ControlFlow::Continue(())
         } else {
-            ty.super_visit_with(self)
+            ty.super_visit_with(self);
         }
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs
index c92320bc0fe..3d32fdd89c8 100644
--- a/compiler/rustc_hir_analysis/src/check/errs.rs
+++ b/compiler/rustc_hir_analysis/src/check/errs.rs
@@ -70,7 +70,7 @@ fn handle_static_mut_ref(
         } else {
             (errors::StaticMutRefSugg::Shared { span, var }, "shared")
         };
-        tcx.sess.parse_sess.dcx.emit_err(errors::StaticMutRef { span, sugg, shared });
+        tcx.sess.psess.dcx.emit_err(errors::StaticMutRef { span, sugg, shared });
         return;
     }
 
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 9d8eb6ad60b..95c51cc0486 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -7,7 +7,7 @@ use crate::errors::{
     WrongNumberOfGenericArgumentsToIntrinsic,
 };
 
-use rustc_errors::{codes::*, struct_span_code_err, DiagnosticMessage};
+use rustc_errors::{codes::*, struct_span_code_err, DiagMessage};
 use rustc_hir as hir;
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -132,14 +132,15 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
         | sym::fsub_algebraic
         | sym::fmul_algebraic
         | sym::fdiv_algebraic
-        | sym::frem_algebraic => hir::Unsafety::Normal,
+        | sym::frem_algebraic
+        | sym::const_eval_select => hir::Unsafety::Normal,
         _ => hir::Unsafety::Unsafe,
     };
 
     if has_safe_attr != is_in_list {
         tcx.dcx().struct_span_err(
             tcx.def_span(intrinsic_id),
-            DiagnosticMessage::from(format!(
+            DiagMessage::from(format!(
                 "intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `{}`",
                 tcx.item_name(intrinsic_id.into())
             )
@@ -247,7 +248,6 @@ pub fn check_intrinsic_type(
                 ],
                 Ty::new_unit(tcx),
             ),
-            sym::drop_in_place => (1, 0, vec![Ty::new_mut_ptr(tcx, param(0))], Ty::new_unit(tcx)),
             sym::needs_drop => (1, 0, vec![], tcx.types.bool),
 
             sym::type_name => (1, 0, vec![], Ty::new_static_str(tcx)),
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index d03b02f028d..9de660407d7 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -470,6 +470,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
                         }
                     };
                 }
+                // No special checking is needed for labels.
+                hir::InlineAsmOperand::Label { .. } => {}
             }
         }
     }
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index 0f5fd7e99b7..2a4dd6b0e0e 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -6,7 +6,7 @@
 //!
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
 
-use rustc_ast::walk_list;
+use rustc_ast::visit::walk_list;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index f03d0f8a885..09689b22e90 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1,7 +1,9 @@
 use crate::autoderef::Autoderef;
+use crate::collect::CollectItemTypesVisitor;
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
 use crate::errors;
 
+use hir::intravisit::Visitor;
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
@@ -225,6 +227,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
         ?item.owner_id,
         item.name = ? tcx.def_path_str(def_id)
     );
+    CollectItemTypesVisitor { tcx }.visit_item(item);
 
     let res = match item.kind {
         // Right now we check that every default trait implementation
@@ -247,7 +250,9 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
         hir::ItemKind::Impl(impl_) => {
             let header = tcx.impl_trait_header(def_id);
             let is_auto = header
-                .is_some_and(|header| tcx.trait_is_auto(header.skip_binder().trait_ref.def_id));
+                .is_some_and(|header| tcx.trait_is_auto(header.trait_ref.skip_binder().def_id));
+
+            crate::impl_wf_check::check_impl_wf(tcx, def_id)?;
             let mut res = Ok(());
             if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
                 let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
@@ -259,7 +264,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
                     .emit());
             }
             // We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
-            match header.map(|h| h.skip_binder().polarity) {
+            match header.map(|h| h.polarity) {
                 // `None` means this is an inherent impl
                 Some(ty::ImplPolarity::Positive) | None => {
                     res = res.and(check_impl(tcx, item, impl_.self_ty, &impl_.of_trait));
@@ -296,31 +301,31 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
         hir::ItemKind::Const(ty, ..) => {
             check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid)
         }
-        hir::ItemKind::Struct(_, ast_generics) => {
+        hir::ItemKind::Struct(_, hir_generics) => {
             let res = check_type_defn(tcx, item, false);
-            check_variances_for_type_defn(tcx, item, ast_generics);
+            check_variances_for_type_defn(tcx, item, hir_generics);
             res
         }
-        hir::ItemKind::Union(_, ast_generics) => {
+        hir::ItemKind::Union(_, hir_generics) => {
             let res = check_type_defn(tcx, item, true);
-            check_variances_for_type_defn(tcx, item, ast_generics);
+            check_variances_for_type_defn(tcx, item, hir_generics);
             res
         }
-        hir::ItemKind::Enum(_, ast_generics) => {
+        hir::ItemKind::Enum(_, hir_generics) => {
             let res = check_type_defn(tcx, item, true);
-            check_variances_for_type_defn(tcx, item, ast_generics);
+            check_variances_for_type_defn(tcx, item, hir_generics);
             res
         }
         hir::ItemKind::Trait(..) => check_trait(tcx, item),
         hir::ItemKind::TraitAlias(..) => check_trait(tcx, item),
         // `ForeignItem`s are handled separately.
         hir::ItemKind::ForeignMod { .. } => Ok(()),
-        hir::ItemKind::TyAlias(hir_ty, ast_generics) => {
+        hir::ItemKind::TyAlias(hir_ty, hir_generics) => {
             if tcx.type_alias_is_lazy(item.owner_id) {
                 // Bounds of lazy type aliases and of eager ones that contain opaque types are respected.
                 // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`.
                 let res = check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow);
-                check_variances_for_type_defn(tcx, item, ast_generics);
+                check_variances_for_type_defn(tcx, item, hir_generics);
                 res
             } else {
                 Ok(())
@@ -334,9 +339,14 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
     res
 }
 
-fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) -> Result<(), ErrorGuaranteed> {
+fn check_foreign_item<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    item: &'tcx hir::ForeignItem<'tcx>,
+) -> Result<(), ErrorGuaranteed> {
     let def_id = item.owner_id.def_id;
 
+    CollectItemTypesVisitor { tcx }.visit_foreign_item(item);
+
     debug!(
         ?item.owner_id,
         item.name = ? tcx.def_path_str(def_id)
@@ -353,12 +363,14 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) -> Result<()
     }
 }
 
-fn check_trait_item(
-    tcx: TyCtxt<'_>,
-    trait_item: &hir::TraitItem<'_>,
+fn check_trait_item<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_item: &'tcx hir::TraitItem<'tcx>,
 ) -> Result<(), ErrorGuaranteed> {
     let def_id = trait_item.owner_id.def_id;
 
+    CollectItemTypesVisitor { tcx }.visit_trait_item(trait_item);
+
     let (method_sig, span) = match trait_item.kind {
         hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span),
         hir::TraitItemKind::Type(_bounds, Some(ty)) => (None, ty.span),
@@ -809,9 +821,7 @@ impl<'tcx> GATArgsCollector<'tcx> {
 }
 
 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> {
-    type BreakTy = !;
-
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, t: Ty<'tcx>) {
         match t.kind() {
             ty::Alias(ty::Projection, p) if p.def_id == self.gat => {
                 for (idx, arg) in p.args.iter().enumerate() {
@@ -895,7 +905,12 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
     }
 }
 
-fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) -> Result<(), ErrorGuaranteed> {
+fn check_impl_item<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    impl_item: &'tcx hir::ImplItem<'tcx>,
+) -> Result<(), ErrorGuaranteed> {
+    CollectItemTypesVisitor { tcx }.visit_impl_item(impl_item);
+
     let (method_sig, span) = match impl_item.kind {
         hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
         // Constrain binding and overflow error spans to `<Ty>` in `type foo = <Ty>`.
@@ -1277,16 +1292,16 @@ fn check_item_type(
     })
 }
 
-#[instrument(level = "debug", skip(tcx, ast_self_ty, ast_trait_ref))]
+#[instrument(level = "debug", skip(tcx, hir_self_ty, hir_trait_ref))]
 fn check_impl<'tcx>(
     tcx: TyCtxt<'tcx>,
     item: &'tcx hir::Item<'tcx>,
-    ast_self_ty: &hir::Ty<'_>,
-    ast_trait_ref: &Option<hir::TraitRef<'_>>,
+    hir_self_ty: &hir::Ty<'_>,
+    hir_trait_ref: &Option<hir::TraitRef<'_>>,
 ) -> Result<(), ErrorGuaranteed> {
     enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
-        match ast_trait_ref {
-            Some(ast_trait_ref) => {
+        match hir_trait_ref {
+            Some(hir_trait_ref) => {
                 // `#[rustc_reservation_impl]` impls are not real impls and
                 // therefore don't need to be WF (the trait's `Self: Trait` predicate
                 // won't hold).
@@ -1294,8 +1309,9 @@ fn check_impl<'tcx>(
                 // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
                 // other `Foo` impls are incoherent.
                 tcx.ensure().coherent_trait(trait_ref.def_id)?;
+                let trait_span = hir_trait_ref.path.span;
                 let trait_ref = wfcx.normalize(
-                    ast_trait_ref.path.span,
+                    trait_span,
                     Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
                     trait_ref,
                 );
@@ -1306,14 +1322,23 @@ fn check_impl<'tcx>(
                     wfcx.param_env,
                     wfcx.body_def_id,
                     trait_pred,
-                    ast_trait_ref.path.span,
+                    trait_span,
                     item,
                 );
                 for obligation in &mut obligations {
+                    if obligation.cause.span != trait_span {
+                        // We already have a better span.
+                        continue;
+                    }
                     if let Some(pred) = obligation.predicate.to_opt_poly_trait_pred()
-                        && pred.self_ty().skip_binder() == trait_ref.self_ty()
+                        && pred.skip_binder().self_ty() == trait_ref.self_ty()
                     {
-                        obligation.cause.span = ast_self_ty.span;
+                        obligation.cause.span = hir_self_ty.span;
+                    }
+                    if let Some(pred) = obligation.predicate.to_opt_poly_projection_pred()
+                        && pred.skip_binder().self_ty() == trait_ref.self_ty()
+                    {
+                        obligation.cause.span = hir_self_ty.span;
                     }
                 }
                 debug!(?obligations);
@@ -1327,7 +1352,7 @@ fn check_impl<'tcx>(
                     self_ty,
                 );
                 wfcx.register_wf_obligation(
-                    ast_self_ty.span,
+                    hir_self_ty.span,
                     Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
                     self_ty.into(),
                 );
@@ -1456,20 +1481,19 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
                 params: FxHashSet<u32>,
             }
             impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for CountParams {
-                type BreakTy = ();
-
-                fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+                type Result = ControlFlow<()>;
+                fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
                     if let ty::Param(param) = t.kind() {
                         self.params.insert(param.index);
                     }
                     t.super_visit_with(self)
                 }
 
-                fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+                fn visit_region(&mut self, _: ty::Region<'tcx>) -> Self::Result {
                     ControlFlow::Break(())
                 }
 
-                fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+                fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {
                     if let ty::ConstKind::Param(param) = c.kind() {
                         self.params.insert(param.index);
                     }
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 6c3a9b747ef..8d8b13d6cb3 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -25,7 +25,7 @@ use rustc_trait_selection::traits::ObligationCtxt;
 use rustc_trait_selection::traits::{self, ObligationCause};
 use std::collections::BTreeMap;
 
-pub fn check_trait<'tcx>(
+pub(super) fn check_trait<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_def_id: DefId,
     impl_def_id: LocalDefId,
@@ -66,10 +66,9 @@ impl<'tcx> Checker<'tcx> {
 
 fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
     let tcx = checker.tcx;
-    let header = checker.impl_header;
     let impl_did = checker.impl_def_id;
     // Destructors only work on local ADT types.
-    match header.trait_ref.self_ty().kind() {
+    match checker.impl_header.trait_ref.instantiate_identity().self_ty().kind() {
         ty::Adt(def, _) if def.did().is_local() => return Ok(()),
         ty::Error(_) => return Ok(()),
         _ => {}
@@ -86,7 +85,7 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran
     let impl_did = checker.impl_def_id;
     debug!("visit_implementation_of_copy: impl_did={:?}", impl_did);
 
-    let self_type = impl_header.trait_ref.self_ty();
+    let self_type = impl_header.trait_ref.instantiate_identity().self_ty();
     debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
 
     let param_env = tcx.param_env(impl_did);
@@ -120,7 +119,7 @@ fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), E
     let tcx = checker.tcx;
     let header = checker.impl_header;
     let impl_did = checker.impl_def_id;
-    let self_type = header.trait_ref.self_ty();
+    let self_type = header.trait_ref.instantiate_identity().self_ty();
     assert!(!self_type.has_escaping_bound_vars());
 
     let param_env = tcx.param_env(impl_did);
@@ -157,9 +156,8 @@ fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), E
 
 fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
     let tcx = checker.tcx;
-    let header = checker.impl_header;
     let impl_did = checker.impl_def_id;
-    let trait_ref = header.trait_ref;
+    let trait_ref = checker.impl_header.trait_ref.instantiate_identity();
     debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did);
 
     let span = tcx.def_span(impl_did);
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index d6281fa08f7..fc7a73e12be 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -134,11 +134,12 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed>
     let mut res = tcx.ensure().specialization_graph_of(def_id);
 
     for &impl_def_id in impls {
-        let trait_header = tcx.impl_trait_header(impl_def_id).unwrap().instantiate_identity();
-        let trait_def = tcx.trait_def(trait_header.trait_ref.def_id);
+        let trait_header = tcx.impl_trait_header(impl_def_id).unwrap();
+        let trait_ref = trait_header.trait_ref.instantiate_identity();
+        let trait_def = tcx.trait_def(trait_ref.def_id);
 
-        res = res.and(check_impl(tcx, impl_def_id, trait_header.trait_ref, trait_def));
-        res = res.and(check_object_overlap(tcx, impl_def_id, trait_header.trait_ref));
+        res = res.and(check_impl(tcx, impl_def_id, trait_ref, trait_def));
+        res = res.and(check_object_overlap(tcx, impl_def_id, trait_ref));
 
         res = res.and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def));
         res = res.and(tcx.ensure().orphan_check_impl(impl_def_id));
diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
index 53a5ada4105..13ce4f07593 100644
--- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
@@ -13,9 +13,10 @@ pub(super) fn check_item(
     trait_header: ImplTraitHeader<'_>,
     trait_def: &TraitDef,
 ) -> Result<(), ErrorGuaranteed> {
-    let trait_ref = trait_header.trait_ref;
     let unsafe_attr =
         tcx.generics_of(def_id).params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle");
+    let trait_ref = trait_header.trait_ref.instantiate_identity();
+
     match (trait_def.unsafety, unsafe_attr, trait_header.unsafety, trait_header.polarity) {
         (Unsafety::Normal, None, Unsafety::Unsafe, Positive | Reservation) => {
             let span = tcx.def_span(def_id);
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index b6e2695590c..10922d53479 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -20,7 +20,7 @@ use rustc_data_structures::unord::UnordMap;
 use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{GenericParamKind, Node};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
@@ -52,11 +52,6 @@ mod resolve_bound_vars;
 mod type_of;
 
 ///////////////////////////////////////////////////////////////////////////
-// Main entry point
-
-fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
-    tcx.hir().visit_item_likes_in_module(module_def_id, &mut CollectItemTypesVisitor { tcx });
-}
 
 pub fn provide(providers: &mut Providers) {
     resolve_bound_vars::provide(providers);
@@ -82,7 +77,6 @@ pub fn provide(providers: &mut Providers) {
         impl_trait_header,
         coroutine_kind,
         coroutine_for_closure,
-        collect_mod_item_types,
         is_type_alias_impl_trait,
         find_field,
         ..*providers
@@ -155,8 +149,8 @@ impl<'v> Visitor<'v> for HirPlaceholderCollector {
     }
 }
 
-struct CollectItemTypesVisitor<'tcx> {
-    tcx: TyCtxt<'tcx>,
+pub struct CollectItemTypesVisitor<'tcx> {
+    pub tcx: TyCtxt<'tcx>,
 }
 
 /// If there are any placeholder types (`_`), emit an error explaining that this is not allowed
@@ -791,7 +785,12 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
 }
 
 fn find_field(tcx: TyCtxt<'_>, (def_id, ident): (DefId, Ident)) -> Option<FieldIdx> {
-    tcx.adt_def(def_id).non_enum_variant().fields.iter_enumerated().find_map(|(idx, field)| {
+    let adt = tcx.adt_def(def_id);
+    if adt.is_enum() {
+        return None;
+    }
+
+    adt.non_enum_variant().fields.iter_enumerated().find_map(|(idx, field)| {
         if field.is_unnamed() {
             let field_ty = tcx.type_of(field.did).instantiate_identity();
             let adt_def = field_ty.ty_adt_def().expect("expect Adt for unnamed field");
@@ -1514,10 +1513,7 @@ fn suggest_impl_trait<'tcx>(
     None
 }
 
-fn impl_trait_header(
-    tcx: TyCtxt<'_>,
-    def_id: LocalDefId,
-) -> Option<ty::EarlyBinder<ty::ImplTraitHeader<'_>>> {
+fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTraitHeader<'_>> {
     let icx = ItemCtxt::new(tcx, def_id);
     let item = tcx.hir().expect_item(def_id);
     let impl_ = item.expect_impl();
@@ -1553,11 +1549,11 @@ fn impl_trait_header(
             } else {
                 icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty)
             };
-            ty::EarlyBinder::bind(ty::ImplTraitHeader {
-                trait_ref,
+            ty::ImplTraitHeader {
+                trait_ref: ty::EarlyBinder::bind(trait_ref),
                 unsafety: impl_.unsafety,
                 polarity: polarity_of_impl(tcx, def_id,  impl_, item.span)
-            })
+            }
         })
 }
 
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 9cc6c16c126..c86788db988 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -14,6 +14,43 @@ use rustc_span::Span;
 pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
     use rustc_hir::*;
 
+    // For an RPITIT, synthesize generics which are equal to the opaque's generics
+    // and parent fn's generics compressed into one list.
+    if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id }) =
+        tcx.opt_rpitit_info(def_id.to_def_id())
+    {
+        let trait_def_id = tcx.parent(fn_def_id);
+        let opaque_ty_generics = tcx.generics_of(opaque_def_id);
+        let opaque_ty_parent_count = opaque_ty_generics.parent_count;
+        let mut params = opaque_ty_generics.params.clone();
+
+        let parent_generics = tcx.generics_of(trait_def_id);
+        let parent_count = parent_generics.parent_count + parent_generics.params.len();
+
+        let mut trait_fn_params = tcx.generics_of(fn_def_id).params.clone();
+
+        for param in &mut params {
+            param.index = param.index + parent_count as u32 + trait_fn_params.len() as u32
+                - opaque_ty_parent_count as u32;
+        }
+
+        trait_fn_params.extend(params);
+        params = trait_fn_params;
+
+        let param_def_id_to_index =
+            params.iter().map(|param| (param.def_id, param.index)).collect();
+
+        return ty::Generics {
+            parent: Some(trait_def_id),
+            parent_count,
+            params,
+            param_def_id_to_index,
+            has_self: opaque_ty_generics.has_self,
+            has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
+            host_effect_index: parent_generics.host_effect_index,
+        };
+    }
+
     let hir_id = tcx.local_def_id_to_hir_id(def_id);
 
     let node = tcx.hir_node(hir_id);
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index f70bb8c4289..2675eacc06e 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -339,7 +339,7 @@ fn compute_bidirectional_outlives_predicates<'tcx>(
     predicates: &mut Vec<(ty::Clause<'tcx>, Span)>,
 ) {
     for param in opaque_own_params {
-        let orig_lifetime = tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local());
+        let orig_lifetime = tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local());
         if let ty::ReEarlyParam(..) = *orig_lifetime {
             let dup_lifetime = ty::Region::new_early_param(
                 tcx,
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index ae01bf84575..7936621c868 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -6,9 +6,9 @@
 //! the types in HIR to identify late-bound lifetimes and assign their Debruijn indices. This file
 //! is also responsible for assigning their semantics to implicit lifetimes in trait objects.
 
-use rustc_ast::walk_list;
+use core::ops::ControlFlow;
+use rustc_ast::visit::walk_list;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
-use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
@@ -417,23 +417,18 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
         {
             if let &hir::ClosureBinder::For { span: for_sp, .. } = binder {
                 fn span_of_infer(ty: &hir::Ty<'_>) -> Option<Span> {
-                    struct V(Option<Span>);
-
+                    struct V;
                     impl<'v> Visitor<'v> for V {
-                        fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
-                            match t.kind {
-                                _ if self.0.is_some() => (),
-                                hir::TyKind::Infer => {
-                                    self.0 = Some(t.span);
-                                }
-                                _ => intravisit::walk_ty(self, t),
+                        type Result = ControlFlow<Span>;
+                        fn visit_ty(&mut self, t: &'v hir::Ty<'v>) -> Self::Result {
+                            if matches!(t.kind, hir::TyKind::Infer) {
+                                ControlFlow::Break(t.span)
+                            } else {
+                                intravisit::walk_ty(self, t)
                             }
                         }
                     }
-
-                    let mut v = V(None);
-                    v.visit_ty(ty);
-                    v.0
+                    V.visit_ty(ty).break_value()
                 }
 
                 let infer_in_rt_sp = match fn_decl.output {
@@ -514,38 +509,11 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                 // These sorts of items have no lifetime parameters at all.
                 intravisit::walk_item(self, item);
             }
-            hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                origin: hir::OpaqueTyOrigin::TyAlias { .. },
-                ..
-            }) => {
-                // Opaque types are visited when we visit the
-                // `TyKind::OpaqueDef`, so that they have the lifetimes from
-                // their parent opaque_ty in scope.
-                //
-                // The core idea here is that since OpaqueTys are generated with the impl Trait as
-                // their owner, we can keep going until we find the Item that owns that. We then
-                // conservatively add all resolved lifetimes. Otherwise we run into problems in
-                // cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
-                let parent_item = self.tcx.hir().get_parent_item(item.hir_id());
-                let resolved_lifetimes: &ResolveBoundVars =
-                    self.tcx.resolve_bound_vars(parent_item);
-                // We need to add *all* deps, since opaque tys may want them from *us*
-                for (&owner, defs) in resolved_lifetimes.defs.iter() {
-                    defs.iter().for_each(|(&local_id, region)| {
-                        self.map.defs.insert(hir::HirId { owner, local_id }, *region);
-                    });
-                }
-                for (&owner, late_bound_vars) in resolved_lifetimes.late_bound_vars.iter() {
-                    late_bound_vars.iter().for_each(|(&local_id, late_bound_vars)| {
-                        self.record_late_bound_vars(
-                            hir::HirId { owner, local_id },
-                            late_bound_vars.clone(),
-                        );
-                    });
-                }
-            }
             hir::ItemKind::OpaqueTy(&hir::OpaqueTy {
-                origin: hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent),
+                origin:
+                    hir::OpaqueTyOrigin::FnReturn(parent)
+                    | hir::OpaqueTyOrigin::AsyncFn(parent)
+                    | hir::OpaqueTyOrigin::TyAlias { parent, .. },
                 generics,
                 ..
             }) => {
@@ -683,26 +651,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                 //                                      the opaque_ty generics
                 let opaque_ty = self.tcx.hir().item(item_id);
                 match &opaque_ty.kind {
-                    hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                        origin: hir::OpaqueTyOrigin::TyAlias { .. },
-                        ..
-                    }) => {
-                        intravisit::walk_ty(self, ty);
-
-                        // Elided lifetimes and late-bound lifetimes (from the parent)
-                        // are not allowed in non-return position impl Trait
-                        let scope = Scope::LateBoundary {
-                            s: &Scope::TraitRefBoundary { s: self.scope },
-                            what: "type alias impl trait",
-                        };
-                        self.with(scope, |this| intravisit::walk_item(this, opaque_ty));
-
-                        return;
-                    }
-                    hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                        origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..),
-                        ..
-                    }) => {}
+                    hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin: _, .. }) => {}
                     i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
                 };
 
@@ -719,34 +668,47 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                     // and ban them. Type variables instantiated inside binders aren't
                     // well-supported at the moment, so this doesn't work.
                     // In the future, this should be fixed and this error should be removed.
-                    let def = self.map.defs.get(&lifetime.hir_id).cloned();
-                    let Some(ResolvedArg::LateBound(_, _, def_id)) = def else { continue };
-                    let Some(def_id) = def_id.as_local() else { continue };
-                    let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
-                    // Ensure that the parent of the def is an item, not HRTB
-                    let parent_id = self.tcx.parent_hir_id(hir_id);
-                    if !parent_id.is_owner() {
-                        struct_span_code_err!(
-                            self.tcx.dcx(),
-                            lifetime.ident.span,
-                            E0657,
-                            "`impl Trait` can only capture lifetimes bound at the fn or impl level"
-                        )
-                        .emit();
-                        self.uninsert_lifetime_on_error(lifetime, def.unwrap());
-                    }
-                    if let hir::Node::Item(hir::Item {
-                        kind: hir::ItemKind::OpaqueTy { .. }, ..
-                    }) = self.tcx.hir_node(parent_id)
+                    let def = self.map.defs.get(&lifetime.hir_id).copied();
+                    let Some(ResolvedArg::LateBound(_, _, lifetime_def_id)) = def else { continue };
+                    let Some(lifetime_def_id) = lifetime_def_id.as_local() else { continue };
+                    let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id);
+
+                    let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id))
                     {
-                        self.tcx.dcx().struct_span_err(
-                            lifetime.ident.span,
-                            "higher kinded lifetime bounds on nested opaque types are not supported yet",
-                        )
-                        .with_span_note(self.tcx.def_span(def_id), "lifetime declared here")
-                        .emit();
-                        self.uninsert_lifetime_on_error(lifetime, def.unwrap());
-                    }
+                        // Opaques do not declare their own lifetimes, so if a lifetime comes from an opaque
+                        // it must be a reified late-bound lifetime from a trait goal.
+                        hir::Node::Item(hir::Item {
+                            kind: hir::ItemKind::OpaqueTy { .. }, ..
+                        }) => "higher-ranked lifetime from outer `impl Trait`",
+                        // Other items are fine.
+                        hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => {
+                            continue;
+                        }
+                        hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(_), .. }) => {
+                            "higher-ranked lifetime from function pointer"
+                        }
+                        hir::Node::Ty(hir::Ty { kind: hir::TyKind::TraitObject(..), .. }) => {
+                            "higher-ranked lifetime from `dyn` type"
+                        }
+                        _ => "higher-ranked lifetime",
+                    };
+
+                    let (span, label) = if lifetime.ident.span == self.tcx.def_span(lifetime_def_id)
+                    {
+                        let opaque_span = self.tcx.def_span(item_id.owner_id);
+                        (opaque_span, Some(opaque_span))
+                    } else {
+                        (lifetime.ident.span, None)
+                    };
+
+                    // Ensure that the parent of the def is an item, not HRTB
+                    self.tcx.dcx().emit_err(errors::OpaqueCapturesHigherRankedLifetime {
+                        span,
+                        label,
+                        decl_span: self.tcx.def_span(lifetime_def_id),
+                        bad_place,
+                    });
+                    self.uninsert_lifetime_on_error(lifetime, def.unwrap());
                 }
             }
             _ => intravisit::walk_ty(self, ty),
@@ -1964,31 +1926,26 @@ fn is_late_bound_map(
         arg_is_constrained: Box<[bool]>,
     }
 
-    use std::ops::ControlFlow;
     use ty::Ty;
     impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstrainedCollectorPostAstConv {
-        fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
+        fn visit_ty(&mut self, t: Ty<'tcx>) {
             match t.kind() {
                 ty::Param(param_ty) => {
                     self.arg_is_constrained[param_ty.index as usize] = true;
                 }
-                ty::Alias(ty::Projection | ty::Inherent, _) => return ControlFlow::Continue(()),
+                ty::Alias(ty::Projection | ty::Inherent, _) => return,
                 _ => (),
             }
             t.super_visit_with(self)
         }
 
-        fn visit_const(&mut self, _: ty::Const<'tcx>) -> ControlFlow<!> {
-            ControlFlow::Continue(())
-        }
+        fn visit_const(&mut self, _: ty::Const<'tcx>) {}
 
-        fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<!> {
+        fn visit_region(&mut self, r: ty::Region<'tcx>) {
             debug!("r={:?}", r.kind());
             if let ty::RegionKind::ReEarlyParam(region) = r.kind() {
                 self.arg_is_constrained[region.index as usize] = true;
             }
-
-            ControlFlow::Continue(())
         }
     }
 
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 417f0fceaa8..a1345c2d81b 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -1,3 +1,4 @@
+use core::ops::ControlFlow;
 use rustc_errors::{Applicability, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -5,7 +6,7 @@ use rustc_hir::HirId;
 use rustc_middle::query::plumbing::CyclePlaceholder;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_middle::ty::util::IntTypeExt;
-use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::symbol::Ident;
 use rustc_span::{Span, DUMMY_SP};
 
@@ -350,22 +351,31 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
     // If we are computing `type_of` the synthesized associated type for an RPITIT in the impl
     // side, use `collect_return_position_impl_trait_in_trait_tys` to infer the value of the
     // associated type in the impl.
-    if let Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) =
-        tcx.opt_rpitit_info(def_id.to_def_id())
-    {
-        match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) {
-            Ok(map) => {
-                let assoc_item = tcx.associated_item(def_id);
-                return map[&assoc_item.trait_item_def_id.unwrap()];
-            }
-            Err(_) => {
-                return ty::EarlyBinder::bind(Ty::new_error_with_message(
-                    tcx,
-                    DUMMY_SP,
-                    "Could not collect return position impl trait in trait tys",
-                ));
+    match tcx.opt_rpitit_info(def_id.to_def_id()) {
+        Some(ty::ImplTraitInTraitData::Impl { fn_def_id }) => {
+            match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) {
+                Ok(map) => {
+                    let assoc_item = tcx.associated_item(def_id);
+                    return map[&assoc_item.trait_item_def_id.unwrap()];
+                }
+                Err(_) => {
+                    return ty::EarlyBinder::bind(Ty::new_error_with_message(
+                        tcx,
+                        DUMMY_SP,
+                        "Could not collect return position impl trait in trait tys",
+                    ));
+                }
             }
         }
+        // For an RPITIT in a trait, just return the corresponding opaque.
+        Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
+            return ty::EarlyBinder::bind(Ty::new_opaque(
+                tcx,
+                opaque_def_id,
+                ty::GenericArgs::identity_for_item(tcx, opaque_def_id),
+            ));
+        }
+        None => {}
     }
 
     let hir_id = tcx.local_def_id_to_hir_id(def_id);
@@ -544,11 +554,11 @@ pub(super) fn type_of_opaque(
         Ok(ty::EarlyBinder::bind(match tcx.hir_node_by_def_id(def_id) {
             Node::Item(item) => match item.kind {
                 ItemKind::OpaqueTy(OpaqueTy {
-                    origin: hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false },
+                    origin: hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. },
                     ..
                 }) => opaque::find_opaque_ty_constraints_for_tait(tcx, def_id),
                 ItemKind::OpaqueTy(OpaqueTy {
-                    origin: hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: true },
+                    origin: hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: true, .. },
                     ..
                 }) => opaque::find_opaque_ty_constraints_for_impl_trait_in_assoc_type(tcx, def_id),
                 // Opaque types desugared from `impl Trait`.
@@ -666,19 +676,16 @@ pub fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
     if tcx.features().lazy_type_alias {
         return true;
     }
-    struct HasTait {
-        has_type_alias_impl_trait: bool,
-    }
+    struct HasTait;
     impl<'tcx> Visitor<'tcx> for HasTait {
-        fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
+        type Result = ControlFlow<()>;
+        fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) -> Self::Result {
             if let hir::TyKind::OpaqueDef(..) = t.kind {
-                self.has_type_alias_impl_trait = true;
+                ControlFlow::Break(())
             } else {
-                hir::intravisit::walk_ty(self, t);
+                hir::intravisit::walk_ty(self, t)
             }
         }
     }
-    let mut has_tait = HasTait { has_type_alias_impl_trait: false };
-    has_tait.visit_ty(tcx.hir().expect_item(def_id).expect_ty_alias().0);
-    has_tait.has_type_alias_impl_trait
+    HasTait.visit_ty(tcx.hir().expect_item(def_id).expect_ty_alias().0).is_break()
 }
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index f0e998b7a00..dcb01a117b0 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -46,9 +46,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
     for &assoc_id in tcx.associated_item_def_ids(impl_def_id) {
         let assoc = tcx.associated_item(assoc_id);
         match assoc.kind {
-            ty::AssocKind::Const | ty::AssocKind::Fn => {
-                locator.check(assoc_id.expect_local(), ImplTraitSource::AssocTy)
-            }
+            ty::AssocKind::Const | ty::AssocKind::Fn => locator.check(assoc_id.expect_local()),
             // Associated types don't have bodies, so they can't constrain hidden types
             ty::AssocKind::Type => {}
         }
@@ -182,15 +180,9 @@ struct TaitConstraintLocator<'tcx> {
     typeck_types: Vec<ty::OpaqueHiddenType<'tcx>>,
 }
 
-#[derive(Debug)]
-enum ImplTraitSource {
-    AssocTy,
-    TyAlias,
-}
-
 impl TaitConstraintLocator<'_> {
     #[instrument(skip(self), level = "debug")]
-    fn check(&mut self, item_def_id: LocalDefId, source: ImplTraitSource) {
+    fn check(&mut self, item_def_id: LocalDefId) {
         // Don't try to check items that cannot possibly constrain the type.
         if !self.tcx.has_typeck_results(item_def_id) {
             debug!("no constraint: no typeck results");
@@ -242,12 +234,8 @@ impl TaitConstraintLocator<'_> {
                 continue;
             }
             constrained = true;
-            let opaque_types_defined_by = match source {
-                ImplTraitSource::AssocTy => {
-                    self.tcx.impl_trait_in_assoc_types_defined_by(item_def_id)
-                }
-                ImplTraitSource::TyAlias => self.tcx.opaque_types_defined_by(item_def_id),
-            };
+            let opaque_types_defined_by = self.tcx.opaque_types_defined_by(item_def_id);
+
             if !opaque_types_defined_by.contains(&self.def_id) {
                 self.tcx.dcx().emit_err(TaitForwardCompat {
                     span: hidden_type.span,
@@ -308,7 +296,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
     }
     fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
         if let hir::ExprKind::Closure(closure) = ex.kind {
-            self.check(closure.def_id, ImplTraitSource::TyAlias);
+            self.check(closure.def_id);
         }
         intravisit::walk_expr(self, ex);
     }
@@ -316,7 +304,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
         trace!(?it.owner_id);
         // The opaque type itself or its children are not within its reveal scope.
         if it.owner_id.def_id != self.def_id {
-            self.check(it.owner_id.def_id, ImplTraitSource::TyAlias);
+            self.check(it.owner_id.def_id);
             intravisit::walk_item(self, it);
         }
     }
@@ -324,13 +312,13 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
         trace!(?it.owner_id);
         // The opaque type itself or its children are not within its reveal scope.
         if it.owner_id.def_id != self.def_id {
-            self.check(it.owner_id.def_id, ImplTraitSource::TyAlias);
+            self.check(it.owner_id.def_id);
             intravisit::walk_impl_item(self, it);
         }
     }
     fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
         trace!(?it.owner_id);
-        self.check(it.owner_id.def_id, ImplTraitSource::TyAlias);
+        self.check(it.owner_id.def_id);
         intravisit::walk_trait_item(self, it);
     }
     fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
index b8de2e46934..3b8bb0731fb 100644
--- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
+++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
@@ -1,9 +1,8 @@
 use rustc_data_structures::fx::FxHashSet;
-use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
+use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitor};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
 use rustc_type_ir::fold::TypeFoldable;
-use std::ops::ControlFlow;
 
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 pub struct Parameter(pub u32);
@@ -61,13 +60,13 @@ struct ParameterCollector {
 }
 
 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector {
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, t: Ty<'tcx>) {
         match *t.kind() {
             // Projections are not injective in general.
             ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _)
                 if !self.include_nonconstraining =>
             {
-                return ControlFlow::Continue(());
+                return;
             }
             // All weak alias types should've been expanded beforehand.
             ty::Alias(ty::Weak, _) if !self.include_nonconstraining => {
@@ -80,18 +79,17 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector {
         t.super_visit_with(self)
     }
 
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_region(&mut self, r: ty::Region<'tcx>) {
         if let ty::ReEarlyParam(data) = *r {
             self.parameters.push(Parameter::from(data));
         }
-        ControlFlow::Continue(())
     }
 
-    fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_const(&mut self, c: ty::Const<'tcx>) {
         match c.kind() {
             ty::ConstKind::Unevaluated(..) if !self.include_nonconstraining => {
                 // Constant expressions are not injective in general.
-                return c.ty().visit_with(self);
+                return;
             }
             ty::ConstKind::Param(data) => {
                 self.parameters.push(Parameter::from(data));
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 5330260fbf5..26349cd1c65 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1607,3 +1607,15 @@ pub struct UnnamedFieldsReprFieldDefined {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_opaque_captures_higher_ranked_lifetime, code = E0657)]
+pub struct OpaqueCapturesHigherRankedLifetime {
+    #[primary_span]
+    pub span: Span,
+    #[label]
+    pub label: Option<Span>,
+    #[note]
+    pub decl_span: Span,
+    pub bad_place: &'static str,
+}
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index 9d7866fe3e0..caa85092415 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -14,8 +14,7 @@ use min_specialization::check_min_specialization;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{LocalDefId, LocalModDefId};
-use rustc_middle::query::Providers;
+use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 use rustc_span::{ErrorGuaranteed, Span, Symbol};
 
@@ -51,23 +50,16 @@ mod min_specialization;
 /// impl<'a> Trait<Foo> for Bar { type X = &'a i32; }
 /// //   ^ 'a is unused and appears in assoc type, error
 /// ```
-fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) -> Result<(), ErrorGuaranteed> {
+pub fn check_impl_wf(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
     let min_specialization = tcx.features().min_specialization;
-    let module = tcx.hir_module_items(module_def_id);
     let mut res = Ok(());
-    for id in module.items() {
-        if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) {
-            res = res.and(enforce_impl_params_are_constrained(tcx, id.owner_id.def_id));
-            if min_specialization {
-                res = res.and(check_min_specialization(tcx, id.owner_id.def_id));
-            }
-        }
+    debug_assert!(matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. }));
+    res = res.and(enforce_impl_params_are_constrained(tcx, impl_def_id));
+    if min_specialization {
+        res = res.and(check_min_specialization(tcx, impl_def_id));
     }
-    res
-}
 
-pub fn provide(providers: &mut Providers) {
-    *providers = Providers { check_mod_impl_wf, ..*providers };
+    res
 }
 
 fn enforce_impl_params_are_constrained(
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 7cb103626da..e056c0e84cf 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -153,27 +153,20 @@ pub fn provide(providers: &mut Providers) {
     check_unused::provide(providers);
     variance::provide(providers);
     outlives::provide(providers);
-    impl_wf_check::provide(providers);
     hir_wf_check::provide(providers);
 }
 
 pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
     let _prof_timer = tcx.sess.timer("type_check_crate");
 
-    // this ensures that later parts of type checking can assume that items
-    // have valid types and not error
-    tcx.sess.time("type_collecting", || {
-        tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
-    });
-
     if tcx.features().rustc_attrs {
         tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx))?;
     }
 
     tcx.sess.time("coherence_checking", || {
-        // Check impls constrain their parameters
-        let res =
-            tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_impl_wf(module));
+        tcx.hir().par_for_each_module(|module| {
+            let _ = tcx.ensure().check_mod_type_wf(module);
+        });
 
         for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
             let _ = tcx.ensure().coherent_trait(trait_def_id);
@@ -181,19 +174,12 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
         // these queries are executed for side-effects (error reporting):
         let _ = tcx.ensure().crate_inherent_impls(());
         let _ = tcx.ensure().crate_inherent_impls_overlap_check(());
-        res
-    })?;
+    });
 
     if tcx.features().rustc_attrs {
         tcx.sess.time("variance_testing", || variance::test::test_variance(tcx))?;
     }
 
-    tcx.sess.time("wf_checking", || {
-        tcx.hir().par_for_each_module(|module| {
-            let _ = tcx.ensure().check_mod_type_wf(module);
-        })
-    });
-
     if tcx.features().rustc_attrs {
         collect::test_opaque_hidden_types(tcx)?;
     }
diff --git a/compiler/rustc_hir_analysis/src/structured_errors.rs b/compiler/rustc_hir_analysis/src/structured_errors.rs
index 9064ba8693e..5abfd25dd95 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors.rs
@@ -9,7 +9,7 @@ pub use self::{
 use rustc_errors::{Diag, ErrCode};
 use rustc_session::Session;
 
-pub trait StructuredDiagnostic<'tcx> {
+pub trait StructuredDiag<'tcx> {
     fn session(&self) -> &Session;
 
     fn code(&self) -> ErrCode;
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
index 921cf37155a..0e78acbeae2 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
@@ -1,4 +1,4 @@
-use crate::{errors, structured_errors::StructuredDiagnostic};
+use crate::{errors, structured_errors::StructuredDiag};
 use rustc_errors::{codes::*, Diag};
 use rustc_middle::ty::{Ty, TypeVisitableExt};
 use rustc_session::Session;
@@ -11,7 +11,7 @@ pub struct MissingCastForVariadicArg<'tcx, 's> {
     pub cast_ty: &'s str,
 }
 
-impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> {
+impl<'tcx> StructuredDiag<'tcx> for MissingCastForVariadicArg<'tcx, '_> {
     fn session(&self) -> &Session {
         self.sess
     }
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
index 1af5e6a9dfc..9e871ff9af0 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
@@ -1,4 +1,4 @@
-use crate::{errors, structured_errors::StructuredDiagnostic};
+use crate::{errors, structured_errors::StructuredDiag};
 use rustc_errors::{codes::*, Diag};
 use rustc_middle::ty::{Ty, TypeVisitableExt};
 use rustc_session::Session;
@@ -11,7 +11,7 @@ pub struct SizedUnsizedCast<'tcx> {
     pub cast_ty: String,
 }
 
-impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> {
+impl<'tcx> StructuredDiag<'tcx> for SizedUnsizedCast<'tcx> {
     fn session(&self) -> &Session {
         self.sess
     }
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index 6f4695ec920..0f5ba26337a 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -1,4 +1,4 @@
-use crate::structured_errors::StructuredDiagnostic;
+use crate::structured_errors::StructuredDiag;
 use rustc_errors::{codes::*, pluralize, Applicability, Diag, MultiSpan};
 use rustc_hir as hir;
 use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt};
@@ -1097,7 +1097,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
     }
 }
 
-impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> {
+impl<'tcx> StructuredDiag<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> {
     fn session(&self) -> &Session {
         self.tcx.sess
     }
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 4d5dcbadc4a..42885b0c832 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -10,7 +10,6 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt};
 use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
-use std::ops::ControlFlow;
 
 /// Defines the `TermsContext` basically houses an arena where we can
 /// allocate terms.
@@ -89,15 +88,14 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
 
     impl<'tcx> OpaqueTypeLifetimeCollector<'tcx> {
         #[instrument(level = "trace", skip(self), ret)]
-        fn visit_opaque(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> ControlFlow<!> {
+        fn visit_opaque(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) {
             if def_id != self.root_def_id && self.tcx.is_descendant_of(def_id, self.root_def_id) {
                 let child_variances = self.tcx.variances_of(def_id);
                 for (a, v) in args.iter().zip_eq(child_variances) {
                     if *v != ty::Bivariant {
-                        a.visit_with(self)?;
+                        a.visit_with(self);
                     }
                 }
-                ControlFlow::Continue(())
             } else {
                 args.visit_with(self)
             }
@@ -106,20 +104,19 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
 
     impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeLifetimeCollector<'tcx> {
         #[instrument(level = "trace", skip(self), ret)]
-        fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+        fn visit_region(&mut self, r: ty::Region<'tcx>) {
             if let ty::RegionKind::ReEarlyParam(ebr) = r.kind() {
                 self.variances[ebr.index as usize] = ty::Invariant;
             }
-            ControlFlow::Continue(())
         }
 
         #[instrument(level = "trace", skip(self), ret)]
-        fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        fn visit_ty(&mut self, t: Ty<'tcx>) {
             match t.kind() {
                 ty::Alias(_, ty::AliasTy { def_id, args, .. })
                     if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) =>
                 {
-                    self.visit_opaque(*def_id, args)
+                    self.visit_opaque(*def_id, args);
                 }
                 _ => t.super_visit_with(self),
             }
@@ -128,15 +125,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
 
     // By default, RPIT are invariant wrt type and const generics, but they are bivariant wrt
     // lifetime generics.
-    let variances = std::iter::repeat(ty::Invariant).take(generics.count());
-
-    let mut variances: Vec<_> = match tcx.opaque_type_origin(item_def_id) {
-        rustc_hir::OpaqueTyOrigin::FnReturn(_) | rustc_hir::OpaqueTyOrigin::AsyncFn(_) => {
-            variances.collect()
-        }
-        // But TAIT are invariant for all generics
-        rustc_hir::OpaqueTyOrigin::TyAlias { .. } => return tcx.arena.alloc_from_iter(variances),
-    };
+    let mut variances = vec![ty::Invariant; generics.count()];
 
     // Mark all lifetimes from parent generics as unused (Bivariant).
     // This will be overridden later if required.
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 8f8f747339b..b5bb063c5ed 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1265,6 +1265,10 @@ impl<'a> State<'a> {
                     s.space();
                     s.print_qpath(path, true);
                 }
+                hir::InlineAsmOperand::Label { block } => {
+                    s.head("label");
+                    s.print_block(block);
+                }
             },
             AsmArg::Options(opts) => {
                 s.word("options");
diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml
index 975f9375642..0a5fa37ed04 100644
--- a/compiler/rustc_hir_typeck/Cargo.toml
+++ b/compiler/rustc_hir_typeck/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
 # tidy-alphabetical-start
 itertools = "0.11"
 rustc_ast = { path = "../rustc_ast" }
+rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index b87d71e3533..25d34531379 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -545,7 +545,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         if let Some(def_id) = def_id
             && self.tcx.def_kind(def_id) == hir::def::DefKind::Fn
-            && matches!(self.tcx.intrinsic(def_id), Some(sym::const_eval_select))
+            && self.tcx.is_intrinsic(def_id, sym::const_eval_select)
         {
             let fn_sig = self.resolve_vars_if_possible(fn_sig);
             for idx in 0..=1 {
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 84d042da138..b8d1eaee812 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -483,9 +483,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                 err.emit();
             }
             CastError::SizedUnsizedCast => {
-                use rustc_hir_analysis::structured_errors::{
-                    SizedUnsizedCast, StructuredDiagnostic,
-                };
+                use rustc_hir_analysis::structured_errors::{SizedUnsizedCast, StructuredDiag};
 
                 SizedUnsizedCast {
                     sess: fcx.tcx.sess,
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 5bdd9412d0e..1ff961a9089 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -56,18 +56,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // It's always helpful for inference if we know the kind of
         // closure sooner rather than later, so first examine the expected
         // type, and see if can glean a closure kind from there.
-        let (expected_sig, expected_kind) = match closure.kind {
-            hir::ClosureKind::Closure => match expected.to_option(self) {
-                Some(ty) => {
-                    self.deduce_closure_signature(self.try_structurally_resolve_type(expr_span, ty))
-                }
-                None => (None, None),
-            },
-            // We don't want to deduce a signature from `Fn` bounds for coroutines
-            // or coroutine-closures, because the former does not implement `Fn`
-            // ever, and the latter's signature doesn't correspond to the coroutine
-            // type that it returns.
-            hir::ClosureKind::Coroutine(_) | hir::ClosureKind::CoroutineClosure(_) => (None, None),
+        let (expected_sig, expected_kind) = match expected.to_option(self) {
+            Some(ty) => self.deduce_closure_signature(
+                self.try_structurally_resolve_type(expr_span, ty),
+                closure.kind,
+            ),
+            None => (None, None),
         };
 
         let ClosureSignatures { bound_sig, mut liberated_sig } =
@@ -323,11 +317,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn deduce_closure_signature(
         &self,
         expected_ty: Ty<'tcx>,
+        closure_kind: hir::ClosureKind,
     ) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
         match *expected_ty.kind() {
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => self
                 .deduce_closure_signature_from_predicates(
                     expected_ty,
+                    closure_kind,
                     self.tcx
                         .explicit_item_bounds(def_id)
                         .iter_instantiated_copied(self.tcx, args)
@@ -336,7 +332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty::Dynamic(object_type, ..) => {
                 let sig = object_type.projection_bounds().find_map(|pb| {
                     let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self);
-                    self.deduce_sig_from_projection(None, pb)
+                    self.deduce_sig_from_projection(None, closure_kind, pb)
                 });
                 let kind = object_type
                     .principal_def_id()
@@ -345,12 +341,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             ty::Infer(ty::TyVar(vid)) => self.deduce_closure_signature_from_predicates(
                 Ty::new_var(self.tcx, self.root_var(vid)),
+                closure_kind,
                 self.obligations_for_self_ty(vid).map(|obl| (obl.predicate, obl.cause.span)),
             ),
-            ty::FnPtr(sig) => {
-                let expected_sig = ExpectedSig { cause_span: None, sig };
-                (Some(expected_sig), Some(ty::ClosureKind::Fn))
-            }
+            ty::FnPtr(sig) => match closure_kind {
+                hir::ClosureKind::Closure => {
+                    let expected_sig = ExpectedSig { cause_span: None, sig };
+                    (Some(expected_sig), Some(ty::ClosureKind::Fn))
+                }
+                hir::ClosureKind::Coroutine(_) | hir::ClosureKind::CoroutineClosure(_) => {
+                    (None, None)
+                }
+            },
             _ => (None, None),
         }
     }
@@ -358,6 +360,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn deduce_closure_signature_from_predicates(
         &self,
         expected_ty: Ty<'tcx>,
+        closure_kind: hir::ClosureKind,
         predicates: impl DoubleEndedIterator<Item = (ty::Predicate<'tcx>, Span)>,
     ) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
         let mut expected_sig = None;
@@ -386,6 +389,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     span,
                     self.deduce_sig_from_projection(
                         Some(span),
+                        closure_kind,
                         bound_predicate.rebind(proj_predicate),
                     ),
                 );
@@ -396,9 +400,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     expected_ty: Ty<'tcx>,
                 }
                 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MentionsTy<'tcx> {
-                    type BreakTy = ();
+                    type Result = ControlFlow<()>;
 
-                    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+                    fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
                         if t == self.expected_ty {
                             ControlFlow::Break(())
                         } else {
@@ -422,13 +426,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => Some(data.def_id()),
                 _ => None,
             };
-            if let Some(closure_kind) =
-                trait_def_id.and_then(|def_id| self.tcx.fn_trait_kind_from_def_id(def_id))
-            {
-                expected_kind = Some(
-                    expected_kind
-                        .map_or_else(|| closure_kind, |current| cmp::min(current, closure_kind)),
-                );
+
+            if let Some(trait_def_id) = trait_def_id {
+                let found_kind = match closure_kind {
+                    hir::ClosureKind::Closure => self.tcx.fn_trait_kind_from_def_id(trait_def_id),
+                    hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => {
+                        self.tcx.async_fn_trait_kind_from_def_id(trait_def_id)
+                    }
+                    _ => None,
+                };
+
+                if let Some(found_kind) = found_kind {
+                    expected_kind = Some(
+                        expected_kind
+                            .map_or_else(|| found_kind, |current| cmp::min(current, found_kind)),
+                    );
+                }
             }
         }
 
@@ -445,14 +458,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn deduce_sig_from_projection(
         &self,
         cause_span: Option<Span>,
+        closure_kind: hir::ClosureKind,
         projection: ty::PolyProjectionPredicate<'tcx>,
     ) -> Option<ExpectedSig<'tcx>> {
         let tcx = self.tcx;
 
         let trait_def_id = projection.trait_def_id(tcx);
-        // For now, we only do signature deduction based off of the `Fn` traits.
-        if !tcx.is_fn_trait(trait_def_id) {
-            return None;
+
+        // For now, we only do signature deduction based off of the `Fn` and `AsyncFn` traits,
+        // for closures and async closures, respectively.
+        match closure_kind {
+            hir::ClosureKind::Closure
+                if self.tcx.fn_trait_kind_from_def_id(trait_def_id).is_some() => {}
+            hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async)
+                if self.tcx.async_fn_trait_kind_from_def_id(trait_def_id).is_some() => {}
+            _ => return None,
         }
 
         let arg_param_ty = projection.skip_binder().projection_ty.args.type_at(1);
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 1d324f128f2..502b9ba6451 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -4,7 +4,7 @@ use std::borrow::Cow;
 use crate::fluent_generated as fluent;
 use rustc_errors::{
     codes::*, AddToDiagnostic, Applicability, Diag, DiagArgValue, EmissionGuarantee,
-    IntoDiagnosticArg, MultiSpan, SubdiagnosticMessageOp,
+    IntoDiagnosticArg, MultiSpan, SubdiagMessageOp,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::Ty;
@@ -195,7 +195,7 @@ pub struct TypeMismatchFruTypo {
 }
 
 impl AddToDiagnostic for TypeMismatchFruTypo {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -374,7 +374,7 @@ pub struct RemoveSemiForCoerce {
 }
 
 impl AddToDiagnostic for RemoveSemiForCoerce {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -550,7 +550,7 @@ pub enum CastUnknownPointerSub {
 }
 
 impl rustc_errors::AddToDiagnostic for CastUnknownPointerSub {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index b8cceebe103..ceaae9cf49f 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -390,7 +390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         );
                         let sp = tcx.sess.source_map().start_point(expr.span).with_parent(None);
                         if let Some(sp) =
-                            tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp)
+                            tcx.sess.psess.ambiguous_block_expr_parse.borrow().get(&sp)
                         {
                             err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp));
                         }
@@ -3232,6 +3232,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> {
+        let mut diverge = asm.options.contains(ast::InlineAsmOptions::NORETURN);
+
         for (op, _op_sp) in asm.operands {
             match op {
                 hir::InlineAsmOperand::In { expr, .. } => {
@@ -3253,13 +3255,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // be well-formed.
                 hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {}
                 hir::InlineAsmOperand::SymStatic { .. } => {}
+                hir::InlineAsmOperand::Label { block } => {
+                    let previous_diverges = self.diverges.get();
+
+                    // The label blocks should have unit return value or diverge.
+                    let ty =
+                        self.check_block_with_expected(block, ExpectHasType(self.tcx.types.unit));
+                    if !ty.is_never() {
+                        self.demand_suptype(block.span, self.tcx.types.unit, ty);
+                        diverge = false;
+                    }
+
+                    // We need this to avoid false unreachable warning when a label diverges.
+                    self.diverges.set(previous_diverges);
+                }
             }
         }
-        if asm.options.contains(ast::InlineAsmOptions::NORETURN) {
-            self.tcx.types.never
-        } else {
-            Ty::new_unit(self.tcx)
-        }
+
+        if diverge { self.tcx.types.never } else { self.tcx.types.unit }
     }
 
     fn check_offset_of(
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 04fb7bcf4f3..ba0383d19b9 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -293,6 +293,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                         | hir::InlineAsmOperand::Const { .. }
                         | hir::InlineAsmOperand::SymFn { .. }
                         | hir::InlineAsmOperand::SymStatic { .. } => {}
+                        hir::InlineAsmOperand::Label { block } => {
+                            self.walk_block(block);
+                        }
                     }
                 }
             }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index f0631dd4b5f..a9a5a89a413 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -337,8 +337,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Option<ty::GenericArg<'tcx>> {
         struct FindAmbiguousParameter<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, DefId);
         impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindAmbiguousParameter<'_, 'tcx> {
-            type BreakTy = ty::GenericArg<'tcx>;
-            fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
+            type Result = ControlFlow<ty::GenericArg<'tcx>>;
+            fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
                 if let Some(origin) = self.0.type_var_origin(ty)
                     && let TypeVariableOriginKind::TypeParameterDefinition(_, def_id) = origin.kind
                     && let generics = self.0.tcx.generics_of(self.1)
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index fc674520295..a08582a67d9 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -27,7 +27,7 @@ use rustc_hir::{ExprKind, Node, QPath};
 use rustc_hir_analysis::astconv::AstConv;
 use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;
 use rustc_hir_analysis::check::potentially_plural_count;
-use rustc_hir_analysis::structured_errors::StructuredDiagnostic;
+use rustc_hir_analysis::structured_errors::StructuredDiag;
 use rustc_index::IndexVec;
 use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 809102557ac..5a1c7b05611 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1117,7 +1117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &hir::Expr<'_>,
     ) -> bool {
         let sp = self.tcx.sess.source_map().start_point(expr.span).with_parent(None);
-        if let Some(sp) = self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) {
+        if let Some(sp) = self.tcx.sess.psess.ambiguous_block_expr_parse.borrow().get(&sp) {
             // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
             err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp));
             true
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 70ddd6b2f4c..d86b4912c89 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -61,7 +61,7 @@ use rustc_hir::{HirIdMap, Node};
 use rustc_hir_analysis::astconv::AstConv;
 use rustc_hir_analysis::check::check_abi;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::traits::ObligationInspector;
+use rustc_infer::traits::{ObligationCauseCode, ObligationInspector, WellFormedLoc};
 use rustc_middle::query::Providers;
 use rustc_middle::traits;
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -253,6 +253,10 @@ fn typeck_with_fallback<'tcx>(
         let expected_type = expected_type.unwrap_or_else(fallback);
 
         let expected_type = fcx.normalize(body.value.span, expected_type);
+
+        let wf_code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(def_id)));
+        fcx.register_wf_obligation(expected_type.into(), body.value.span, wf_code);
+
         fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
 
         // Gather locals in statics (because of block expressions).
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index 441558da60a..3b26a791f65 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -11,7 +11,7 @@ pub use self::suggest::SelfSource;
 pub use self::MethodError::*;
 
 use crate::FnCtxt;
-use rustc_errors::{Applicability, Diag, SubdiagnosticMessage};
+use rustc_errors::{Applicability, Diag, SubdiagMessage};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace};
 use rustc_hir::def_id::DefId;
@@ -127,7 +127,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(crate) fn suggest_method_call(
         &self,
         err: &mut Diag<'_>,
-        msg: impl Into<SubdiagnosticMessage> + std::fmt::Debug,
+        msg: impl Into<SubdiagMessage> + std::fmt::Debug,
         method_name: Ident,
         self_ty: Ty<'tcx>,
         call_expr: &hir::Expr<'tcx>,
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 440d0ad1140..4c413e4d1c6 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -6,6 +6,7 @@
 use crate::errors::{self, CandidateTraitNote, NoAssociatedItem};
 use crate::Expectation;
 use crate::FnCtxt;
+use core::ops::ControlFlow;
 use rustc_ast::ast::Mutability;
 use rustc_attr::parse_confusables;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
@@ -166,7 +167,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return false;
         }
 
-        match ty.kind() {
+        match ty.peel_refs().kind() {
             ty::Param(param) => {
                 let generics = self.tcx.generics_of(self.body_id);
                 let generic_param = generics.type_param(&param, self.tcx);
@@ -184,7 +185,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 }
             }
-            ty::Alias(ty::AliasKind::Opaque, _) => {
+            ty::Slice(..) | ty::Adt(..) | ty::Alias(ty::AliasKind::Opaque, _) => {
                 for unsatisfied in unsatisfied_predicates.iter() {
                     if is_iterator_predicate(unsatisfied.0, self.tcx) {
                         return true;
@@ -2212,30 +2213,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let map = self.infcx.tcx.hir();
                 let body_id = self.tcx.hir().body_owned_by(self.body_id);
                 let body = map.body(body_id);
-                struct LetVisitor<'a> {
-                    result: Option<&'a hir::Expr<'a>>,
+                struct LetVisitor {
                     ident_name: Symbol,
                 }
 
                 // FIXME: This really should be taking scoping, etc into account.
-                impl<'v> Visitor<'v> for LetVisitor<'v> {
-                    fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
-                        if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind
+                impl<'v> Visitor<'v> for LetVisitor {
+                    type Result = ControlFlow<Option<&'v hir::Expr<'v>>>;
+                    fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result {
+                        if let hir::StmtKind::Local(&hir::Local { pat, init, .. }) = ex.kind
                             && let Binding(_, _, ident, ..) = pat.kind
                             && ident.name == self.ident_name
                         {
-                            self.result = *init;
+                            ControlFlow::Break(init)
                         } else {
-                            hir::intravisit::walk_stmt(self, ex);
+                            hir::intravisit::walk_stmt(self, ex)
                         }
                     }
                 }
 
-                let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name };
-                visitor.visit_body(body);
-
                 if let Node::Expr(call_expr) = self.tcx.parent_hir_node(seg1.hir_id)
-                    && let Some(expr) = visitor.result
+                    && let ControlFlow::Break(Some(expr)) =
+                        (LetVisitor { ident_name: seg1.ident.name }).visit_body(body)
                     && let Some(self_ty) = self.node_ty_opt(expr.hir_id)
                 {
                     let probe = self.lookup_probe_for_diagnostic(
@@ -3368,11 +3367,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 "inherent impls can't be candidates, only trait impls can be",
                             )
                         })
-                        .filter(|header| {
-                            header.skip_binder().polarity == ty::ImplPolarity::Negative
-                        })
+                        .filter(|header| header.polarity == ty::ImplPolarity::Negative)
                         .any(|header| {
-                            let imp = header.instantiate_identity().trait_ref;
+                            let imp = header.trait_ref.instantiate_identity();
                             let imp_simp =
                                 simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup);
                             imp_simp.is_some_and(|s| s == simp_rcvr_ty)
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index 9c9507d5852..79f574aa7fd 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -818,7 +818,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                     let sp = self.tcx.sess.source_map().start_point(ex.span).with_parent(None);
                     if let Some(sp) =
-                        self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp)
+                        self.tcx.sess.psess.ambiguous_block_expr_parse.borrow().get(&sp)
                     {
                         // If the previous expression was a block expression, suggest parentheses
                         // (turning this into a binary subtraction operation instead.)
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index 8311a735133..24512dea939 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -395,7 +395,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
 /// a cfg flag called `foo`.
 fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool {
     debug!("check_config(attr={:?})", attr);
-    let config = &tcx.sess.parse_sess.config;
+    let config = &tcx.sess.psess.config;
     debug!("check_config: config={:?}", config);
     let mut cfg = None;
     for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs
index d876174e620..88298150a79 100644
--- a/compiler/rustc_index/src/vec.rs
+++ b/compiler/rustc_index/src/vec.rs
@@ -12,7 +12,24 @@ use std::vec;
 use crate::{Idx, IndexSlice};
 
 /// An owned contiguous collection of `T`s, indexed by `I` rather than by `usize`.
-/// Its purpose is to avoid mixing indexes.
+///
+/// ## Why use this instead of a `Vec`?
+///
+/// An `IndexVec` allows element access only via a specific associated index type, meaning that
+/// trying to use the wrong index type (possibly accessing an invalid element) will fail at
+/// compile time.
+///
+/// It also documents what the index is indexing: in a `HashMap<usize, Something>` it's not
+/// immediately clear what the `usize` means, while a `HashMap<FieldIdx, Something>` makes it obvious.
+///
+/// ```compile_fail
+/// use rustc_index::{Idx, IndexVec};
+///
+/// fn f<I1: Idx, I2: Idx>(vec1: IndexVec<I1, u8>, idx1: I1, idx2: I2) {
+///   &vec1[idx1]; // Ok
+///   &vec1[idx2]; // Compile error!
+/// }
+/// ```
 ///
 /// While it's possible to use `u32` or `usize` directly for `I`,
 /// you almost certainly want to use a [`newtype_index!`]-generated type instead.
diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml
index 73a02a431df..c1565a7d40f 100644
--- a/compiler/rustc_infer/Cargo.toml
+++ b/compiler/rustc_infer/Cargo.toml
@@ -8,6 +8,7 @@ doctest = false
 
 [dependencies]
 # tidy-alphabetical-start
+rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index cecc52c8326..af09ac2de96 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -1,7 +1,7 @@
 use hir::GenericParamKind;
 use rustc_errors::{
-    codes::*, AddToDiagnostic, Applicability, Diag, DiagStyledString, DiagnosticMessage,
-    EmissionGuarantee, IntoDiagnosticArg, MultiSpan, SubdiagnosticMessageOp,
+    codes::*, AddToDiagnostic, Applicability, Diag, DiagMessage, DiagStyledString,
+    EmissionGuarantee, IntoDiagnosticArg, MultiSpan, SubdiagMessageOp,
 };
 use rustc_hir as hir;
 use rustc_hir::FnRetTy;
@@ -209,11 +209,11 @@ impl<'a> SourceKindMultiSuggestion<'a> {
 pub enum RegionOriginNote<'a> {
     Plain {
         span: Span,
-        msg: DiagnosticMessage,
+        msg: DiagMessage,
     },
     WithName {
         span: Span,
-        msg: DiagnosticMessage,
+        msg: DiagMessage,
         name: &'a str,
         continues: bool,
     },
@@ -225,12 +225,12 @@ pub enum RegionOriginNote<'a> {
 }
 
 impl AddToDiagnostic for RegionOriginNote<'_> {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
     ) {
-        let mut label_or_note = |span, msg: DiagnosticMessage| {
+        let mut label_or_note = |span, msg: DiagMessage| {
             let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
             let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
             let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span);
@@ -290,7 +290,7 @@ pub enum LifetimeMismatchLabels {
 }
 
 impl AddToDiagnostic for LifetimeMismatchLabels {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -338,7 +338,7 @@ pub struct AddLifetimeParamsSuggestion<'a> {
 }
 
 impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -440,7 +440,7 @@ pub struct IntroducesStaticBecauseUnmetLifetimeReq {
 }
 
 impl AddToDiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         mut self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -759,14 +759,14 @@ pub struct ConsiderBorrowingParamHelp {
 }
 
 impl AddToDiagnostic for ConsiderBorrowingParamHelp {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
     ) {
         let mut type_param_span: MultiSpan = self.spans.clone().into();
         for &span in &self.spans {
-            // Seems like we can't call f() here as Into<DiagnosticMessage> is required
+            // Seems like we can't call f() here as Into<DiagMessage> is required
             type_param_span.push_span_label(span, fluent::infer_tid_consider_borrowing);
         }
         let msg = f(diag, fluent::infer_tid_param_help.into());
@@ -804,7 +804,7 @@ pub struct DynTraitConstraintSuggestion {
 }
 
 impl AddToDiagnostic for DynTraitConstraintSuggestion {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
@@ -851,7 +851,7 @@ pub struct ReqIntroducedLocations {
 }
 
 impl AddToDiagnostic for ReqIntroducedLocations {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         mut self,
         diag: &mut Diag<'_, G>,
         f: F,
@@ -874,7 +874,7 @@ pub struct MoreTargeted {
 }
 
 impl AddToDiagnostic for MoreTargeted {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -1297,7 +1297,7 @@ pub struct SuggestTuplePatternMany {
 }
 
 impl AddToDiagnostic for SuggestTuplePatternMany {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs
index bbcb613b3e4..7bb71d47031 100644
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ b/compiler/rustc_infer/src/errors/note_and_explain.rs
@@ -1,8 +1,6 @@
 use crate::fluent_generated as fluent;
 use crate::infer::error_reporting::nice_region_error::find_anon_type;
-use rustc_errors::{
-    AddToDiagnostic, Diag, EmissionGuarantee, IntoDiagnosticArg, SubdiagnosticMessageOp,
-};
+use rustc_errors::{AddToDiagnostic, Diag, EmissionGuarantee, IntoDiagnosticArg, SubdiagMessageOp};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::{symbol::kw, Span};
 
@@ -162,7 +160,7 @@ impl RegionExplanation<'_> {
 }
 
 impl AddToDiagnostic for RegionExplanation<'_> {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 342f18a18dc..ea5c6b8c057 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1623,7 +1623,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         }
 
         impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypesVisitor<'tcx> {
-            fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+            fn visit_ty(&mut self, t: Ty<'tcx>) {
                 if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) {
                     let span = self.tcx.def_span(def_id);
                     // Avoid cluttering the output when the "found" and error span overlap:
@@ -2129,15 +2129,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         let tykind = match self.tcx.opt_hir_node_by_def_id(trace.cause.body_id) {
             Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) => {
                 let body = hir.body(*body_id);
-                struct LetVisitor<'v> {
+                struct LetVisitor {
                     span: Span,
-                    result: Option<&'v hir::Ty<'v>>,
                 }
-                impl<'v> Visitor<'v> for LetVisitor<'v> {
-                    fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) {
-                        if self.result.is_some() {
-                            return;
-                        }
+                impl<'v> Visitor<'v> for LetVisitor {
+                    type Result = ControlFlow<&'v hir::TyKind<'v>>;
+                    fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) -> Self::Result {
                         // Find a local statement where the initializer has
                         // the same span as the error and the type is specified.
                         if let hir::Stmt {
@@ -2151,13 +2148,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         } = s
                             && init_span == &self.span
                         {
-                            self.result = Some(*array_ty);
+                            ControlFlow::Break(&array_ty.peel_refs().kind)
+                        } else {
+                            ControlFlow::Continue(())
                         }
                     }
                 }
-                let mut visitor = LetVisitor { span, result: None };
-                visitor.visit_body(body);
-                visitor.result.map(|r| &r.peel_refs().kind)
+                LetVisitor { span }.visit_body(body).break_value()
             }
             Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _, _), .. })) => {
                 Some(&ty.peel_refs().kind)
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
index 4f74365d06c..265a315a559 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
@@ -1,3 +1,4 @@
+use core::ops::ControlFlow;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::hir::map::Map;
@@ -43,14 +44,9 @@ fn find_component_for_bound_region<'tcx>(
     arg: &'tcx hir::Ty<'tcx>,
     br: &ty::BoundRegionKind,
 ) -> Option<&'tcx hir::Ty<'tcx>> {
-    let mut nested_visitor = FindNestedTypeVisitor {
-        tcx,
-        bound_region: *br,
-        found_type: None,
-        current_index: ty::INNERMOST,
-    };
-    nested_visitor.visit_ty(arg);
-    nested_visitor.found_type
+    FindNestedTypeVisitor { tcx, bound_region: *br, current_index: ty::INNERMOST }
+        .visit_ty(arg)
+        .break_value()
 }
 
 // The FindNestedTypeVisitor captures the corresponding `hir::Ty` of the
@@ -65,26 +61,24 @@ struct FindNestedTypeVisitor<'tcx> {
     // The bound_region corresponding to the Refree(freeregion)
     // associated with the anonymous region we are looking for.
     bound_region: ty::BoundRegionKind,
-    // The type where the anonymous lifetime appears
-    // for e.g., Vec<`&u8`> and <`&u8`>
-    found_type: Option<&'tcx hir::Ty<'tcx>>,
     current_index: ty::DebruijnIndex,
 }
 
 impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
+    type Result = ControlFlow<&'tcx hir::Ty<'tcx>>;
     type NestedFilter = nested_filter::OnlyBodies;
 
     fn nested_visit_map(&mut self) -> Self::Map {
         self.tcx.hir()
     }
 
-    fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
+    fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) -> Self::Result {
         match arg.kind {
             hir::TyKind::BareFn(_) => {
                 self.current_index.shift_in(1);
                 intravisit::walk_ty(self, arg);
                 self.current_index.shift_out(1);
-                return;
+                return ControlFlow::Continue(());
             }
 
             hir::TyKind::TraitObject(bounds, ..) => {
@@ -105,8 +99,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
                     (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
                         debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
                         if id == def_id {
-                            self.found_type = Some(arg);
-                            return; // we can stop visiting now
+                            return ControlFlow::Break(arg);
                         }
                     }
 
@@ -123,8 +116,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
                         );
                         debug!("LateBound id={:?} def_id={:?}", id, def_id);
                         if debruijn_index == self.current_index && id == def_id {
-                            self.found_type = Some(arg);
-                            return; // we can stop visiting now
+                            return ControlFlow::Break(arg);
                         }
                     }
 
@@ -145,23 +137,30 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
             }
             // Checks if it is of type `hir::TyKind::Path` which corresponds to a struct.
             hir::TyKind::Path(_) => {
-                let subvisitor = &mut TyPathVisitor {
-                    tcx: self.tcx,
-                    found_it: false,
-                    bound_region: self.bound_region,
-                    current_index: self.current_index,
+                // Prefer using the lifetime in type arguments rather than lifetime arguments.
+                intravisit::walk_ty(self, arg)?;
+
+                // Call `walk_ty` as `visit_ty` is empty.
+                return if intravisit::walk_ty(
+                    &mut TyPathVisitor {
+                        tcx: self.tcx,
+                        bound_region: self.bound_region,
+                        current_index: self.current_index,
+                    },
+                    arg,
+                )
+                .is_break()
+                {
+                    ControlFlow::Break(arg)
+                } else {
+                    ControlFlow::Continue(())
                 };
-                intravisit::walk_ty(subvisitor, arg); // call walk_ty; as visit_ty is empty,
-                // this will visit only outermost type
-                if subvisitor.found_it {
-                    self.found_type = Some(arg);
-                }
             }
             _ => {}
         }
         // walk the embedded contents: e.g., if we are visiting `Vec<&Foo>`,
         // go on to visit `&Foo`
-        intravisit::walk_ty(self, arg);
+        intravisit::walk_ty(self, arg)
     }
 }
 
@@ -173,26 +172,25 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
 // specific part of the type in the error message.
 struct TyPathVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
-    found_it: bool,
     bound_region: ty::BoundRegionKind,
     current_index: ty::DebruijnIndex,
 }
 
 impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
+    type Result = ControlFlow<()>;
     type NestedFilter = nested_filter::OnlyBodies;
 
     fn nested_visit_map(&mut self) -> Map<'tcx> {
         self.tcx.hir()
     }
 
-    fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
+    fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) -> Self::Result {
         match (self.tcx.named_bound_var(lifetime.hir_id), self.bound_region) {
             // the lifetime of the TyPath!
             (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
                 debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
                 if id == def_id {
-                    self.found_it = true;
-                    return; // we can stop visiting now
+                    return ControlFlow::Break(());
                 }
             }
 
@@ -201,8 +199,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
                 debug!("id={:?}", id);
                 debug!("def_id={:?}", def_id);
                 if debruijn_index == self.current_index && id == def_id {
-                    self.found_it = true;
-                    return; // we can stop visiting now
+                    return ControlFlow::Break(());
                 }
             }
 
@@ -220,9 +217,10 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
                 debug!("no arg found");
             }
         }
+        ControlFlow::Continue(())
     }
 
-    fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
+    fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) -> Self::Result {
         // ignore nested types
         //
         // If you have a type like `Foo<'a, &Ty>` we
@@ -231,5 +229,6 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
         // Making `visit_ty` empty will ignore the `&Ty` embedded
         // inside, it will get reached by the outer visitor.
         debug!("`Ty` corresponding to a struct is {:?}", arg);
+        ControlFlow::Continue(())
     }
 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 33538309b04..adde45f081a 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -23,7 +23,6 @@ use rustc_span::symbol::Ident;
 use rustc_span::Span;
 
 use rustc_span::def_id::LocalDefId;
-use std::ops::ControlFlow;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when the return type is a static `impl Trait`,
@@ -545,13 +544,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
 pub struct TraitObjectVisitor(pub FxIndexSet<DefId>);
 
 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for TraitObjectVisitor {
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, t: Ty<'tcx>) {
         match t.kind() {
             ty::Dynamic(preds, re, _) if re.is_static() => {
                 if let Some(def_id) = preds.principal_def_id() {
                     self.0.insert(def_id);
                 }
-                ControlFlow::Continue(())
             }
             _ => t.super_visit_with(self),
         }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
index ded628fe136..b4cf727bf8f 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
@@ -16,8 +16,6 @@ use rustc_middle::ty::print::RegionHighlightMode;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
 use rustc_span::Span;
 
-use std::ops::ControlFlow;
-
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
     pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorGuaranteed> {
@@ -76,12 +74,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         }
 
         impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for HighlightBuilder<'tcx> {
-            fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+            fn visit_region(&mut self, r: ty::Region<'tcx>) {
                 if !r.has_name() && self.counter <= 3 {
                     self.highlight.highlighting_region(r, self.counter);
                     self.counter += 1;
                 }
-                ControlFlow::Continue(())
             }
         }
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
index 472dab639d5..8cdf39b1739 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -1,4 +1,5 @@
 use crate::infer::error_reporting::hir::Path;
+use core::ops::ControlFlow;
 use hir::def::CtorKind;
 use hir::intravisit::{walk_expr, walk_stmt, Visitor};
 use hir::{Local, QPath};
@@ -563,62 +564,55 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         cause: &ObligationCause<'_>,
         span: Span,
     ) -> Option<TypeErrorAdditionalDiags> {
-        let hir = self.tcx.hir();
-        if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(cause.body_id) {
-            let body = hir.body(body_id);
+        /// Find the if expression with given span
+        struct IfVisitor {
+            pub found_if: bool,
+            pub err_span: Span,
+        }
 
-            /// Find the if expression with given span
-            struct IfVisitor {
-                pub result: bool,
-                pub found_if: bool,
-                pub err_span: Span,
-            }
-
-            impl<'v> Visitor<'v> for IfVisitor {
-                fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
-                    if self.result {
-                        return;
+        impl<'v> Visitor<'v> for IfVisitor {
+            type Result = ControlFlow<()>;
+            fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) -> Self::Result {
+                match ex.kind {
+                    hir::ExprKind::If(cond, _, _) => {
+                        self.found_if = true;
+                        walk_expr(self, cond)?;
+                        self.found_if = false;
+                        ControlFlow::Continue(())
                     }
-                    match ex.kind {
-                        hir::ExprKind::If(cond, _, _) => {
-                            self.found_if = true;
-                            walk_expr(self, cond);
-                            self.found_if = false;
-                        }
-                        _ => walk_expr(self, ex),
-                    }
-                }
-
-                fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
-                    if let hir::StmtKind::Local(hir::Local {
-                        span,
-                        pat: hir::Pat { .. },
-                        ty: None,
-                        init: Some(_),
-                        ..
-                    }) = &ex.kind
-                        && self.found_if
-                        && span.eq(&self.err_span)
-                    {
-                        self.result = true;
-                    }
-                    walk_stmt(self, ex);
-                }
-
-                fn visit_body(&mut self, body: &'v hir::Body<'v>) {
-                    hir::intravisit::walk_body(self, body);
+                    _ => walk_expr(self, ex),
                 }
             }
 
-            let mut visitor = IfVisitor { err_span: span, found_if: false, result: false };
-            visitor.visit_body(body);
-            if visitor.result {
-                return Some(TypeErrorAdditionalDiags::AddLetForLetChains {
-                    span: span.shrink_to_lo(),
-                });
+            fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result {
+                if let hir::StmtKind::Local(hir::Local {
+                    span,
+                    pat: hir::Pat { .. },
+                    ty: None,
+                    init: Some(_),
+                    ..
+                }) = &ex.kind
+                    && self.found_if
+                    && span.eq(&self.err_span)
+                {
+                    ControlFlow::Break(())
+                } else {
+                    walk_stmt(self, ex)
+                }
+            }
+
+            fn visit_body(&mut self, body: &'v hir::Body<'v>) -> Self::Result {
+                hir::intravisit::walk_body(self, body)
             }
         }
-        None
+
+        self.tcx.hir().maybe_body_owned_by(cause.body_id).and_then(|body_id| {
+            let body = self.tcx.hir().body(body_id);
+            IfVisitor { err_span: span, found_if: false }
+                .visit_body(body)
+                .is_break()
+                .then(|| TypeErrorAdditionalDiags::AddLetForLetChains { span: span.shrink_to_lo() })
+        })
     }
 
     /// For "one type is more general than the other" errors on closures, suggest changing the lifetime
diff --git a/compiler/rustc_infer/src/infer/higher_ranked/README.md b/compiler/rustc_infer/src/infer/higher_ranked/README.md
deleted file mode 100644
index 533d0ef7e6c..00000000000
--- a/compiler/rustc_infer/src/infer/higher_ranked/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-To learn more about how Higher-ranked trait bounds work in the _old_ trait
-solver, see [this chapter][oldhrtb] of the rustc-dev-guide.
-
-To learn more about how they work in the _new_ trait solver, see [this
-chapter][newhrtb].
-
-[oldhrtb]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
-[newhrtb]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference.html#placeholders-and-universes
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 73a25637e1a..15cdd6a910e 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1,23 +1,25 @@
-pub use self::at::DefineOpaqueTypes;
-pub use self::freshen::TypeFreshener;
-pub use self::lexical_region_resolve::RegionResolutionError;
-pub use self::BoundRegionConversionTime::*;
-pub use self::RegionVariableOrigin::*;
-pub use self::SubregionOrigin::*;
-pub use self::ValuePairs::*;
+pub use at::DefineOpaqueTypes;
+pub use freshen::TypeFreshener;
+pub use lexical_region_resolve::RegionResolutionError;
+pub use relate::combine::CombineFields;
 pub use relate::combine::ObligationEmittingRelation;
-use rustc_data_structures::captures::Captures;
-use rustc_data_structures::undo_log::UndoLogs;
-use rustc_middle::infer::unify_key::EffectVarValue;
-use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey};
-
-use self::opaque_types::OpaqueTypeStorage;
-pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog};
+pub use relate::StructurallyRelateAliases;
+pub use rustc_middle::ty::IntVarValue;
+pub use BoundRegionConversionTime::*;
+pub use RegionVariableOrigin::*;
+pub use SubregionOrigin::*;
+pub use ValuePairs::*;
 
 use crate::traits::{
     self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, TraitEngineExt,
 };
-
+use error_reporting::TypeErrCtxt;
+use free_regions::RegionRelations;
+use lexical_region_resolve::LexicalRegionResolutions;
+use opaque_types::OpaqueTypeStorage;
+use region_constraints::{GenericKind, VarInfos, VerifyBound};
+use region_constraints::{RegionConstraintCollector, RegionConstraintStorage};
+use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
@@ -27,7 +29,9 @@ use rustc_errors::{Diag, DiagCtxt, ErrorGuaranteed};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
 use rustc_middle::infer::unify_key::ConstVariableValue;
+use rustc_middle::infer::unify_key::EffectVarValue;
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
+use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey};
 use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::traits::{select, DefiningAnchor};
@@ -36,33 +40,21 @@ use rustc_middle::ty::fold::BoundVarReplacerDelegate;
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::relate::RelateResult;
 use rustc_middle::ty::visit::TypeVisitableExt;
-pub use rustc_middle::ty::IntVarValue;
 use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtxt};
 use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid};
 use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef};
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
-
+use snapshot::undo_log::InferCtxtUndoLogs;
 use std::cell::{Cell, RefCell};
 use std::fmt;
-
-use self::error_reporting::TypeErrCtxt;
-use self::free_regions::RegionRelations;
-use self::lexical_region_resolve::LexicalRegionResolutions;
-use self::region_constraints::{GenericKind, VarInfos, VerifyBound};
-use self::region_constraints::{
-    RegionConstraintCollector, RegionConstraintStorage, RegionSnapshot,
-};
-pub use self::relate::combine::CombineFields;
-pub use self::relate::StructurallyRelateAliases;
-use self::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 
 pub mod at;
 pub mod canonical;
 pub mod error_reporting;
 pub mod free_regions;
 mod freshen;
-mod fudge;
 mod lexical_region_resolve;
 pub mod opaque_types;
 pub mod outlives;
@@ -70,8 +62,8 @@ mod projection;
 pub mod region_constraints;
 mod relate;
 pub mod resolve;
+pub(crate) mod snapshot;
 pub mod type_variable;
-mod undo_log;
 
 #[must_use]
 #[derive(Debug)]
@@ -738,13 +730,6 @@ impl<'tcx> InferOk<'tcx, ()> {
     }
 }
 
-#[must_use = "once you start a snapshot, you should always consume it"]
-pub struct CombinedSnapshot<'tcx> {
-    undo_snapshot: Snapshot<'tcx>,
-    region_constraints_snapshot: RegionSnapshot,
-    universe: ty::UniverseIndex,
-}
-
 impl<'tcx> InferCtxt<'tcx> {
     pub fn dcx(&self) -> &'tcx DiagCtxt {
         self.tcx.dcx()
@@ -842,90 +827,6 @@ impl<'tcx> InferCtxt<'tcx> {
         }
     }
 
-    pub fn in_snapshot(&self) -> bool {
-        UndoLogs::<UndoLog<'tcx>>::in_snapshot(&self.inner.borrow_mut().undo_log)
-    }
-
-    pub fn num_open_snapshots(&self) -> usize {
-        UndoLogs::<UndoLog<'tcx>>::num_open_snapshots(&self.inner.borrow_mut().undo_log)
-    }
-
-    fn start_snapshot(&self) -> CombinedSnapshot<'tcx> {
-        debug!("start_snapshot()");
-
-        let mut inner = self.inner.borrow_mut();
-
-        CombinedSnapshot {
-            undo_snapshot: inner.undo_log.start_snapshot(),
-            region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(),
-            universe: self.universe(),
-        }
-    }
-
-    #[instrument(skip(self, snapshot), level = "debug")]
-    fn rollback_to(&self, snapshot: CombinedSnapshot<'tcx>) {
-        let CombinedSnapshot { undo_snapshot, region_constraints_snapshot, universe } = snapshot;
-
-        self.universe.set(universe);
-
-        let mut inner = self.inner.borrow_mut();
-        inner.rollback_to(undo_snapshot);
-        inner.unwrap_region_constraints().rollback_to(region_constraints_snapshot);
-    }
-
-    #[instrument(skip(self, snapshot), level = "debug")]
-    fn commit_from(&self, snapshot: CombinedSnapshot<'tcx>) {
-        let CombinedSnapshot { undo_snapshot, region_constraints_snapshot: _, universe: _ } =
-            snapshot;
-
-        self.inner.borrow_mut().commit(undo_snapshot);
-    }
-
-    /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`.
-    #[instrument(skip(self, f), level = "debug")]
-    pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E>
-    where
-        F: FnOnce(&CombinedSnapshot<'tcx>) -> Result<T, E>,
-    {
-        let snapshot = self.start_snapshot();
-        let r = f(&snapshot);
-        debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok());
-        match r {
-            Ok(_) => {
-                self.commit_from(snapshot);
-            }
-            Err(_) => {
-                self.rollback_to(snapshot);
-            }
-        }
-        r
-    }
-
-    /// Execute `f` then unroll any bindings it creates.
-    #[instrument(skip(self, f), level = "debug")]
-    pub fn probe<R, F>(&self, f: F) -> R
-    where
-        F: FnOnce(&CombinedSnapshot<'tcx>) -> R,
-    {
-        let snapshot = self.start_snapshot();
-        let r = f(&snapshot);
-        self.rollback_to(snapshot);
-        r
-    }
-
-    /// Scan the constraints produced since `snapshot` and check whether
-    /// we added any region constraints.
-    pub fn region_constraints_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool {
-        self.inner
-            .borrow_mut()
-            .unwrap_region_constraints()
-            .region_constraints_added_in_snapshot(&snapshot.undo_snapshot)
-    }
-
-    pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool {
-        self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot)
-    }
-
     pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, expected: T, actual: T) -> bool
     where
         T: at::ToTrace<'tcx>,
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
similarity index 94%
rename from compiler/rustc_infer/src/infer/opaque_types.rs
rename to compiler/rustc_infer/src/infer/opaque_types/mod.rs
index 7a789a1b41b..3d6829ba657 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
@@ -17,7 +17,6 @@ use rustc_middle::ty::{
     TypeVisitable, TypeVisitableExt, TypeVisitor,
 };
 use rustc_span::Span;
-use std::ops::ControlFlow;
 
 mod table;
 
@@ -101,6 +100,15 @@ impl<'tcx> InferCtxt<'tcx> {
         let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) if def_id.is_local() => {
                 let def_id = def_id.expect_local();
+                if self.intercrate {
+                    // See comment on `insert_hidden_type` for why this is sufficient in coherence
+                    return Some(self.register_hidden_type(
+                        OpaqueTypeKey { def_id, args },
+                        cause.clone(),
+                        param_env,
+                        b,
+                    ));
+                }
                 match self.defining_use_anchor {
                     DefiningAnchor::Bind(_) => {
                         // Check that this is `impl Trait` type is
@@ -142,8 +150,10 @@ impl<'tcx> InferCtxt<'tcx> {
                         }
                     }
                     DefiningAnchor::Bubble => {}
-                    DefiningAnchor::Error => return None,
-                };
+                    DefiningAnchor::Error => {
+                        return None;
+                    }
+                }
                 if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() {
                     // We could accept this, but there are various ways to handle this situation, and we don't
                     // want to make a decision on it right now. Likely this case is so super rare anyway, that
@@ -381,7 +391,7 @@ impl<'tcx> InferCtxt<'tcx> {
             // Anonymous `impl Trait`
             hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id,
             // Named `type Foo = impl Bar;`
-            hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => {
+            hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => {
                 if in_assoc_ty {
                     self.tcx.opaque_types_defined_by(parent_def_id).contains(&def_id)
                 } else {
@@ -415,29 +425,22 @@ impl<'tcx, OP> TypeVisitor<TyCtxt<'tcx>> for ConstrainOpaqueTypeRegionVisitor<'t
 where
     OP: FnMut(ty::Region<'tcx>),
 {
-    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
-        &mut self,
-        t: &ty::Binder<'tcx, T>,
-    ) -> ControlFlow<Self::BreakTy> {
+    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
         t.super_visit_with(self);
-        ControlFlow::Continue(())
     }
 
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_region(&mut self, r: ty::Region<'tcx>) {
         match *r {
             // ignore bound regions, keep visiting
-            ty::ReBound(_, _) => ControlFlow::Continue(()),
-            _ => {
-                (self.op)(r);
-                ControlFlow::Continue(())
-            }
+            ty::ReBound(_, _) => {}
+            _ => (self.op)(r),
         }
     }
 
-    fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, ty: Ty<'tcx>) {
         // We're only interested in types involving regions
         if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) {
-            return ControlFlow::Continue(());
+            return;
         }
 
         match ty.kind() {
@@ -488,8 +491,6 @@ where
                 ty.super_visit_with(self);
             }
         }
-
-        ControlFlow::Continue(())
     }
 }
 
@@ -591,8 +592,25 @@ impl<'tcx> InferCtxt<'tcx> {
         obligations: &mut Vec<PredicateObligation<'tcx>>,
     ) {
         let tcx = self.tcx;
-        let item_bounds = tcx.explicit_item_bounds(def_id);
+        // Require that the hidden type is well-formed. We have to
+        // make sure we wf-check the hidden type to fix #114728.
+        //
+        // However, we don't check that all types are well-formed.
+        // We only do so for types provided by the user or if they are
+        // "used", e.g. for method selection.
+        //
+        // This means we never check the wf requirements of the hidden
+        // type during MIR borrowck, causing us to infer the wrong
+        // lifetime for its member constraints which then results in
+        // unexpected region errors.
+        obligations.push(traits::Obligation::new(
+            tcx,
+            cause.clone(),
+            param_env,
+            ty::ClauseKind::WellFormed(hidden_ty.into()),
+        ));
 
+        let item_bounds = tcx.explicit_item_bounds(def_id);
         for (predicate, _) in item_bounds.iter_instantiated_copied(tcx, args) {
             let predicate = predicate.fold_with(&mut BottomUpFolder {
                 tcx,
diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs
index 9f49ed00219..a7ddf475436 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/table.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs
@@ -1,7 +1,7 @@
 use rustc_data_structures::undo_log::UndoLogs;
 use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty};
 
-use crate::infer::{InferCtxtUndoLogs, UndoLog};
+use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog};
 
 use super::{OpaqueTypeDecl, OpaqueTypeMap};
 
diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs
index 42e3d6cad5a..488f435994d 100644
--- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs
+++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs
@@ -2,8 +2,6 @@ use rustc_middle::ty::{
     self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
 };
 
-use std::ops::ControlFlow;
-
 use crate::infer::outlives::test_type_match;
 use crate::infer::region_constraints::VerifyIfEq;
 
@@ -26,29 +24,22 @@ impl<'tcx, OP> TypeVisitor<TyCtxt<'tcx>> for FreeRegionsVisitor<'tcx, OP>
 where
     OP: FnMut(ty::Region<'tcx>),
 {
-    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
-        &mut self,
-        t: &ty::Binder<'tcx, T>,
-    ) -> ControlFlow<Self::BreakTy> {
+    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
         t.super_visit_with(self);
-        ControlFlow::Continue(())
     }
 
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_region(&mut self, r: ty::Region<'tcx>) {
         match *r {
             // ignore bound regions, keep visiting
-            ty::ReBound(_, _) => ControlFlow::Continue(()),
-            _ => {
-                (self.op)(r);
-                ControlFlow::Continue(())
-            }
+            ty::ReBound(_, _) => {}
+            _ => (self.op)(r),
         }
     }
 
-    fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, ty: Ty<'tcx>) {
         // We're only interested in types involving regions
         if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) {
-            return ControlFlow::Continue(());
+            return;
         }
 
         // FIXME: Don't consider alias bounds on types that have escaping bound
@@ -102,7 +93,7 @@ where
                     && outlives_bounds[1..].iter().all(|other_r| other_r == r)
                 {
                     assert!(r.type_flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS));
-                    r.visit_with(self)?;
+                    r.visit_with(self);
                 } else {
                     // Skip lifetime parameters that are not captures.
                     let variances = match kind {
@@ -114,17 +105,13 @@ where
                         if variances.map(|variances| variances[idx])
                             != Some(ty::Variance::Bivariant)
                         {
-                            s.visit_with(self)?;
+                            s.visit_with(self);
                         }
                     }
                 }
             }
 
-            _ => {
-                ty.super_visit_with(self)?;
-            }
+            _ => ty.super_visit_with(self),
         }
-
-        ControlFlow::Continue(())
     }
 }
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index 8dd3a1f40cc..fe323982ec0 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -63,9 +63,8 @@ use crate::infer::outlives::components::{push_outlives_components, Component};
 use crate::infer::outlives::env::RegionBoundPairs;
 use crate::infer::outlives::verify::VerifyBoundCx;
 use crate::infer::resolve::OpportunisticRegionResolver;
-use crate::infer::{
-    self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound,
-};
+use crate::infer::snapshot::undo_log::UndoLog;
+use crate::infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound};
 use crate::traits::{ObligationCause, ObligationCauseCode};
 use rustc_data_structures::undo_log::UndoLogs;
 use rustc_middle::mir::ConstraintCategory;
diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
index 9e2f3a10b6a..06f8dd4a4c6 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
@@ -1,9 +1,7 @@
 use super::*;
-use crate::infer::CombinedSnapshot;
-use rustc_data_structures::{
-    fx::FxIndexMap,
-    graph::{scc::Sccs, vec_graph::VecGraph},
-};
+use crate::infer::snapshot::CombinedSnapshot;
+use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::graph::{scc::Sccs, vec_graph::VecGraph};
 use rustc_index::Idx;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::relate::RelateResult;
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index ee97dd36807..0f3f2bc5fa6 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -3,9 +3,8 @@
 use self::CombineMapType::*;
 use self::UndoLog::*;
 
-use super::{
-    InferCtxtUndoLogs, MiscVariable, RegionVariableOrigin, Rollback, Snapshot, SubregionOrigin,
-};
+use super::{MiscVariable, RegionVariableOrigin, Rollback, SubregionOrigin};
+use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, Snapshot};
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
@@ -360,7 +359,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
     ///
     /// Not legal during a snapshot.
     pub fn into_infos_and_data(self) -> (VarInfos, RegionConstraintData<'tcx>) {
-        assert!(!UndoLogs::<super::UndoLog<'_>>::in_snapshot(&self.undo_log));
+        assert!(!UndoLogs::<UndoLog<'_>>::in_snapshot(&self.undo_log));
         (mem::take(&mut self.storage.var_infos), mem::take(&mut self.storage.data))
     }
 
@@ -377,7 +376,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
     ///
     /// Not legal during a snapshot.
     pub fn take_and_reset_data(&mut self) -> RegionConstraintData<'tcx> {
-        assert!(!UndoLogs::<super::UndoLog<'_>>::in_snapshot(&self.undo_log));
+        assert!(!UndoLogs::<UndoLog<'_>>::in_snapshot(&self.undo_log));
 
         // If you add a new field to `RegionConstraintCollector`, you
         // should think carefully about whether it needs to be cleared
diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs
index f30e366c198..70ed7cf9af1 100644
--- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs
+++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs
@@ -1,7 +1,7 @@
 //! Helper routines for higher-ranked things. See the `doc` module at
 //! the end of the file for details.
 
-use crate::infer::CombinedSnapshot;
+use crate::infer::snapshot::CombinedSnapshot;
 use crate::infer::InferCtxt;
 use rustc_middle::ty::fold::FnMutDelegate;
 use rustc_middle::ty::relate::RelateResult;
@@ -77,7 +77,7 @@ impl<'tcx> InferCtxt<'tcx> {
         // that name placeholders created in this function. Nested goals from type relations can
         // also contain placeholders created by this function.
         let value = self.enter_forall_and_leak_universe(forall);
-        debug!("?value");
+        debug!(?value);
         f(value)
     }
 
diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs
similarity index 98%
rename from compiler/rustc_infer/src/infer/fudge.rs
rename to compiler/rustc_infer/src/infer/snapshot/fudge.rs
index 99033922bdf..14de461cd17 100644
--- a/compiler/rustc_infer/src/infer/fudge.rs
+++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs
@@ -2,9 +2,9 @@ use rustc_middle::infer::unify_key::{ConstVariableOriginKind, ConstVariableValue
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid};
 
-use super::type_variable::TypeVariableOrigin;
-use super::InferCtxt;
-use super::{ConstVariableOrigin, RegionVariableOrigin, UnificationTable};
+use crate::infer::type_variable::TypeVariableOrigin;
+use crate::infer::InferCtxt;
+use crate::infer::{ConstVariableOrigin, RegionVariableOrigin, UnificationTable};
 
 use rustc_data_structures::snapshot_vec as sv;
 use rustc_data_structures::unify as ut;
diff --git a/compiler/rustc_infer/src/infer/snapshot/mod.rs b/compiler/rustc_infer/src/infer/snapshot/mod.rs
new file mode 100644
index 00000000000..9eef1471b1a
--- /dev/null
+++ b/compiler/rustc_infer/src/infer/snapshot/mod.rs
@@ -0,0 +1,102 @@
+use super::region_constraints::RegionSnapshot;
+use super::InferCtxt;
+use rustc_data_structures::undo_log::UndoLogs;
+use rustc_middle::ty;
+
+mod fudge;
+pub(crate) mod undo_log;
+
+use undo_log::{Snapshot, UndoLog};
+
+#[must_use = "once you start a snapshot, you should always consume it"]
+pub struct CombinedSnapshot<'tcx> {
+    pub(super) undo_snapshot: Snapshot<'tcx>,
+    region_constraints_snapshot: RegionSnapshot,
+    universe: ty::UniverseIndex,
+}
+
+impl<'tcx> InferCtxt<'tcx> {
+    pub fn in_snapshot(&self) -> bool {
+        UndoLogs::<UndoLog<'tcx>>::in_snapshot(&self.inner.borrow_mut().undo_log)
+    }
+
+    pub fn num_open_snapshots(&self) -> usize {
+        UndoLogs::<UndoLog<'tcx>>::num_open_snapshots(&self.inner.borrow_mut().undo_log)
+    }
+
+    fn start_snapshot(&self) -> CombinedSnapshot<'tcx> {
+        debug!("start_snapshot()");
+
+        let mut inner = self.inner.borrow_mut();
+
+        CombinedSnapshot {
+            undo_snapshot: inner.undo_log.start_snapshot(),
+            region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(),
+            universe: self.universe(),
+        }
+    }
+
+    #[instrument(skip(self, snapshot), level = "debug")]
+    fn rollback_to(&self, snapshot: CombinedSnapshot<'tcx>) {
+        let CombinedSnapshot { undo_snapshot, region_constraints_snapshot, universe } = snapshot;
+
+        self.universe.set(universe);
+
+        let mut inner = self.inner.borrow_mut();
+        inner.rollback_to(undo_snapshot);
+        inner.unwrap_region_constraints().rollback_to(region_constraints_snapshot);
+    }
+
+    #[instrument(skip(self, snapshot), level = "debug")]
+    fn commit_from(&self, snapshot: CombinedSnapshot<'tcx>) {
+        let CombinedSnapshot { undo_snapshot, region_constraints_snapshot: _, universe: _ } =
+            snapshot;
+
+        self.inner.borrow_mut().commit(undo_snapshot);
+    }
+
+    /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`.
+    #[instrument(skip(self, f), level = "debug")]
+    pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E>
+    where
+        F: FnOnce(&CombinedSnapshot<'tcx>) -> Result<T, E>,
+    {
+        let snapshot = self.start_snapshot();
+        let r = f(&snapshot);
+        debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok());
+        match r {
+            Ok(_) => {
+                self.commit_from(snapshot);
+            }
+            Err(_) => {
+                self.rollback_to(snapshot);
+            }
+        }
+        r
+    }
+
+    /// Execute `f` then unroll any bindings it creates.
+    #[instrument(skip(self, f), level = "debug")]
+    pub fn probe<R, F>(&self, f: F) -> R
+    where
+        F: FnOnce(&CombinedSnapshot<'tcx>) -> R,
+    {
+        let snapshot = self.start_snapshot();
+        let r = f(&snapshot);
+        self.rollback_to(snapshot);
+        r
+    }
+
+    /// Scan the constraints produced since `snapshot` and check whether
+    /// we added any region constraints.
+    pub fn region_constraints_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool {
+        self.inner
+            .borrow_mut()
+            .unwrap_region_constraints()
+            .region_constraints_added_in_snapshot(&snapshot.undo_snapshot)
+    }
+
+    pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool {
+        self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot)
+    }
+}
diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs
similarity index 100%
rename from compiler/rustc_infer/src/infer/undo_log.rs
rename to compiler/rustc_infer/src/infer/snapshot/undo_log.rs
diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs
index 97f9a4b291d..029bddda1e1 100644
--- a/compiler/rustc_infer/src/lib.rs
+++ b/compiler/rustc_infer/src/lib.rs
@@ -20,6 +20,7 @@
 #![allow(rustc::untranslatable_diagnostic)]
 #![feature(associated_type_bounds)]
 #![feature(box_patterns)]
+#![feature(control_flow_enum)]
 #![feature(extend_one)]
 #![feature(let_chains)]
 #![feature(if_let_guard)]
diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs
index afba2e50a23..31ceb234332 100644
--- a/compiler/rustc_infer/src/traits/project.rs
+++ b/compiler/rustc_infer/src/traits/project.rs
@@ -2,7 +2,7 @@
 
 use super::PredicateObligation;
 
-use crate::infer::InferCtxtUndoLogs;
+use crate::infer::snapshot::undo_log::InferCtxtUndoLogs;
 
 use rustc_data_structures::{
     snapshot_map::{self, SnapshotMapRef, SnapshotMapStorage},
diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs
index bf4f88530d0..064e09b8750 100644
--- a/compiler/rustc_infer/src/traits/structural_impls.rs
+++ b/compiler/rustc_infer/src/traits/structural_impls.rs
@@ -1,11 +1,11 @@
 use crate::traits;
 use crate::traits::project::Normalized;
+use rustc_ast_ir::try_visit;
 use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable};
 use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor};
 use rustc_middle::ty::{self, TyCtxt};
 
 use std::fmt;
-use std::ops::ControlFlow;
 
 // Structural impls for the structs in `traits`.
 
@@ -84,8 +84,8 @@ impl<'tcx, O: TypeFoldable<TyCtxt<'tcx>>> TypeFoldable<TyCtxt<'tcx>>
 impl<'tcx, O: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>>
     for traits::Obligation<'tcx, O>
 {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.predicate.visit_with(visitor)?;
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
+        try_visit!(self.predicate.visit_with(visitor));
         self.param_env.visit_with(visitor)
     }
 }
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index cd7957c3bce..284d965979e 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -45,9 +45,10 @@ 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(format!(
-                "this error occurred on the command line: `--cfg={s}`"
-            ));
+            let psess = ParseSess::with_silent_emitter(
+                vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
+                format!("this error occurred on the command line: `--cfg={s}`"),
+            );
             let filename = FileName::cfg_spec_source_code(&s);
 
             macro_rules! error {
@@ -61,7 +62,7 @@ pub(crate) fn parse_cfg(dcx: &DiagCtxt, cfgs: Vec<String>) -> Cfg {
                 };
             }
 
-            match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) {
+            match maybe_new_parser_from_source_str(&psess, filename, s.to_string()) {
                 Ok(mut parser) => match parser.parse_meta_item() {
                     Ok(meta_item) if parser.token == token::Eof => {
                         if meta_item.path.segments.len() != 1 {
@@ -107,9 +108,10 @@ 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(format!(
-            "this error occurred on the command line: `--check-cfg={s}`"
-        ));
+        let psess = ParseSess::with_silent_emitter(
+            vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
+            format!("this error occurred on the command line: `--check-cfg={s}`"),
+        );
         let filename = FileName::cfg_spec_source_code(&s);
 
         macro_rules! error {
@@ -127,7 +129,7 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg {
             error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`")
         };
 
-        let mut parser = match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) {
+        let mut parser = match maybe_new_parser_from_source_str(&psess, filename, s.to_string()) {
             Ok(parser) => parser,
             Err(errs) => {
                 errs.into_iter().for_each(|err| err.cancel());
@@ -277,7 +279,7 @@ pub struct Config {
     pub lint_caps: FxHashMap<lint::LintId, lint::Level>,
 
     /// This is a callback from the driver that is called when [`ParseSess`] is created.
-    pub parse_sess_created: Option<Box<dyn FnOnce(&mut ParseSess) + Send>>,
+    pub psess_created: Option<Box<dyn FnOnce(&mut ParseSess) + Send>>,
 
     /// This is a callback to hash otherwise untracked state used by the caller, if the
     /// hash changes between runs the incremental cache will be cleared.
@@ -318,6 +320,7 @@ pub struct Config {
 
 // JUSTIFICATION: before session exists, only config
 #[allow(rustc::bad_opt_access)]
+#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
 pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R {
     trace!("run_compiler");
 
@@ -393,14 +396,14 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
             let cfg = parse_cfg(&sess.dcx(), config.crate_cfg);
             let mut cfg = config::build_configuration(&sess, cfg);
             util::add_configuration(&mut cfg, &mut sess, &*codegen_backend);
-            sess.parse_sess.config = cfg;
+            sess.psess.config = cfg;
 
             let mut check_cfg = parse_check_cfg(&sess.dcx(), config.crate_check_cfg);
             check_cfg.fill_well_known(&sess.target);
-            sess.parse_sess.check_config = check_cfg;
+            sess.psess.check_config = check_cfg;
 
-            if let Some(parse_sess_created) = config.parse_sess_created {
-                parse_sess_created(&mut sess.parse_sess);
+            if let Some(psess_created) = config.psess_created {
+                psess_created(&mut sess.psess);
             }
 
             if let Some(hash_untracked_state) = config.hash_untracked_state {
@@ -422,7 +425,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
             let compiler =
                 Compiler { sess, codegen_backend, override_queries: config.override_queries };
 
-            rustc_span::set_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
+            rustc_span::set_source_map(compiler.sess.psess.clone_source_map(), move || {
                 // There are two paths out of `f`.
                 // - Normal exit.
                 // - Panic, e.g. triggered by `abort_if_errors`.
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 66140168759..4b4c1d6cf67 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -44,9 +44,9 @@ use std::{env, fs, iter};
 
 pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> {
     let krate = sess.time("parse_crate", || match &sess.io.input {
-        Input::File(file) => parse_crate_from_file(file, &sess.parse_sess),
+        Input::File(file) => parse_crate_from_file(file, &sess.psess),
         Input::Str { input, name } => {
-            parse_crate_from_source_str(name.clone(), input.clone(), &sess.parse_sess)
+            parse_crate_from_source_str(name.clone(), input.clone(), &sess.psess)
         }
     })?;
 
@@ -205,7 +205,7 @@ fn configure_and_expand(
 
         // The rest is error reporting
 
-        sess.parse_sess.buffered_lints.with_lock(|buffered_lints: &mut Vec<BufferedEarlyLint>| {
+        sess.psess.buffered_lints.with_lock(|buffered_lints: &mut Vec<BufferedEarlyLint>| {
             buffered_lints.append(&mut ecx.buffered_early_lint);
         });
 
@@ -280,7 +280,7 @@ fn configure_and_expand(
 
 fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
     let sess = tcx.sess;
-    let (resolver, krate) = &*tcx.resolver_for_lowering(()).borrow();
+    let (resolver, krate) = &*tcx.resolver_for_lowering().borrow();
     let mut lint_buffer = resolver.lint_buffer.steal();
 
     if sess.opts.unstable_opts.input_stats {
@@ -297,7 +297,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
     });
 
     // Add all buffered lints from the `ParseSess` to the `Session`.
-    sess.parse_sess.buffered_lints.with_lock(|buffered_lints| {
+    sess.psess.buffered_lints.with_lock(|buffered_lints| {
         info!("{} parse sess buffered_lints", buffered_lints.len());
         for early_lint in buffered_lints.drain(..) {
             lint_buffer.add_early_lint(early_lint);
@@ -305,7 +305,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
     });
 
     // Gate identifiers containing invalid Unicode codepoints that were recovered during lexing.
-    sess.parse_sess.bad_unicode_identifiers.with_lock(|identifiers| {
+    sess.psess.bad_unicode_identifiers.with_lock(|identifiers| {
         for (ident, mut spans) in identifiers.drain(..) {
             spans.sort();
             if ident == sym::ferris {
@@ -422,7 +422,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P
 
         // Account for explicitly marked-to-track files
         // (e.g. accessed in proc macros).
-        let file_depinfo = sess.parse_sess.file_depinfo.borrow();
+        let file_depinfo = sess.psess.file_depinfo.borrow();
 
         let normalize_path = |path: PathBuf| {
             let file = FileName::from(path);
@@ -485,7 +485,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P
             }
 
             // Emit special comments with information about accessed environment variables.
-            let env_depinfo = sess.parse_sess.env_depinfo.borrow();
+            let env_depinfo = sess.psess.env_depinfo.borrow();
             if !env_depinfo.is_empty() {
                 // We will soon sort, so the initial order does not matter.
                 #[allow(rustc::potential_query_instability)]
@@ -531,10 +531,10 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P
     }
 }
 
-fn resolver_for_lowering<'tcx>(
+fn resolver_for_lowering_raw<'tcx>(
     tcx: TyCtxt<'tcx>,
     (): (),
-) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> {
+) -> (&'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)>, &'tcx ty::ResolverGlobalCtxt) {
     let arenas = Resolver::arenas();
     let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`.
     let (krate, pre_configured_attrs) = tcx.crate_for_resolver(()).steal();
@@ -549,16 +549,15 @@ fn resolver_for_lowering<'tcx>(
         ast_lowering: untracked_resolver_for_lowering,
     } = resolver.into_outputs();
 
-    let feed = tcx.feed_unit_query();
-    feed.resolutions(tcx.arena.alloc(untracked_resolutions));
-    tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate))))
+    let resolutions = tcx.arena.alloc(untracked_resolutions);
+    (tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))), resolutions)
 }
 
 pub(crate) fn write_dep_info(tcx: TyCtxt<'_>) {
     // Make sure name resolution and macro expansion is run for
     // the side-effect of providing a complete set of all
     // accessed files and env vars.
-    let _ = tcx.resolver_for_lowering(());
+    let _ = tcx.resolver_for_lowering();
 
     let sess = tcx.sess;
     let _timer = sess.timer("write_dep_info");
@@ -607,7 +606,10 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
     let providers = &mut Providers::default();
     providers.analysis = analysis;
     providers.hir_crate = rustc_ast_lowering::lower_to_hir;
-    providers.resolver_for_lowering = resolver_for_lowering;
+    providers.resolver_for_lowering_raw = resolver_for_lowering_raw;
+    providers.stripped_cfg_items =
+        |tcx, _| tcx.arena.alloc_from_iter(tcx.resolutions(()).stripped_cfg_items.steal());
+    providers.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1;
     providers.early_lint_checks = early_lint_checks;
     proc_macro_decls::provide(providers);
     rustc_const_eval::provide(providers);
@@ -686,6 +688,11 @@ pub fn create_global_ctxt<'tcx>(
 /// Runs the type-checking, region checking and other miscellaneous analysis
 /// passes on the crate.
 fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
+    if tcx.sess.opts.unstable_opts.hir_stats {
+        rustc_passes::hir_stats::print_hir_stats(tcx);
+    }
+
+    #[cfg(debug_assertions)]
     rustc_passes::hir_id_validator::check_crate(tcx);
 
     let sess = tcx.sess;
@@ -956,7 +963,7 @@ fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit
         // `check_builtin_attribute`), but by the time that runs the macro
         // is expanded, and it doesn't give an error.
         validate_attr::emit_fatal_malformed_builtin_attribute(
-            &sess.parse_sess,
+            &sess.psess,
             attr,
             sym::recursion_limit,
         );
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 86858bfe41d..da11d090b74 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -8,8 +8,7 @@ use rustc_codegen_ssa::CodegenResults;
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, OnceLock, WorkerLocal};
-use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
+use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE};
 use rustc_hir::definitions::Definitions;
 use rustc_incremental::setup_dep_graph;
 use rustc_metadata::creader::CStore;
@@ -120,7 +119,7 @@ impl<'tcx> Queries<'tcx> {
 
             rustc_builtin_macros::cmdline_attrs::inject(
                 &mut krate,
-                &sess.parse_sess,
+                &sess.psess,
                 &sess.opts.unstable_opts.crate_attr,
             );
 
@@ -144,10 +143,8 @@ impl<'tcx> Queries<'tcx> {
                 stable_crate_id,
             )) as _);
             let definitions = FreezeLock::new(Definitions::new(stable_crate_id));
-            let source_span = AppendOnlyIndexVec::new();
-            let _id = source_span.push(krate.spans.inner_span);
-            debug_assert_eq!(_id, CRATE_DEF_ID);
-            let untracked = Untracked { cstore, source_span, definitions };
+            let untracked =
+                Untracked { cstore, source_span: AppendOnlyIndexVec::new(), definitions };
 
             let qcx = passes::create_global_ctxt(
                 self.compiler,
@@ -172,9 +169,6 @@ impl<'tcx> Queries<'tcx> {
                 )));
                 feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs))));
                 feed.output_filenames(Arc::new(outputs));
-
-                let feed = tcx.feed_local_def_id(CRATE_DEF_ID);
-                feed.def_kind(DefKind::Mod);
             });
             Ok(qcx)
         })
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 5e1fc248b80..4f15d1c1d3a 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -590,7 +590,7 @@ fn test_codegen_options_tracking_hash() {
     tracked!(force_frame_pointers, Some(false));
     tracked!(force_unwind_tables, Some(true));
     tracked!(inline_threshold, Some(0xf007ba11));
-    tracked!(instrument_coverage, InstrumentCoverage::All);
+    tracked!(instrument_coverage, InstrumentCoverage::Yes);
     tracked!(link_dead_code, Some(true));
     tracked!(linker_plugin_lto, LinkerPluginLto::LinkerPluginAuto);
     tracked!(llvm_args, vec![String::from("1"), String::from("2")]);
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 823614e1f06..0d50200133c 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -9,7 +9,7 @@ use rustc_parse::validate_attr;
 use rustc_session as session;
 use rustc_session::config::{self, Cfg, CrateType, OutFileName, OutputFilenames, OutputTypes};
 use rustc_session::filesearch::sysroot_candidates;
-use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer};
+use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer};
 use rustc_session::{filesearch, output, Session};
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::edition::Edition;
@@ -160,6 +160,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
     })
 }
 
+#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
 fn load_backend_from_dylib(early_dcx: &EarlyDiagCtxt, path: &Path) -> MakeBackendFn {
     match unsafe { load_symbol_from_dylib::<MakeBackendFn>(path, "__rustc_codegen_backend") } {
         Ok(backend_sym) => backend_sym,
@@ -227,6 +228,7 @@ fn get_rustc_path_inner(bin_path: &str) -> Option<PathBuf> {
     })
 }
 
+#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
 fn get_codegen_sysroot(
     early_dcx: &EarlyDiagCtxt,
     maybe_sysroot: &Option<PathBuf>,
@@ -319,6 +321,7 @@ fn get_codegen_sysroot(
     }
 }
 
+#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
 pub(crate) fn check_attr_crate_type(
     sess: &Session,
     attrs: &[ast::Attribute],
@@ -345,7 +348,7 @@ pub(crate) fn check_attr_crate_type(
                             ast::CRATE_NODE_ID,
                             span,
                             "invalid `crate_type` value",
-                            BuiltinLintDiagnostics::UnknownCrateTypes(
+                            BuiltinLintDiag::UnknownCrateTypes(
                                 span,
                                 "did you mean".to_string(),
                                 format!("\"{candidate}\""),
@@ -369,7 +372,7 @@ pub(crate) fn check_attr_crate_type(
                 // by the time that runs the macro is expanded, and it doesn't
                 // give an error.
                 validate_attr::emit_fatal_malformed_builtin_attribute(
-                    &sess.parse_sess,
+                    &sess.psess,
                     a,
                     sym::crate_type,
                 );
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 9f73d2e6812..5f0af6aee6a 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -58,7 +58,7 @@ use rustc_middle::ty::GenericArgKind;
 use rustc_middle::ty::ToPredicate;
 use rustc_middle::ty::TypeVisitableExt;
 use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef};
-use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason};
+use rustc_session::lint::{BuiltinLintDiag, FutureIncompatibilityReason};
 use rustc_span::edition::Edition;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -1231,7 +1231,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
         }
 
         fn def_id_is_transmute(cx: &LateContext<'_>, def_id: DefId) -> bool {
-            matches!(cx.tcx.intrinsic(def_id), Some(sym::transmute))
+            cx.tcx.is_intrinsic(def_id, sym::transmute)
         }
     }
 }
@@ -1868,7 +1868,7 @@ impl KeywordIdents {
         };
 
         // Don't lint `r#foo`.
-        if cx.sess().parse_sess.raw_identifier_spans.contains(ident.span) {
+        if cx.sess().psess.raw_identifier_spans.contains(ident.span) {
             return;
         }
 
@@ -2831,7 +2831,7 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
                             Some(target_spans),
                             fluent::lint_builtin_asm_labels,
                             |_| {},
-                            BuiltinLintDiagnostics::NamedAsmLabel(
+                            BuiltinLintDiag::NamedAsmLabel(
                                 "only local labels of the form `<number>:` should be used in inline asm"
                                     .to_string(),
                             ),
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index ab76da36ee3..89cdde11726 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -21,7 +21,7 @@ use crate::passes::{EarlyLintPassObject, LateLintPassObject};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sync;
 use rustc_data_structures::unord::UnordMap;
-use rustc_errors::{DecorateLint, Diag, DiagnosticMessage, MultiSpan};
+use rustc_errors::{DecorateLint, Diag, DiagMessage, MultiSpan};
 use rustc_feature::Features;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
@@ -31,7 +31,7 @@ use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::print::{with_no_trimmed_paths, PrintError};
 use rustc_middle::ty::{self, print::Printer, GenericArg, RegisteredTools, Ty, TyCtxt};
-use rustc_session::lint::{BuiltinLintDiagnostics, LintExpectationId};
+use rustc_session::lint::{BuiltinLintDiag, LintExpectationId};
 use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
 use rustc_session::{LintStoreMarker, Session};
 use rustc_span::edit_distance::find_best_match_for_names;
@@ -536,9 +536,9 @@ pub trait LintContext {
         &self,
         lint: &'static Lint,
         span: Option<impl Into<MultiSpan>>,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
         decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
-        diagnostic: BuiltinLintDiagnostics,
+        diagnostic: BuiltinLintDiag,
     ) {
         // We first generate a blank diagnostic.
         self.opt_span_lint(lint, span, msg, |db| {
@@ -559,7 +559,7 @@ pub trait LintContext {
         &self,
         lint: &'static Lint,
         span: Option<S>,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
         decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
     );
 
@@ -584,7 +584,7 @@ pub trait LintContext {
         &self,
         lint: &'static Lint,
         span: S,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
         decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
     ) {
         self.opt_span_lint(lint, Some(span), msg, decorate);
@@ -605,7 +605,7 @@ pub trait LintContext {
     fn lint(
         &self,
         lint: &'static Lint,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
         decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
     ) {
         self.opt_span_lint(lint, None as Option<Span>, msg, decorate);
@@ -621,12 +621,13 @@ pub trait LintContext {
     /// Note that this function should only be called for [`LintExpectationId`]s
     /// retrieved from the current lint pass. Buffered or manually created ids can
     /// cause ICEs.
-    #[rustc_lint_diagnostics]
     fn fulfill_expectation(&self, expectation: LintExpectationId) {
         // We need to make sure that submitted expectation ids are correctly fulfilled suppressed
         // and stored between compilation sessions. To not manually do these steps, we simply create
-        // a dummy diagnostic and emit is as usual, which will be suppressed and stored like a normal
-        // expected lint diagnostic.
+        // a dummy diagnostic and emit it as usual, which will be suppressed and stored like a
+        // normal expected lint diagnostic.
+        #[allow(rustc::diagnostic_outside_of_impl)]
+        #[allow(rustc::untranslatable_diagnostic)]
         self.sess()
             .dcx()
             .struct_expect(
@@ -670,7 +671,7 @@ impl<'tcx> LintContext for LateContext<'tcx> {
         &self,
         lint: &'static Lint,
         span: Option<S>,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
         decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
     ) {
         let hir_id = self.last_node_with_lint_attrs;
@@ -697,7 +698,7 @@ impl LintContext for EarlyContext<'_> {
         &self,
         lint: &'static Lint,
         span: Option<S>,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
         decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
     ) {
         self.builder.opt_span_lint(lint, span.map(|s| s.into()), msg, decorate)
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index 728996f0741..a0be1c09c9a 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -6,15 +6,52 @@ use rustc_errors::{add_elided_lifetime_in_path_suggestion, Diag};
 use rustc_errors::{Applicability, SuggestionStyle};
 use rustc_middle::middle::stability;
 use rustc_session::config::ExpectedValues;
-use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::Session;
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::BytePos;
 
-pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: &mut Diag<'_, ()>) {
+const MAX_CHECK_CFG_NAMES_OR_VALUES: usize = 35;
+
+fn check_cfg_expected_note(
+    sess: &Session,
+    possibilities: &[Symbol],
+    type_: &str,
+    name: Option<Symbol>,
+    suffix: &str,
+) -> String {
+    use std::fmt::Write;
+
+    let n_possibilities = if sess.opts.unstable_opts.check_cfg_all_expected {
+        possibilities.len()
+    } else {
+        std::cmp::min(possibilities.len(), MAX_CHECK_CFG_NAMES_OR_VALUES)
+    };
+
+    let mut possibilities = possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
+    possibilities.sort();
+
+    let and_more = possibilities.len().saturating_sub(n_possibilities);
+    let possibilities = possibilities[..n_possibilities].join("`, `");
+
+    let mut note = String::with_capacity(50 + possibilities.len());
+
+    write!(&mut note, "expected {type_}").unwrap();
+    if let Some(name) = name {
+        write!(&mut note, " for `{name}`").unwrap();
+    }
+    write!(&mut note, " are: {suffix}`{possibilities}`").unwrap();
+    if and_more > 0 {
+        write!(&mut note, " and {and_more} more").unwrap();
+    }
+
+    note
+}
+
+pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) {
     match diagnostic {
-        BuiltinLintDiagnostics::UnicodeTextFlow(span, content) => {
+        BuiltinLintDiag::UnicodeTextFlow(span, content) => {
             let spans: Vec<_> = content
                 .char_indices()
                 .filter_map(|(i, c)| {
@@ -51,8 +88,8 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
                 );
             }
         }
-        BuiltinLintDiagnostics::Normal => (),
-        BuiltinLintDiagnostics::AbsPathWithModule(span) => {
+        BuiltinLintDiag::Normal => (),
+        BuiltinLintDiag::AbsPathWithModule(span) => {
             let (sugg, app) = match sess.source_map().span_to_snippet(span) {
                 Ok(ref s) => {
                     // FIXME(Manishearth) ideally the emitting code
@@ -65,21 +102,16 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
             };
             diag.span_suggestion(span, "use `crate`", sugg, app);
         }
-        BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(span) => {
+        BuiltinLintDiag::ProcMacroDeriveResolutionFallback(span) => {
             diag.span_label(
                 span,
                 "names from parent modules are not accessible without an explicit import",
             );
         }
-        BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
+        BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
             diag.span_note(span_def, "the macro is defined here");
         }
-        BuiltinLintDiagnostics::ElidedLifetimesInPaths(
-            n,
-            path_span,
-            incl_angl_brckt,
-            insertion_span,
-        ) => {
+        BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => {
             add_elided_lifetime_in_path_suggestion(
                 sess.source_map(),
                 diag,
@@ -89,10 +121,10 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
                 insertion_span,
             );
         }
-        BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
+        BuiltinLintDiag::UnknownCrateTypes(span, note, sugg) => {
             diag.span_suggestion(span, note, sugg, Applicability::MaybeIncorrect);
         }
-        BuiltinLintDiagnostics::UnusedImports(message, replaces, in_test_module) => {
+        BuiltinLintDiag::UnusedImports(message, replaces, in_test_module) => {
             if !replaces.is_empty() {
                 diag.tool_only_multipart_suggestion(
                     message,
@@ -108,21 +140,25 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
                 );
             }
         }
-        BuiltinLintDiagnostics::RedundantImport(spans, ident) => {
+        BuiltinLintDiag::RedundantImport(spans, ident) => {
             for (span, is_imported) in spans {
                 let introduced = if is_imported { "imported" } else { "defined" };
-                diag.span_label(span, format!("the item `{ident}` is already {introduced} here"));
+                let span_msg = if span.is_dummy() { "by prelude" } else { "here" };
+                diag.span_label(
+                    span,
+                    format!("the item `{ident}` is already {introduced} {span_msg}"),
+                );
             }
         }
-        BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => {
+        BuiltinLintDiag::DeprecatedMacro(suggestion, span) => {
             stability::deprecation_suggestion(diag, "macro", suggestion, span)
         }
-        BuiltinLintDiagnostics::UnusedDocComment(span) => {
+        BuiltinLintDiag::UnusedDocComment(span) => {
             diag.span_label(span, "rustdoc does not generate documentation for macro invocations");
             diag.help("to document an item produced by a macro, \
                                   the macro must produce the documentation as part of its expansion");
         }
-        BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident) => {
+        BuiltinLintDiag::PatternsInFnsWithoutBody(span, ident) => {
             diag.span_suggestion(
                 span,
                 "remove `mut` from the parameter",
@@ -130,17 +166,17 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
                 Applicability::MachineApplicable,
             );
         }
-        BuiltinLintDiagnostics::MissingAbi(span, default_abi) => {
+        BuiltinLintDiag::MissingAbi(span, default_abi) => {
             diag.span_label(span, "ABI should be specified here");
             diag.help(format!("the default ABI is {}", default_abi.name()));
         }
-        BuiltinLintDiagnostics::LegacyDeriveHelpers(span) => {
+        BuiltinLintDiag::LegacyDeriveHelpers(span) => {
             diag.span_label(span, "the attribute is introduced here");
         }
-        BuiltinLintDiagnostics::ProcMacroBackCompat(note) => {
+        BuiltinLintDiag::ProcMacroBackCompat(note) => {
             diag.note(note);
         }
-        BuiltinLintDiagnostics::OrPatternsBackCompat(span, suggestion) => {
+        BuiltinLintDiag::OrPatternsBackCompat(span, suggestion) => {
             diag.span_suggestion(
                 span,
                 "use pat_param to preserve semantics",
@@ -148,7 +184,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
                 Applicability::MachineApplicable,
             );
         }
-        BuiltinLintDiagnostics::ReservedPrefix(span) => {
+        BuiltinLintDiag::ReservedPrefix(span) => {
             diag.span_label(span, "unknown prefix");
             diag.span_suggestion_verbose(
                 span.shrink_to_hi(),
@@ -157,19 +193,19 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
                 Applicability::MachineApplicable,
             );
         }
-        BuiltinLintDiagnostics::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => {
+        BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => {
             diag.span_note(
                         invoc_span,
                         format!("the built-in attribute `{attr_name}` will be ignored, since it's applied to the macro invocation `{macro_name}`")
                     );
         }
-        BuiltinLintDiagnostics::TrailingMacro(is_trailing, name) => {
+        BuiltinLintDiag::TrailingMacro(is_trailing, name) => {
             if is_trailing {
                 diag.note("macro invocations at the end of a block are treated as expressions");
                 diag.note(format!("to ignore the value produced by the macro, add a semicolon after the invocation of `{name}`"));
             }
         }
-        BuiltinLintDiagnostics::BreakWithLabelAndLoop(span) => {
+        BuiltinLintDiag::BreakWithLabelAndLoop(span) => {
             diag.multipart_suggestion(
                 "wrap this expression in parentheses",
                 vec![
@@ -179,19 +215,19 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
                 Applicability::MachineApplicable,
             );
         }
-        BuiltinLintDiagnostics::NamedAsmLabel(help) => {
+        BuiltinLintDiag::NamedAsmLabel(help) => {
             diag.help(help);
             diag.note("see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information");
         }
-        BuiltinLintDiagnostics::UnexpectedCfgName((name, name_span), value) => {
+        BuiltinLintDiag::UnexpectedCfgName((name, name_span), value) => {
             #[allow(rustc::potential_query_instability)]
             let possibilities: Vec<Symbol> =
-                sess.parse_sess.check_config.expecteds.keys().copied().collect();
+                sess.psess.check_config.expecteds.keys().copied().collect();
 
             let mut names_possibilities: Vec<_> = if value.is_none() {
                 // We later sort and display all the possibilities, so the order here does not matter.
                 #[allow(rustc::potential_query_instability)]
-                sess.parse_sess
+                sess.psess
                     .check_config
                     .expecteds
                     .iter()
@@ -212,7 +248,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
             // Suggest the most probable if we found one
             } else if let Some(best_match) = find_best_match_for_name(&possibilities, name, None) {
                 if let Some(ExpectedValues::Some(best_match_values)) =
-                    sess.parse_sess.check_config.expecteds.get(&best_match)
+                    sess.psess.check_config.expecteds.get(&best_match)
                 {
                     // We will soon sort, so the initial order does not matter.
                     #[allow(rustc::potential_query_instability)]
@@ -291,16 +327,13 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
                     }
                 }
                 if !possibilities.is_empty() {
-                    let mut possibilities =
-                        possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
-                    possibilities.sort();
-                    let possibilities = possibilities.join("`, `");
-
-                    // The list of expected names can be long (even by default) and
-                    // so the diagnostic produced can take a lot of space. To avoid
-                    // cloging the user output we only want to print that diagnostic
-                    // once.
-                    diag.help_once(format!("expected names are: `{possibilities}`"));
+                    diag.help_once(check_cfg_expected_note(
+                        sess,
+                        &possibilities,
+                        "names",
+                        None,
+                        "",
+                    ));
                 }
             }
 
@@ -321,9 +354,8 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
                 diag.note("see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration");
             }
         }
-        BuiltinLintDiagnostics::UnexpectedCfgValue((name, name_span), value) => {
-            let Some(ExpectedValues::Some(values)) =
-                &sess.parse_sess.check_config.expecteds.get(&name)
+        BuiltinLintDiag::UnexpectedCfgValue((name, name_span), value) => {
+            let Some(ExpectedValues::Some(values)) = &sess.psess.check_config.expecteds.get(&name)
             else {
                 bug!(
                     "it shouldn't be possible to have a diagnostic on a value whose name is not in values"
@@ -344,16 +376,13 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
             // Show the full list if all possible values for a given name, but don't do it
             // for names as the possibilities could be very long
             if !possibilities.is_empty() {
-                {
-                    let mut possibilities =
-                        possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
-                    possibilities.sort();
-
-                    let possibilities = possibilities.join("`, `");
-                    let none = if have_none_possibility { "(none), " } else { "" };
-
-                    diag.note(format!("expected values for `{name}` are: {none}`{possibilities}`"));
-                }
+                diag.note(check_cfg_expected_note(
+                    sess,
+                    &possibilities,
+                    "values",
+                    Some(name),
+                    if have_none_possibility { "(none), " } else { "" },
+                ));
 
                 if let Some((value, value_span)) = value {
                     // Suggest the most probable if we found one
@@ -398,8 +427,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
             // We don't want to suggest adding values to well known names
             // since those are defined by rustc it-self. Users can still
             // do it if they want, but should not encourage them.
-            let is_cfg_a_well_know_name =
-                sess.parse_sess.check_config.well_known_names.contains(&name);
+            let is_cfg_a_well_know_name = sess.psess.check_config.well_known_names.contains(&name);
 
             let inst = if let Some((value, _value_span)) = value {
                 let pre = if is_from_cargo { "\\" } else { "" };
@@ -428,7 +456,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
                 diag.note("see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration");
             }
         }
-        BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(sugg) => {
+        BuiltinLintDiag::DeprecatedWhereclauseLocation(sugg) => {
             let left_sp = diag.span.primary_span().unwrap();
             match sugg {
                 Some((right_sp, sugg)) => diag.multipart_suggestion(
@@ -445,7 +473,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
             };
             diag.note("see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information");
         }
-        BuiltinLintDiagnostics::SingleUseLifetime {
+        BuiltinLintDiag::SingleUseLifetime {
             param_span,
             use_span: Some((use_span, elide)),
             deletion_span,
@@ -476,11 +504,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
                 diag.multipart_suggestion(msg, suggestions, Applicability::MachineApplicable);
             }
         }
-        BuiltinLintDiagnostics::SingleUseLifetime {
-            param_span: _,
-            use_span: None,
-            deletion_span,
-        } => {
+        BuiltinLintDiag::SingleUseLifetime { param_span: _, use_span: None, deletion_span } => {
             debug!(?deletion_span);
             if let Some(deletion_span) = deletion_span {
                 diag.span_suggestion(
@@ -491,7 +515,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
                 );
             }
         }
-        BuiltinLintDiagnostics::NamedArgumentUsedPositionally {
+        BuiltinLintDiag::NamedArgumentUsedPositionally {
             position_sp_to_replace,
             position_sp_for_msg,
             named_arg_sp,
@@ -527,13 +551,13 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
                 );
             }
         }
-        BuiltinLintDiagnostics::ByteSliceInPackedStructWithDerive => {
+        BuiltinLintDiag::ByteSliceInPackedStructWithDerive => {
             diag.help("consider implementing the trait by hand, or remove the `packed` attribute");
         }
-        BuiltinLintDiagnostics::UnusedExternCrate { removal_span } => {
+        BuiltinLintDiag::UnusedExternCrate { removal_span } => {
             diag.span_suggestion(removal_span, "remove it", "", Applicability::MachineApplicable);
         }
-        BuiltinLintDiagnostics::ExternCrateNotIdiomatic { vis_span, ident_span } => {
+        BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span } => {
             let suggestion_span = vis_span.between(ident_span);
             diag.span_suggestion_verbose(
                 suggestion_span,
@@ -542,10 +566,10 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
                 Applicability::MachineApplicable,
             );
         }
-        BuiltinLintDiagnostics::AmbiguousGlobImports { diag: ambiguity } => {
+        BuiltinLintDiag::AmbiguousGlobImports { diag: ambiguity } => {
             rustc_errors::report_ambiguity_error(diag, ambiguity);
         }
-        BuiltinLintDiagnostics::AmbiguousGlobReexports {
+        BuiltinLintDiag::AmbiguousGlobReexports {
             name,
             namespace,
             first_reexport_span,
@@ -562,7 +586,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
                 ),
             );
         }
-        BuiltinLintDiagnostics::HiddenGlobReexports {
+        BuiltinLintDiag::HiddenGlobReexports {
             name,
             namespace,
             glob_reexport_span,
@@ -571,7 +595,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
             diag.span_note(glob_reexport_span, format!("the name `{name}` in the {namespace} namespace is supposed to be publicly re-exported here"));
             diag.span_note(private_item_span, "but the private item here shadows it".to_owned());
         }
-        BuiltinLintDiagnostics::UnusedQualifications { removal_span } => {
+        BuiltinLintDiag::UnusedQualifications { removal_span } => {
             diag.span_suggestion_verbose(
                 removal_span,
                 "remove the unnecessary path segments",
@@ -579,7 +603,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
                 Applicability::MachineApplicable,
             );
         }
-        BuiltinLintDiagnostics::AssociatedConstElidedLifetime { elided, span } => {
+        BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span } => {
             diag.span_suggestion_verbose(
                 if elided { span.shrink_to_hi() } else { span },
                 "use the `'static` lifetime",
@@ -587,7 +611,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
                 Applicability::MachineApplicable,
             );
         }
-        BuiltinLintDiagnostics::RedundantImportVisibility { max_vis, span } => {
+        BuiltinLintDiag::RedundantImportVisibility { max_vis, span } => {
             diag.span_note(span, format!("the most public imported item is `{max_vis}`"));
             diag.help(
                 "reduce the glob import's visibility or increase visibility of imported items",
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 0862204d88e..d78ec8c0dd3 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -17,8 +17,8 @@
 use crate::context::{EarlyContext, LintContext, LintStore};
 use crate::passes::{EarlyLintPass, EarlyLintPassObject};
 use rustc_ast::ptr::P;
-use rustc_ast::visit::{self as ast_visit, Visitor};
-use rustc_ast::{self as ast, walk_list, HasAttrs};
+use rustc_ast::visit::{self as ast_visit, walk_list, Visitor};
+use rustc_ast::{self as ast, HasAttrs};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_feature::Features;
 use rustc_middle::ty::RegisteredTools;
diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs
index 3be792a9e4f..d73f9e7a4a1 100644
--- a/compiler/rustc_lint/src/errors.rs
+++ b/compiler/rustc_lint/src/errors.rs
@@ -1,5 +1,5 @@
 use crate::fluent_generated as fluent;
-use rustc_errors::{codes::*, AddToDiagnostic, Diag, EmissionGuarantee, SubdiagnosticMessageOp};
+use rustc_errors::{codes::*, AddToDiagnostic, Diag, EmissionGuarantee, SubdiagMessageOp};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_session::lint::Level;
 use rustc_span::{Span, Symbol};
@@ -24,7 +24,7 @@ pub enum OverruledAttributeSub {
 }
 
 impl AddToDiagnostic for OverruledAttributeSub {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index a071fa488bc..e8fcf4132ea 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -10,7 +10,7 @@ use rustc_ast as ast;
 use rustc_hir::def::Res;
 use rustc_hir::{def_id::DefId, Expr, ExprKind, GenericArg, PatKind, Path, PathSegment, QPath};
 use rustc_hir::{BinOp, BinOpKind, HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind};
-use rustc_middle::ty;
+use rustc_middle::ty::{self, Ty as MiddleTy};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -338,10 +338,11 @@ impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword {
 }
 
 declare_tool_lint! {
-    /// The `untranslatable_diagnostic` lint detects diagnostics created
-    /// without using translatable Fluent strings.
+    /// The `untranslatable_diagnostic` lint detects messages passed to functions with `impl
+    /// Into<{D,Subd}iagMessage` parameters without using translatable Fluent strings.
     ///
-    /// More details on translatable diagnostics can be found [here](https://rustc-dev-guide.rust-lang.org/diagnostics/translation.html).
+    /// More details on translatable diagnostics can be found
+    /// [here](https://rustc-dev-guide.rust-lang.org/diagnostics/translation.html).
     pub rustc::UNTRANSLATABLE_DIAGNOSTIC,
     Deny,
     "prevent creation of diagnostics which cannot be translated",
@@ -349,11 +350,13 @@ declare_tool_lint! {
 }
 
 declare_tool_lint! {
-    /// The `diagnostic_outside_of_impl` lint detects diagnostics created manually,
-    /// and inside an `IntoDiagnostic`/`AddToDiagnostic` implementation,
-    /// or a `#[derive(Diagnostic)]`/`#[derive(Subdiagnostic)]` expansion.
+    /// The `diagnostic_outside_of_impl` lint detects calls to functions annotated with
+    /// `#[rustc_lint_diagnostics]` that are outside an `IntoDiagnostic`, `AddToDiagnostic`, or
+    /// `DecorateLint` impl, or a `#[derive(Diagnostic)]`, `#[derive(Subdiagnostic)]`,
+    /// `#[derive(DecorateLint)]` expansion.
     ///
-    /// More details on diagnostics implementations can be found [here](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html).
+    /// More details on diagnostics implementations can be found
+    /// [here](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html).
     pub rustc::DIAGNOSTIC_OUTSIDE_OF_IMPL,
     Deny,
     "prevent creation of diagnostics outside of `IntoDiagnostic`/`AddToDiagnostic` impls",
@@ -364,54 +367,132 @@ declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE
 
 impl LateLintPass<'_> for Diagnostics {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        let Some((span, def_id, args)) = typeck_results_of_method_fn(cx, expr) else { return };
-        debug!(?span, ?def_id, ?args);
-        let has_attr = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, args)
+        // Only check function calls and method calls.
+        let (span, def_id, fn_gen_args, call_tys) = match expr.kind {
+            ExprKind::Call(callee, args) => {
+                match cx.typeck_results().node_type(callee.hir_id).kind() {
+                    &ty::FnDef(def_id, fn_gen_args) => {
+                        let call_tys: Vec<_> =
+                            args.iter().map(|arg| cx.typeck_results().expr_ty(arg)).collect();
+                        (callee.span, def_id, fn_gen_args, call_tys)
+                    }
+                    _ => return, // occurs for fns passed as args
+                }
+            }
+            ExprKind::MethodCall(_segment, _recv, args, _span) => {
+                let Some((span, def_id, fn_gen_args)) = typeck_results_of_method_fn(cx, expr)
+                else {
+                    return;
+                };
+                let mut call_tys: Vec<_> =
+                    args.iter().map(|arg| cx.typeck_results().expr_ty(arg)).collect();
+                call_tys.insert(0, cx.tcx.types.self_param); // dummy inserted for `self`
+                (span, def_id, fn_gen_args, call_tys)
+            }
+            _ => return,
+        };
+
+        // Is the callee marked with `#[rustc_lint_diagnostics]`?
+        let has_attr = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, fn_gen_args)
             .ok()
             .flatten()
             .is_some_and(|inst| cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics));
-        if !has_attr {
+
+        // Closure: is the type `{D,Subd}iagMessage`?
+        let is_diag_message = |ty: MiddleTy<'_>| {
+            if let Some(adt_def) = ty.ty_adt_def()
+                && let Some(name) = cx.tcx.get_diagnostic_name(adt_def.did())
+                && matches!(name, sym::DiagMessage | sym::SubdiagMessage)
+            {
+                true
+            } else {
+                false
+            }
+        };
+
+        // Does the callee have a `impl Into<{D,Subd}iagMessage>` parameter? (There should be at
+        // most one.)
+        let mut impl_into_diagnostic_message_param = None;
+        let fn_sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder();
+        let predicates = cx.tcx.predicates_of(def_id).instantiate_identity(cx.tcx).predicates;
+        for (i, &param_ty) in fn_sig.inputs().iter().enumerate() {
+            if let ty::Param(p) = param_ty.kind() {
+                // It is a type parameter. Check if it is `impl Into<{D,Subd}iagMessage>`.
+                for pred in predicates.iter() {
+                    if let Some(trait_pred) = pred.as_trait_clause()
+                        && let trait_ref = trait_pred.skip_binder().trait_ref
+                        && trait_ref.self_ty() == param_ty // correct predicate for the param?
+                        && cx.tcx.is_diagnostic_item(sym::Into, trait_ref.def_id)
+                        && let ty1 = trait_ref.args.type_at(1)
+                        && is_diag_message(ty1)
+                    {
+                        if impl_into_diagnostic_message_param.is_some() {
+                            cx.tcx.dcx().span_bug(
+                                span,
+                                "can't handle multiple `impl Into<{D,Sub}iagMessage>` params",
+                            );
+                        }
+                        impl_into_diagnostic_message_param = Some((i, p.name));
+                    }
+                }
+            }
+        }
+
+        // Is the callee interesting?
+        if !has_attr && impl_into_diagnostic_message_param.is_none() {
             return;
         }
 
-        let mut found_parent_with_attr = false;
-        let mut found_impl = false;
-        for (hir_id, parent) in cx.tcx.hir().parent_iter(expr.hir_id) {
-            if let Some(owner_did) = hir_id.as_owner() {
-                found_parent_with_attr = found_parent_with_attr
-                    || cx.tcx.has_attr(owner_did, sym::rustc_lint_diagnostics);
-            }
-
-            debug!(?parent);
-            if let Node::Item(Item { kind: ItemKind::Impl(impl_), .. }) = parent
-                && let Impl { of_trait: Some(of_trait), .. } = impl_
-                && let Some(def_id) = of_trait.trait_def_id()
-                && let Some(name) = cx.tcx.get_diagnostic_name(def_id)
-                && matches!(name, sym::IntoDiagnostic | sym::AddToDiagnostic | sym::DecorateLint)
+        // Is the parent method marked with `#[rustc_lint_diagnostics]`?
+        let mut parent_has_attr = false;
+        for (hir_id, _parent) in cx.tcx.hir().parent_iter(expr.hir_id) {
+            if let Some(owner_did) = hir_id.as_owner()
+                && cx.tcx.has_attr(owner_did, sym::rustc_lint_diagnostics)
             {
-                found_impl = true;
+                parent_has_attr = true;
                 break;
             }
         }
-        debug!(?found_impl);
-        if !found_parent_with_attr && !found_impl {
-            cx.emit_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, DiagOutOfImpl);
-        }
 
-        let mut found_diagnostic_message = false;
-        for ty in args.types() {
-            debug!(?ty);
-            if let Some(adt_def) = ty.ty_adt_def()
-                && let Some(name) = cx.tcx.get_diagnostic_name(adt_def.did())
-                && matches!(name, sym::DiagnosticMessage | sym::SubdiagnosticMessage)
-            {
-                found_diagnostic_message = true;
-                break;
+        // Calls to `#[rustc_lint_diagnostics]`-marked functions should only occur:
+        // - inside an impl of `IntoDiagnostic`, `AddToDiagnostic`, or `DecorateLint`, or
+        // - inside a parent function that is itself marked with `#[rustc_lint_diagnostics]`.
+        //
+        // Otherwise, emit a `DIAGNOSTIC_OUTSIDE_OF_IMPL` lint.
+        if has_attr && !parent_has_attr {
+            let mut is_inside_appropriate_impl = false;
+            for (_hir_id, parent) in cx.tcx.hir().parent_iter(expr.hir_id) {
+                debug!(?parent);
+                if let Node::Item(Item { kind: ItemKind::Impl(impl_), .. }) = parent
+                    && let Impl { of_trait: Some(of_trait), .. } = impl_
+                    && let Some(def_id) = of_trait.trait_def_id()
+                    && let Some(name) = cx.tcx.get_diagnostic_name(def_id)
+                    && matches!(
+                        name,
+                        sym::IntoDiagnostic | sym::AddToDiagnostic | sym::DecorateLint
+                    )
+                {
+                    is_inside_appropriate_impl = true;
+                    break;
+                }
+            }
+            debug!(?is_inside_appropriate_impl);
+            if !is_inside_appropriate_impl {
+                cx.emit_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, DiagOutOfImpl);
             }
         }
-        debug!(?found_diagnostic_message);
-        if !found_parent_with_attr && !found_diagnostic_message {
-            cx.emit_span_lint(UNTRANSLATABLE_DIAGNOSTIC, span, UntranslatableDiag);
+
+        // Calls to methods with an `impl Into<{D,Subd}iagMessage>` parameter must be passed an arg
+        // with type `{D,Subd}iagMessage` or `impl Into<{D,Subd}iagMessage>`. Otherwise, emit an
+        // `UNTRANSLATABLE_DIAGNOSTIC` lint.
+        if let Some((param_i, param_i_p_name)) = impl_into_diagnostic_message_param {
+            // Is the arg type `{Sub,D}iagMessage`or `impl Into<{Sub,D}iagMessage>`?
+            let arg_ty = call_tys[param_i];
+            let is_translatable = is_diag_message(arg_ty)
+                || matches!(arg_ty.kind(), ty::Param(p) if p.name == param_i_p_name);
+            if !is_translatable {
+                cx.emit_span_lint(UNTRANSLATABLE_DIAGNOSTIC, span, UntranslatableDiag);
+            }
         }
     }
 }
@@ -425,7 +506,7 @@ declare_tool_lint! {
     report_in_external_macro: true
 }
 
-declare_lint_pass!(BadOptAccess => [ BAD_OPT_ACCESS ]);
+declare_lint_pass!(BadOptAccess => [BAD_OPT_ACCESS]);
 
 impl LateLintPass<'_> for BadOptAccess {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs
index c552b983255..de642f373b5 100644
--- a/compiler/rustc_lint/src/let_underscore.rs
+++ b/compiler/rustc_lint/src/let_underscore.rs
@@ -104,6 +104,7 @@ const SYNC_GUARD_SYMBOLS: [Symbol; 3] = [
 ];
 
 impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::Local<'_>) {
         if matches!(local.source, rustc_hir::LocalSource::AsyncFn) {
             return;
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index ad4a0fc47db..2f08cd53b75 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -16,7 +16,7 @@ use crate::{
 use rustc_ast as ast;
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxIndexMap;
-use rustc_errors::{DecorateLint, Diag, DiagnosticMessage, MultiSpan};
+use rustc_errors::{DecorateLint, Diag, DiagMessage, MultiSpan};
 use rustc_feature::{Features, GateIssue};
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
@@ -724,6 +724,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
         };
     }
 
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn add(&mut self, attrs: &[ast::Attribute], is_crate_node: bool, source_hir_id: Option<HirId>) {
         let sess = self.sess;
         for (attr_index, attr) in attrs.iter().enumerate() {
@@ -1106,7 +1107,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
         &self,
         lint: &'static Lint,
         span: Option<MultiSpan>,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
         decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
     ) {
         let (level, src) = self.lint_level(lint);
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index a9a2592ac7a..7e0ac1bfff1 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -5,8 +5,8 @@ use std::num::NonZero;
 use crate::errors::RequestedLevel;
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    codes::*, AddToDiagnostic, Applicability, DecorateLint, Diag, DiagStyledString,
-    DiagnosticMessage, EmissionGuarantee, SubdiagnosticMessageOp, SuggestionStyle,
+    codes::*, AddToDiagnostic, Applicability, DecorateLint, Diag, DiagMessage, DiagStyledString,
+    EmissionGuarantee, SubdiagMessageOp, SuggestionStyle,
 };
 use rustc_hir::def_id::DefId;
 use rustc_macros::{LintDiagnostic, Subdiagnostic};
@@ -141,7 +141,7 @@ impl<'a> DecorateLint<'a, ()> for BuiltinMissingDebugImpl<'_> {
         diag.arg("debug", self.tcx.def_path_str(self.def_id));
     }
 
-    fn msg(&self) -> DiagnosticMessage {
+    fn msg(&self) -> DiagMessage {
         fluent::lint_builtin_missing_debug_impl
     }
 }
@@ -251,7 +251,7 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
         );
     }
 
-    fn msg(&self) -> DiagnosticMessage {
+    fn msg(&self) -> DiagMessage {
         fluent::lint_ungated_async_fn_track_caller
     }
 }
@@ -271,7 +271,7 @@ pub struct SuggestChangingAssocTypes<'a, 'b> {
 }
 
 impl<'a, 'b> AddToDiagnostic for SuggestChangingAssocTypes<'a, 'b> {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -327,7 +327,7 @@ pub struct BuiltinTypeAliasGenericBoundsSuggestion {
 }
 
 impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -416,7 +416,7 @@ pub struct BuiltinFeatureIssueNote {
 }
 
 pub struct BuiltinUnpermittedTypeInit<'a> {
-    pub msg: DiagnosticMessage,
+    pub msg: DiagMessage,
     pub ty: Ty<'a>,
     pub label: Span,
     pub sub: BuiltinUnpermittedTypeInitSub,
@@ -437,7 +437,7 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
         self.sub.add_to_diagnostic(diag);
     }
 
-    fn msg(&self) -> DiagnosticMessage {
+    fn msg(&self) -> DiagMessage {
         self.msg.clone()
     }
 }
@@ -448,7 +448,7 @@ pub struct BuiltinUnpermittedTypeInitSub {
 }
 
 impl AddToDiagnostic for BuiltinUnpermittedTypeInitSub {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -503,7 +503,7 @@ pub struct BuiltinClashingExternSub<'a> {
 }
 
 impl AddToDiagnostic for BuiltinClashingExternSub<'_> {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -785,7 +785,7 @@ pub struct HiddenUnicodeCodepointsDiagLabels {
 }
 
 impl AddToDiagnostic for HiddenUnicodeCodepointsDiagLabels {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -803,7 +803,7 @@ pub enum HiddenUnicodeCodepointsDiagSub {
 
 // Used because of multiple multipart_suggestion and note
 impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -951,7 +951,7 @@ pub struct NonBindingLetSub {
 }
 
 impl AddToDiagnostic for NonBindingLetSub {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -1179,7 +1179,7 @@ impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused {
         }
     }
 
-    fn msg(&self) -> DiagnosticMessage {
+    fn msg(&self) -> DiagMessage {
         fluent::lint_non_fmt_panic_unused
     }
 }
@@ -1237,7 +1237,7 @@ pub enum NonSnakeCaseDiagSub {
 }
 
 impl AddToDiagnostic for NonSnakeCaseDiagSub {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -1403,7 +1403,7 @@ impl<'a> DecorateLint<'a, ()> for DropTraitConstraintsDiag<'_> {
         diag.arg("needs_drop", self.tcx.def_path_str(self.def_id));
     }
 
-    fn msg(&self) -> DiagnosticMessage {
+    fn msg(&self) -> DiagMessage {
         fluent::lint_drop_trait_constraints
     }
 }
@@ -1419,7 +1419,7 @@ impl<'a> DecorateLint<'a, ()> for DropGlue<'_> {
         diag.arg("needs_drop", self.tcx.def_path_str(self.def_id));
     }
 
-    fn msg(&self) -> DiagnosticMessage {
+    fn msg(&self) -> DiagMessage {
         fluent::lint_drop_glue
     }
 }
@@ -1479,7 +1479,7 @@ pub enum OverflowingBinHexSign {
 }
 
 impl AddToDiagnostic for OverflowingBinHexSign {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -1683,12 +1683,12 @@ pub struct ImproperCTypes<'a> {
     pub ty: Ty<'a>,
     pub desc: &'a str,
     pub label: Span,
-    pub help: Option<DiagnosticMessage>,
-    pub note: DiagnosticMessage,
+    pub help: Option<DiagMessage>,
+    pub note: DiagMessage,
     pub span_note: Option<Span>,
 }
 
-// Used because of the complexity of Option<DiagnosticMessage>, DiagnosticMessage, and Option<Span>
+// Used because of the complexity of Option<DiagMessage>, DiagMessage, and Option<Span>
 impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> {
     fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
         diag.arg("ty", self.ty);
@@ -1703,7 +1703,7 @@ impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> {
         }
     }
 
-    fn msg(&self) -> DiagnosticMessage {
+    fn msg(&self) -> DiagMessage {
         fluent::lint_improper_ctypes
     }
 }
@@ -1846,7 +1846,7 @@ impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> {
         }
     }
 
-    fn msg(&self) -> DiagnosticMessage {
+    fn msg(&self) -> DiagMessage {
         fluent::lint_unused_def
     }
 }
@@ -1923,7 +1923,7 @@ impl<'a> DecorateLint<'a, ()> for AsyncFnInTraitDiag {
         }
     }
 
-    fn msg(&self) -> DiagnosticMessage {
+    fn msg(&self) -> DiagMessage {
         fluent::lint_async_fn_in_trait
     }
 }
diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs
index 5e66ade0357..79bc78ae55a 100644
--- a/compiler/rustc_lint/src/non_ascii_idents.rs
+++ b/compiler/rustc_lint/src/non_ascii_idents.rs
@@ -172,7 +172,7 @@ impl EarlyLintPass for NonAsciiIdents {
         }
 
         let mut has_non_ascii_idents = false;
-        let symbols = cx.sess().parse_sess.symbol_gallery.symbols.lock();
+        let symbols = cx.sess().psess.symbol_gallery.symbols.lock();
 
         // Sort by `Span` so that error messages make sense with respect to the
         // order of identifier locations in the code.
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index ebef77f6879..a2d07fff506 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -231,7 +231,7 @@ fn check_panic_str<'tcx>(
 
     let fmt_span = arg.span.source_callsite();
 
-    let (snippet, style) = match cx.sess().parse_sess.source_map().span_to_snippet(fmt_span) {
+    let (snippet, style) = match cx.sess().psess.source_map().span_to_snippet(fmt_span) {
         Ok(snippet) => {
             // Count the number of `#`s between the `r` and `"`.
             let style = snippet.strip_prefix('r').and_then(|s| s.find('"'));
@@ -282,7 +282,7 @@ fn check_panic_str<'tcx>(
 /// Given the span of `some_macro!(args);`, gives the span of `(` and `)`,
 /// and the type of (opening) delimiter used.
 fn find_delimiters(cx: &LateContext<'_>, span: Span) -> Option<(Span, Span, char)> {
-    let snippet = cx.sess().parse_sess.source_map().span_to_snippet(span).ok()?;
+    let snippet = cx.sess().psess.source_map().span_to_snippet(span).ok()?;
     let (open, open_ch) = snippet.char_indices().find(|&(_, c)| "([{".contains(c))?;
     let close = snippet.rfind(|c| ")]}".contains(c))?;
     Some((
diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs
index 6cb6fd1cbd5..a4fd5a7c45f 100644
--- a/compiler/rustc_lint/src/non_local_def.rs
+++ b/compiler/rustc_lint/src/non_local_def.rs
@@ -14,6 +14,7 @@ declare_lint! {
     /// ### Example
     ///
     /// ```rust
+    /// #![warn(non_local_definitions)]
     /// trait MyTrait {}
     /// struct MyStruct;
     ///
@@ -36,7 +37,7 @@ declare_lint! {
     /// All nested bodies (functions, enum discriminant, array length, consts) (expect for
     /// `const _: Ty = { ... }` in top-level module, which is still undecided) are checked.
     pub NON_LOCAL_DEFINITIONS,
-    Warn,
+    Allow,
     "checks for non-local definitions",
     report_in_external_macro
 }
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index a87e2410b3d..5d36a8b3d0e 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -14,7 +14,7 @@ use crate::{LateContext, LateLintPass, LintContext};
 use rustc_ast as ast;
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::DiagnosticMessage;
+use rustc_errors::DiagMessage;
 use rustc_hir as hir;
 use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
 use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
@@ -959,7 +959,7 @@ struct ImproperCTypesVisitor<'a, 'tcx> {
 enum FfiResult<'tcx> {
     FfiSafe,
     FfiPhantom(Ty<'tcx>),
-    FfiUnsafe { ty: Ty<'tcx>, reason: DiagnosticMessage, help: Option<DiagnosticMessage> },
+    FfiUnsafe { ty: Ty<'tcx>, reason: DiagMessage, help: Option<DiagMessage> },
 }
 
 pub(crate) fn nonnull_optimization_guaranteed<'tcx>(
@@ -1446,8 +1446,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         &mut self,
         ty: Ty<'tcx>,
         sp: Span,
-        note: DiagnosticMessage,
-        help: Option<DiagnosticMessage>,
+        note: DiagMessage,
+        help: Option<DiagMessage>,
     ) {
         let lint = match self.mode {
             CItemKind::Declaration => IMPROPER_CTYPES,
@@ -1474,9 +1474,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
     fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
         struct ProhibitOpaqueTypes;
         impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for ProhibitOpaqueTypes {
-            type BreakTy = Ty<'tcx>;
+            type Result = ControlFlow<Ty<'tcx>>;
 
-            fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+            fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
                 if !ty.has_opaque_types() {
                     return ControlFlow::Continue(());
                 }
@@ -1620,9 +1620,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         }
 
         impl<'vis, 'a, 'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for FnPtrFinder<'vis, 'a, 'tcx> {
-            type BreakTy = Ty<'tcx>;
+            type Result = ControlFlow<Ty<'tcx>>;
 
-            fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+            fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
                 if let ty::FnPtr(sig) = ty.kind()
                     && !self.visitor.is_internal_abi(sig.abi())
                 {
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 3481c66da70..f84d1c6c2d0 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -20,6 +20,7 @@ use rustc_span::symbol::Symbol;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::{BytePos, Span};
 use std::iter;
+use std::ops::ControlFlow;
 
 declare_lint! {
     /// The `unused_must_use` lint detects unused result of a type flagged as
@@ -753,21 +754,18 @@ trait UnusedDelimLint {
         // fn f(){(print!(á
         // ```
         use rustc_ast::visit::{walk_expr, Visitor};
-        struct ErrExprVisitor {
-            has_error: bool,
-        }
+        struct ErrExprVisitor;
         impl<'ast> Visitor<'ast> for ErrExprVisitor {
-            fn visit_expr(&mut self, expr: &'ast ast::Expr) {
+            type Result = ControlFlow<()>;
+            fn visit_expr(&mut self, expr: &'ast ast::Expr) -> ControlFlow<()> {
                 if let ExprKind::Err(_) = expr.kind {
-                    self.has_error = true;
-                    return;
+                    ControlFlow::Break(())
+                } else {
+                    walk_expr(self, expr)
                 }
-                walk_expr(self, expr)
             }
         }
-        let mut visitor = ErrExprVisitor { has_error: false };
-        visitor.visit_expr(value);
-        if visitor.has_error {
+        if ErrExprVisitor.visit_expr(value).is_break() {
             return;
         }
         let spans = match value.kind {
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 94f8bbe2437..f2560b35aa2 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -67,6 +67,7 @@ declare_lint_pass! {
         MISSING_FRAGMENT_SPECIFIER,
         MUST_NOT_SUSPEND,
         NAMED_ARGUMENTS_USED_POSITIONALLY,
+        NON_CONTIGUOUS_RANGE_ENDPOINTS,
         NON_EXHAUSTIVE_OMITTED_PATTERNS,
         ORDER_DEPENDENT_TRAIT_OBJECTS,
         OVERLAPPING_RANGE_ENDPOINTS,
@@ -812,6 +813,36 @@ declare_lint! {
     "detects range patterns with overlapping endpoints"
 }
 
+declare_lint! {
+    /// The `non_contiguous_range_endpoints` lint detects likely off-by-one errors when using
+    /// exclusive [range patterns].
+    ///
+    /// [range patterns]: https://doc.rust-lang.org/nightly/reference/patterns.html#range-patterns
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// # #![feature(exclusive_range_pattern)]
+    /// let x = 123u32;
+    /// match x {
+    ///     0..100 => { println!("small"); }
+    ///     101..1000 => { println!("large"); }
+    ///     _ => { println!("larger"); }
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// It is likely a mistake to have range patterns in a match expression that miss out a single
+    /// number. Check that the beginning and end values are what you expect, and keep in mind that
+    /// with `..=` the right bound is inclusive, and with `..` it is exclusive.
+    pub NON_CONTIGUOUS_RANGE_ENDPOINTS,
+    Warn,
+    "detects off-by-one errors with exclusive range patterns"
+}
+
 declare_lint! {
     /// The `bindings_with_variant_name` lint detects pattern bindings with
     /// the same name as one of the matched variants.
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 198008d4d0d..7f200a7b623 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -8,7 +8,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::stable_hasher::{
     HashStable, StableCompare, StableHasher, ToStableHashKey,
 };
-use rustc_error_messages::{DiagnosticMessage, MultiSpan};
+use rustc_error_messages::{DiagMessage, MultiSpan};
 use rustc_hir::HashStableContext;
 use rustc_hir::HirId;
 use rustc_span::edition::Edition;
@@ -569,7 +569,7 @@ pub struct AmbiguityErrorDiag {
 // This could be a closure, but then implementing derive trait
 // becomes hacky (and it gets allocated).
 #[derive(Debug)]
-pub enum BuiltinLintDiagnostics {
+pub enum BuiltinLintDiag {
     Normal,
     AbsPathWithModule(Span),
     ProcMacroDeriveResolutionFallback(Span),
@@ -674,7 +674,7 @@ pub struct BufferedEarlyLint {
     pub span: MultiSpan,
 
     /// The lint message.
-    pub msg: DiagnosticMessage,
+    pub msg: DiagMessage,
 
     /// The `NodeId` of the AST node that generated the lint.
     pub node_id: NodeId,
@@ -684,7 +684,7 @@ pub struct BufferedEarlyLint {
     pub lint_id: LintId,
 
     /// Customization of the `Diag<'_>` for the lint.
-    pub diagnostic: BuiltinLintDiagnostics,
+    pub diagnostic: BuiltinLintDiag,
 }
 
 #[derive(Default, Debug)]
@@ -703,8 +703,8 @@ impl LintBuffer {
         lint: &'static Lint,
         node_id: NodeId,
         span: MultiSpan,
-        msg: impl Into<DiagnosticMessage>,
-        diagnostic: BuiltinLintDiagnostics,
+        msg: impl Into<DiagMessage>,
+        diagnostic: BuiltinLintDiag,
     ) {
         let lint_id = LintId::of(lint);
         let msg = msg.into();
@@ -721,9 +721,9 @@ impl LintBuffer {
         lint: &'static Lint,
         id: NodeId,
         sp: impl Into<MultiSpan>,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
     ) {
-        self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal)
+        self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiag::Normal)
     }
 
     pub fn buffer_lint_with_diagnostic(
@@ -731,8 +731,8 @@ impl LintBuffer {
         lint: &'static Lint,
         id: NodeId,
         sp: impl Into<MultiSpan>,
-        msg: impl Into<DiagnosticMessage>,
-        diagnostic: BuiltinLintDiagnostics,
+        msg: impl Into<DiagMessage>,
+        diagnostic: BuiltinLintDiag,
     ) {
         self.add_lint(lint, id, sp.into(), msg, diagnostic)
     }
diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml
index 6598f1db86d..c206380a06f 100644
--- a/compiler/rustc_llvm/Cargo.toml
+++ b/compiler/rustc_llvm/Cargo.toml
@@ -8,12 +8,7 @@ edition = "2021"
 libc = "0.2.73"
 # tidy-alphabetical-end
 
-# FIXME: updating cc past 1.0.79 breaks libstd bootstrapping, pin
-# to the last working version here so `cargo update` doesn't cause the
-# a higher version to be selected
-# https://github.com/rust-lang/cc-rs/issues/913
-# 1.0.{84, 85} fix this but have been yanked
 [build-dependencies]
 # tidy-alphabetical-start
-cc = "=1.0.79"
+cc = "1.0.90"
 # tidy-alphabetical-end
diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
index 627be997513..60789b07e54 100644
--- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
@@ -120,7 +120,7 @@ extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
   }
   auto FilenamesWriter =
       coverage::CoverageFilenamesSectionWriter(ArrayRef<std::string>(FilenameRefs));
-  RawRustStringOstream OS(BufferOut);
+  auto OS = RawRustStringOstream(BufferOut);
   FilenamesWriter.write(OS);
 }
 
@@ -160,7 +160,7 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer(
       ArrayRef<unsigned>(VirtualFileMappingIDs, NumVirtualFileMappingIDs),
       Expressions,
       MappingRegions);
-  RawRustStringOstream OS(BufferOut);
+  auto OS = RawRustStringOstream(BufferOut);
   CoverageMappingWriter.write(OS);
 }
 
@@ -168,23 +168,23 @@ extern "C" LLVMValueRef LLVMRustCoverageCreatePGOFuncNameVar(
     LLVMValueRef F,
     const char *FuncName,
     size_t FuncNameLen) {
-  StringRef FuncNameRef(FuncName, FuncNameLen);
+  auto FuncNameRef = StringRef(FuncName, FuncNameLen);
   return wrap(createPGOFuncNameVar(*cast<Function>(unwrap(F)), FuncNameRef));
 }
 
 extern "C" uint64_t LLVMRustCoverageHashByteArray(
     const char *Bytes,
     size_t NumBytes) {
-  StringRef StrRef(Bytes, NumBytes);
+  auto StrRef = StringRef(Bytes, NumBytes);
   return IndexedInstrProf::ComputeHash(StrRef);
 }
 
 static void WriteSectionNameToString(LLVMModuleRef M,
                                      InstrProfSectKind SK,
                                      RustStringRef Str) {
-  Triple TargetTriple(unwrap(M)->getTargetTriple());
+  auto TargetTriple = Triple(unwrap(M)->getTargetTriple());
   auto name = getInstrProfSectionName(SK, TargetTriple.getObjectFormat());
-  RawRustStringOstream OS(Str);
+  auto OS = RawRustStringOstream(Str);
   OS << name;
 }
 
@@ -200,7 +200,7 @@ extern "C" void LLVMRustCoverageWriteFuncSectionNameToString(LLVMModuleRef M,
 
 extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) {
   auto name = getCoverageMappingVarName();
-  RawRustStringOstream OS(Str);
+  auto OS = RawRustStringOstream(Str);
   OS << name;
 }
 
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 4ec784e2590..f6253068eaa 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -77,9 +77,9 @@ extern "C" void LLVMRustTimeTraceProfilerFinishThread() {
 }
 
 extern "C" void LLVMRustTimeTraceProfilerFinish(const char* FileName) {
-  StringRef FN(FileName);
+  auto FN = StringRef(FileName);
   std::error_code EC;
-  raw_fd_ostream OS(FN, EC, sys::fs::CD_CreateAlways);
+  auto OS = raw_fd_ostream(FN, EC, sys::fs::CD_CreateAlways);
 
   timeTraceProfilerWrite(OS);
   timeTraceProfilerCleanup();
@@ -424,7 +424,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
   auto CM = fromRust(RustCM);
 
   std::string Error;
-  Triple Trip(Triple::normalize(TripleStr));
+  auto Trip = Triple(Triple::normalize(TripleStr));
   const llvm::Target *TheTarget =
       TargetRegistry::lookupTarget(Trip.getTriple(), Error);
   if (TheTarget == nullptr) {
@@ -451,14 +451,30 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
       Options.ObjectFilenameForDebug = OutputObjFile;
   }
   if (!strcmp("zlib", DebugInfoCompression) && llvm::compression::zlib::isAvailable()) {
+#if LLVM_VERSION_GE(19, 0)
+    Options.MCOptions.CompressDebugSections = DebugCompressionType::Zlib;
+#else
     Options.CompressDebugSections = DebugCompressionType::Zlib;
+#endif
   } else if (!strcmp("zstd", DebugInfoCompression) && llvm::compression::zstd::isAvailable()) {
+#if LLVM_VERSION_GE(19, 0)
+    Options.MCOptions.CompressDebugSections = DebugCompressionType::Zstd;
+#else
     Options.CompressDebugSections = DebugCompressionType::Zstd;
+#endif
   } else if (!strcmp("none", DebugInfoCompression)) {
+#if LLVM_VERSION_GE(19, 0)
+    Options.MCOptions.CompressDebugSections = DebugCompressionType::None;
+#else
     Options.CompressDebugSections = DebugCompressionType::None;
+#endif
   }
 
+#if LLVM_VERSION_GE(19, 0)
+  Options.MCOptions.X86RelaxRelocations = RelaxELFRelocations;
+#else
   Options.RelaxELFRelocations = RelaxELFRelocations;
+#endif
   Options.UseInitArray = UseInitArray;
 
 #if LLVM_VERSION_LT(17, 0)
@@ -537,8 +553,8 @@ extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
 // TargetLibraryInfo pass, so we use this method to do so.
 extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M,
                                        bool DisableSimplifyLibCalls) {
-  Triple TargetTriple(unwrap(M)->getTargetTriple());
-  TargetLibraryInfoImpl TLII(TargetTriple);
+  auto TargetTriple = Triple(unwrap(M)->getTargetTriple());
+  auto TLII = TargetLibraryInfoImpl(TargetTriple);
   if (DisableSimplifyLibCalls)
     TLII.disableAllFunctions();
   unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII));
@@ -589,7 +605,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
 
   std::string ErrorInfo;
   std::error_code EC;
-  raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
+  auto OS = raw_fd_ostream(Path, EC, sys::fs::OF_None);
   if (EC)
     ErrorInfo = EC.message();
   if (ErrorInfo != "") {
@@ -597,9 +613,9 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
     return LLVMRustResult::Failure;
   }
 
-  buffer_ostream BOS(OS);
+  auto BOS = buffer_ostream(OS);
   if (DwoPath) {
-    raw_fd_ostream DOS(DwoPath, EC, sys::fs::OF_None);
+    auto DOS = raw_fd_ostream(DwoPath, EC, sys::fs::OF_None);
     EC.clear();
     if (EC)
         ErrorInfo = EC.message();
@@ -607,7 +623,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
       LLVMRustSetLastError(ErrorInfo.c_str());
       return LLVMRustResult::Failure;
     }
-    buffer_ostream DBOS(DOS);
+    auto DBOS = buffer_ostream(DOS);
     unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, false);
     PM->run(*unwrap(M));
   } else {
@@ -796,7 +812,7 @@ LLVMRustOptimize(
                         DebugInfoForProfiling);
   }
 
-  PassBuilder PB(TM, PTO, PGOOpt, &PIC);
+  auto PB = PassBuilder(TM, PTO, PGOOpt, &PIC);
   LoopAnalysisManager LAM;
   FunctionAnalysisManager FAM;
   CGSCCAnalysisManager CGAM;
@@ -1112,7 +1128,7 @@ extern "C" LLVMRustResult
 LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) {
   std::string ErrorInfo;
   std::error_code EC;
-  raw_fd_ostream OS(Path, EC, sys::fs::OF_None);
+  auto OS = raw_fd_ostream(Path, EC, sys::fs::OF_None);
   if (EC)
     ErrorInfo = EC.message();
   if (ErrorInfo != "") {
@@ -1120,8 +1136,8 @@ LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) {
     return LLVMRustResult::Failure;
   }
 
-  RustAssemblyAnnotationWriter AAW(Demangle);
-  formatted_raw_ostream FOS(OS);
+  auto AAW = RustAssemblyAnnotationWriter(Demangle);
+  auto FOS = formatted_raw_ostream(OS);
   unwrap(M)->print(FOS, &AAW);
 
   return LLVMRustResult::Success;
@@ -1281,8 +1297,8 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
   // Load each module's summary and merge it into one combined index
   for (int i = 0; i < num_modules; i++) {
     auto module = &modules[i];
-    StringRef buffer(module->data, module->len);
-    MemoryBufferRef mem_buffer(buffer, module->identifier);
+    auto buffer = StringRef(module->data, module->len);
+    auto mem_buffer = MemoryBufferRef(buffer, module->identifier);
 
     Ret->ModuleMap[module->identifier] = mem_buffer;
 
@@ -1485,7 +1501,7 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
     return MOrErr;
   };
   bool ClearDSOLocal = clearDSOLocalOnDeclarations(Mod, Target);
-  FunctionImporter Importer(Data->Index, Loader, ClearDSOLocal);
+  auto Importer = FunctionImporter(Data->Index, Loader, ClearDSOLocal);
   Expected<bool> Result = Importer.importFunctions(Mod, ImportList);
   if (!Result) {
     LLVMRustSetLastError(toString(Result.takeError()).c_str());
@@ -1510,7 +1526,7 @@ extern "C" LLVMRustThinLTOBuffer*
 LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) {
   auto Ret = std::make_unique<LLVMRustThinLTOBuffer>();
   {
-    raw_string_ostream OS(Ret->data);
+    auto OS = raw_string_ostream(Ret->data);
     {
       if (is_thin) {
         PassBuilder PB;
@@ -1557,8 +1573,8 @@ LLVMRustParseBitcodeForLTO(LLVMContextRef Context,
                            const char *data,
                            size_t len,
                            const char *identifier) {
-  StringRef Data(data, len);
-  MemoryBufferRef Buffer(Data, identifier);
+  auto Data = StringRef(data, len);
+  auto Buffer = MemoryBufferRef(Data, identifier);
   unwrap(Context)->enableDebugTypeODRUniquing();
   Expected<std::unique_ptr<Module>> SrcOrError =
       parseBitcodeFile(Buffer, *unwrap(Context));
@@ -1576,8 +1592,8 @@ extern "C" const char *LLVMRustGetSliceFromObjectDataByName(const char *data,
                                                             const char *name,
                                                             size_t *out_len) {
   *out_len = 0;
-  StringRef Data(data, len);
-  MemoryBufferRef Buffer(Data, ""); // The id is unused.
+  auto Data = StringRef(data, len);
+  auto Buffer = MemoryBufferRef(Data, ""); // The id is unused.
   file_magic Type = identify_magic(Buffer.getBuffer());
   Expected<std::unique_ptr<object::ObjectFile>> ObjFileOrError =
       object::ObjectFile::createObjectFile(Buffer, Type);
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index cb7cce4da0d..3e998d428ee 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -66,12 +66,22 @@ static LLVM_THREAD_LOCAL char *LastError;
 static void FatalErrorHandler(void *UserData,
                               const char* Reason,
                               bool GenCrashDiag) {
-  // Do the same thing that the default error handler does.
-  std::cerr << "LLVM ERROR: " << Reason << std::endl;
+  // Once upon a time we emitted "LLVM ERROR:" specifically to mimic LLVM. Then,
+  // we developed crater and other tools which only expose logs, not error codes.
+  // Use a more greppable prefix that will still match the "LLVM ERROR:" prefix.
+  std::cerr << "rustc-LLVM ERROR: " << Reason << std::endl;
 
   // Since this error handler exits the process, we have to run any cleanup that
   // LLVM would run after handling the error. This might change with an LLVM
   // upgrade.
+  //
+  // In practice, this will do nothing, because the only cleanup LLVM does is
+  // to remove all files that were registered with it via a frontend calling
+  // one of the `createOutputFile` family of functions in LLVM and passing true
+  // to RemoveFileOnSignal, something that rustc does not do. However, it would
+  // be... inadvisable to suddenly stop running these handlers, if LLVM gets
+  // "interesting" ideas in the future about what cleanup should be done.
+  // We might even find it useful for generating less artifacts.
   sys::RunInterruptHandlers();
 
   exit(101);
@@ -109,7 +119,7 @@ extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M,
 
 extern "C" const char *LLVMRustPrintPassTimings(size_t *Len) {
   std::string buf;
-  raw_string_ostream SS(buf);
+  auto SS = raw_string_ostream(buf);
   TimerGroup::printAll(SS);
   SS.flush();
   *Len = buf.length();
@@ -120,7 +130,7 @@ extern "C" const char *LLVMRustPrintPassTimings(size_t *Len) {
 
 extern "C" const char *LLVMRustPrintStatistics(size_t *Len) {
   std::string buf;
-  raw_string_ostream SS(buf);
+  auto SS = raw_string_ostream(buf);
   llvm::PrintStatistics(SS);
   SS.flush();
   *Len = buf.length();
@@ -174,7 +184,7 @@ extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
 extern "C" LLVMValueRef
 LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) {
   Module *Mod = unwrap(M);
-  StringRef NameRef(Name, NameLen);
+  auto NameRef = StringRef(Name, NameLen);
 
   // We don't use Module::getOrInsertGlobal because that returns a Constant*,
   // which may either be the real GlobalVariable*, or a constant bitcast of it
@@ -285,7 +295,7 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
 template<typename T> static inline void AddAttributes(T *t, unsigned Index,
                                                       LLVMAttributeRef *Attrs, size_t AttrsLen) {
   AttributeList PAL = t->getAttributes();
-  AttrBuilder B(t->getContext());
+  auto B = AttrBuilder(t->getContext());
   for (LLVMAttributeRef Attr : ArrayRef<LLVMAttributeRef>(Attrs, AttrsLen))
     B.addAttribute(unwrap(Attr));
   AttributeList PALNew = PAL.addAttributesAtIndex(t->getContext(), Index, B);
@@ -1195,13 +1205,13 @@ extern "C" int64_t LLVMRustDIBuilderCreateOpLLVMFragment() {
 }
 
 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
-  RawRustStringOstream OS(Str);
+  auto OS = RawRustStringOstream(Str);
   unwrap<llvm::Type>(Ty)->print(OS);
 }
 
 extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
                                            RustStringRef Str) {
-  RawRustStringOstream OS(Str);
+  auto OS = RawRustStringOstream(Str);
   if (!V) {
     OS << "(null)";
   } else {
@@ -1224,7 +1234,7 @@ extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
 
 extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
-  RawRustStringOstream OS(Str);
+  auto OS = RawRustStringOstream(Str);
   unwrap(T)->print(OS);
 }
 
@@ -1236,11 +1246,11 @@ extern "C" void LLVMRustUnpackOptimizationDiagnostic(
   llvm::DiagnosticInfoOptimizationBase *Opt =
       static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
 
-  RawRustStringOstream PassNameOS(PassNameOut);
+  auto PassNameOS = RawRustStringOstream(PassNameOut);
   PassNameOS << Opt->getPassName();
   *FunctionOut = wrap(&Opt->getFunction());
 
-  RawRustStringOstream FilenameOS(FilenameOut);
+  auto FilenameOS = RawRustStringOstream(FilenameOut);
   DiagnosticLocation loc = Opt->getLocation();
   if (loc.isValid()) {
     *Line = loc.getLine();
@@ -1248,7 +1258,7 @@ extern "C" void LLVMRustUnpackOptimizationDiagnostic(
     FilenameOS << loc.getAbsolutePath();
   }
 
-  RawRustStringOstream MessageOS(MessageOut);
+  auto MessageOS = RawRustStringOstream(MessageOut);
   MessageOS << Opt->getMsg();
 }
 
@@ -1291,8 +1301,8 @@ LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
 
 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
                                                     RustStringRef Str) {
-  RawRustStringOstream OS(Str);
-  DiagnosticPrinterRawOStream DP(OS);
+  auto OS = RawRustStringOstream(Str);
+  auto DP = DiagnosticPrinterRawOStream(OS);
   unwrap(DI)->print(DP);
 }
 
@@ -1406,7 +1416,7 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
   default:
     {
       std::string error;
-      llvm::raw_string_ostream stream(error);
+      auto stream = llvm::raw_string_ostream(error);
       stream << "Rust does not support the TypeID: " << unwrap(Ty)->getTypeID()
              << " for the type: " << *unwrap(Ty);
       stream.flush();
@@ -1432,7 +1442,7 @@ extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
                                            unsigned* RangesOut,
                                            size_t* NumRanges) {
   SMDiagnostic& D = *unwrap(DRef);
-  RawRustStringOstream MessageOS(MessageOut);
+  auto MessageOS = RawRustStringOstream(MessageOut);
   MessageOS << D.getMessage();
 
   switch (D.getKind()) {
@@ -1539,6 +1549,31 @@ LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
                                       Name));
 }
 
+extern "C" LLVMValueRef
+LLVMRustBuildCallBr(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
+                    LLVMBasicBlockRef DefaultDest,
+                    LLVMBasicBlockRef *IndirectDests, unsigned NumIndirectDests,
+                    LLVMValueRef *Args, unsigned NumArgs,
+                    OperandBundleDef **OpBundles, unsigned NumOpBundles,
+                    const char *Name) {
+  Value *Callee = unwrap(Fn);
+  FunctionType *FTy = unwrap<FunctionType>(Ty);
+
+  // FIXME: Is there a way around this?
+  std::vector<BasicBlock*> IndirectDestsUnwrapped;
+  IndirectDestsUnwrapped.reserve(NumIndirectDests);
+  for (unsigned i = 0; i < NumIndirectDests; ++i) {
+    IndirectDestsUnwrapped.push_back(unwrap(IndirectDests[i]));
+  }
+
+  return wrap(unwrap(B)->CreateCallBr(
+      FTy, Callee, unwrap(DefaultDest),
+      ArrayRef<BasicBlock*>(IndirectDestsUnwrapped),
+      ArrayRef<Value*>(unwrap(Args), NumArgs),
+      ArrayRef<OperandBundleDef>(*OpBundles, NumOpBundles),
+      Name));
+}
+
 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
                                                LLVMBasicBlockRef BB) {
   auto Point = unwrap(BB)->getFirstInsertionPt();
@@ -1547,7 +1582,7 @@ extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
 
 extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
                                   const char *Name, size_t NameLen) {
-  Triple TargetTriple(unwrap(M)->getTargetTriple());
+  Triple TargetTriple = Triple(unwrap(M)->getTargetTriple());
   GlobalObject *GV = unwrap<GlobalObject>(V);
   if (TargetTriple.supportsCOMDAT()) {
     StringRef NameRef(Name, NameLen);
@@ -1711,7 +1746,7 @@ extern "C" LLVMRustModuleBuffer*
 LLVMRustModuleBufferCreate(LLVMModuleRef M) {
   auto Ret = std::make_unique<LLVMRustModuleBuffer>();
   {
-    raw_string_ostream OS(Ret->data);
+    auto OS = raw_string_ostream(Ret->data);
     WriteBitcodeToFile(*unwrap(M), OS);
   }
   return Ret.release();
@@ -1741,8 +1776,8 @@ LLVMRustModuleCost(LLVMModuleRef M) {
 extern "C" void
 LLVMRustModuleInstructionStats(LLVMModuleRef M, RustStringRef Str)
 {
-  RawRustStringOstream OS(Str);
-  llvm::json::OStream JOS(OS);
+  auto OS = RawRustStringOstream(Str);
+  auto JOS = llvm::json::OStream(OS);
   auto Module = unwrap(M);
 
   JOS.object([&] {
@@ -1857,7 +1892,7 @@ extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
     MinGW);
   if (Error) {
     std::string errorString;
-    llvm::raw_string_ostream stream(errorString);
+    auto stream = llvm::raw_string_ostream(errorString);
     stream << Error;
     stream.flush();
     LLVMRustSetLastError(errorString.c_str());
@@ -2041,7 +2076,7 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler(
 }
 
 extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
-  RawRustStringOstream OS(Str);
+  auto OS = RawRustStringOstream(Str);
   GlobalValue *GV = unwrap<GlobalValue>(V);
   Mangler().getNameWithPrefix(OS, GV, true);
 }
diff --git a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
index 91f84692df8..ee8239ef8e7 100644
--- a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
@@ -11,6 +11,7 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/Object/ObjectFile.h"
+#include <llvm/Support/raw_ostream.h>
 
 using namespace llvm;
 using namespace llvm::sys;
@@ -42,7 +43,7 @@ extern "C" void *LLVMRustGetSymbols(
     MemoryBuffer::getMemBuffer(StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"),
                                false);
   SmallString<0> SymNameBuf;
-  raw_svector_ostream SymName(SymNameBuf);
+  auto SymName = raw_svector_ostream(SymNameBuf);
 
   // In the scenario when LLVMContext is populated SymbolicFile will contain a
   // reference to it, thus SymbolicFile should be destroyed first.
@@ -60,7 +61,7 @@ extern "C" void *LLVMRustGetSymbols(
     if (!ObjOrErr) {
       Error E = ObjOrErr.takeError();
       SmallString<0> ErrorBuf;
-      raw_svector_ostream Error(ErrorBuf);
+      auto Error = raw_svector_ostream(ErrorBuf);
       Error << E << '\0';
       return ErrorCallback(Error.str().data());
     }
@@ -70,7 +71,7 @@ extern "C" void *LLVMRustGetSymbols(
     if (!ObjOrErr) {
       Error E = ObjOrErr.takeError();
       SmallString<0> ErrorBuf;
-      raw_svector_ostream Error(ErrorBuf);
+      auto Error = raw_svector_ostream(ErrorBuf);
       Error << E << '\0';
       return ErrorCallback(Error.str().data());
     }
@@ -83,7 +84,7 @@ extern "C" void *LLVMRustGetSymbols(
       continue;
     if (Error E = S.printName(SymName)) {
       SmallString<0> ErrorBuf;
-      raw_svector_ostream Error(ErrorBuf);
+      auto Error = raw_svector_ostream(ErrorBuf);
       Error << E << '\0';
       return ErrorCallback(Error.str().data());
     }
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
index 5659569c645..a1a7b19642b 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
@@ -165,7 +165,7 @@ impl<'a> LintDiagnosticDerive<'a> {
                     #implementation;
                 }
 
-                fn msg(&self) -> rustc_errors::DiagnosticMessage {
+                fn msg(&self) -> rustc_errors::DiagMessage {
                     #msg
                 }
             }
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index 6cbebcc7320..ef326106404 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -93,7 +93,7 @@ impl SubdiagnosticDeriveBuilder {
                     #f: __F
                 ) where
                     __G: rustc_errors::EmissionGuarantee,
-                    __F: rustc_errors::SubdiagnosticMessageOp<__G>,
+                    __F: rustc_errors::SubdiagMessageOp<__G>,
                 {
                     #implementation
                 }
diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs
index c8430380345..94e86e0e246 100644
--- a/compiler/rustc_macros/src/type_visitable.rs
+++ b/compiler/rustc_macros/src/type_visitable.rs
@@ -34,7 +34,14 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:
     s.add_bounds(synstructure::AddBounds::Generics);
     let body_visit = s.each(|bind| {
         quote! {
-            ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor)?;
+            match ::rustc_ast_ir::visit::VisitorResult::branch(
+                ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor)
+            ) {
+                ::core::ops::ControlFlow::Continue(()) => {},
+                ::core::ops::ControlFlow::Break(r) => {
+                    return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
+                },
+            }
         }
     });
     s.bind_with(|_| synstructure::BindStyle::Move);
@@ -45,9 +52,9 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:
             fn visit_with<__V: ::rustc_middle::ty::visit::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>(
                 &self,
                 __visitor: &mut __V
-            ) -> ::std::ops::ControlFlow<__V::BreakTy> {
+            ) -> __V::Result {
                 match *self { #body_visit }
-                ::std::ops::ControlFlow::Continue(())
+                <__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
             }
         },
     )
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index f65fe1a29c7..72757d90e42 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -947,6 +947,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
         }
     }
 
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn report_unused_deps(&mut self, krate: &ast::Crate) {
         // Make a point span rather than covering the whole file
         let span = krate.spans.inner_span.shrink_to_lo();
@@ -971,7 +972,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
                 continue;
             }
 
-            self.sess.parse_sess.buffer_lint(
+            self.sess.psess.buffer_lint(
                     lint::builtin::UNUSED_CRATE_DEPENDENCIES,
                     span,
                     ast::CRATE_NODE_ID,
@@ -1132,7 +1133,13 @@ fn load_dylib(path: &Path, max_attempts: usize) -> Result<libloading::Library, S
             Err(err) => {
                 // Only try to recover from this specific error.
                 if !matches!(err, libloading::Error::LoadLibraryExW { .. }) {
-                    return Err(err.to_string());
+                    let err = format_dlopen_err(&err);
+                    // We include the path of the dylib in the error ourselves, so
+                    // if it's in the error, we strip it.
+                    if let Some(err) = err.strip_prefix(&format!(": {}", path.display())) {
+                        return Err(err.to_string());
+                    }
+                    return Err(err);
                 }
 
                 last_error = Some(err);
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index 90e68a6b5b9..dcccace12b0 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -1077,7 +1077,7 @@ impl CrateError {
                         crate_rejections,
                     });
                 } else {
-                    dcx.emit_err(errors::CannotFindCrate {
+                    let error = errors::CannotFindCrate {
                         span,
                         crate_name,
                         add_info,
@@ -1091,11 +1091,18 @@ impl CrateError {
                         profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime),
                         locator_triple: locator.triple,
                         is_ui_testing: sess.opts.unstable_opts.ui_testing,
-                    });
+                    };
+                    // The diagnostic for missing core is very good, but it is followed by a lot of
+                    // other diagnostics that do not add information.
+                    if missing_core {
+                        dcx.emit_fatal(error);
+                    } else {
+                        dcx.emit_err(error);
+                    }
                 }
             }
             CrateError::NotFound(crate_name) => {
-                dcx.emit_err(errors::CannotFindCrate {
+                let error = errors::CannotFindCrate {
                     span,
                     crate_name,
                     add_info: String::new(),
@@ -1105,7 +1112,14 @@ impl CrateError {
                     profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime),
                     locator_triple: sess.opts.target_triple.clone(),
                     is_ui_testing: sess.opts.unstable_opts.ui_testing,
-                });
+                };
+                // The diagnostic for missing core is very good, but it is followed by a lot of
+                // other diagnostics that do not add information.
+                if missing_core {
+                    dcx.emit_fatal(error);
+                } else {
+                    dcx.emit_err(error);
+                }
             }
         }
     }
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index cdcc586b09e..baa2e1ff602 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -93,6 +93,7 @@ struct Collector<'tcx> {
 }
 
 impl<'tcx> Collector<'tcx> {
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn process_module(&mut self, module: &ForeignModule) {
         let ForeignModule { def_id, abi, ref foreign_items } = *module;
         let def_id = def_id.expect_local();
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index e7c80639a0d..da384007c22 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -420,7 +420,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnIndex {
 impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> {
     fn decode_attr_id(&mut self) -> rustc_span::AttrId {
         let sess = self.sess.expect("can't decode AttrId without Session");
-        sess.parse_sess.attr_id_generator.mk_attr_id()
+        sess.psess.attr_id_generator.mk_attr_id()
     }
 
     fn decode_crate_num(&mut self) -> CrateNum {
@@ -504,7 +504,11 @@ impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> {
         let data = if tag.kind() == SpanKind::Indirect {
             // Skip past the tag we just peek'd.
             self.read_u8();
-            let offset_or_position = self.read_usize();
+            // indirect tag lengths are safe to access, since they're (0, 8)
+            let bytes_needed = tag.length().unwrap().0 as usize;
+            let mut total = [0u8; usize::BITS as usize / 8];
+            total[..bytes_needed].copy_from_slice(self.read_raw_bytes(bytes_needed));
+            let offset_or_position = usize::from_le_bytes(total);
             let position = if tag.is_relative_offset() {
                 start - offset_or_position
             } else {
@@ -1749,7 +1753,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         self.root.tables.attr_flags.get(self, index)
     }
 
-    fn get_intrinsic(self, index: DefIndex) -> Option<Symbol> {
+    fn get_intrinsic(self, index: DefIndex) -> Option<ty::IntrinsicDef> {
         self.root.tables.intrinsic.get(self, index).map(|d| d.decode(self))
     }
 
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 2f507b258fe..1c59af51589 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -356,7 +356,7 @@ provide! { tcx, def_id, other, cdata,
         cdata.get_stability_implications(tcx).iter().copied().collect()
     }
     stripped_cfg_items => { cdata.get_stripped_cfg_items(cdata.cnum, tcx) }
-    intrinsic => { cdata.get_intrinsic(def_id.index) }
+    intrinsic_raw => { cdata.get_intrinsic(def_id.index) }
     defined_lang_items => { cdata.get_lang_items(tcx) }
     diagnostic_items => { cdata.get_diagnostic_items() }
     missing_lang_items => { cdata.get_missing_lang_items(tcx) }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index fdb2b4f2024..6e9cbfdcfee 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -172,11 +172,19 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> {
                 // previously saved offset must be smaller than the current position.
                 let offset = self.opaque.position() - last_location;
                 if offset < last_location {
-                    SpanTag::indirect(true).encode(self);
-                    offset.encode(self);
+                    let needed = bytes_needed(offset);
+                    SpanTag::indirect(true, needed as u8).encode(self);
+                    self.opaque.write_with(|dest| {
+                        *dest = offset.to_le_bytes();
+                        needed
+                    });
                 } else {
-                    SpanTag::indirect(false).encode(self);
-                    last_location.encode(self);
+                    let needed = bytes_needed(last_location);
+                    SpanTag::indirect(false, needed as u8).encode(self);
+                    self.opaque.write_with(|dest| {
+                        *dest = last_location.to_le_bytes();
+                        needed
+                    });
                 }
             }
             Entry::Vacant(v) => {
@@ -212,6 +220,10 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> {
     }
 }
 
+fn bytes_needed(n: usize) -> usize {
+    (usize::BITS - n.leading_zeros()).div_ceil(u8::BITS) as usize
+}
+
 impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData {
     fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
         // Don't serialize any `SyntaxContext`s from a proc-macro crate,
@@ -1053,11 +1065,14 @@ fn should_encode_mir(
         // Full-fledged functions + closures
         DefKind::AssocFn | DefKind::Fn | DefKind::Closure => {
             let generics = tcx.generics_of(def_id);
-            let opt = tcx.sess.opts.unstable_opts.always_encode_mir
+            let mut opt = tcx.sess.opts.unstable_opts.always_encode_mir
                 || (tcx.sess.opts.output_types.should_codegen()
                     && reachable_set.contains(&def_id)
                     && (generics.requires_monomorphization(tcx)
                         || tcx.cross_crate_inlinable(def_id)));
+            if let Some(intrinsic) = tcx.intrinsic(def_id) {
+                opt &= !intrinsic.must_be_overridden;
+            }
             // The function has a `const` modifier or is in a `#[const_trait]`.
             let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id())
                 || tcx.is_const_default_method(def_id.to_def_id());
@@ -1409,9 +1424,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             if let DefKind::Fn | DefKind::AssocFn = def_kind {
                 self.tables.asyncness.set_some(def_id.index, tcx.asyncness(def_id));
                 record_array!(self.tables.fn_arg_names[def_id] <- tcx.fn_arg_names(def_id));
-                if let Some(name) = tcx.intrinsic(def_id) {
-                    record!(self.tables.intrinsic[def_id] <- name);
-                }
+            }
+            if let Some(name) = tcx.intrinsic(def_id) {
+                record!(self.tables.intrinsic[def_id] <- name);
             }
             if let DefKind::TyParam = def_kind {
                 let default = self.tcx.object_lifetime_default(def_id);
@@ -1789,7 +1804,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             let stability = tcx.lookup_stability(CRATE_DEF_ID);
             let macros =
                 self.lazy_array(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index));
-            for (i, span) in self.tcx.sess.parse_sess.proc_macro_quoted_spans() {
+            for (i, span) in self.tcx.sess.psess.proc_macro_quoted_spans() {
                 let span = self.lazy(span);
                 self.tables.proc_macro_quoted_spans.set_some(i, span);
             }
@@ -1978,9 +1993,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
             if of_trait && let Some(header) = tcx.impl_trait_header(def_id) {
                 record!(self.tables.impl_trait_header[def_id] <- header);
-                let trait_ref = header.map_bound(|h| h.trait_ref);
 
-                let trait_ref = trait_ref.instantiate_identity();
+                let trait_ref = header.trait_ref.instantiate_identity();
                 let simplified_self_ty = fast_reject::simplify_type(
                     self.tcx,
                     trait_ref.self_ty(),
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 9c0e8029571..8aa31ef564f 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -375,7 +375,7 @@ macro_rules! define_tables {
 
 define_tables! {
 - defaulted:
-    intrinsic: Table<DefIndex, Option<LazyValue<Symbol>>>,
+    intrinsic: Table<DefIndex, Option<LazyValue<ty::IntrinsicDef>>>,
     is_macro_rules: Table<DefIndex, bool>,
     is_type_alias_impl_trait: Table<DefIndex, bool>,
     type_alias_is_lazy: Table<DefIndex, bool>,
@@ -423,7 +423,7 @@ define_tables! {
     variances_of: Table<DefIndex, LazyArray<ty::Variance>>,
     fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::PolyFnSig<'static>>>>,
     codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>,
-    impl_trait_header: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::ImplTraitHeader<'static>>>>,
+    impl_trait_header: Table<DefIndex, LazyValue<ty::ImplTraitHeader<'static>>>,
     const_param_default: Table<DefIndex, LazyValue<ty::EarlyBinder<rustc_middle::ty::Const<'static>>>>,
     object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>,
     optimized_mir: Table<DefIndex, LazyValue<mir::Body<'static>>>,
@@ -530,11 +530,13 @@ impl SpanTag {
         SpanTag(data)
     }
 
-    fn indirect(relative: bool) -> SpanTag {
+    fn indirect(relative: bool, length_bytes: u8) -> SpanTag {
         let mut tag = SpanTag(SpanKind::Indirect as u8);
         if relative {
             tag.0 |= 0b100;
         }
+        assert!(length_bytes <= 8);
+        tag.0 |= length_bytes << 3;
         tag
     }
 
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index 0f6ec656932..0d3cffd2047 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -1,6 +1,6 @@
 use std::fmt;
 
-use rustc_errors::{codes::*, DiagArgName, DiagArgValue, DiagnosticMessage};
+use rustc_errors::{codes::*, DiagArgName, DiagArgValue, DiagMessage};
 use rustc_macros::Diagnostic;
 use rustc_span::{Span, Symbol};
 
@@ -93,16 +93,16 @@ pub(super) struct ConstNotUsedTraitAlias {
 }
 
 pub struct CustomSubdiagnostic<'a> {
-    pub msg: fn() -> DiagnosticMessage,
+    pub msg: fn() -> DiagMessage,
     pub add_args: Box<dyn FnOnce(&mut dyn FnMut(DiagArgName, DiagArgValue)) + 'a>,
 }
 
 impl<'a> CustomSubdiagnostic<'a> {
-    pub fn label(x: fn() -> DiagnosticMessage) -> Self {
+    pub fn label(x: fn() -> DiagMessage) -> Self {
         Self::label_and_then(x, |_| {})
     }
     pub fn label_and_then<F: FnOnce(&mut dyn FnMut(DiagArgName, DiagArgValue)) + 'a>(
-        msg: fn() -> DiagnosticMessage,
+        msg: fn() -> DiagMessage,
         f: F,
     ) -> Self {
         Self { msg, add_args: Box::new(move |x| f(x)) }
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index db27e2bd630..4960369a0a7 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -3,8 +3,7 @@ use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
 use crate::query::LocalCrate;
 use crate::ty::TyCtxt;
 use rustc_ast as ast;
-use rustc_ast::visit::VisitorResult;
-use rustc_ast::walk_list;
+use rustc_ast::visit::{walk_list, VisitorResult};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::svh::Svh;
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 6a3522553c4..d8d6899f057 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -2,7 +2,7 @@ use std::cmp;
 
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sorted_map::SortedMap;
-use rustc_errors::{Diag, DiagnosticMessage, MultiSpan};
+use rustc_errors::{Diag, DiagMessage, MultiSpan};
 use rustc_hir::{HirId, ItemLocalId};
 use rustc_session::lint::{
     builtin::{self, FORBIDDEN_LINT_GROUPS},
@@ -268,7 +268,7 @@ pub fn lint_level(
     level: Level,
     src: LintLevelSource,
     span: Option<MultiSpan>,
-    msg: impl Into<DiagnosticMessage>,
+    msg: impl Into<DiagMessage>,
     decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
 ) {
     // Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to
@@ -280,7 +280,7 @@ pub fn lint_level(
         level: Level,
         src: LintLevelSource,
         span: Option<MultiSpan>,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
         decorate: Box<dyn '_ + for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>)>,
     ) {
         // Check for future incompatibility lints and issue a stronger warning.
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index 26ca90db018..0ee97a6bed0 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -85,9 +85,9 @@ macro_rules! TrivialTypeTraversalImpls {
                 fn visit_with<F: $crate::ty::visit::TypeVisitor<$crate::ty::TyCtxt<'tcx>>>(
                     &self,
                     _: &mut F)
-                    -> ::std::ops::ControlFlow<F::BreakTy>
+                    -> F::Result
                 {
-                    ::std::ops::ControlFlow::Continue(())
+                    <F::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
                 }
             }
         )+
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 31f986403ab..c393287da95 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -16,7 +16,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};
 use rustc_hir::{self as hir, HirId};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
-use rustc_session::lint::{BuiltinLintDiagnostics, Level, Lint, LintBuffer};
+use rustc_session::lint::{BuiltinLintDiag, Level, Lint, LintBuffer};
 use rustc_session::parse::feature_err_issue;
 use rustc_session::Session;
 use rustc_span::symbol::{sym, Symbol};
@@ -199,7 +199,7 @@ pub fn early_report_deprecation(
         return;
     }
 
-    let diag = BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span);
+    let diag = BuiltinLintDiag::DeprecatedMacro(suggestion, span);
     lint_buffer.buffer_lint_with_diagnostic(lint, node_id, span, message, diag);
 }
 
@@ -269,7 +269,7 @@ fn suggestion_for_allocator_api(
     if feature == sym::allocator_api {
         if let Some(trait_) = tcx.opt_parent(def_id) {
             if tcx.is_diagnostic_item(sym::Vec, trait_) {
-                let sm = tcx.sess.parse_sess.source_map();
+                let sm = tcx.sess.psess.source_map();
                 let inner_types = sm.span_extend_to_prev_char(span, '<', true);
                 if let Ok(snippet) = sm.span_to_snippet(inner_types) {
                     return Some((
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index b85354e10f9..aea88c4588b 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -6,9 +6,7 @@ use crate::ty::{layout, tls, Ty, TyCtxt, ValTree};
 
 use rustc_ast_ir::Mutability;
 use rustc_data_structures::sync::Lock;
-use rustc_errors::{
-    DiagArgName, DiagArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg,
-};
+use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagnosticArg};
 use rustc_macros::HashStable;
 use rustc_session::CtfeBacktrace;
 use rustc_span::{def_id::DefId, Span, DUMMY_SP};
@@ -489,7 +487,7 @@ pub enum ResourceExhaustionInfo {
 /// A trait for machine-specific errors (or other "machine stop" conditions).
 pub trait MachineStopType: Any + fmt::Debug + Send {
     /// The diagnostic message for this error
-    fn diagnostic_message(&self) -> DiagnosticMessage;
+    fn diagnostic_message(&self) -> DiagMessage;
     /// 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(DiagArgName, DiagArgValue));
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 5ce2e26a0bc..0221bc6c363 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -14,9 +14,7 @@ use crate::ty::{AdtDef, InstanceDef, UserTypeAnnotationIndex};
 use crate::ty::{GenericArg, GenericArgsRef};
 
 use rustc_data_structures::captures::Captures;
-use rustc_errors::{
-    DiagArgName, DiagArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg,
-};
+use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagnosticArg};
 use rustc_hir::def::{CtorKind, Namespace};
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
 use rustc_hir::{self, CoroutineDesugaring, CoroutineKind, ImplicitSelfKind};
@@ -1718,13 +1716,13 @@ mod size_asserts {
     use super::*;
     use rustc_data_structures::static_assert_size;
     // tidy-alphabetical-start
-    static_assert_size!(BasicBlockData<'_>, 136);
+    static_assert_size!(BasicBlockData<'_>, 144);
     static_assert_size!(LocalDecl<'_>, 40);
     static_assert_size!(SourceScopeData<'_>, 72);
     static_assert_size!(Statement<'_>, 32);
     static_assert_size!(StatementKind<'_>, 16);
-    static_assert_size!(Terminator<'_>, 104);
-    static_assert_size!(TerminatorKind<'_>, 88);
+    static_assert_size!(Terminator<'_>, 112);
+    static_assert_size!(TerminatorKind<'_>, 96);
     static_assert_size!(VarDebugInfo<'_>, 88);
     // tidy-alphabetical-end
 }
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index b81e9fa1aab..33412297017 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
@@ -11,6 +11,8 @@ pub struct MirPatch<'tcx> {
     resume_block: Option<BasicBlock>,
     // Only for unreachable in cleanup path.
     unreachable_cleanup_block: Option<BasicBlock>,
+    // Only for unreachable not in cleanup path.
+    unreachable_no_cleanup_block: Option<BasicBlock>,
     // Cached block for UnwindTerminate (with reason)
     terminate_block: Option<(BasicBlock, UnwindTerminateReason)>,
     body_span: Span,
@@ -27,6 +29,7 @@ impl<'tcx> MirPatch<'tcx> {
             next_local: body.local_decls.len(),
             resume_block: None,
             unreachable_cleanup_block: None,
+            unreachable_no_cleanup_block: None,
             terminate_block: None,
             body_span: body.span,
         };
@@ -43,9 +46,12 @@ impl<'tcx> MirPatch<'tcx> {
             // Check if we already have an unreachable block
             if matches!(block.terminator().kind, TerminatorKind::Unreachable)
                 && block.statements.is_empty()
-                && block.is_cleanup
             {
-                result.unreachable_cleanup_block = Some(bb);
+                if block.is_cleanup {
+                    result.unreachable_cleanup_block = Some(bb);
+                } else {
+                    result.unreachable_no_cleanup_block = Some(bb);
+                }
                 continue;
             }
 
@@ -95,6 +101,23 @@ impl<'tcx> MirPatch<'tcx> {
         bb
     }
 
+    pub fn unreachable_no_cleanup_block(&mut self) -> BasicBlock {
+        if let Some(bb) = self.unreachable_no_cleanup_block {
+            return bb;
+        }
+
+        let bb = self.new_block(BasicBlockData {
+            statements: vec![],
+            terminator: Some(Terminator {
+                source_info: SourceInfo::outermost(self.body_span),
+                kind: TerminatorKind::Unreachable,
+            }),
+            is_cleanup: false,
+        });
+        self.unreachable_no_cleanup_block = Some(bb);
+        bb
+    }
+
     pub fn terminate_block(&mut self, reason: UnwindTerminateReason) -> BasicBlock {
         if let Some((cached_bb, cached_reason)) = self.terminate_block
             && reason == cached_reason
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 5638b575b31..e058302af31 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -7,7 +7,7 @@ use std::path::{Path, PathBuf};
 use crate::mir::interpret::ConstAllocation;
 
 use super::graphviz::write_mir_fn_graphviz;
-use rustc_ast::InlineAsmTemplatePiece;
+use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_middle::mir::interpret::{
     alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer,
     Provenance,
@@ -830,6 +830,9 @@ impl<'tcx> TerminatorKind<'tcx> {
                         InlineAsmOperand::SymStatic { def_id } => {
                             write!(fmt, "sym_static {def_id:?}")?;
                         }
+                        InlineAsmOperand::Label { target_index } => {
+                            write!(fmt, "label {target_index}")?;
+                        }
                     }
                 }
                 write!(fmt, ", options({options:?}))")
@@ -868,16 +871,19 @@ impl<'tcx> TerminatorKind<'tcx> {
                 vec!["real".into(), "unwind".into()]
             }
             FalseUnwind { unwind: _, .. } => vec!["real".into()],
-            InlineAsm { destination: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
-                vec!["return".into(), "unwind".into()]
+            InlineAsm { options, ref targets, unwind, .. } => {
+                let mut vec = Vec::with_capacity(targets.len() + 1);
+                if !options.contains(InlineAsmOptions::NORETURN) {
+                    vec.push("return".into());
+                }
+                vec.resize(targets.len(), "label".into());
+
+                if let UnwindAction::Cleanup(_) = unwind {
+                    vec.push("unwind".into());
+                }
+
+                vec
             }
-            InlineAsm { destination: Some(_), unwind: _, .. } => {
-                vec!["return".into()]
-            }
-            InlineAsm { destination: None, unwind: UnwindAction::Cleanup(_), .. } => {
-                vec!["unwind".into()]
-            }
-            InlineAsm { destination: None, unwind: _, .. } => vec![],
         }
     }
 }
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 5c9857b9c53..f188923f876 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -793,9 +793,10 @@ pub enum TerminatorKind<'tcx> {
         /// used to map assembler errors back to the line in the source code.
         line_spans: &'tcx [Span],
 
-        /// Destination block after the inline assembly returns, unless it is
-        /// diverging (InlineAsmOptions::NORETURN).
-        destination: Option<BasicBlock>,
+        /// Valid targets for the inline assembly.
+        /// The first element is the fallthrough destination, unless
+        /// InlineAsmOptions::NORETURN is set.
+        targets: Vec<BasicBlock>,
 
         /// Action to be taken if the inline assembly unwinds. This is present
         /// if and only if InlineAsmOptions::MAY_UNWIND is set.
@@ -918,6 +919,10 @@ pub enum InlineAsmOperand<'tcx> {
     SymStatic {
         def_id: DefId,
     },
+    Label {
+        /// This represents the index into the `targets` array in `TerminatorKind::InlineAsm`.
+        target_index: usize,
+    },
 }
 
 /// Type for MIR `Assert` terminator error messages.
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 4c7df0a7ae2..a4a4df55c48 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -74,6 +74,17 @@ impl SwitchTargets {
     pub fn target_for_value(&self, value: u128) -> BasicBlock {
         self.iter().find_map(|(v, t)| (v == value).then_some(t)).unwrap_or_else(|| self.otherwise())
     }
+
+    /// Adds a new target to the switch. But You cannot add an already present value.
+    #[inline]
+    pub fn add_target(&mut self, value: u128, bb: BasicBlock) {
+        let value = Pu128(value);
+        if self.values.contains(&value) {
+            bug!("target value {:?} already present", value);
+        }
+        self.values.push(value);
+        self.targets.insert(self.targets.len() - 1, bb);
+    }
 }
 
 pub struct SwitchTargetsIter<'a> {
@@ -251,7 +262,7 @@ impl<O> AssertKind<O> {
     /// `AssertKind::description` and the lang items mentioned in its docs).
     /// Note that we deliberately show more details here than we do at runtime, such as the actual
     /// numbers that overflowed -- it is much easier to do so here than at runtime.
-    pub fn diagnostic_message(&self) -> DiagnosticMessage {
+    pub fn diagnostic_message(&self) -> DiagMessage {
         use crate::fluent_generated::*;
         use AssertKind::*;
 
@@ -336,8 +347,7 @@ pub struct Terminator<'tcx> {
 }
 
 pub type Successors<'a> = impl DoubleEndedIterator<Item = BasicBlock> + 'a;
-pub type SuccessorsMut<'a> =
-    iter::Chain<std::option::IntoIter<&'a mut BasicBlock>, slice::IterMut<'a, BasicBlock>>;
+pub type SuccessorsMut<'a> = impl DoubleEndedIterator<Item = &'a mut BasicBlock> + 'a;
 
 impl<'tcx> Terminator<'tcx> {
     #[inline]
@@ -371,40 +381,36 @@ impl<'tcx> TerminatorKind<'tcx> {
     pub fn successors(&self) -> Successors<'_> {
         use self::TerminatorKind::*;
         match *self {
-            Call { target: Some(t), unwind: UnwindAction::Cleanup(ref u), .. }
-            | Yield { resume: t, drop: Some(ref u), .. }
-            | Drop { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
-            | Assert { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
-            | FalseUnwind { real_target: t, unwind: UnwindAction::Cleanup(ref u) }
-            | InlineAsm { destination: Some(t), unwind: UnwindAction::Cleanup(ref u), .. } => {
-                Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied())
+            Call { target: Some(ref t), unwind: UnwindAction::Cleanup(u), .. }
+            | Yield { resume: ref t, drop: Some(u), .. }
+            | Drop { target: ref t, unwind: UnwindAction::Cleanup(u), .. }
+            | Assert { target: ref t, unwind: UnwindAction::Cleanup(u), .. }
+            | FalseUnwind { real_target: ref t, unwind: UnwindAction::Cleanup(u) } => {
+                slice::from_ref(t).into_iter().copied().chain(Some(u))
             }
-            Goto { target: t }
-            | Call { target: None, unwind: UnwindAction::Cleanup(t), .. }
-            | Call { target: Some(t), unwind: _, .. }
-            | Yield { resume: t, drop: None, .. }
-            | Drop { target: t, unwind: _, .. }
-            | Assert { target: t, unwind: _, .. }
-            | FalseUnwind { real_target: t, unwind: _ }
-            | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. }
-            | InlineAsm { destination: Some(t), unwind: _, .. } => {
-                Some(t).into_iter().chain((&[]).into_iter().copied())
+            Goto { target: ref t }
+            | Call { target: None, unwind: UnwindAction::Cleanup(ref t), .. }
+            | Call { target: Some(ref t), unwind: _, .. }
+            | Yield { resume: ref t, drop: None, .. }
+            | Drop { target: ref t, unwind: _, .. }
+            | Assert { target: ref t, unwind: _, .. }
+            | FalseUnwind { real_target: ref t, unwind: _ } => {
+                slice::from_ref(t).into_iter().copied().chain(None)
             }
             UnwindResume
             | UnwindTerminate(_)
             | CoroutineDrop
             | Return
             | Unreachable
-            | Call { target: None, unwind: _, .. }
-            | InlineAsm { destination: None, unwind: _, .. } => {
-                None.into_iter().chain((&[]).into_iter().copied())
+            | Call { target: None, unwind: _, .. } => (&[]).into_iter().copied().chain(None),
+            InlineAsm { ref targets, unwind: UnwindAction::Cleanup(u), .. } => {
+                targets.iter().copied().chain(Some(u))
             }
-            SwitchInt { ref targets, .. } => {
-                None.into_iter().chain(targets.targets.iter().copied())
+            InlineAsm { ref targets, unwind: _, .. } => targets.iter().copied().chain(None),
+            SwitchInt { ref targets, .. } => targets.targets.iter().copied().chain(None),
+            FalseEdge { ref real_target, imaginary_target } => {
+                slice::from_ref(real_target).into_iter().copied().chain(Some(imaginary_target))
             }
-            FalseEdge { real_target, ref imaginary_target } => Some(real_target)
-                .into_iter()
-                .chain(slice::from_ref(imaginary_target).into_iter().copied()),
         }
     }
 
@@ -416,33 +422,31 @@ impl<'tcx> TerminatorKind<'tcx> {
             | Yield { resume: ref mut t, drop: Some(ref mut u), .. }
             | Drop { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
             | Assert { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
-            | FalseUnwind { real_target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u) }
-            | InlineAsm {
-                destination: Some(ref mut t),
-                unwind: UnwindAction::Cleanup(ref mut u),
-                ..
-            } => Some(t).into_iter().chain(slice::from_mut(u)),
+            | FalseUnwind { real_target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u) } => {
+                slice::from_mut(t).into_iter().chain(Some(u))
+            }
             Goto { target: ref mut t }
             | Call { target: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
             | Call { target: Some(ref mut t), unwind: _, .. }
             | Yield { resume: ref mut t, drop: None, .. }
             | Drop { target: ref mut t, unwind: _, .. }
             | Assert { target: ref mut t, unwind: _, .. }
-            | FalseUnwind { real_target: ref mut t, unwind: _ }
-            | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
-            | InlineAsm { destination: Some(ref mut t), unwind: _, .. } => {
-                Some(t).into_iter().chain(&mut [])
+            | FalseUnwind { real_target: ref mut t, unwind: _ } => {
+                slice::from_mut(t).into_iter().chain(None)
             }
             UnwindResume
             | UnwindTerminate(_)
             | CoroutineDrop
             | Return
             | Unreachable
-            | Call { target: None, unwind: _, .. }
-            | InlineAsm { destination: None, unwind: _, .. } => None.into_iter().chain(&mut []),
-            SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets.targets),
+            | Call { target: None, unwind: _, .. } => (&mut []).into_iter().chain(None),
+            InlineAsm { ref mut targets, unwind: UnwindAction::Cleanup(ref mut u), .. } => {
+                targets.iter_mut().chain(Some(u))
+            }
+            InlineAsm { ref mut targets, unwind: _, .. } => targets.iter_mut().chain(None),
+            SwitchInt { ref mut targets, .. } => targets.targets.iter_mut().chain(None),
             FalseEdge { ref mut real_target, ref mut imaginary_target } => {
-                Some(real_target).into_iter().chain(slice::from_mut(imaginary_target))
+                slice::from_mut(real_target).into_iter().chain(Some(imaginary_target))
             }
         }
     }
@@ -514,7 +518,7 @@ pub enum TerminatorEdges<'mir, 'tcx> {
     Double(BasicBlock, BasicBlock),
     /// Special action for `Yield`, `Call` and `InlineAsm` terminators.
     AssignOnReturn {
-        return_: Option<BasicBlock>,
+        return_: &'mir [BasicBlock],
         /// The cleanup block, if it exists.
         cleanup: Option<BasicBlock>,
         place: CallReturnPlaces<'mir, 'tcx>,
@@ -578,31 +582,37 @@ impl<'tcx> TerminatorKind<'tcx> {
                 TerminatorEdges::Double(real_target, imaginary_target)
             }
 
-            Yield { resume: target, drop, resume_arg, value: _ } => {
+            Yield { resume: ref target, drop, resume_arg, value: _ } => {
                 TerminatorEdges::AssignOnReturn {
-                    return_: Some(target),
+                    return_: slice::from_ref(target),
                     cleanup: drop,
                     place: CallReturnPlaces::Yield(resume_arg),
                 }
             }
 
-            Call { unwind, destination, target, func: _, args: _, fn_span: _, call_source: _ } => {
-                TerminatorEdges::AssignOnReturn {
-                    return_: target,
-                    cleanup: unwind.cleanup_block(),
-                    place: CallReturnPlaces::Call(destination),
-                }
-            }
+            Call {
+                unwind,
+                destination,
+                ref target,
+                func: _,
+                args: _,
+                fn_span: _,
+                call_source: _,
+            } => TerminatorEdges::AssignOnReturn {
+                return_: target.as_ref().map(slice::from_ref).unwrap_or_default(),
+                cleanup: unwind.cleanup_block(),
+                place: CallReturnPlaces::Call(destination),
+            },
 
             InlineAsm {
                 template: _,
                 ref operands,
                 options: _,
                 line_spans: _,
-                destination,
+                ref targets,
                 unwind,
             } => TerminatorEdges::AssignOnReturn {
-                return_: destination,
+                return_: targets,
                 cleanup: unwind.cleanup_block(),
                 place: CallReturnPlaces::InlineAsm(operands),
             },
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 2c5ca82a4cd..845b1717550 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -565,7 +565,7 @@ macro_rules! make_mir_visitor {
                         operands,
                         options: _,
                         line_spans: _,
-                        destination: _,
+                        targets: _,
                         unwind: _,
                     } => {
                         for op in operands {
@@ -595,7 +595,8 @@ macro_rules! make_mir_visitor {
                                     self.visit_constant(value, location);
                                 }
                                 InlineAsmOperand::Out { place: None, .. }
-                                | InlineAsmOperand::SymStatic { def_id: _ } => {}
+                                | InlineAsmOperand::SymStatic { def_id: _ }
+                                | InlineAsmOperand::Label { target_index: _ } => {}
                             }
                         }
                     }
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 2cdcdcb1492..33ee3371605 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -177,8 +177,8 @@ impl EraseType for Option<mir::DestructuredConstant<'_>> {
     type Result = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()];
 }
 
-impl EraseType for Option<ty::EarlyBinder<ty::ImplTraitHeader<'_>>> {
-    type Result = [u8; size_of::<Option<ty::EarlyBinder<ty::ImplTraitHeader<'static>>>>()];
+impl EraseType for Option<ty::ImplTraitHeader<'_>> {
+    type Result = [u8; size_of::<Option<ty::ImplTraitHeader<'static>>>()];
 }
 
 impl EraseType for Option<ty::EarlyBinder<Ty<'_>>> {
@@ -241,7 +241,7 @@ trivial! {
     Option<rustc_target::abi::FieldIdx>,
     Option<rustc_target::spec::PanicStrategy>,
     Option<usize>,
-    Option<rustc_span::Symbol>,
+    Option<rustc_middle::ty::IntrinsicDef>,
     Result<(), rustc_errors::ErrorGuaranteed>,
     Result<(), rustc_middle::traits::query::NoSolution>,
     Result<rustc_middle::traits::EvaluationResult, rustc_middle::traits::OverflowError>,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index e87bc581e6e..332ebdbdd94 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -125,12 +125,11 @@ rustc_queries! {
     }
 
     query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt {
-        feedable
         no_hash
         desc { "getting the resolver outputs" }
     }
 
-    query resolver_for_lowering(_: ()) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> {
+    query resolver_for_lowering_raw(_: ()) -> (&'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)>, &'tcx ty::ResolverGlobalCtxt) {
         eval_always
         no_hash
         desc { "getting the resolver for lowering" }
@@ -344,15 +343,6 @@ rustc_queries! {
         }
     }
 
-    query impl_trait_in_assoc_types_defined_by(
-        key: LocalDefId
-    ) -> &'tcx ty::List<LocalDefId> {
-        desc {
-            |tcx| "computing the opaque types defined by `{}`",
-            tcx.def_path_str(key.to_def_id())
-        }
-    }
-
     /// Returns the list of bounds that can be used for
     /// `SelectionCandidate::ProjectionCandidate(_)` and
     /// `ProjectionTyCandidate::TraitDef`.
@@ -772,6 +762,7 @@ rustc_queries! {
         desc { |tcx| "computing the variances of `{}`", tcx.def_path_str(def_id) }
         cache_on_disk_if { def_id.is_local() }
         separate_provide_extern
+        cycle_delay_bug
     }
 
     /// Maps from thee `DefId` of a type to its (inferred) outlives.
@@ -835,7 +826,7 @@ rustc_queries! {
     /// creates and returns the associated items that correspond to each impl trait in return position
     /// of the implemented trait.
     query associated_types_for_impl_traits_in_associated_fn(fn_def_id: DefId) -> &'tcx [DefId] {
-        desc { |tcx| "creating associated items for impl trait in trait returned by `{}`", tcx.def_path_str(fn_def_id) }
+        desc { |tcx| "creating associated items for opaque types returned by `{}`", tcx.def_path_str(fn_def_id) }
         cache_on_disk_if { fn_def_id.is_local() }
         separate_provide_extern
     }
@@ -843,13 +834,13 @@ rustc_queries! {
     /// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding
     /// associated item.
     query associated_type_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId {
-        desc { |tcx| "creates the associated item corresponding to the opaque type `{}`", tcx.def_path_str(opaque_ty_def_id.to_def_id()) }
+        desc { |tcx| "creating the associated item corresponding to the opaque type `{}`", tcx.def_path_str(opaque_ty_def_id.to_def_id()) }
         cache_on_disk_if { true }
     }
 
     /// Given an `impl_id`, return the trait it implements along with some header information.
     /// Return `None` if this is an inherent impl.
-    query impl_trait_header(impl_id: DefId) -> Option<ty::EarlyBinder<ty::ImplTraitHeader<'tcx>>> {
+    query impl_trait_header(impl_id: DefId) -> Option<ty::ImplTraitHeader<'tcx>> {
         desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) }
         cache_on_disk_if { impl_id.is_local() }
         separate_provide_extern
@@ -964,20 +955,11 @@ rustc_queries! {
         desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) }
     }
 
-    query check_mod_impl_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> {
-        desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) }
-        ensure_forwards_result_if_red
-    }
-
     query check_mod_type_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> {
         desc { |tcx| "checking that types are well-formed in {}", describe_as_module(key, tcx) }
         ensure_forwards_result_if_red
     }
 
-    query collect_mod_item_types(key: LocalModDefId) {
-        desc { |tcx| "collecting item types in {}", describe_as_module(key, tcx) }
-    }
-
     /// Caches `CoerceUnsized` kinds for impls on custom types.
     query coerce_unsized_info(key: DefId) -> Result<ty::adjustment::CoerceUnsizedInfo, ErrorGuaranteed> {
         desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) }
@@ -1760,7 +1742,7 @@ rustc_queries! {
         separate_provide_extern
     }
     /// Whether the function is an intrinsic
-    query intrinsic(def_id: DefId) -> Option<Symbol> {
+    query intrinsic_raw(def_id: DefId) -> Option<rustc_middle::ty::IntrinsicDef> {
         desc { |tcx| "fetch intrinsic name if `{}` is an intrinsic", tcx.def_path_str(def_id) }
         separate_provide_extern
     }
@@ -2230,7 +2212,6 @@ rustc_queries! {
     /// Should not be called for the local crate before the resolver outputs are created, as it
     /// is only fed there.
     query stripped_cfg_items(cnum: CrateNum) -> &'tcx [StrippedCfgItem] {
-        feedable
         desc { "getting cfg-ed out item names" }
         separate_provide_extern
     }
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 65875ff3f9a..913d0072c29 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -565,6 +565,9 @@ pub enum InlineAsmOperand<'tcx> {
     SymStatic {
         def_id: DefId,
     },
+    Label {
+        block: BlockId,
+    },
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, HashStable)]
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
index 4847a7bea91..5952c296fb6 100644
--- a/compiler/rustc_middle/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -162,6 +162,7 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
                     | Const { value: _, span: _ }
                     | SymFn { value: _, span: _ }
                     | SymStatic { def_id: _ } => {}
+                    Label { block } => visitor.visit_block(&visitor.thir()[*block]),
                 }
             }
         }
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
index 0dc65126011..95139b50cb8 100644
--- a/compiler/rustc_middle/src/traits/solve.rs
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -1,6 +1,6 @@
-use std::ops::ControlFlow;
-
+use rustc_ast_ir::try_visit;
 use rustc_data_structures::intern::Interned;
+use rustc_span::def_id::DefId;
 
 use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints};
 use crate::traits::query::NoSolution;
@@ -9,7 +9,6 @@ use crate::ty::{
     self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable,
     TypeVisitor,
 };
-use rustc_span::def_id::DefId;
 
 use super::BuiltinImplSource;
 
@@ -196,13 +195,9 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
 }
 
 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
-        &self,
-        visitor: &mut V,
-    ) -> std::ops::ControlFlow<V::BreakTy> {
-        self.region_constraints.visit_with(visitor)?;
-        self.opaque_types.visit_with(visitor)?;
-        ControlFlow::Continue(())
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
+        try_visit!(self.region_constraints.visit_with(visitor));
+        self.opaque_types.visit_with(visitor)
     }
 }
 
@@ -235,10 +230,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> {
 }
 
 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
-        &self,
-        visitor: &mut V,
-    ) -> std::ops::ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
         self.opaque_types.visit_with(visitor)
     }
 }
diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
index 89c5eb517e5..8d3109a7b28 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
@@ -4,22 +4,31 @@ pub(super) struct ProofTreeFormatter<'a, 'b> {
     f: &'a mut (dyn Write + 'b),
 }
 
+enum IndentorState {
+    StartWithNewline,
+    OnNewline,
+    Inline,
+}
+
 /// A formatter which adds 4 spaces of indentation to its input before
 /// passing it on to its nested formatter.
 ///
 /// We can use this for arbitrary levels of indentation by nesting it.
 struct Indentor<'a, 'b> {
     f: &'a mut (dyn Write + 'b),
-    on_newline: bool,
+    state: IndentorState,
 }
 
 impl Write for Indentor<'_, '_> {
     fn write_str(&mut self, s: &str) -> std::fmt::Result {
         for line in s.split_inclusive('\n') {
-            if self.on_newline {
-                self.f.write_str("    ")?;
+            match self.state {
+                IndentorState::StartWithNewline => self.f.write_str("\n    ")?,
+                IndentorState::OnNewline => self.f.write_str("    ")?,
+                IndentorState::Inline => {}
             }
-            self.on_newline = line.ends_with('\n');
+            self.state =
+                if line.ends_with('\n') { IndentorState::OnNewline } else { IndentorState::Inline };
             self.f.write_str(line)?;
         }
 
@@ -32,11 +41,15 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
         ProofTreeFormatter { f }
     }
 
-    fn nested<F, R>(&mut self, func: F) -> R
+    fn nested<F>(&mut self, func: F) -> std::fmt::Result
     where
-        F: FnOnce(&mut ProofTreeFormatter<'_, '_>) -> R,
+        F: FnOnce(&mut ProofTreeFormatter<'_, '_>) -> std::fmt::Result,
     {
-        func(&mut ProofTreeFormatter { f: &mut Indentor { f: self.f, on_newline: true } })
+        write!(self.f, " {{")?;
+        func(&mut ProofTreeFormatter {
+            f: &mut Indentor { f: self.f, state: IndentorState::StartWithNewline },
+        })?;
+        writeln!(self.f, "}}")
     }
 
     pub(super) fn format_goal_evaluation(&mut self, eval: &GoalEvaluation<'_>) -> std::fmt::Result {
@@ -47,7 +60,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
                 IsNormalizesToHack::Yes => "NORMALIZES-TO HACK GOAL",
             },
         };
-        writeln!(self.f, "{}: {:?}", goal_text, eval.uncanonicalized_goal)?;
+        write!(self.f, "{}: {:?}", goal_text, eval.uncanonicalized_goal)?;
         self.nested(|this| this.format_canonical_goal_evaluation(&eval.evaluation))
     }
 
@@ -69,7 +82,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
             }
             CanonicalGoalEvaluationKind::Evaluation { revisions } => {
                 for (n, step) in revisions.iter().enumerate() {
-                    writeln!(self.f, "REVISION {n}")?;
+                    write!(self.f, "REVISION {n}")?;
                     self.nested(|this| this.format_evaluation_step(step))?;
                 }
                 writeln!(self.f, "RESULT: {:?}", eval.result)
@@ -88,25 +101,25 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
     pub(super) fn format_probe(&mut self, probe: &Probe<'_>) -> std::fmt::Result {
         match &probe.kind {
             ProbeKind::Root { result } => {
-                writeln!(self.f, "ROOT RESULT: {result:?}")
+                write!(self.f, "ROOT RESULT: {result:?}")
             }
             ProbeKind::NormalizedSelfTyAssembly => {
-                writeln!(self.f, "NORMALIZING SELF TY FOR ASSEMBLY:")
+                write!(self.f, "NORMALIZING SELF TY FOR ASSEMBLY:")
             }
             ProbeKind::UnsizeAssembly => {
-                writeln!(self.f, "ASSEMBLING CANDIDATES FOR UNSIZING:")
+                write!(self.f, "ASSEMBLING CANDIDATES FOR UNSIZING:")
             }
             ProbeKind::UpcastProjectionCompatibility => {
-                writeln!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:")
+                write!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:")
             }
             ProbeKind::CommitIfOk => {
-                writeln!(self.f, "COMMIT_IF_OK:")
+                write!(self.f, "COMMIT_IF_OK:")
             }
             ProbeKind::MiscCandidate { name, result } => {
-                writeln!(self.f, "CANDIDATE {name}: {result:?}")
+                write!(self.f, "CANDIDATE {name}: {result:?}")
             }
             ProbeKind::TraitCandidate { source, result } => {
-                writeln!(self.f, "CANDIDATE {source:?}: {result:?}")
+                write!(self.f, "CANDIDATE {source:?}: {result:?}")
             }
         }?;
 
@@ -137,7 +150,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
         writeln!(self.f, "TRY_EVALUATE_ADDED_GOALS: {:?}", added_goals_evaluation.result)?;
 
         for (n, iterations) in added_goals_evaluation.evaluations.iter().enumerate() {
-            writeln!(self.f, "ITERATION {n}")?;
+            write!(self.f, "ITERATION {n}")?;
             self.nested(|this| {
                 for goal_evaluation in iterations {
                     this.format_goal_evaluation(goal_evaluation)?;
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 5e4d899f517..5b62c0bf931 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -175,7 +175,20 @@ impl<'tcx> Const<'tcx> {
         let reported = tcx.dcx().span_delayed_bug(span, msg);
         Const::new_error(tcx, reported, ty)
     }
+}
 
+impl<'tcx> rustc_type_ir::new::Const<TyCtxt<'tcx>> for Const<'tcx> {
+    fn new_anon_bound(
+        tcx: TyCtxt<'tcx>,
+        debruijn: ty::DebruijnIndex,
+        var: ty::BoundVar,
+        ty: Ty<'tcx>,
+    ) -> Self {
+        Const::new_bound(tcx, debruijn, var, ty)
+    }
+}
+
+impl<'tcx> Const<'tcx> {
     /// Literals and const generic parameters are eagerly converted to a constant, everything else
     /// becomes `Unevaluated`.
     #[instrument(skip(tcx), level = "debug")]
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index b2a7f5599b6..f947832d28c 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -39,11 +39,11 @@ use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::steal::Steal;
-use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, WorkerLocal};
+use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, WorkerLocal};
 #[cfg(parallel_compiler)]
 use rustc_data_structures::sync::{DynSend, DynSync};
 use rustc_data_structures::unord::UnordSet;
-use rustc_errors::{DecorateLint, Diag, DiagCtxt, DiagnosticMessage, ErrorGuaranteed, MultiSpan};
+use rustc_errors::{DecorateLint, Diag, DiagCtxt, DiagMessage, ErrorGuaranteed, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
@@ -60,7 +60,7 @@ use rustc_session::config::CrateType;
 use rustc_session::cstore::{CrateStoreDyn, Untracked};
 use rustc_session::lint::Lint;
 use rustc_session::{Limit, MetadataKind, Session};
-use rustc_span::def_id::{DefPathHash, StableCrateId};
+use rustc_span::def_id::{DefPathHash, StableCrateId, CRATE_DEF_ID};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
@@ -74,6 +74,7 @@ use std::cmp::Ordering;
 use std::fmt;
 use std::hash::{Hash, Hasher};
 use std::iter;
+use std::marker::PhantomData;
 use std::mem;
 use std::ops::{Bound, Deref};
 
@@ -130,27 +131,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars {
         self.mk_canonical_var_infos(infos)
     }
-
-    fn mk_bound_ty(self, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self::Ty {
-        Ty::new_bound(self, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon })
-    }
-
-    fn mk_bound_region(self, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self::Region {
-        Region::new_bound(
-            self,
-            debruijn,
-            ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon },
-        )
-    }
-
-    fn mk_bound_const(
-        self,
-        debruijn: ty::DebruijnIndex,
-        var: ty::BoundVar,
-        ty: Self::Ty,
-    ) -> Self::Const {
-        Const::new_bound(self, debruijn, var, ty)
-    }
 }
 
 type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
@@ -519,14 +499,55 @@ pub struct TyCtxtFeed<'tcx, KEY: Copy> {
     key: KEY,
 }
 
+/// Never return a `Feed` from a query. Only queries that create a `DefId` are
+/// allowed to feed queries for that `DefId`.
+impl<KEY: Copy, CTX> !HashStable<CTX> for TyCtxtFeed<'_, KEY> {}
+
+/// The same as `TyCtxtFeed`, but does not contain a `TyCtxt`.
+/// Use this to pass around when you have a `TyCtxt` elsewhere.
+/// Just an optimization to save space and not store hundreds of
+/// `TyCtxtFeed` in the resolver.
+#[derive(Copy, Clone)]
+pub struct Feed<'tcx, KEY: Copy> {
+    _tcx: PhantomData<TyCtxt<'tcx>>,
+    // Do not allow direct access, as downstream code must not mutate this field.
+    key: KEY,
+}
+
+/// Never return a `Feed` from a query. Only queries that create a `DefId` are
+/// allowed to feed queries for that `DefId`.
+impl<KEY: Copy, CTX> !HashStable<CTX> for Feed<'_, KEY> {}
+
+impl<T: fmt::Debug + Copy> fmt::Debug for Feed<'_, T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.key.fmt(f)
+    }
+}
+
+/// Some workarounds to use cases that cannot use `create_def`.
+/// Do not add new ways to create `TyCtxtFeed` without consulting
+/// with T-compiler and making an analysis about why your addition
+/// does not cause incremental compilation issues.
 impl<'tcx> TyCtxt<'tcx> {
+    /// Can only be fed before queries are run, and is thus exempt from any
+    /// incremental issues. Do not use except for the initial query feeding.
     pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> {
+        self.dep_graph.assert_ignored();
         TyCtxtFeed { tcx: self, key: () }
     }
+
+    /// Can only be fed before queries are run, and is thus exempt from any
+    /// incremental issues. Do not use except for the initial query feeding.
     pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> {
+        self.dep_graph.assert_ignored();
         TyCtxtFeed { tcx: self, key: LOCAL_CRATE }
     }
-    pub fn feed_local_def_id(self, key: LocalDefId) -> TyCtxtFeed<'tcx, LocalDefId> {
+
+    /// Only used in the resolver to register the `CRATE_DEF_ID` `DefId` and feed
+    /// some queries for it. It will panic if used twice.
+    pub fn create_local_crate_def_id(self, span: Span) -> TyCtxtFeed<'tcx, LocalDefId> {
+        let key = self.untracked().source_span.push(span);
+        assert_eq!(key, CRATE_DEF_ID);
         TyCtxtFeed { tcx: self, key }
     }
 
@@ -544,6 +565,23 @@ impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> {
     pub fn key(&self) -> KEY {
         self.key
     }
+
+    #[inline(always)]
+    pub fn downgrade(self) -> Feed<'tcx, KEY> {
+        Feed { _tcx: PhantomData, key: self.key }
+    }
+}
+
+impl<'tcx, KEY: Copy> Feed<'tcx, KEY> {
+    #[inline(always)]
+    pub fn key(&self) -> KEY {
+        self.key
+    }
+
+    #[inline(always)]
+    pub fn upgrade(self, tcx: TyCtxt<'tcx>) -> TyCtxtFeed<'tcx, KEY> {
+        TyCtxtFeed { tcx, key: self.key }
+    }
 }
 
 impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
@@ -1088,7 +1126,7 @@ impl<'tcx> TyCtxt<'tcx> {
         // needs to be re-evaluated.
         self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
 
-        let feed = self.feed_local_def_id(def_id);
+        let feed = TyCtxtFeed { tcx: self, key: def_id };
         feed.def_kind(def_kind);
         // Unique types created for closures participate in type privacy checking.
         // They have visibilities inherited from the module they are defined in.
@@ -1216,7 +1254,7 @@ impl<'tcx> TyCtxt<'tcx> {
             if self.def_kind(scope) == DefKind::OpaqueTy {
                 // Lifetime params of opaque types are synthetic and thus irrelevant to
                 // diagnostics. Map them back to their origin!
-                region = self.map_rpit_lifetime_to_fn_lifetime(def_id);
+                region = self.map_opaque_lifetime_to_parent_lifetime(def_id);
                 continue;
             }
             break (scope, ty::BrNamed(def_id.into(), self.item_name(def_id.into())));
@@ -2118,7 +2156,7 @@ impl<'tcx> TyCtxt<'tcx> {
         lint: &'static Lint,
         hir_id: HirId,
         span: impl Into<MultiSpan>,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
         decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
     ) {
         let (level, src) = self.lint_level_at_node(lint, hir_id);
@@ -2148,7 +2186,7 @@ impl<'tcx> TyCtxt<'tcx> {
         self,
         lint: &'static Lint,
         id: HirId,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
         decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
     ) {
         let (level, src) = self.lint_level_at_node(lint, id);
@@ -2181,31 +2219,31 @@ impl<'tcx> TyCtxt<'tcx> {
         )
     }
 
-    /// Given the def-id of an early-bound lifetime on an RPIT corresponding to
+    /// Given the def-id of an early-bound lifetime on an opaque corresponding to
     /// a duplicated captured lifetime, map it back to the early- or late-bound
     /// lifetime of the function from which it originally as captured. If it is
     /// a late-bound lifetime, this will represent the liberated (`ReLateParam`) lifetime
     /// of the signature.
     // FIXME(RPITIT): if we ever synthesize new lifetimes for RPITITs and not just
     // re-use the generics of the opaque, this function will need to be tweaked slightly.
-    pub fn map_rpit_lifetime_to_fn_lifetime(
+    pub fn map_opaque_lifetime_to_parent_lifetime(
         self,
-        mut rpit_lifetime_param_def_id: LocalDefId,
+        mut opaque_lifetime_param_def_id: LocalDefId,
     ) -> ty::Region<'tcx> {
         debug_assert!(
-            matches!(self.def_kind(rpit_lifetime_param_def_id), DefKind::LifetimeParam),
-            "{rpit_lifetime_param_def_id:?} is a {}",
-            self.def_descr(rpit_lifetime_param_def_id.to_def_id())
+            matches!(self.def_kind(opaque_lifetime_param_def_id), DefKind::LifetimeParam),
+            "{opaque_lifetime_param_def_id:?} is a {}",
+            self.def_descr(opaque_lifetime_param_def_id.to_def_id())
         );
 
         loop {
-            let parent = self.local_parent(rpit_lifetime_param_def_id);
+            let parent = self.local_parent(opaque_lifetime_param_def_id);
             let hir::OpaqueTy { lifetime_mapping, .. } =
                 self.hir_node_by_def_id(parent).expect_item().expect_opaque_ty();
 
             let Some((lifetime, _)) = lifetime_mapping
                 .iter()
-                .find(|(_, duplicated_param)| *duplicated_param == rpit_lifetime_param_def_id)
+                .find(|(_, duplicated_param)| *duplicated_param == opaque_lifetime_param_def_id)
             else {
                 bug!("duplicated lifetime param should be present");
             };
@@ -2218,7 +2256,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     // of the opaque we mapped from. Continue mapping.
                     if matches!(self.def_kind(new_parent), DefKind::OpaqueTy) {
                         debug_assert_eq!(self.parent(parent.to_def_id()), new_parent);
-                        rpit_lifetime_param_def_id = ebv.expect_local();
+                        opaque_lifetime_param_def_id = ebv.expect_local();
                         continue;
                     }
 
@@ -2296,6 +2334,14 @@ impl<'tcx> TyCtxt<'tcx> {
         )
     }
 
+    pub fn intrinsic(self, def_id: impl IntoQueryParam<DefId> + Copy) -> Option<ty::IntrinsicDef> {
+        match self.def_kind(def_id) {
+            DefKind::Fn | DefKind::AssocFn => {}
+            _ => return None,
+        }
+        self.intrinsic_raw(def_id)
+    }
+
     pub fn local_def_id_to_hir_id(self, local_def_id: LocalDefId) -> HirId {
         self.opt_local_def_id_to_hir_id(local_def_id).unwrap()
     }
@@ -2325,18 +2371,21 @@ impl<'tcx> TyCtxt<'tcx> {
         self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..])
     }
 
+    pub fn resolver_for_lowering(self) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> {
+        self.resolver_for_lowering_raw(()).0
+    }
+
     /// Given an `impl_id`, return the trait it implements.
     /// Return `None` if this is an inherent impl.
     pub fn impl_trait_ref(
         self,
         def_id: impl IntoQueryParam<DefId>,
     ) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> {
-        Some(self.impl_trait_header(def_id)?.map_bound(|h| h.trait_ref))
+        Some(self.impl_trait_header(def_id)?.trait_ref)
     }
 
     pub fn impl_polarity(self, def_id: impl IntoQueryParam<DefId>) -> ty::ImplPolarity {
-        self.impl_trait_header(def_id)
-            .map_or(ty::ImplPolarity::Positive, |h| h.skip_binder().polarity)
+        self.impl_trait_header(def_id).map_or(ty::ImplPolarity::Positive, |h| h.polarity)
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 712fbf24440..2506456f1fb 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -482,9 +482,9 @@ pub struct IsSuggestableVisitor<'tcx> {
 }
 
 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> {
-    type BreakTy = ();
+    type Result = ControlFlow<()>;
 
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
         match *t.kind() {
             Infer(InferTy::TyVar(_)) if self.infer_suggestable => {}
 
@@ -536,7 +536,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> {
         t.super_visit_with(self)
     }
 
-    fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_const(&mut self, c: Const<'tcx>) -> Self::Result {
         match c.kind() {
             ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => {}
 
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index c87ef870a08..8079ad121ad 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -6,6 +6,8 @@ use crate::ty::sty::{ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineCon
 use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor};
 use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
 
+use rustc_ast_ir::visit::VisitorResult;
+use rustc_ast_ir::walk_visitable_list;
 use rustc_data_structures::intern::Interned;
 use rustc_errors::{DiagArgValue, IntoDiagnosticArg};
 use rustc_hir::def_id::DefId;
@@ -19,7 +21,7 @@ use std::cmp::Ordering;
 use std::marker::PhantomData;
 use std::mem;
 use std::num::NonZero;
-use std::ops::{ControlFlow, Deref};
+use std::ops::Deref;
 use std::ptr::NonNull;
 
 /// An entity in the Rust type system, which can be one of
@@ -240,7 +242,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for GenericArg<'tcx> {
 }
 
 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for GenericArg<'tcx> {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
         match self.unpack() {
             GenericArgKind::Lifetime(lt) => lt.visit_with(visitor),
             GenericArgKind::Type(ty) => ty.visit_with(visitor),
@@ -554,8 +556,9 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> {
 
 impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for &'tcx ty::List<T> {
     #[inline]
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.iter().try_for_each(|t| t.visit_with(visitor))
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
+        walk_visitable_list!(visitor, self.iter());
+        V::Result::output()
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 260d0885089..9fc8d418f5b 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -694,6 +694,7 @@ impl<'tcx> Instance<'tcx> {
     }
 
     #[inline(always)]
+    // Keep me in sync with try_instantiate_mir_and_normalize_erasing_regions
     pub fn instantiate_mir_and_normalize_erasing_regions<T>(
         &self,
         tcx: TyCtxt<'tcx>,
@@ -701,16 +702,17 @@ impl<'tcx> Instance<'tcx> {
         v: EarlyBinder<T>,
     ) -> T
     where
-        T: TypeFoldable<TyCtxt<'tcx>> + Clone,
+        T: TypeFoldable<TyCtxt<'tcx>>,
     {
         if let Some(args) = self.args_for_mir_body() {
             tcx.instantiate_and_normalize_erasing_regions(args, param_env, v)
         } else {
-            tcx.normalize_erasing_regions(param_env, v.skip_binder())
+            tcx.normalize_erasing_regions(param_env, v.instantiate_identity())
         }
     }
 
     #[inline(always)]
+    // Keep me in sync with instantiate_mir_and_normalize_erasing_regions
     pub fn try_instantiate_mir_and_normalize_erasing_regions<T>(
         &self,
         tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/intrinsic.rs b/compiler/rustc_middle/src/ty/intrinsic.rs
new file mode 100644
index 00000000000..18d08ed23a5
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/intrinsic.rs
@@ -0,0 +1,17 @@
+use rustc_span::{def_id::DefId, Symbol};
+
+use super::TyCtxt;
+
+#[derive(Copy, Clone, Debug, Decodable, Encodable, HashStable)]
+pub struct IntrinsicDef {
+    pub name: Symbol,
+    /// Whether the intrinsic has no meaningful body and all backends need to shim all calls to it.
+    pub must_be_overridden: bool,
+}
+
+impl TyCtxt<'_> {
+    pub fn is_intrinsic(self, def_id: DefId, name: Symbol) -> bool {
+        let Some(i) = self.intrinsic(def_id) else { return false };
+        i.name == name
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 529d847bfb0..b1bfd2f1105 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -3,7 +3,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::query::TyCtxtAt;
 use crate::ty::normalize_erasing_regions::NormalizationError;
 use crate::ty::{self, ConstKind, Ty, TyCtxt, TypeVisitableExt};
-use rustc_error_messages::DiagnosticMessage;
+use rustc_error_messages::DiagMessage;
 use rustc_errors::{
     Diag, DiagArgValue, DiagCtxt, EmissionGuarantee, IntoDiagnostic, IntoDiagnosticArg, Level,
 };
@@ -17,6 +17,7 @@ use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::*;
 use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target};
 
+use std::borrow::Cow;
 use std::cmp;
 use std::fmt;
 use std::num::NonZero;
@@ -205,7 +206,7 @@ pub enum LayoutError<'tcx> {
 }
 
 impl<'tcx> LayoutError<'tcx> {
-    pub fn diagnostic_message(&self) -> DiagnosticMessage {
+    pub fn diagnostic_message(&self) -> DiagMessage {
         use crate::fluent_generated::*;
         use LayoutError::*;
         match self {
@@ -268,7 +269,7 @@ pub struct LayoutCx<'tcx, C> {
 impl<'tcx> LayoutCalculator for LayoutCx<'tcx, TyCtxt<'tcx>> {
     type TargetDataLayoutRef = &'tcx TargetDataLayout;
 
-    fn delayed_bug(&self, txt: String) {
+    fn delayed_bug(&self, txt: impl Into<Cow<'static, str>>) {
         self.tcx.dcx().delayed_bug(txt);
     }
 
@@ -969,6 +970,8 @@ where
         }
     }
 
+    /// Compute the information for the pointer stored at the given offset inside this type.
+    /// This will recurse into fields of ADTs to find the inner pointer.
     fn ty_and_layout_pointee_info_at(
         this: TyAndLayout<'tcx>,
         cx: &C,
@@ -1068,15 +1071,17 @@ where
                     }
                 }
 
-                // FIXME(eddyb) This should be for `ptr::Unique<T>`, not `Box<T>`.
+                // Fixup info for the first field of a `Box`. Recursive traversal will have found
+                // the raw pointer, so size and align are set to the boxed type, but `pointee.safe`
+                // will still be `None`.
                 if let Some(ref mut pointee) = result {
-                    if let ty::Adt(def, _) = this.ty.kind() {
-                        if def.is_box() && offset.bytes() == 0 {
-                            let optimize = tcx.sess.opts.optimize != OptLevel::No;
-                            pointee.safe = Some(PointerKind::Box {
-                                unpin: optimize && this.ty.boxed_ty().is_unpin(tcx, cx.param_env()),
-                            });
-                        }
+                    if offset.bytes() == 0 && this.ty.is_box() {
+                        debug_assert!(pointee.safe.is_none());
+                        let optimize = tcx.sess.opts.optimize != OptLevel::No;
+                        pointee.safe = Some(PointerKind::Box {
+                            unpin: optimize && this.ty.boxed_ty().is_unpin(tcx, cx.param_env()),
+                            global: this.ty.is_box_global(tcx),
+                        });
                     }
                 }
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index f005a240504..5c2d3973d61 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -30,9 +30,11 @@ pub use adt::*;
 pub use assoc::*;
 pub use generic_args::*;
 pub use generics::*;
+pub use intrinsic::IntrinsicDef;
 use rustc_ast as ast;
+use rustc_ast::expand::StrippedCfgItem;
 use rustc_ast::node_id::NodeMap;
-pub use rustc_ast_ir::{Movability, Mutability};
+pub use rustc_ast_ir::{try_visit, Movability, Mutability};
 use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::intern::Interned;
@@ -63,7 +65,6 @@ use std::hash::{Hash, Hasher};
 use std::marker::PhantomData;
 use std::mem;
 use std::num::NonZero;
-use std::ops::ControlFlow;
 use std::ptr::NonNull;
 use std::{fmt, str};
 
@@ -85,7 +86,8 @@ pub use self::consts::{
     Const, ConstData, ConstInt, ConstKind, Expr, ScalarInt, UnevaluatedConst, ValTree,
 };
 pub use self::context::{
-    tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed,
+    tls, CtxtInterners, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,
+    TyCtxtFeed,
 };
 pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams};
 pub use self::list::List;
@@ -149,6 +151,7 @@ mod generic_args;
 mod generics;
 mod impls_ty;
 mod instance;
+mod intrinsic;
 mod list;
 mod opaque_types;
 mod parameterized;
@@ -188,6 +191,7 @@ pub struct ResolverGlobalCtxt {
     pub doc_link_resolutions: FxHashMap<LocalDefId, DocLinkResMap>,
     pub doc_link_traits_in_scope: FxHashMap<LocalDefId, Vec<DefId>>,
     pub all_macro_rules: FxHashMap<Symbol, Res<ast::NodeId>>,
+    pub stripped_cfg_items: Steal<Vec<StrippedCfgItem>>,
 }
 
 /// Resolutions that should only be used for lowering.
@@ -249,9 +253,9 @@ pub struct ImplHeader<'tcx> {
     pub predicates: Vec<Predicate<'tcx>>,
 }
 
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, TyEncodable, TyDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub struct ImplTraitHeader<'tcx> {
-    pub trait_ref: ty::TraitRef<'tcx>,
+    pub trait_ref: ty::EarlyBinder<ty::TraitRef<'tcx>>,
     pub polarity: ImplPolarity,
     pub unsafety: hir::Unsafety,
 }
@@ -597,7 +601,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Term<'tcx> {
 }
 
 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
         self.unpack().visit_with(visitor)
     }
 }
@@ -1041,8 +1045,8 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ParamEnv<'tcx> {
 }
 
 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ParamEnv<'tcx> {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.caller_bounds().visit_with(visitor)?;
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
+        try_visit!(self.caller_bounds().visit_with(visitor));
         self.reveal().visit_with(visitor)
     }
 }
@@ -1623,12 +1627,15 @@ impl<'tcx> TyCtxt<'tcx> {
         def_id1: DefId,
         def_id2: DefId,
     ) -> Option<ImplOverlapKind> {
-        let impl1 = self.impl_trait_header(def_id1).unwrap().instantiate_identity();
-        let impl2 = self.impl_trait_header(def_id2).unwrap().instantiate_identity();
+        let impl1 = self.impl_trait_header(def_id1).unwrap();
+        let impl2 = self.impl_trait_header(def_id2).unwrap();
+
+        let trait_ref1 = impl1.trait_ref.skip_binder();
+        let trait_ref2 = impl2.trait_ref.skip_binder();
 
         // If either trait impl references an error, they're allowed to overlap,
         // as one of them essentially doesn't exist.
-        if impl1.references_error() || impl2.references_error() {
+        if trait_ref1.references_error() || trait_ref2.references_error() {
             return Some(ImplOverlapKind::Permitted { marker: false });
         }
 
@@ -1649,7 +1656,7 @@ impl<'tcx> TyCtxt<'tcx> {
         let is_marker_overlap = {
             let is_marker_impl =
                 |trait_ref: TraitRef<'_>| -> bool { self.trait_def(trait_ref.def_id).is_marker };
-            is_marker_impl(impl1.trait_ref) && is_marker_impl(impl2.trait_ref)
+            is_marker_impl(trait_ref1) && is_marker_impl(trait_ref2)
         };
 
         if is_marker_overlap {
@@ -1933,18 +1940,6 @@ impl<'tcx> TyCtxt<'tcx> {
         matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait))
     }
 
-    /// Returns the `DefId` of the item within which the `impl Trait` is declared.
-    /// For type-alias-impl-trait this is the `type` alias.
-    /// For impl-trait-in-assoc-type this is the assoc type.
-    /// For return-position-impl-trait this is the function.
-    pub fn impl_trait_parent(self, mut def_id: LocalDefId) -> LocalDefId {
-        // Find the surrounding item (type alias or assoc type)
-        while let DefKind::OpaqueTy = self.def_kind(def_id) {
-            def_id = self.local_parent(def_id);
-        }
-        def_id
-    }
-
     pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool {
         if self.def_kind(def_id) != DefKind::AssocFn {
             return false;
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 22f0574d614..571c6e918dc 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -75,6 +75,7 @@ trivially_parameterized_over_tcx! {
     ty::Visibility<DefIndex>,
     ty::adjustment::CoerceUnsizedInfo,
     ty::fast_reject::SimplifiedType,
+    ty::IntrinsicDef,
     rustc_ast::Attribute,
     rustc_ast::DelimArgs,
     rustc_ast::expand::StrippedCfgItem<rustc_hir::def_id::DefIndex>,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 540803d9530..c8c9afa7f4d 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -27,7 +27,7 @@ use std::cell::Cell;
 use std::collections::BTreeMap;
 use std::fmt::{self, Write as _};
 use std::iter;
-use std::ops::{ControlFlow, Deref, DerefMut};
+use std::ops::{Deref, DerefMut};
 
 // `pretty` is a separate module only for organization.
 use super::*;
@@ -2667,9 +2667,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
         }
 
         impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for RegionNameCollector<'tcx> {
-            type BreakTy = ();
-
-            fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+            fn visit_region(&mut self, r: ty::Region<'tcx>) {
                 trace!("address: {:p}", r.0.0);
 
                 // Collect all named lifetimes. These allow us to prevent duplication
@@ -2678,18 +2676,14 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                 if let Some(name) = r.get_name() {
                     self.used_region_names.insert(name);
                 }
-
-                ControlFlow::Continue(())
             }
 
             // We collect types in order to prevent really large types from compiling for
             // a really long time. See issue #83150 for why this is necessary.
-            fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+            fn visit_ty(&mut self, ty: Ty<'tcx>) {
                 let not_previously_inserted = self.type_collector.insert(ty);
                 if not_previously_inserted {
                     ty.super_visit_with(self)
-                } else {
-                    ControlFlow::Continue(())
                 }
             }
         }
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
index 51a4a9f411c..7abc3cd2838 100644
--- a/compiler/rustc_middle/src/ty/region.rs
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -136,6 +136,12 @@ impl<'tcx> Region<'tcx> {
     }
 }
 
+impl<'tcx> rustc_type_ir::new::Region<TyCtxt<'tcx>> for Region<'tcx> {
+    fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
+        Region::new_bound(tcx, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon })
+    }
+}
+
 /// Region utilities
 impl<'tcx> Region<'tcx> {
     pub fn kind(self) -> RegionKind<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index c6805ba9323..c8fb11673cf 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -8,13 +8,14 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
 use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
 use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
+use rustc_ast_ir::try_visit;
+use rustc_ast_ir::visit::VisitorResult;
 use rustc_hir::def::Namespace;
 use rustc_span::source_map::Spanned;
 use rustc_target::abi::TyAndLayout;
 use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, WithInfcx};
 
 use std::fmt::{self, Debug};
-use std::ops::ControlFlow;
 
 use super::print::PrettyPrinter;
 use super::{GenericArg, GenericArgKind, Region};
@@ -482,11 +483,8 @@ impl<'a, 'tcx> Lift<'tcx> for Term<'a> {
 // Traversal implementations.
 
 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::AdtDef<'tcx> {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
-        &self,
-        _visitor: &mut V,
-    ) -> ControlFlow<V::BreakTy> {
-        ControlFlow::Continue(())
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, _visitor: &mut V) -> V::Result {
+        V::Result::output()
     }
 }
 
@@ -500,7 +498,7 @@ impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> TypeFoldable<TyCtxt<'tcx>> for ty::Bin
 }
 
 impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
         visitor.visit_binder(self)
     }
 }
@@ -517,10 +515,7 @@ impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> TypeSuperFoldable<TyCtxt<'tcx>> for ty
 impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeSuperVisitable<TyCtxt<'tcx>>
     for ty::Binder<'tcx, T>
 {
-    fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
-        &self,
-        visitor: &mut V,
-    ) -> ControlFlow<V::BreakTy> {
+    fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
         self.as_ref().skip_binder().visit_with(visitor)
     }
 }
@@ -553,7 +548,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
 }
 
 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
         visitor.visit_ty(*self)
     }
 }
@@ -609,27 +604,24 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
 }
 
 impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
-    fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
-        &self,
-        visitor: &mut V,
-    ) -> ControlFlow<V::BreakTy> {
+    fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
         match self.kind() {
             ty::RawPtr(ref tm) => tm.visit_with(visitor),
             ty::Array(typ, sz) => {
-                typ.visit_with(visitor)?;
+                try_visit!(typ.visit_with(visitor));
                 sz.visit_with(visitor)
             }
             ty::Slice(typ) => typ.visit_with(visitor),
             ty::Adt(_, args) => args.visit_with(visitor),
             ty::Dynamic(ref trait_ty, ref reg, _) => {
-                trait_ty.visit_with(visitor)?;
+                try_visit!(trait_ty.visit_with(visitor));
                 reg.visit_with(visitor)
             }
             ty::Tuple(ts) => ts.visit_with(visitor),
             ty::FnDef(_, args) => args.visit_with(visitor),
             ty::FnPtr(ref f) => f.visit_with(visitor),
             ty::Ref(r, ty, _) => {
-                r.visit_with(visitor)?;
+                try_visit!(r.visit_with(visitor));
                 ty.visit_with(visitor)
             }
             ty::Coroutine(_did, ref args) => args.visit_with(visitor),
@@ -650,7 +642,7 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
             | ty::Placeholder(..)
             | ty::Param(..)
             | ty::Never
-            | ty::Foreign(..) => ControlFlow::Continue(()),
+            | ty::Foreign(..) => V::Result::output(),
         }
     }
 }
@@ -665,7 +657,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Region<'tcx> {
 }
 
 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Region<'tcx> {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
         visitor.visit_region(*self)
     }
 }
@@ -690,13 +682,13 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Clause<'tcx> {
 }
 
 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
         visitor.visit_predicate(*self)
     }
 }
 
 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Clause<'tcx> {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
         visitor.visit_predicate(self.as_predicate())
     }
 }
@@ -712,10 +704,7 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
 }
 
 impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
-    fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
-        &self,
-        visitor: &mut V,
-    ) -> ControlFlow<V::BreakTy> {
+    fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
         self.kind().visit_with(visitor)
     }
 }
@@ -739,7 +728,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
 }
 
 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
         visitor.visit_const(*self)
     }
 }
@@ -771,16 +760,13 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
 }
 
 impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
-    fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
-        &self,
-        visitor: &mut V,
-    ) -> ControlFlow<V::BreakTy> {
-        self.ty().visit_with(visitor)?;
+    fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
+        try_visit!(self.ty().visit_with(visitor));
         match self.kind() {
             ConstKind::Param(p) => p.visit_with(visitor),
             ConstKind::Infer(i) => i.visit_with(visitor),
             ConstKind::Bound(d, b) => {
-                d.visit_with(visitor)?;
+                try_visit!(d.visit_with(visitor));
                 b.visit_with(visitor)
             }
             ConstKind::Placeholder(p) => p.visit_with(visitor),
@@ -802,25 +788,19 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for InferConst {
 }
 
 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for InferConst {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
-        &self,
-        _visitor: &mut V,
-    ) -> ControlFlow<V::BreakTy> {
-        ControlFlow::Continue(())
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, _visitor: &mut V) -> V::Result {
+        V::Result::output()
     }
 }
 
 impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::UnevaluatedConst<'tcx> {
-    fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
-        &self,
-        visitor: &mut V,
-    ) -> ControlFlow<V::BreakTy> {
+    fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
         self.args.visit_with(visitor)
     }
 }
 
 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for TyAndLayout<'tcx, Ty<'tcx>> {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
         visitor.visit_ty(self.ty)
     }
 }
@@ -828,10 +808,9 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for TyAndLayout<'tcx, Ty<'tcx>> {
 impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>> + Debug + Clone> TypeVisitable<TyCtxt<'tcx>>
     for Spanned<T>
 {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.node.visit_with(visitor)?;
-        self.span.visit_with(visitor)?;
-        ControlFlow::Continue(())
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
+        try_visit!(self.node.visit_with(visitor));
+        self.span.visit_with(visitor)
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 53690cc5811..427c0f04bd1 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -13,9 +13,7 @@ use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
 use crate::ty::{List, ParamEnv};
 use hir::def::DefKind;
 use rustc_data_structures::captures::Captures;
-use rustc_errors::{
-    DiagArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan,
-};
+use rustc_errors::{DiagArgValue, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::LangItem;
@@ -1426,7 +1424,8 @@ impl From<BoundVar> for BoundTy {
 
 /// Constructors for `Ty`
 impl<'tcx> Ty<'tcx> {
-    // Avoid this in favour of more specific `new_*` methods, where possible.
+    /// Avoid using this in favour of more specific `new_*` methods, where possible.
+    /// The more specific methods will often optimize their creation.
     #[allow(rustc::usage_of_ty_tykind)]
     #[inline]
     pub fn new(tcx: TyCtxt<'tcx>, st: TyKind<'tcx>) -> Ty<'tcx> {
@@ -1544,7 +1543,7 @@ impl<'tcx> Ty<'tcx> {
     pub fn new_error_with_message<S: Into<MultiSpan>>(
         tcx: TyCtxt<'tcx>,
         span: S,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<Cow<'static, str>>,
     ) -> Ty<'tcx> {
         let reported = tcx.dcx().span_delayed_bug(span, msg);
         Ty::new(tcx, Error(reported))
@@ -1813,6 +1812,12 @@ impl<'tcx> Ty<'tcx> {
     }
 }
 
+impl<'tcx> rustc_type_ir::new::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
+    fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
+        Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon })
+    }
+}
+
 /// Type utilities
 impl<'tcx> Ty<'tcx> {
     #[inline(always)]
@@ -1994,6 +1999,27 @@ impl<'tcx> Ty<'tcx> {
         }
     }
 
+    /// Tests whether this is a Box using the global allocator.
+    #[inline]
+    pub fn is_box_global(self, tcx: TyCtxt<'tcx>) -> bool {
+        match self.kind() {
+            Adt(def, args) if def.is_box() => {
+                let Some(alloc) = args.get(1) else {
+                    // Single-argument Box is always global. (for "minicore" tests)
+                    return true;
+                };
+                if let Some(alloc_adt) = alloc.expect_ty().ty_adt_def() {
+                    let global_alloc = tcx.require_lang_item(LangItem::GlobalAlloc, None);
+                    alloc_adt.did() == global_alloc
+                } else {
+                    // Allocator is not an ADT...
+                    false
+                }
+            }
+            _ => false,
+        }
+    }
+
     /// Panics if called on any type other than `Box<T>`.
     pub fn boxed_ty(self) -> Ty<'tcx> {
         match self.kind() {
@@ -2108,9 +2134,9 @@ impl<'tcx> Ty<'tcx> {
         struct ContainsTyVisitor<'tcx>(Ty<'tcx>);
 
         impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTyVisitor<'tcx> {
-            type BreakTy = ();
+            type Result = ControlFlow<()>;
 
-            fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+            fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
                 if self.0 == t { ControlFlow::Break(()) } else { t.super_visit_with(self) }
             }
         }
@@ -2126,9 +2152,9 @@ impl<'tcx> Ty<'tcx> {
         struct ContainsClosureVisitor;
 
         impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsClosureVisitor {
-            type BreakTy = ();
+            type Result = ControlFlow<()>;
 
-            fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+            fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
                 if let ty::Closure(..) = t.kind() {
                     ControlFlow::Break(())
                 } else {
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 5ead620927c..4bb0d2c7d1c 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -19,7 +19,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_macros::HashStable;
 use rustc_session::Limit;
-use rustc_span::{sym, Symbol};
+use rustc_span::sym;
 use rustc_target::abi::{Integer, IntegerType, Primitive, Size};
 use rustc_target::spec::abi::Abi;
 use smallvec::SmallVec;
@@ -1641,12 +1641,15 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
         .any(|items| items.iter().any(|item| item.has_name(sym::notable_trait)))
 }
 
-/// Determines whether an item is an intrinsic by Abi. or by whether it has a `rustc_intrinsic` attribute
-pub fn intrinsic(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<Symbol> {
+/// Determines whether an item is an intrinsic (which may be via Abi or via the `rustc_intrinsic` attribute)
+pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::IntrinsicDef> {
     if matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic)
         || tcx.has_attr(def_id, sym::rustc_intrinsic)
     {
-        Some(tcx.item_name(def_id.into()))
+        Some(ty::IntrinsicDef {
+            name: tcx.item_name(def_id.into()),
+            must_be_overridden: tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden),
+        })
     } else {
         None
     }
@@ -1657,7 +1660,7 @@ pub fn provide(providers: &mut Providers) {
         reveal_opaque_types_in_bounds,
         is_doc_hidden,
         is_doc_notable_trait,
-        intrinsic,
+        intrinsic_raw,
         ..*providers
     }
 }
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 59d09c3dc78..218567bbd59 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -64,19 +64,19 @@ impl<'tcx> TyCtxt<'tcx> {
         where
             F: FnMut(ty::Region<'tcx>) -> bool,
         {
-            type BreakTy = ();
+            type Result = ControlFlow<()>;
 
             fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
                 &mut self,
                 t: &Binder<'tcx, T>,
-            ) -> ControlFlow<Self::BreakTy> {
+            ) -> Self::Result {
                 self.outer_index.shift_in(1);
                 let result = t.super_visit_with(self);
                 self.outer_index.shift_out(1);
                 result
             }
 
-            fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+            fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
                 match *r {
                     ty::ReBound(debruijn, _) if debruijn < self.outer_index => {
                         ControlFlow::Continue(())
@@ -91,7 +91,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 }
             }
 
-            fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+            fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
                 // We're only interested in types involving regions
                 if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) {
                     ty.super_visit_with(self)
@@ -140,8 +140,7 @@ impl<'tcx> TyCtxt<'tcx> {
         let mut collector = LateBoundRegionsCollector::new(just_constrained);
         let value = value.skip_binder();
         let value = if just_constrained { self.expand_weak_alias_tys(value) } else { value };
-        let result = value.visit_with(&mut collector);
-        assert!(result.is_continue()); // should never have stopped early
+        value.visit_with(&mut collector);
         collector.regions
     }
 }
@@ -165,19 +164,19 @@ impl<'tcx> ValidateBoundVars<'tcx> {
 }
 
 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> {
-    type BreakTy = ();
+    type Result = ControlFlow<()>;
 
     fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
         &mut self,
         t: &Binder<'tcx, T>,
-    ) -> ControlFlow<Self::BreakTy> {
+    ) -> Self::Result {
         self.binder_index.shift_in(1);
         let result = t.super_visit_with(self);
         self.binder_index.shift_out(1);
         result
     }
 
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
         if t.outer_exclusive_binder() < self.binder_index
             || !self.visited.insert((self.binder_index, t))
         {
@@ -211,7 +210,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> {
         t.super_visit_with(self)
     }
 
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
         match *r {
             ty::ReBound(index, br) if index == self.binder_index => {
                 if self.bound_vars.len() <= br.var.as_usize() {
@@ -266,23 +265,19 @@ impl LateBoundRegionsCollector {
 }
 
 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector {
-    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
-        &mut self,
-        t: &Binder<'tcx, T>,
-    ) -> ControlFlow<Self::BreakTy> {
+    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &Binder<'tcx, T>) {
         self.current_index.shift_in(1);
-        let result = t.super_visit_with(self);
+        t.super_visit_with(self);
         self.current_index.shift_out(1);
-        result
     }
 
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, t: Ty<'tcx>) {
         if self.just_constrained {
             match t.kind() {
                 // If we are only looking for "constrained" regions, we have to ignore the
                 // inputs to a projection as they may not appear in the normalized form.
                 ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) => {
-                    return ControlFlow::Continue(());
+                    return;
                 }
                 // All weak alias types should've been expanded beforehand.
                 ty::Alias(ty::Weak, _) => bug!("unexpected weak alias type"),
@@ -293,26 +288,25 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector {
         t.super_visit_with(self)
     }
 
-    fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_const(&mut self, c: ty::Const<'tcx>) {
         // if we are only looking for "constrained" region, we have to
         // ignore the inputs of an unevaluated const, as they may not appear
         // in the normalized form
         if self.just_constrained {
             if let ty::ConstKind::Unevaluated(..) = c.kind() {
-                return ControlFlow::Continue(());
+                return;
             }
         }
 
         c.super_visit_with(self)
     }
 
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_region(&mut self, r: ty::Region<'tcx>) {
         if let ty::ReBound(debruijn, br) = *r {
             if debruijn == self.current_index {
                 self.regions.insert(br.kind);
             }
         }
-        ControlFlow::Continue(())
     }
 }
 
@@ -332,7 +326,7 @@ impl MaxUniverse {
 }
 
 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxUniverse {
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, t: Ty<'tcx>) {
         if let ty::Placeholder(placeholder) = t.kind() {
             self.max_universe = ty::UniverseIndex::from_u32(
                 self.max_universe.as_u32().max(placeholder.universe.as_u32()),
@@ -342,7 +336,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxUniverse {
         t.super_visit_with(self)
     }
 
-    fn visit_const(&mut self, c: ty::consts::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_const(&mut self, c: ty::consts::Const<'tcx>) {
         if let ty::ConstKind::Placeholder(placeholder) = c.kind() {
             self.max_universe = ty::UniverseIndex::from_u32(
                 self.max_universe.as_u32().max(placeholder.universe.as_u32()),
@@ -352,13 +346,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxUniverse {
         c.super_visit_with(self)
     }
 
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_region(&mut self, r: ty::Region<'tcx>) {
         if let ty::RePlaceholder(placeholder) = *r {
             self.max_universe = ty::UniverseIndex::from_u32(
                 self.max_universe.as_u32().max(placeholder.universe.as_u32()),
             );
         }
-
-        ControlFlow::Continue(())
     }
 }
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 27b48f46e75..f7a3879a7d4 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -131,6 +131,27 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::EarlyBinder<ty::Binder<'_, ty::FnSig<'_>>
     }
 }
 
+impl<'tcx> Value<TyCtxt<'tcx>> for &[ty::Variance] {
+    fn from_cycle_error(
+        tcx: TyCtxt<'tcx>,
+        cycle_error: &CycleError,
+        _guar: ErrorGuaranteed,
+    ) -> Self {
+        if let Some(frame) = cycle_error.cycle.get(0)
+            && frame.query.dep_kind == dep_kinds::variances_of
+            && let Some(def_id) = frame.query.def_id
+        {
+            let n = tcx.generics_of(def_id).params.len();
+            vec![ty::Variance::Bivariant; n].leak()
+        } else {
+            span_bug!(
+                cycle_error.usage.as_ref().unwrap().0,
+                "only `variances_of` returns `&[ty::Variance]`"
+            );
+        }
+    }
+}
+
 // Take a cycle of `Q` and try `try_cycle` on every permutation, falling back to `otherwise`.
 fn search_for_cycle_permutation<Q, T>(
     cycle: &[Q],
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index f2cf6fe613c..b4eeeccc127 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -58,52 +58,60 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 this.thir[scrutinee].span,
             ),
             ExprKind::If { cond, then, else_opt, if_then_scope } => {
-                let then_blk;
                 let then_span = this.thir[then].span;
                 let then_source_info = this.source_info(then_span);
                 let condition_scope = this.local_scope();
 
-                let mut else_blk = unpack!(
-                    then_blk = this.in_scope(
-                        (if_then_scope, then_source_info),
-                        LintLevel::Inherited,
-                        |this| {
-                            let source_info = if this.is_let(cond) {
-                                let variable_scope =
-                                    this.new_source_scope(then_span, LintLevel::Inherited, None);
-                                this.source_scope = variable_scope;
-                                SourceInfo { span: then_span, scope: variable_scope }
-                            } else {
-                                this.source_info(then_span)
-                            };
-                            let (then_block, else_block) =
-                                this.in_if_then_scope(condition_scope, then_span, |this| {
-                                    let then_blk = unpack!(this.then_else_break(
-                                        block,
-                                        cond,
-                                        Some(condition_scope),
-                                        condition_scope,
-                                        source_info,
-                                        true,
-                                    ));
+                let then_and_else_blocks = this.in_scope(
+                    (if_then_scope, then_source_info),
+                    LintLevel::Inherited,
+                    |this| {
+                        // FIXME: Does this need extra logic to handle let-chains?
+                        let source_info = if this.is_let(cond) {
+                            let variable_scope =
+                                this.new_source_scope(then_span, LintLevel::Inherited, None);
+                            this.source_scope = variable_scope;
+                            SourceInfo { span: then_span, scope: variable_scope }
+                        } else {
+                            this.source_info(then_span)
+                        };
 
-                                    this.expr_into_dest(destination, then_blk, then)
-                                });
-                            then_block.and(else_block)
-                        },
-                    )
+                        // Lower the condition, and have it branch into `then` and `else` blocks.
+                        let (then_block, else_block) =
+                            this.in_if_then_scope(condition_scope, then_span, |this| {
+                                let then_blk = unpack!(this.then_else_break(
+                                    block,
+                                    cond,
+                                    Some(condition_scope), // Temp scope
+                                    source_info,
+                                    true, // Declare `let` bindings normally
+                                ));
+
+                                // Lower the `then` arm into its block.
+                                this.expr_into_dest(destination, then_blk, then)
+                            });
+
+                        // Pack `(then_block, else_block)` into `BlockAnd<BasicBlock>`.
+                        then_block.and(else_block)
+                    },
                 );
 
-                else_blk = if let Some(else_opt) = else_opt {
-                    unpack!(this.expr_into_dest(destination, else_blk, else_opt))
+                // Unpack `BlockAnd<BasicBlock>` into `(then_blk, else_blk)`.
+                let (then_blk, mut else_blk);
+                else_blk = unpack!(then_blk = then_and_else_blocks);
+
+                // If there is an `else` arm, lower it into `else_blk`.
+                if let Some(else_expr) = else_opt {
+                    unpack!(else_blk = this.expr_into_dest(destination, else_blk, else_expr));
                 } else {
-                    // Body of the `if` expression without an `else` clause must return `()`, thus
-                    // we implicitly generate an `else {}` if it is not specified.
+                    // There is no `else` arm, so we know both arms have type `()`.
+                    // Generate the implicit `else {}` by assigning unit.
                     let correct_si = this.source_info(expr_span.shrink_to_hi());
                     this.cfg.push_assign_unit(else_blk, correct_si, destination, this.tcx);
-                    else_blk
-                };
+                }
 
+                // The `then` and `else` arms have been lowered into their respective
+                // blocks, so make both of them meet up in a new block.
                 let join_block = this.cfg.start_new_block();
                 this.cfg.goto(then_blk, source_info, join_block);
                 this.cfg.goto(else_blk, source_info, join_block);
@@ -146,9 +154,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         this.then_else_break(
                             block,
                             lhs,
-                            Some(condition_scope),
-                            condition_scope,
+                            Some(condition_scope), // Temp scope
                             source_info,
+                            // This flag controls how inner `let` expressions are lowered,
+                            // but either way there shouldn't be any of those in here.
                             true,
                         )
                     });
@@ -374,6 +383,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 line_spans,
             }) => {
                 use rustc_middle::{mir, thir};
+
+                let destination_block = this.cfg.start_new_block();
+                let mut targets = if options.contains(InlineAsmOptions::NORETURN) {
+                    vec![]
+                } else {
+                    vec![destination_block]
+                };
+
                 let operands = operands
                     .into_iter()
                     .map(|op| match *op {
@@ -429,14 +446,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         thir::InlineAsmOperand::SymStatic { def_id } => {
                             mir::InlineAsmOperand::SymStatic { def_id }
                         }
+                        thir::InlineAsmOperand::Label { block } => {
+                            let target = this.cfg.start_new_block();
+                            let target_index = targets.len();
+                            targets.push(target);
+
+                            let tmp = this.get_unit_temp();
+                            let target = unpack!(this.ast_block(tmp, target, block, source_info));
+                            this.cfg.terminate(
+                                target,
+                                source_info,
+                                TerminatorKind::Goto { target: destination_block },
+                            );
+
+                            mir::InlineAsmOperand::Label { target_index }
+                        }
                     })
                     .collect();
 
-                if !options.contains(InlineAsmOptions::NORETURN) {
+                if !expr.ty.is_never() {
                     this.cfg.push_assign_unit(block, source_info, destination, this.tcx);
                 }
 
-                let destination_block = this.cfg.start_new_block();
                 this.cfg.terminate(
                     block,
                     source_info,
@@ -445,11 +476,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         operands,
                         options,
                         line_spans,
-                        destination: if options.contains(InlineAsmOptions::NORETURN) {
-                            None
-                        } else {
-                            Some(destination_block)
-                        },
+                        targets,
                         unwind: if options.contains(InlineAsmOptions::MAY_UNWIND) {
                             UnwindAction::Continue
                         } else {
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index a6273b92e5d..31591983101 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -30,21 +30,46 @@ mod util;
 use std::borrow::Borrow;
 use std::mem;
 
+/// Arguments to [`Builder::then_else_break_inner`] that are usually forwarded
+/// to recursive invocations.
+#[derive(Clone, Copy)]
+struct ThenElseArgs {
+    /// Used as the temp scope for lowering `expr`. If absent (for match guards),
+    /// `self.local_scope()` is used.
+    temp_scope_override: Option<region::Scope>,
+    variable_source_info: SourceInfo,
+    /// Forwarded to [`Builder::lower_let_expr`] when lowering [`ExprKind::Let`].
+    /// When false (for match guards), `let` bindings won't be declared.
+    declare_let_bindings: bool,
+}
+
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Lowers a condition in a way that ensures that variables bound in any let
     /// expressions are definitely initialized in the if body.
     ///
-    /// If `declare_bindings` is false then variables created in `let`
+    /// If `declare_let_bindings` is false then variables created in `let`
     /// expressions will not be declared. This is for if let guards on arms with
     /// an or pattern, where the guard is lowered multiple times.
     pub(crate) fn then_else_break(
         &mut self,
-        mut block: BasicBlock,
+        block: BasicBlock,
         expr_id: ExprId,
         temp_scope_override: Option<region::Scope>,
-        break_scope: region::Scope,
         variable_source_info: SourceInfo,
-        declare_bindings: bool,
+        declare_let_bindings: bool,
+    ) -> BlockAnd<()> {
+        self.then_else_break_inner(
+            block,
+            expr_id,
+            ThenElseArgs { temp_scope_override, variable_source_info, declare_let_bindings },
+        )
+    }
+
+    fn then_else_break_inner(
+        &mut self,
+        block: BasicBlock, // Block that the condition and branch will be lowered into
+        expr_id: ExprId,   // Condition expression to lower
+        args: ThenElseArgs,
     ) -> BlockAnd<()> {
         let this = self;
         let expr = &this.thir[expr_id];
@@ -52,54 +77,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
         match expr.kind {
             ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } => {
-                let lhs_then_block = unpack!(this.then_else_break(
-                    block,
-                    lhs,
-                    temp_scope_override,
-                    break_scope,
-                    variable_source_info,
-                    declare_bindings,
-                ));
-
-                let rhs_then_block = unpack!(this.then_else_break(
-                    lhs_then_block,
-                    rhs,
-                    temp_scope_override,
-                    break_scope,
-                    variable_source_info,
-                    declare_bindings,
-                ));
-
+                let lhs_then_block = unpack!(this.then_else_break_inner(block, lhs, args));
+                let rhs_then_block = unpack!(this.then_else_break_inner(lhs_then_block, rhs, args));
                 rhs_then_block.unit()
             }
             ExprKind::LogicalOp { op: LogicalOp::Or, lhs, rhs } => {
                 let local_scope = this.local_scope();
                 let (lhs_success_block, failure_block) =
                     this.in_if_then_scope(local_scope, expr_span, |this| {
-                        this.then_else_break(
+                        this.then_else_break_inner(
                             block,
                             lhs,
-                            temp_scope_override,
-                            local_scope,
-                            variable_source_info,
-                            true,
+                            ThenElseArgs { declare_let_bindings: true, ..args },
                         )
                     });
-                let rhs_success_block = unpack!(this.then_else_break(
+                let rhs_success_block = unpack!(this.then_else_break_inner(
                     failure_block,
                     rhs,
-                    temp_scope_override,
-                    break_scope,
-                    variable_source_info,
-                    true,
+                    ThenElseArgs { declare_let_bindings: true, ..args },
                 ));
 
                 // Make the LHS and RHS success arms converge to a common block.
                 // (We can't just make LHS goto RHS, because `rhs_success_block`
                 // might contain statements that we don't want on the LHS path.)
                 let success_block = this.cfg.start_new_block();
-                this.cfg.goto(lhs_success_block, variable_source_info, success_block);
-                this.cfg.goto(rhs_success_block, variable_source_info, success_block);
+                this.cfg.goto(lhs_success_block, args.variable_source_info, success_block);
+                this.cfg.goto(rhs_success_block, args.variable_source_info, success_block);
                 success_block.unit()
             }
             ExprKind::Unary { op: UnOp::Not, arg } => {
@@ -111,50 +114,33 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         if this.tcx.sess.instrument_coverage() {
                             this.cfg.push_coverage_span_marker(block, this.source_info(expr_span));
                         }
-                        this.then_else_break(
+                        this.then_else_break_inner(
                             block,
                             arg,
-                            temp_scope_override,
-                            local_scope,
-                            variable_source_info,
-                            true,
+                            ThenElseArgs { declare_let_bindings: true, ..args },
                         )
                     });
-                this.break_for_else(success_block, break_scope, variable_source_info);
+                this.break_for_else(success_block, args.variable_source_info);
                 failure_block.unit()
             }
             ExprKind::Scope { region_scope, lint_level, value } => {
                 let region_scope = (region_scope, this.source_info(expr_span));
                 this.in_scope(region_scope, lint_level, |this| {
-                    this.then_else_break(
-                        block,
-                        value,
-                        temp_scope_override,
-                        break_scope,
-                        variable_source_info,
-                        declare_bindings,
-                    )
+                    this.then_else_break_inner(block, value, args)
                 })
             }
-            ExprKind::Use { source } => this.then_else_break(
-                block,
-                source,
-                temp_scope_override,
-                break_scope,
-                variable_source_info,
-                declare_bindings,
-            ),
+            ExprKind::Use { source } => this.then_else_break_inner(block, source, args),
             ExprKind::Let { expr, ref pat } => this.lower_let_expr(
                 block,
                 expr,
                 pat,
-                break_scope,
-                Some(variable_source_info.scope),
-                variable_source_info.span,
-                declare_bindings,
+                Some(args.variable_source_info.scope),
+                args.variable_source_info.span,
+                args.declare_let_bindings,
             ),
             _ => {
-                let temp_scope = temp_scope_override.unwrap_or_else(|| this.local_scope());
+                let mut block = block;
+                let temp_scope = args.temp_scope_override.unwrap_or_else(|| this.local_scope());
                 let mutability = Mutability::Mut;
                 let place =
                     unpack!(block = this.as_temp(block, Some(temp_scope), expr_id, mutability));
@@ -166,7 +152,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                 let source_info = this.source_info(expr_span);
                 this.cfg.terminate(block, source_info, term);
-                this.break_for_else(else_block, break_scope, source_info);
+                this.break_for_else(else_block, source_info);
 
                 then_block.unit()
             }
@@ -1907,7 +1893,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         mut block: BasicBlock,
         expr_id: ExprId,
         pat: &Pat<'tcx>,
-        else_target: region::Scope,
         source_scope: Option<SourceScope>,
         span: Span,
         declare_bindings: bool,
@@ -1929,7 +1914,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let expr_place = expr_place_builder.try_to_place(self);
         let opt_expr_place = expr_place.as_ref().map(|place| (Some(place), expr_span));
         let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap();
-        self.break_for_else(otherwise_post_guard_block, else_target, self.source_info(expr_span));
+        self.break_for_else(otherwise_post_guard_block, self.source_info(expr_span));
 
         if declare_bindings {
             self.declare_bindings(source_scope, pat.span.to(span), pat, None, opt_expr_place);
@@ -2105,10 +2090,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     this.then_else_break(
                         block,
                         guard,
-                        None,
-                        match_scope,
+                        None, // Use `self.local_scope()` as the temp scope
                         this.source_info(arm.span),
-                        false,
+                        false, // For guards, `let` bindings are declared separately
                     )
                 });
 
@@ -2439,7 +2423,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 None,
                 true,
             );
-            this.break_for_else(failure, *let_else_scope, this.source_info(initializer_span));
+            this.break_for_else(failure, this.source_info(initializer_span));
             matching.unit()
         });
         matching.and(failure)
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 04740a96291..961502566ba 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -683,20 +683,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.cfg.start_new_block().unit()
     }
 
-    pub(crate) fn break_for_else(
-        &mut self,
-        block: BasicBlock,
-        target: region::Scope,
-        source_info: SourceInfo,
-    ) {
-        let scope_index = self.scopes.scope_index(target, source_info.span);
+    /// Sets up the drops for breaking from `block` due to an `if` condition
+    /// that turned out to be false.
+    ///
+    /// Must be called in the context of [`Builder::in_if_then_scope`], so that
+    /// there is an if-then scope to tell us what the target scope is.
+    pub(crate) fn break_for_else(&mut self, block: BasicBlock, source_info: SourceInfo) {
         let if_then_scope = self
             .scopes
             .if_then_scope
-            .as_mut()
+            .as_ref()
             .unwrap_or_else(|| span_bug!(source_info.span, "no if-then scope found"));
 
-        assert_eq!(if_then_scope.region_scope, target, "breaking to incorrect scope");
+        let target = if_then_scope.region_scope;
+        let scope_index = self.scopes.scope_index(target, source_info.span);
+
+        // Upgrade `if_then_scope` to `&mut`.
+        let if_then_scope = self.scopes.if_then_scope.as_mut().expect("upgrading & to &mut");
 
         let mut drop_idx = ROOT_NODE;
         let drops = &mut if_then_scope.else_drops;
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index d889f89f281..9a298a13eb6 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -2,7 +2,7 @@ use crate::fluent_generated as fluent;
 use rustc_errors::DiagArgValue;
 use rustc_errors::{
     codes::*, AddToDiagnostic, Applicability, Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic,
-    Level, MultiSpan, SubdiagnosticMessageOp,
+    Level, MultiSpan, SubdiagMessageOp,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::{self, Ty};
@@ -420,7 +420,7 @@ pub struct UnsafeNotInheritedLintNote {
 }
 
 impl AddToDiagnostic for UnsafeNotInheritedLintNote {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -868,7 +868,7 @@ pub struct Variant {
 }
 
 impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs
index 3f2b7c482a6..2c817d605af 100644
--- a/compiler/rustc_mir_build/src/lints.rs
+++ b/compiler/rustc_mir_build/src/lints.rs
@@ -199,9 +199,10 @@ impl<'mir, 'tcx, C: TerminatorClassifier<'tcx>> TriColorVisitor<BasicBlocks<'tcx
             | TerminatorKind::Unreachable
             | TerminatorKind::Yield { .. } => ControlFlow::Break(NonRecursive),
 
-            // A diverging InlineAsm is treated as non-recursing
-            TerminatorKind::InlineAsm { destination, .. } => {
-                if destination.is_some() {
+            // A InlineAsm without targets (diverging and contains no labels)
+            // is treated as non-recursing.
+            TerminatorKind::InlineAsm { ref targets, .. } => {
+                if !targets.is_empty() {
                     ControlFlow::Continue(())
                 } else {
                     ControlFlow::Break(NonRecursive)
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 62762168cf4..2318e84292b 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -656,6 +656,9 @@ impl<'tcx> Cx<'tcx> {
                         hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
                             InlineAsmOperand::SymStatic { def_id }
                         }
+                        hir::InlineAsmOperand::Label { block } => {
+                            InlineAsmOperand::Label { block: self.mirror_block(block) }
+                        }
                     })
                     .collect(),
                 options: asm.options,
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index 267ea3aa3e1..d53704f89e7 100644
--- a/compiler/rustc_mir_build/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -889,6 +889,12 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
                 print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
                 print_indented!(self, "}", depth_lvl + 1);
             }
+            InlineAsmOperand::Label { block } => {
+                print_indented!(self, "InlineAsmOperand::Block {", depth_lvl);
+                print_indented!(self, "block:", depth_lvl + 1);
+                self.print_block(*block, depth_lvl + 2);
+                print_indented!(self, "}", depth_lvl + 1);
+            }
         }
     }
 }
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index 4c3fadf487b..f57e8b8bd6f 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -242,9 +242,9 @@ impl Direction for Backward {
                     propagate(pred, &tmp);
                 }
 
-                mir::TerminatorKind::InlineAsm {
-                    destination: Some(dest), ref operands, ..
-                } if dest == bb => {
+                mir::TerminatorKind::InlineAsm { ref targets, ref operands, .. }
+                    if targets.contains(&bb) =>
+                {
                     let mut tmp = exit_state.clone();
                     analysis.apply_call_return_effect(
                         &mut tmp,
@@ -491,9 +491,12 @@ impl Direction for Forward {
                 if let Some(cleanup) = cleanup {
                     propagate(cleanup, exit_state);
                 }
-                if let Some(return_) = return_ {
+
+                if !return_.is_empty() {
                     analysis.apply_call_return_effect(exit_state, bb, place);
-                    propagate(return_, exit_state);
+                    for &target in return_ {
+                        propagate(target, exit_state);
+                    }
                 }
             }
             TerminatorEdges::SwitchInt { targets, discr } => {
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index 0270e059a58..a827f6a8dbd 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -299,7 +299,9 @@ where
                 })?;
             }
 
-            mir::TerminatorKind::InlineAsm { destination: Some(_), ref operands, .. } => {
+            mir::TerminatorKind::InlineAsm { ref targets, ref operands, .. }
+                if !targets.is_empty() =>
+            {
                 self.write_row(w, "", "(on successful return)", |this, w, fmt| {
                     let state_on_unwind = this.results.get().clone();
                     this.results.apply_custom_effect(|analysis, state| {
diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
index 595c2ff5bf7..29169c31263 100644
--- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
@@ -271,7 +271,8 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
                         InlineAsmOperand::In { .. }
                         | InlineAsmOperand::Const { .. }
                         | InlineAsmOperand::SymFn { .. }
-                        | InlineAsmOperand::SymStatic { .. } => {}
+                        | InlineAsmOperand::SymStatic { .. }
+                        | InlineAsmOperand::Label { .. } => {}
                     }
                 }
             }
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index c6ec1b5aee4..db48ecd702b 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -491,7 +491,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
                 ref operands,
                 options: _,
                 line_spans: _,
-                destination: _,
+                targets: _,
                 unwind: _,
             } => {
                 for op in operands {
@@ -515,7 +515,8 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
                         }
                         InlineAsmOperand::Const { value: _ }
                         | InlineAsmOperand::SymFn { value: _ }
-                        | InlineAsmOperand::SymStatic { def_id: _ } => {}
+                        | InlineAsmOperand::SymStatic { def_id: _ }
+                        | InlineAsmOperand::Label { target_index: _ } => {}
                     }
                 }
             }
diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
index 1575f31e75e..d7e3c91b875 100644
--- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs
+++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
@@ -202,7 +202,7 @@ impl PeekCall {
             &terminator.kind
         {
             if let ty::FnDef(def_id, fn_args) = *func.const_.ty().kind() {
-                if tcx.intrinsic(def_id)? != sym::rustc_peek {
+                if tcx.intrinsic(def_id)?.name != sym::rustc_peek {
                     return None;
                 }
 
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index c97192435ce..ed8c4d8283d 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -349,12 +349,20 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera
         | FalseUnwind { real_target: target, .. }
         | Goto { target } => CoverageSuccessors::Chainable(target),
 
-        // These terminators can normally be chained, except when they have no
+        // A call terminator can normally be chained, except when they have no
         // successor because they are known to diverge.
-        Call { target: maybe_target, .. } | InlineAsm { destination: maybe_target, .. } => {
-            match maybe_target {
-                Some(target) => CoverageSuccessors::Chainable(target),
-                None => CoverageSuccessors::NotChainable(&[]),
+        Call { target: maybe_target, .. } => match maybe_target {
+            Some(target) => CoverageSuccessors::Chainable(target),
+            None => CoverageSuccessors::NotChainable(&[]),
+        },
+
+        // An inline asm terminator can normally be chained, except when it diverges or uses asm
+        // goto.
+        InlineAsm { ref targets, .. } => {
+            if targets.len() == 1 {
+                CoverageSuccessors::Chainable(targets[0])
+            } else {
+                CoverageSuccessors::NotChainable(targets)
             }
         }
 
diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs
index d9a3c0cb162..569998de35e 100644
--- a/compiler/rustc_mir_transform/src/coverage/tests.rs
+++ b/compiler/rustc_mir_transform/src/coverage/tests.rs
@@ -88,7 +88,6 @@ impl<'tcx> MockBlocks<'tcx> {
             | TerminatorKind::FalseEdge { real_target: ref mut target, .. }
             | TerminatorKind::FalseUnwind { real_target: ref mut target, .. }
             | TerminatorKind::Goto { ref mut target }
-            | TerminatorKind::InlineAsm { destination: Some(ref mut target), .. }
             | TerminatorKind::Yield { resume: ref mut target, .. } => *target = to_block,
             ref invalid => bug!("Invalid from_block: {:?}", invalid),
         }
@@ -185,10 +184,12 @@ fn debug_basic_blocks(mir_body: &Body<'_>) -> String {
                     | TerminatorKind::FalseEdge { real_target: target, .. }
                     | TerminatorKind::FalseUnwind { real_target: target, .. }
                     | TerminatorKind::Goto { target }
-                    | TerminatorKind::InlineAsm { destination: Some(target), .. }
                     | TerminatorKind::Yield { resume: target, .. } => {
                         format!("{}{:?}:{} -> {:?}", sp, bb, kind.name(), target)
                     }
+                    TerminatorKind::InlineAsm { targets, .. } => {
+                        format!("{}{:?}:{} -> {:?}", sp, bb, kind.name(), targets)
+                    }
                     TerminatorKind::SwitchInt { targets, .. } => {
                         format!("{}{:?}:{} -> {:?}", sp, bb, kind.name(), targets)
                     }
diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
index 483fd753e70..07e6ecccaa4 100644
--- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs
+++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
@@ -23,6 +23,10 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
         return false;
     }
 
+    if tcx.intrinsic(def_id).is_some_and(|i| i.must_be_overridden) {
+        return false;
+    }
+
     // This just reproduces the logic from Instance::requires_inline.
     match tcx.def_kind(def_id) {
         DefKind::Ctor(..) | DefKind::Closure => return true,
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 6e635529d96..19109735d48 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -36,7 +36,7 @@ pub(crate) macro throw_machine_stop_str($($tt:tt)*) {{
     }
 
     impl rustc_middle::mir::interpret::MachineStopType for Zst {
-        fn diagnostic_message(&self) -> rustc_errors::DiagnosticMessage {
+        fn diagnostic_message(&self) -> rustc_errors::DiagMessage {
             self.to_string().into()
         }
 
@@ -929,7 +929,7 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm
         _instance: ty::Instance<'tcx>,
         _abi: rustc_target::spec::abi::Abi,
         _args: &[rustc_const_eval::interpret::FnArg<'tcx, Self::Provenance>],
-        _destination: &rustc_const_eval::interpret::PlaceTy<'tcx, Self::Provenance>,
+        _destination: &rustc_const_eval::interpret::MPlaceTy<'tcx, Self::Provenance>,
         _target: Option<BasicBlock>,
         _unwind: UnwindAction,
     ) -> interpret::InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> {
@@ -947,7 +947,7 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _instance: ty::Instance<'tcx>,
         _args: &[rustc_const_eval::interpret::OpTy<'tcx, Self::Provenance>],
-        _destination: &rustc_const_eval::interpret::PlaceTy<'tcx, Self::Provenance>,
+        _destination: &rustc_const_eval::interpret::MPlaceTy<'tcx, Self::Provenance>,
         _target: Option<BasicBlock>,
         _unwind: UnwindAction,
     ) -> interpret::InterpResult<'tcx> {
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 2c8201b1903..10fea09531a 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -648,7 +648,8 @@ impl WriteInfo {
                         }
                         InlineAsmOperand::Const { .. }
                         | InlineAsmOperand::SymFn { .. }
-                        | InlineAsmOperand::SymStatic { .. } => (),
+                        | InlineAsmOperand::SymStatic { .. }
+                        | InlineAsmOperand::Label { .. } => {}
                     }
                 }
             }
diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs
index f3eff247bc7..80e9172bbe1 100644
--- a/compiler/rustc_mir_transform/src/errors.rs
+++ b/compiler/rustc_mir_transform/src/errors.rs
@@ -1,7 +1,7 @@
 use std::borrow::Cow;
 
 use rustc_errors::{
-    codes::*, Applicability, DecorateLint, Diag, DiagArgValue, DiagCtxt, DiagnosticMessage,
+    codes::*, Applicability, DecorateLint, Diag, DiagArgValue, DiagCtxt, DiagMessage,
     EmissionGuarantee, IntoDiagnostic, Level,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@@ -149,7 +149,7 @@ impl RequiresUnsafeDetail {
         }
     }
 
-    fn label(&self) -> DiagnosticMessage {
+    fn label(&self) -> DiagMessage {
         use UnsafetyViolationDetails::*;
         match self.violation {
             CallToUnsafeFunction => fluent::mir_transform_call_to_unsafe_label,
@@ -199,7 +199,7 @@ impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn {
         }
     }
 
-    fn msg(&self) -> DiagnosticMessage {
+    fn msg(&self) -> DiagMessage {
         fluent::mir_transform_unsafe_op_in_unsafe_fn
     }
 }
@@ -224,7 +224,7 @@ impl<'a, P: std::fmt::Debug> DecorateLint<'a, ()> for AssertLint<P> {
         diag.span_label(self.span, message);
     }
 
-    fn msg(&self) -> DiagnosticMessage {
+    fn msg(&self) -> DiagMessage {
         match self.lint_kind {
             AssertLintKind::ArithmeticOverflow => fluent::mir_transform_arithmetic_overflow,
             AssertLintKind::UnconditionalPanic => fluent::mir_transform_operation_will_panic,
@@ -281,7 +281,7 @@ impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> {
         diag.arg("post", self.post);
     }
 
-    fn msg(&self) -> rustc_errors::DiagnosticMessage {
+    fn msg(&self) -> rustc_errors::DiagMessage {
         fluent::mir_transform_must_not_suspend
     }
 }
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 36546a03cdf..f6a0945c222 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -1036,8 +1036,8 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
             {
                 bug!("False unwinds should have been removed before inlining")
             }
-            TerminatorKind::InlineAsm { ref mut destination, ref mut unwind, .. } => {
-                if let Some(ref mut tgt) = *destination {
+            TerminatorKind::InlineAsm { ref mut targets, ref mut unwind, .. } => {
+                for tgt in targets.iter_mut() {
                     *tgt = self.map_block(*tgt);
                 }
                 *unwind = self.map_unwind(*unwind);
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 73102a5f026..6b33d81c1c4 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -323,8 +323,8 @@ fn resolve_rust_intrinsic<'tcx>(
     func_ty: Ty<'tcx>,
 ) -> Option<(Symbol, GenericArgsRef<'tcx>)> {
     if let ty::FnDef(def_id, args) = *func_ty.kind() {
-        let name = tcx.intrinsic(def_id)?;
-        return Some((name, args));
+        let intrinsic = tcx.intrinsic(def_id)?;
+        return Some((intrinsic.name, args));
     }
     None
 }
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 945c3c662a6..cd9b98e4f32 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -160,7 +160,7 @@ fn remap_mir_for_const_eval_select<'tcx>(
                 fn_span,
                 ..
             } if let ty::FnDef(def_id, _) = *const_.ty().kind()
-                && matches!(tcx.intrinsic(def_id), Some(sym::const_eval_select)) =>
+                && tcx.is_intrinsic(def_id, sym::const_eval_select) =>
             {
                 let [tupled_args, called_in_const, called_at_rt]: [_; 3] =
                     std::mem::take(args).try_into().unwrap();
@@ -632,6 +632,12 @@ fn optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> &Body<'_> {
 }
 
 fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
+    if tcx.intrinsic(did).is_some_and(|i| i.must_be_overridden) {
+        span_bug!(
+            tcx.def_span(did),
+            "this intrinsic must be overridden by the codegen backend, it has no meaningful body",
+        )
+    }
     if tcx.is_constructor(did.to_def_id()) {
         // There's no reason to run all of the MIR passes on constructors when
         // we can just output the MIR we want directly. This also saves const
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index a0af902c4e1..f317c025e96 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -14,9 +14,9 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
             if let TerminatorKind::Call { func, args, destination, target, .. } =
                 &mut terminator.kind
                 && let ty::FnDef(def_id, generic_args) = *func.ty(local_decls, tcx).kind()
-                && let Some(intrinsic_name) = tcx.intrinsic(def_id)
+                && let Some(intrinsic) = tcx.intrinsic(def_id)
             {
-                match intrinsic_name {
+                match intrinsic.name {
                     sym::unreachable => {
                         terminator.kind = TerminatorKind::Unreachable;
                     }
@@ -105,7 +105,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                             lhs = args.next().unwrap();
                             rhs = args.next().unwrap();
                         }
-                        let bin_op = match intrinsic_name {
+                        let bin_op = match intrinsic.name {
                             sym::wrapping_add => BinOp::Add,
                             sym::wrapping_sub => BinOp::Sub,
                             sym::wrapping_mul => BinOp::Mul,
@@ -136,7 +136,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                                 lhs = args.next().unwrap();
                                 rhs = args.next().unwrap();
                             }
-                            let bin_op = match intrinsic_name {
+                            let bin_op = match intrinsic.name {
                                 sym::add_with_overflow => BinOp::Add,
                                 sym::sub_with_overflow => BinOp::Sub,
                                 sym::mul_with_overflow => BinOp::Mul,
@@ -155,7 +155,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                     sym::size_of | sym::min_align_of => {
                         if let Some(target) = *target {
                             let tp_ty = generic_args.type_at(0);
-                            let null_op = match intrinsic_name {
+                            let null_op = match intrinsic.name {
                                 sym::size_of => NullOp::SizeOf,
                                 sym::min_align_of => NullOp::AlignOf,
                                 _ => bug!("unexpected intrinsic"),
diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
index e68d37f4c70..57fe46ad75a 100644
--- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
@@ -2,8 +2,10 @@
 
 use crate::MirPass;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::{
-    BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, Terminator, TerminatorKind,
+    BasicBlock, BasicBlockData, BasicBlocks, Body, Local, Operand, Rvalue, StatementKind,
+    TerminatorKind,
 };
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::ty::{Ty, TyCtxt};
@@ -77,7 +79,8 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         trace!("UninhabitedEnumBranching starting for {:?}", body.source);
 
-        let mut removable_switchs = Vec::new();
+        let mut unreachable_targets = Vec::new();
+        let mut patch = MirPatch::new(body);
 
         for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
             trace!("processing block {:?}", bb);
@@ -92,46 +95,73 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
                 tcx.param_env_reveal_all_normalized(body.source.def_id()).and(discriminant_ty),
             );
 
-            let allowed_variants = if let Ok(layout) = layout {
+            let mut allowed_variants = if let Ok(layout) = layout {
                 variant_discriminants(&layout, discriminant_ty, tcx)
+            } else if let Some(variant_range) = discriminant_ty.variant_range(tcx) {
+                variant_range
+                    .map(|variant| {
+                        discriminant_ty.discriminant_for_variant(tcx, variant).unwrap().val
+                    })
+                    .collect()
             } else {
                 continue;
             };
 
             trace!("allowed_variants = {:?}", allowed_variants);
 
-            let terminator = bb_data.terminator();
-            let TerminatorKind::SwitchInt { targets, .. } = &terminator.kind else { bug!() };
+            unreachable_targets.clear();
+            let TerminatorKind::SwitchInt { targets, discr } = &bb_data.terminator().kind else {
+                bug!()
+            };
 
-            let mut reachable_count = 0;
             for (index, (val, _)) in targets.iter().enumerate() {
-                if allowed_variants.contains(&val) {
-                    reachable_count += 1;
-                } else {
-                    removable_switchs.push((bb, index));
+                if !allowed_variants.remove(&val) {
+                    unreachable_targets.push(index);
                 }
             }
-
-            if reachable_count == allowed_variants.len() {
-                removable_switchs.push((bb, targets.iter().count()));
+            let otherwise_is_empty_unreachable =
+                body.basic_blocks[targets.otherwise()].is_empty_unreachable();
+            // After resolving https://github.com/llvm/llvm-project/issues/78578,
+            // we can remove the limit on the number of successors.
+            fn check_successors(basic_blocks: &BasicBlocks<'_>, bb: BasicBlock) -> bool {
+                let mut successors = basic_blocks[bb].terminator().successors();
+                let Some(first_successor) = successors.next() else { return true };
+                if successors.next().is_some() {
+                    return true;
+                }
+                if let TerminatorKind::SwitchInt { .. } =
+                    &basic_blocks[first_successor].terminator().kind
+                {
+                    return false;
+                };
+                true
             }
+            let otherwise_is_last_variant = !otherwise_is_empty_unreachable
+                && allowed_variants.len() == 1
+                && check_successors(&body.basic_blocks, targets.otherwise());
+            let replace_otherwise_to_unreachable = otherwise_is_last_variant
+                || !otherwise_is_empty_unreachable && allowed_variants.is_empty();
+
+            if unreachable_targets.is_empty() && !replace_otherwise_to_unreachable {
+                continue;
+            }
+
+            let unreachable_block = patch.unreachable_no_cleanup_block();
+            let mut targets = targets.clone();
+            if replace_otherwise_to_unreachable {
+                if otherwise_is_last_variant {
+                    #[allow(rustc::potential_query_instability)]
+                    let last_variant = *allowed_variants.iter().next().unwrap();
+                    targets.add_target(last_variant, targets.otherwise());
+                }
+                unreachable_targets.push(targets.iter().count());
+            }
+            for index in unreachable_targets.iter() {
+                targets.all_targets_mut()[*index] = unreachable_block;
+            }
+            patch.patch_terminator(bb, TerminatorKind::SwitchInt { targets, discr: discr.clone() });
         }
 
-        if removable_switchs.is_empty() {
-            return;
-        }
-
-        let new_block = BasicBlockData::new(Some(Terminator {
-            source_info: body.basic_blocks[removable_switchs[0].0].terminator().source_info,
-            kind: TerminatorKind::Unreachable,
-        }));
-        let unreachable_block = body.basic_blocks.as_mut().push(new_block);
-
-        for (bb, index) in removable_switchs {
-            let bb = &mut body.basic_blocks.as_mut()[bb];
-            let terminator = bb.terminator_mut();
-            let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind else { bug!() };
-            targets.all_targets_mut()[index] = unreachable_block;
-        }
+        patch.apply(body);
     }
 }
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 5593de60784..32f823a5ac6 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -446,7 +446,8 @@ fn collect_items_rec<'tcx>(
                         hir::InlineAsmOperand::In { .. }
                         | hir::InlineAsmOperand::Out { .. }
                         | hir::InlineAsmOperand::InOut { .. }
-                        | hir::InlineAsmOperand::SplitInOut { .. } => {
+                        | hir::InlineAsmOperand::SplitInOut { .. }
+                        | hir::InlineAsmOperand::Label { .. } => {
                             span_bug!(*op_sp, "invalid operand type for global_asm!")
                         }
                     }
@@ -1019,6 +1020,11 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
         return false;
     }
 
+    if tcx.intrinsic(def_id).is_some_and(|i| i.must_be_overridden) {
+        // These are implemented by backends directly and have no meaningful body.
+        return false;
+    }
+
     if def_id.is_local() {
         // Local items cannot be referred to locally without monomorphizing them locally.
         return true;
@@ -1356,7 +1362,7 @@ fn create_mono_items_for_default_impls<'tcx>(
         return;
     };
 
-    if matches!(impl_.skip_binder().polarity, ty::ImplPolarity::Negative) {
+    if matches!(impl_.polarity, ty::ImplPolarity::Negative) {
         return;
     }
 
@@ -1380,7 +1386,7 @@ fn create_mono_items_for_default_impls<'tcx>(
         }
     };
     let impl_args = GenericArgs::for_item(tcx, item.owner_id.to_def_id(), only_region_params);
-    let trait_ref = impl_.instantiate(tcx, impl_args).trait_ref;
+    let trait_ref = impl_.trait_ref.instantiate(tcx, impl_args);
 
     // Unlike 'lazy' monomorphization that begins by collecting items transitively
     // called by `main` or other global items, when eagerly monomorphizing impl
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index fb42532e247..1070d1a1380 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -18,7 +18,6 @@ use rustc_middle::ty::{
     GenericArgsRef, Ty, TyCtxt, UnusedGenericParams,
 };
 use rustc_span::symbol::sym;
-use std::ops::ControlFlow;
 
 use crate::errors::UnusedGenericParamsHint;
 
@@ -291,31 +290,29 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
 
 impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
-    fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_const(&mut self, c: ty::Const<'tcx>) {
         if !c.has_non_region_param() {
-            return ControlFlow::Continue(());
+            return;
         }
 
         match c.kind() {
             ty::ConstKind::Param(param) => {
                 debug!(?param);
                 self.unused_parameters.mark_used(param.index);
-                ControlFlow::Continue(())
             }
             ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args })
                 if matches!(self.tcx.def_kind(def), DefKind::AnonConst) =>
             {
                 self.visit_child_body(def, args);
-                ControlFlow::Continue(())
             }
             _ => c.super_visit_with(self),
         }
     }
 
     #[instrument(level = "debug", skip(self))]
-    fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, ty: Ty<'tcx>) {
         if !ty.has_non_region_param() {
-            return ControlFlow::Continue(());
+            return;
         }
 
         match *ty.kind() {
@@ -323,18 +320,16 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
                 debug!(?def_id);
                 // Avoid cycle errors with coroutines.
                 if def_id == self.def_id {
-                    return ControlFlow::Continue(());
+                    return;
                 }
 
                 // Consider any generic parameters used by any closures/coroutines as used in the
                 // parent.
                 self.visit_child_body(def_id, args);
-                ControlFlow::Continue(())
             }
             ty::Param(param) => {
                 debug!(?param);
                 self.unused_parameters.mark_used(param.index);
-                ControlFlow::Continue(())
             }
             _ => ty.super_visit_with(self),
         }
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index 7b73e2aebf0..95b30066662 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -1,6 +1,7 @@
 use std::cmp::Ordering;
 
 use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
+use rustc_type_ir::new::{Const, Region, Ty};
 use rustc_type_ir::visit::TypeVisitableExt;
 use rustc_type_ir::{
     self as ty, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, ConstTy,
@@ -293,7 +294,7 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
             var
         });
 
-        self.interner().mk_bound_region(self.binder_index, var)
+        Region::new_anon_bound(self.interner(), self.binder_index, var)
     }
 
     fn fold_ty(&mut self, t: I::Ty) -> I::Ty
@@ -375,7 +376,7 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
             }),
         );
 
-        self.interner().mk_bound_ty(self.binder_index, var)
+        Ty::new_anon_bound(self.interner(), self.binder_index, var)
     }
 
     fn fold_const(&mut self, c: I::Const) -> I::Const
@@ -435,6 +436,6 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
             }),
         );
 
-        self.interner().mk_bound_const(self.binder_index, var, c.ty())
+        Const::new_anon_bound(self.interner(), self.binder_index, var, c.ty())
     }
 }
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 91dbf0321d2..c72b7e2cfa7 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -4,7 +4,7 @@ use rustc_ast::token::Token;
 use rustc_ast::{Path, Visibility};
 use rustc_errors::{
     codes::*, AddToDiagnostic, Applicability, Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic,
-    Level, SubdiagnosticMessageOp,
+    Level, SubdiagMessageOp,
 };
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_session::errors::ExprParenthesesNeeded;
@@ -1467,7 +1467,7 @@ pub(crate) struct FnTraitMissingParen {
 }
 
 impl AddToDiagnostic for FnTraitMissingParen {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _: F,
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 4cfd061ebd9..f57945a52df 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -14,7 +14,7 @@ use rustc_lexer::{Cursor, LiteralKind};
 use rustc_session::lint::builtin::{
     RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
 };
-use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::Symbol;
 use rustc_span::{edition::Edition, BytePos, Pos, Span};
@@ -42,12 +42,12 @@ pub struct UnmatchedDelim {
     pub candidate_span: Option<Span>,
 }
 
-pub(crate) fn parse_token_trees<'sess, 'src>(
-    sess: &'sess ParseSess,
+pub(crate) fn parse_token_trees<'psess, 'src>(
+    psess: &'psess ParseSess,
     mut src: &'src str,
     mut start_pos: BytePos,
     override_span: Option<Span>,
-) -> Result<TokenStream, Vec<Diag<'sess>>> {
+) -> Result<TokenStream, Vec<Diag<'psess>>> {
     // Skip `#!`, if present.
     if let Some(shebang_len) = rustc_lexer::strip_shebang(src) {
         src = &src[shebang_len..];
@@ -56,7 +56,7 @@ pub(crate) fn parse_token_trees<'sess, 'src>(
 
     let cursor = Cursor::new(src);
     let string_reader = StringReader {
-        sess,
+        psess,
         start_pos,
         pos: start_pos,
         src,
@@ -75,7 +75,7 @@ pub(crate) fn parse_token_trees<'sess, 'src>(
 
             let mut buffer = Vec::with_capacity(1);
             for unmatched in unmatched_delims {
-                if let Some(err) = make_unclosed_delims_error(unmatched, sess) {
+                if let Some(err) = make_unclosed_delims_error(unmatched, psess) {
                     buffer.push(err);
                 }
             }
@@ -90,8 +90,8 @@ pub(crate) fn parse_token_trees<'sess, 'src>(
     }
 }
 
-struct StringReader<'sess, 'src> {
-    sess: &'sess ParseSess,
+struct StringReader<'psess, 'src> {
+    psess: &'psess ParseSess,
     /// Initial position, read-only.
     start_pos: BytePos,
     /// The absolute offset within the source_map of the current character.
@@ -107,9 +107,9 @@ struct StringReader<'sess, 'src> {
     nbsp_is_whitespace: bool,
 }
 
-impl<'sess, 'src> StringReader<'sess, 'src> {
-    pub fn dcx(&self) -> &'sess DiagCtxt {
-        &self.sess.dcx
+impl<'psess, 'src> StringReader<'psess, 'src> {
+    pub fn dcx(&self) -> &'psess DiagCtxt {
+        &self.psess.dcx
     }
 
     fn mk_sp(&self, lo: BytePos, hi: BytePos) -> Span {
@@ -176,11 +176,11 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
                 rustc_lexer::TokenKind::RawIdent => {
                     let sym = nfc_normalize(self.str_from(start + BytePos(2)));
                     let span = self.mk_sp(start, self.pos);
-                    self.sess.symbol_gallery.insert(sym, span);
+                    self.psess.symbol_gallery.insert(sym, span);
                     if !sym.can_be_raw() {
                         self.dcx().emit_err(errors::CannotBeRawIdent { span, ident: sym });
                     }
-                    self.sess.raw_identifier_spans.push(span);
+                    self.psess.raw_identifier_spans.push(span);
                     token::Ident(sym, IdentIsRaw::Yes)
                 }
                 rustc_lexer::TokenKind::UnknownPrefix => {
@@ -199,7 +199,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
                 {
                     let sym = nfc_normalize(self.str_from(start));
                     let span = self.mk_sp(start, self.pos);
-                    self.sess.bad_unicode_identifiers.borrow_mut().entry(sym).or_default()
+                    self.psess.bad_unicode_identifiers.borrow_mut().entry(sym).or_default()
                         .push(span);
                     token::Ident(sym, IdentIsRaw::No)
                 }
@@ -230,7 +230,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
                     let suffix = if suffix_start < self.pos {
                         let string = self.str_from(suffix_start);
                         if string == "_" {
-                            self.sess
+                            self.psess
                                 .dcx
                                 .emit_err(errors::UnderscoreLiteralSuffix { span: self.mk_sp(suffix_start, self.pos) });
                             None
@@ -338,7 +338,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
     fn ident(&self, start: BytePos) -> TokenKind {
         let sym = nfc_normalize(self.str_from(start));
         let span = self.mk_sp(start, self.pos);
-        self.sess.symbol_gallery.insert(sym, span);
+        self.psess.symbol_gallery.insert(sym, span);
         token::Ident(sym, IdentIsRaw::No)
     }
 
@@ -350,12 +350,12 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
         let content = self.str_from(content_start);
         if contains_text_flow_control_chars(content) {
             let span = self.mk_sp(start, self.pos);
-            self.sess.buffer_lint_with_diagnostic(
+            self.psess.buffer_lint_with_diagnostic(
                 TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
                 span,
                 ast::CRATE_NODE_ID,
                 "unicode codepoint changing visible direction of text present in comment",
-                BuiltinLintDiagnostics::UnicodeTextFlow(span, content.to_string()),
+                BuiltinLintDiag::UnicodeTextFlow(span, content.to_string()),
             );
         }
     }
@@ -566,7 +566,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
     }
 
     fn report_non_started_raw_string(&self, start: BytePos, bad_char: char) -> ! {
-        self.sess
+        self.psess
             .dcx
             .struct_span_fatal(
                 self.mk_sp(start, self.pos),
@@ -680,12 +680,12 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
             self.dcx().emit_err(errors::UnknownPrefix { span: prefix_span, prefix, sugg });
         } else {
             // Before Rust 2021, only emit a lint for migration.
-            self.sess.buffer_lint_with_diagnostic(
+            self.psess.buffer_lint_with_diagnostic(
                 RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
                 prefix_span,
                 ast::CRATE_NODE_ID,
                 format!("prefix `{prefix}` is unknown"),
-                BuiltinLintDiagnostics::ReservedPrefix(prefix_span),
+                BuiltinLintDiag::ReservedPrefix(prefix_span),
             );
         }
     }
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index c9ff2d58e2c..a506f98bf3a 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -8,18 +8,18 @@ use rustc_ast_pretty::pprust::token_to_string;
 use rustc_errors::{Applicability, PErr};
 use rustc_span::symbol::kw;
 
-pub(super) struct TokenTreesReader<'sess, 'src> {
-    string_reader: StringReader<'sess, 'src>,
+pub(super) struct TokenTreesReader<'psess, 'src> {
+    string_reader: StringReader<'psess, 'src>,
     /// The "next" token, which has been obtained from the `StringReader` but
     /// not yet handled by the `TokenTreesReader`.
     token: Token,
     diag_info: TokenTreeDiagInfo,
 }
 
-impl<'sess, 'src> TokenTreesReader<'sess, 'src> {
+impl<'psess, 'src> TokenTreesReader<'psess, 'src> {
     pub(super) fn parse_all_token_trees(
-        string_reader: StringReader<'sess, 'src>,
-    ) -> (TokenStream, Result<(), Vec<PErr<'sess>>>, Vec<UnmatchedDelim>) {
+        string_reader: StringReader<'psess, 'src>,
+    ) -> (TokenStream, Result<(), Vec<PErr<'psess>>>, Vec<UnmatchedDelim>) {
         let mut tt_reader = TokenTreesReader {
             string_reader,
             token: Token::dummy(),
@@ -35,7 +35,7 @@ impl<'sess, 'src> TokenTreesReader<'sess, 'src> {
     fn parse_token_trees(
         &mut self,
         is_delimited: bool,
-    ) -> (Spacing, TokenStream, Result<(), Vec<PErr<'sess>>>) {
+    ) -> (Spacing, TokenStream, Result<(), Vec<PErr<'psess>>>) {
         // Move past the opening delimiter.
         let (_, open_spacing) = self.bump(false);
 
@@ -71,9 +71,9 @@ impl<'sess, 'src> TokenTreesReader<'sess, 'src> {
         }
     }
 
-    fn eof_err(&mut self) -> PErr<'sess> {
+    fn eof_err(&mut self) -> PErr<'psess> {
         let msg = "this file contains an unclosed delimiter";
-        let mut err = self.string_reader.sess.dcx.struct_span_err(self.token.span, msg);
+        let mut err = self.string_reader.psess.dcx.struct_span_err(self.token.span, msg);
         for &(_, sp) in &self.diag_info.open_braces {
             err.span_label(sp, "unclosed delimiter");
             self.diag_info.unmatched_delims.push(UnmatchedDelim {
@@ -89,7 +89,7 @@ impl<'sess, 'src> TokenTreesReader<'sess, 'src> {
             report_suspicious_mismatch_block(
                 &mut err,
                 &self.diag_info,
-                self.string_reader.sess.source_map(),
+                self.string_reader.psess.source_map(),
                 *delim,
             )
         }
@@ -99,7 +99,7 @@ impl<'sess, 'src> TokenTreesReader<'sess, 'src> {
     fn parse_token_tree_open_delim(
         &mut self,
         open_delim: Delimiter,
-    ) -> Result<TokenTree, Vec<PErr<'sess>>> {
+    ) -> Result<TokenTree, Vec<PErr<'psess>>> {
         // The span for beginning of the delimited section
         let pre_span = self.token.span;
 
@@ -115,7 +115,7 @@ impl<'sess, 'src> TokenTreesReader<'sess, 'src> {
 
         // Expand to cover the entire delimited token tree
         let delim_span = DelimSpan::from_pair(pre_span, self.token.span);
-        let sm = self.string_reader.sess.source_map();
+        let sm = self.string_reader.psess.source_map();
 
         let close_spacing = match self.token.kind {
             // Correct delimiter.
@@ -232,11 +232,11 @@ impl<'sess, 'src> TokenTreesReader<'sess, 'src> {
     fn unclosed_delim_err(
         &mut self,
         tts: TokenStream,
-        mut errs: Vec<PErr<'sess>>,
-    ) -> Vec<PErr<'sess>> {
+        mut errs: Vec<PErr<'psess>>,
+    ) -> Vec<PErr<'psess>> {
         // If there are unclosed delims, see if there are diff markers and if so, point them
         // out instead of complaining about the unclosed delims.
-        let mut parser = crate::stream_to_parser(self.string_reader.sess, tts, None);
+        let mut parser = crate::stream_to_parser(self.string_reader.psess, tts, None);
         let mut diff_errs = vec![];
         // Suggest removing a `{` we think appears in an `if`/`while` condition
         // We want to suggest removing a `{` only if we think we're in an `if`/`while` condition, but
@@ -289,17 +289,17 @@ impl<'sess, 'src> TokenTreesReader<'sess, 'src> {
         return errs;
     }
 
-    fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'sess> {
+    fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'psess> {
         // An unexpected closing delimiter (i.e., there is no
         // matching opening delimiter).
         let token_str = token_to_string(&self.token);
         let msg = format!("unexpected closing delimiter: `{token_str}`");
-        let mut err = self.string_reader.sess.dcx.struct_span_err(self.token.span, msg);
+        let mut err = self.string_reader.psess.dcx.struct_span_err(self.token.span, msg);
 
         report_suspicious_mismatch_block(
             &mut err,
             &self.diag_info,
-            self.string_reader.sess.source_map(),
+            self.string_reader.psess.source_map(),
             delim,
         );
         err.span_label(self.token.span, "unexpected closing delimiter");
diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs
index 3b4e05332fa..6b055fc844a 100644
--- a/compiler/rustc_parse/src/lexer/unicode_chars.rs
+++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs
@@ -350,7 +350,7 @@ pub(super) fn check_for_substitution(
 
     let Some((_, ascii_name, token)) = ASCII_ARRAY.iter().find(|&&(s, _, _)| s == ascii_str) else {
         let msg = format!("substitution character not found for '{ch}'");
-        reader.sess.dcx.span_bug(span, msg);
+        reader.psess.dcx.span_bug(span, msg);
     };
 
     // special help suggestion for "directed" double quotes
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 53bcb35101e..a46372d368f 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -57,84 +57,84 @@ macro_rules! panictry_buffer {
     }};
 }
 
-pub fn parse_crate_from_file<'a>(input: &Path, sess: &'a ParseSess) -> PResult<'a, ast::Crate> {
-    let mut parser = new_parser_from_file(sess, input, None);
+pub fn parse_crate_from_file<'a>(input: &Path, psess: &'a ParseSess) -> PResult<'a, ast::Crate> {
+    let mut parser = new_parser_from_file(psess, input, None);
     parser.parse_crate_mod()
 }
 
 pub fn parse_crate_attrs_from_file<'a>(
     input: &Path,
-    sess: &'a ParseSess,
+    psess: &'a ParseSess,
 ) -> PResult<'a, ast::AttrVec> {
-    let mut parser = new_parser_from_file(sess, input, None);
+    let mut parser = new_parser_from_file(psess, input, None);
     parser.parse_inner_attributes()
 }
 
 pub fn parse_crate_from_source_str(
     name: FileName,
     source: String,
-    sess: &ParseSess,
+    psess: &ParseSess,
 ) -> PResult<'_, ast::Crate> {
-    new_parser_from_source_str(sess, name, source).parse_crate_mod()
+    new_parser_from_source_str(psess, name, source).parse_crate_mod()
 }
 
 pub fn parse_crate_attrs_from_source_str(
     name: FileName,
     source: String,
-    sess: &ParseSess,
+    psess: &ParseSess,
 ) -> PResult<'_, ast::AttrVec> {
-    new_parser_from_source_str(sess, name, source).parse_inner_attributes()
+    new_parser_from_source_str(psess, name, source).parse_inner_attributes()
 }
 
 pub fn parse_stream_from_source_str(
     name: FileName,
     source: String,
-    sess: &ParseSess,
+    psess: &ParseSess,
     override_span: Option<Span>,
 ) -> TokenStream {
-    source_file_to_stream(sess, sess.source_map().new_source_file(name, source), override_span)
+    source_file_to_stream(psess, psess.source_map().new_source_file(name, source), override_span)
 }
 
 /// Creates a new parser from a source string.
-pub fn new_parser_from_source_str(sess: &ParseSess, name: FileName, source: String) -> Parser<'_> {
-    panictry_buffer!(maybe_new_parser_from_source_str(sess, name, source))
+pub fn new_parser_from_source_str(psess: &ParseSess, name: FileName, source: String) -> Parser<'_> {
+    panictry_buffer!(maybe_new_parser_from_source_str(psess, name, source))
 }
 
 /// Creates a new parser from a source string. Returns any buffered errors from lexing the initial
 /// token stream; these must be consumed via `emit`, `cancel`, etc., otherwise a panic will occur
 /// when they are dropped.
 pub fn maybe_new_parser_from_source_str(
-    sess: &ParseSess,
+    psess: &ParseSess,
     name: FileName,
     source: String,
 ) -> Result<Parser<'_>, Vec<Diag<'_>>> {
-    maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source))
+    maybe_source_file_to_parser(psess, psess.source_map().new_source_file(name, source))
 }
 
 /// Creates a new parser, aborting if the file doesn't exist. If a span is given, that is used on
 /// an error as the source of the problem.
-pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path, sp: Option<Span>) -> Parser<'a> {
-    let source_file = sess.source_map().load_file(path).unwrap_or_else(|e| {
+pub fn new_parser_from_file<'a>(psess: &'a ParseSess, path: &Path, sp: Option<Span>) -> Parser<'a> {
+    let source_file = psess.source_map().load_file(path).unwrap_or_else(|e| {
         let msg = format!("couldn't read {}: {}", path.display(), e);
-        let mut err = sess.dcx.struct_fatal(msg);
+        let mut err = psess.dcx.struct_fatal(msg);
         if let Some(sp) = sp {
             err.span(sp);
         }
         err.emit();
     });
 
-    panictry_buffer!(maybe_source_file_to_parser(sess, source_file))
+    panictry_buffer!(maybe_source_file_to_parser(psess, source_file))
 }
 
 /// Given a session and a `source_file`, return a parser. Returns any buffered errors from lexing
 /// the initial token stream.
 fn maybe_source_file_to_parser(
-    sess: &ParseSess,
+    psess: &ParseSess,
     source_file: Lrc<SourceFile>,
 ) -> Result<Parser<'_>, Vec<Diag<'_>>> {
     let end_pos = source_file.end_position();
-    let stream = maybe_file_to_stream(sess, source_file, None)?;
-    let mut parser = stream_to_parser(sess, stream, None);
+    let stream = maybe_file_to_stream(psess, source_file, None)?;
+    let mut parser = stream_to_parser(psess, stream, None);
     if parser.token == token::Eof {
         parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt(), None);
     }
@@ -146,47 +146,47 @@ fn maybe_source_file_to_parser(
 
 /// Given a `source_file`, produces a sequence of token trees.
 pub fn source_file_to_stream(
-    sess: &ParseSess,
+    psess: &ParseSess,
     source_file: Lrc<SourceFile>,
     override_span: Option<Span>,
 ) -> TokenStream {
-    panictry_buffer!(maybe_file_to_stream(sess, source_file, override_span))
+    panictry_buffer!(maybe_file_to_stream(psess, source_file, override_span))
 }
 
 /// Given a source file, produces a sequence of token trees. Returns any buffered errors from
 /// parsing the token stream.
-fn maybe_file_to_stream<'sess>(
-    sess: &'sess ParseSess,
+fn maybe_file_to_stream<'psess>(
+    psess: &'psess ParseSess,
     source_file: Lrc<SourceFile>,
     override_span: Option<Span>,
-) -> Result<TokenStream, Vec<Diag<'sess>>> {
+) -> Result<TokenStream, Vec<Diag<'psess>>> {
     let src = source_file.src.as_ref().unwrap_or_else(|| {
-        sess.dcx.bug(format!(
+        psess.dcx.bug(format!(
             "cannot lex `source_file` without source: {}",
-            sess.source_map().filename_for_diagnostics(&source_file.name)
+            psess.source_map().filename_for_diagnostics(&source_file.name)
         ));
     });
 
-    lexer::parse_token_trees(sess, src.as_str(), source_file.start_pos, override_span)
+    lexer::parse_token_trees(psess, src.as_str(), source_file.start_pos, override_span)
 }
 
 /// Given a stream and the `ParseSess`, produces a parser.
 pub fn stream_to_parser<'a>(
-    sess: &'a ParseSess,
+    psess: &'a ParseSess,
     stream: TokenStream,
     subparser_name: Option<&'static str>,
 ) -> Parser<'a> {
-    Parser::new(sess, stream, subparser_name)
+    Parser::new(psess, stream, subparser_name)
 }
 
 /// Runs the given subparser `f` on the tokens of the given `attr`'s item.
 pub fn parse_in<'a, T>(
-    sess: &'a ParseSess,
+    psess: &'a ParseSess,
     tts: TokenStream,
     name: &'static str,
     mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
 ) -> PResult<'a, T> {
-    let mut parser = Parser::new(sess, tts, Some(name));
+    let mut parser = Parser::new(psess, tts, Some(name));
     let result = f(&mut parser)?;
     if parser.token != token::Eof {
         parser.unexpected()?;
@@ -194,28 +194,28 @@ pub fn parse_in<'a, T>(
     Ok(result)
 }
 
-pub fn fake_token_stream_for_item(sess: &ParseSess, item: &ast::Item) -> TokenStream {
+pub fn fake_token_stream_for_item(psess: &ParseSess, item: &ast::Item) -> TokenStream {
     let source = pprust::item_to_string(item);
     let filename = FileName::macro_expansion_source_code(&source);
-    parse_stream_from_source_str(filename, source, sess, Some(item.span))
+    parse_stream_from_source_str(filename, source, psess, Some(item.span))
 }
 
-pub fn fake_token_stream_for_crate(sess: &ParseSess, krate: &ast::Crate) -> TokenStream {
+pub fn fake_token_stream_for_crate(psess: &ParseSess, krate: &ast::Crate) -> TokenStream {
     let source = pprust::crate_to_string_for_macros(krate);
     let filename = FileName::macro_expansion_source_code(&source);
-    parse_stream_from_source_str(filename, source, sess, Some(krate.spans.inner_span))
+    parse_stream_from_source_str(filename, source, psess, Some(krate.spans.inner_span))
 }
 
 pub fn parse_cfg_attr(
     attr: &Attribute,
-    parse_sess: &ParseSess,
+    psess: &ParseSess,
 ) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> {
     match attr.get_normal_item().args {
         ast::AttrArgs::Delimited(ast::DelimArgs { dspan, delim, ref tokens })
             if !tokens.is_empty() =>
         {
-            crate::validate_attr::check_cfg_attr_bad_delim(parse_sess, dspan, delim);
-            match parse_in(parse_sess, tokens.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) {
+            crate::validate_attr::check_cfg_attr_bad_delim(psess, dspan, delim);
+            match parse_in(psess, tokens.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) {
                 Ok(r) => return Some(r),
                 Err(e) => {
                     e.with_help(format!("the valid syntax is `{CFG_ATTR_GRAMMAR_HELP}`"))
@@ -224,7 +224,7 @@ pub fn parse_cfg_attr(
                 }
             }
         }
-        _ => error_malformed_cfg_attr_missing(attr.span, parse_sess),
+        _ => error_malformed_cfg_attr_missing(attr.span, psess),
     }
     None
 }
@@ -234,6 +234,6 @@ const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
     <https://doc.rust-lang.org/reference/conditional-compilation.html\
     #the-cfg_attr-attribute>";
 
-fn error_malformed_cfg_attr_missing(span: Span, parse_sess: &ParseSess) {
-    parse_sess.dcx.emit_err(errors::MalformedCfgAttr { span, sugg: CFG_ATTR_GRAMMAR_HELP });
+fn error_malformed_cfg_attr_missing(span: Span, psess: &ParseSess) {
+    psess.dcx.emit_err(errors::MalformedCfgAttr { span, sugg: CFG_ATTR_GRAMMAR_HELP });
 }
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index 685af6546f5..eb9a10f4bda 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -85,7 +85,7 @@ impl<'a> Parser<'a> {
                 // Always make an outer attribute - this allows us to recover from a misplaced
                 // inner attribute.
                 Some(attr::mk_doc_comment(
-                    &self.sess.attr_id_generator,
+                    &self.psess.attr_id_generator,
                     comment_kind,
                     ast::AttrStyle::Outer,
                     data,
@@ -135,7 +135,7 @@ impl<'a> Parser<'a> {
                 this.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy);
             }
 
-            Ok(attr::mk_attr_from_item(&self.sess.attr_id_generator, item, None, style, attr_sp))
+            Ok(attr::mk_attr_from_item(&self.psess.attr_id_generator, item, None, style, attr_sp))
         })
     }
 
@@ -288,7 +288,7 @@ impl<'a> Parser<'a> {
                 if attr_style == ast::AttrStyle::Inner {
                     self.bump();
                     Some(attr::mk_doc_comment(
-                        &self.sess.attr_id_generator,
+                        &self.psess.attr_id_generator,
                         comment_kind,
                         attr_style,
                         data,
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index 2307f4cfffa..a1dd7d6f673 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -40,8 +40,8 @@ impl AttrWrapper {
         AttrWrapper { attrs: AttrVec::new(), start_pos: usize::MAX }
     }
 
-    pub(crate) fn take_for_recovery(self, sess: &ParseSess) -> AttrVec {
-        sess.dcx.span_delayed_bug(
+    pub(crate) fn take_for_recovery(self, psess: &ParseSess) -> AttrVec {
+        psess.dcx.span_delayed_bug(
             self.attrs.get(0).map(|attr| attr.span).unwrap_or(DUMMY_SP),
             "AttrVec is taken for recovery but no error is produced",
         );
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 2a8cb74337b..2f7ac7d3a12 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -242,7 +242,7 @@ impl<'a> DerefMut for SnapshotParser<'a> {
 
 impl<'a> Parser<'a> {
     pub fn dcx(&self) -> &'a DiagCtxt {
-        &self.sess.dcx
+        &self.psess.dcx
     }
 
     /// Replace `self` with `snapshot.parser`.
@@ -257,7 +257,7 @@ impl<'a> Parser<'a> {
     }
 
     pub(super) fn span_to_snippet(&self, span: Span) -> Result<String, SpanSnippetError> {
-        self.sess.source_map().span_to_snippet(span)
+        self.psess.source_map().span_to_snippet(span)
     }
 
     /// Emits an error with suggestions if an identifier was expected but not found.
@@ -364,7 +364,7 @@ impl<'a> Parser<'a> {
 
                             if !self.look_ahead(1, |t| *t == token::Lt)
                                 && let Ok(snippet) =
-                                    self.sess.source_map().span_to_snippet(generic.span)
+                                    self.psess.source_map().span_to_snippet(generic.span)
                             {
                                 err.multipart_suggestion_verbose(
                                         format!("place the generic parameter name after the {ident_name} name"),
@@ -489,7 +489,7 @@ impl<'a> Parser<'a> {
         expected.sort_by_cached_key(|x| x.to_string());
         expected.dedup();
 
-        let sm = self.sess.source_map();
+        let sm = self.psess.source_map();
 
         // Special-case "expected `;`" errors.
         if expected.contains(&TokenType::Token(token::Semi)) {
@@ -822,7 +822,7 @@ impl<'a> Parser<'a> {
                 // #[cfg(..)]
                 // other_expr
                 // So we suggest using `if cfg!(..) { expr } else if cfg!(..) { other_expr }`.
-                let margin = self.sess.source_map().span_to_margin(next_expr.span).unwrap_or(0);
+                let margin = self.psess.source_map().span_to_margin(next_expr.span).unwrap_or(0);
                 let sugg = vec![
                     (attr.span.with_hi(segment.span().hi()), "if cfg!".to_string()),
                     (args_span.shrink_to_hi().with_hi(attr.span.hi()), " {".to_string()),
@@ -850,7 +850,7 @@ impl<'a> Parser<'a> {
     }
 
     fn check_too_many_raw_str_terminators(&mut self, err: &mut Diag<'_>) -> bool {
-        let sm = self.sess.source_map();
+        let sm = self.psess.source_map();
         match (&self.prev_token.kind, &self.token.kind) {
             (
                 TokenKind::Literal(Lit {
@@ -935,7 +935,7 @@ impl<'a> Parser<'a> {
                         // expand `before` so that we take care of module path such as:
                         // `foo::Bar { ... } `
                         // we expect to suggest `(foo::Bar { ... })` instead of `foo::(Bar { ... })`
-                        let sm = self.sess.source_map();
+                        let sm = self.psess.source_map();
                         let before = maybe_struct_name.span.shrink_to_lo();
                         if let Ok(extend_before) = sm.span_extend_prev_while(before, |t| {
                             t.is_alphanumeric() || t == ':' || t == '_'
@@ -1872,7 +1872,7 @@ impl<'a> Parser<'a> {
         );
         let mut err = self.dcx().struct_span_err(sp, msg);
         let label_exp = format!("expected `{token_str}`");
-        let sm = self.sess.source_map();
+        let sm = self.psess.source_map();
         if !sm.is_multiline(prev_sp.until(sp)) {
             // When the spans are in the same line, it means that the only content
             // between them is whitespace, point only at the found token.
@@ -1893,7 +1893,7 @@ impl<'a> Parser<'a> {
 
     pub(super) fn recover_colon_as_semi(&mut self) -> bool {
         let line_idx = |span: Span| {
-            self.sess
+            self.psess
                 .source_map()
                 .span_to_lines(span)
                 .ok()
@@ -1906,7 +1906,7 @@ impl<'a> Parser<'a> {
         {
             self.dcx().emit_err(ColonAsSemi {
                 span: self.token.span,
-                type_ascription: self.sess.unstable_features.is_nightly_build().then_some(()),
+                type_ascription: self.psess.unstable_features.is_nightly_build().then_some(()),
             });
             self.bump();
             return true;
@@ -2357,8 +2357,8 @@ impl<'a> Parser<'a> {
             ),
         };
         let mut err = self.dcx().struct_span_err(span, msg);
-        let sp = self.sess.source_map().start_point(self.token.span);
-        if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
+        let sp = self.psess.source_map().start_point(self.token.span);
+        if let Some(sp) = self.psess.ambiguous_block_expr_parse.borrow().get(&sp) {
             err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp));
         }
         err.span_label(span, "expected expression");
@@ -2539,7 +2539,7 @@ impl<'a> Parser<'a> {
         };
 
         let ident = param.ident.to_string();
-        let sugg = match (ty_generics, self.sess.source_map().span_to_snippet(param.span())) {
+        let sugg = match (ty_generics, self.psess.source_map().span_to_snippet(param.span())) {
             (Some(Generics { params, span: impl_generics, .. }), Ok(snippet)) => {
                 Some(match &params[..] {
                     [] => UnexpectedConstParamDeclarationSugg::AddParam {
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 54771cccd75..7a34bc7890c 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -13,13 +13,14 @@ use ast::mut_visit::{noop_visit_expr, MutVisitor};
 use ast::token::IdentIsRaw;
 use ast::{CoroutineKind, ForLoopKind, GenBlockKind, Pat, Path, PathSegment};
 use core::mem;
+use core::ops::ControlFlow;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::Spacing;
 use rustc_ast::util::case::Case;
 use rustc_ast::util::classify;
 use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity};
-use rustc_ast::visit::Visitor;
+use rustc_ast::visit::{walk_expr, Visitor};
 use rustc_ast::{self as ast, AttrStyle, AttrVec, CaptureBy, ExprField, UnOp, DUMMY_NODE_ID};
 use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind};
 use rustc_ast::{Arm, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
@@ -31,7 +32,7 @@ use rustc_lexer::unescape::unescape_char;
 use rustc_macros::Subdiagnostic;
 use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded};
 use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
-use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_session::lint::BuiltinLintDiag;
 use rustc_span::source_map::{self, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, ErrorGuaranteed, Pos, Span};
@@ -403,8 +404,8 @@ impl<'a> Parser<'a> {
                 // suggestions based on the assumption that double-refs are rarely intentional,
                 // and closures are distinct enough that they don't get mixed up with their
                 // return value.
-                let sp = self.sess.source_map().start_point(self.token.span);
-                self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
+                let sp = self.psess.source_map().start_point(self.token.span);
+                self.psess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
                 false
             }
             (true, Some(op)) if !op.can_continue_expr_unambiguously() => false,
@@ -608,7 +609,7 @@ impl<'a> Parser<'a> {
                 };
 
                 // a block on the LHS might have been intended to be an expression instead
-                if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
+                if let Some(sp) = this.psess.ambiguous_block_expr_parse.borrow().get(&lo) {
                     err.add_parentheses = Some(ExprParenthesesNeeded::surrounding(*sp));
                 } else {
                     err.remove_plus = Some(lo);
@@ -666,7 +667,7 @@ impl<'a> Parser<'a> {
     fn parse_expr_box(&mut self, box_kw: Span) -> PResult<'a, (Span, ExprKind)> {
         let (span, _) = self.parse_expr_prefix_common(box_kw)?;
         let inner_span = span.with_lo(box_kw.hi());
-        let code = self.sess.source_map().span_to_snippet(inner_span).unwrap();
+        let code = self.psess.source_map().span_to_snippet(inner_span).unwrap();
         let guar = self.dcx().emit_err(errors::BoxSyntaxRemoved { span: span, code: code.trim() });
         Ok((span, ExprKind::Err(guar)))
     }
@@ -700,7 +701,7 @@ impl<'a> Parser<'a> {
             // Span the `not` plus trailing whitespace to avoid
             // trailing whitespace after the `!` in our suggestion
             sub: sub_diag(
-                self.sess.source_map().span_until_non_whitespace(lo.to(negated_token.span)),
+                self.psess.source_map().span_until_non_whitespace(lo.to(negated_token.span)),
             ),
         });
 
@@ -915,7 +916,7 @@ impl<'a> Parser<'a> {
             let found_raw = self.eat_keyword(kw::Raw);
             assert!(found_raw);
             let mutability = self.parse_const_or_mut().unwrap();
-            self.sess.gated_spans.gate(sym::raw_ref_op, lo.to(self.prev_token.span));
+            self.psess.gated_spans.gate(sym::raw_ref_op, lo.to(self.prev_token.span));
             (ast::BorrowKind::Raw, mutability)
         } else {
             // `mut?`
@@ -1013,7 +1014,7 @@ impl<'a> Parser<'a> {
     fn error_unexpected_after_dot(&self) {
         let actual = pprust::token_to_string(&self.token);
         let span = self.token.span;
-        let sm = self.sess.source_map();
+        let sm = self.psess.source_map();
         let (span, actual) = match (&self.token.kind, self.subparser_name) {
             (token::Eof, Some(_)) if let Ok(actual) = sm.span_to_snippet(sm.next_point(span)) => {
                 (span.shrink_to_hi(), actual.into())
@@ -1434,7 +1435,7 @@ impl<'a> Parser<'a> {
                 this.parse_expr_closure().map_err(|mut err| {
                     // If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }`
                     // then suggest parens around the lhs.
-                    if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
+                    if let Some(sp) = this.psess.ambiguous_block_expr_parse.borrow().get(&lo) {
                         err.subdiagnostic(this.dcx(), ExprParenthesesNeeded::surrounding(*sp));
                     }
                     err
@@ -1634,7 +1635,7 @@ impl<'a> Parser<'a> {
             && let Some(expr) = self.maybe_parse_struct_expr(&qself, &path)
         {
             if qself.is_some() {
-                self.sess.gated_spans.gate(sym::more_qualified_paths, path.span);
+                self.psess.gated_spans.gate(sym::more_qualified_paths, path.span);
             }
             return expr;
         } else {
@@ -1703,19 +1704,20 @@ impl<'a> Parser<'a> {
                 let span = expr.span;
 
                 let found_labeled_breaks = {
-                    struct FindLabeledBreaksVisitor(bool);
+                    struct FindLabeledBreaksVisitor;
 
                     impl<'ast> Visitor<'ast> for FindLabeledBreaksVisitor {
-                        fn visit_expr_post(&mut self, ex: &'ast Expr) {
+                        type Result = ControlFlow<()>;
+                        fn visit_expr(&mut self, ex: &'ast Expr) -> ControlFlow<()> {
                             if let ExprKind::Break(Some(_label), _) = ex.kind {
-                                self.0 = true;
+                                ControlFlow::Break(())
+                            } else {
+                                walk_expr(self, ex)
                             }
                         }
                     }
 
-                    let mut vis = FindLabeledBreaksVisitor(false);
-                    vis.visit_expr(&expr);
-                    vis.0
+                    FindLabeledBreaksVisitor.visit_expr(&expr).is_break()
                 };
 
                 // Suggestion involves adding a labeled block.
@@ -1821,7 +1823,7 @@ impl<'a> Parser<'a> {
         let kind = ExprKind::Yeet(self.parse_expr_opt()?);
 
         let span = lo.to(self.prev_token.span);
-        self.sess.gated_spans.gate(sym::yeet_expr, span);
+        self.psess.gated_spans.gate(sym::yeet_expr, span);
         let expr = self.mk_expr(span, kind);
         self.maybe_recover_from_bad_qpath(expr)
     }
@@ -1831,7 +1833,7 @@ impl<'a> Parser<'a> {
         let lo = self.prev_token.span;
         let kind = ExprKind::Become(self.parse_expr()?);
         let span = lo.to(self.prev_token.span);
-        self.sess.gated_spans.gate(sym::explicit_tail_calls, span);
+        self.psess.gated_spans.gate(sym::explicit_tail_calls, span);
         let expr = self.mk_expr(span, kind);
         self.maybe_recover_from_bad_qpath(expr)
     }
@@ -1875,12 +1877,12 @@ impl<'a> Parser<'a> {
                             | ExprKind::Block(_, None)
                     )
                 {
-                    self.sess.buffer_lint_with_diagnostic(
+                    self.psess.buffer_lint_with_diagnostic(
                         BREAK_WITH_LABEL_AND_LOOP,
                         lo.to(expr.span),
                         ast::CRATE_NODE_ID,
                         "this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression",
-                        BuiltinLintDiagnostics::BreakWithLabelAndLoop(expr.span),
+                        BuiltinLintDiag::BreakWithLabelAndLoop(expr.span),
                     );
                 }
 
@@ -1926,7 +1928,7 @@ impl<'a> Parser<'a> {
         let lo = self.prev_token.span;
         let kind = ExprKind::Yield(self.parse_expr_opt()?);
         let span = lo.to(self.prev_token.span);
-        self.sess.gated_spans.gate(sym::yield_expr, span);
+        self.psess.gated_spans.gate(sym::yield_expr, span);
         let expr = self.mk_expr(span, kind);
         self.maybe_recover_from_bad_qpath(expr)
     }
@@ -1955,7 +1957,7 @@ impl<'a> Parser<'a> {
             let err = self.dcx().create_err(errors::ExpectedBuiltinIdent { span: self.token.span });
             return Err(err);
         };
-        self.sess.gated_spans.gate(sym::builtin_syntax, ident.span);
+        self.psess.gated_spans.gate(sym::builtin_syntax, ident.span);
         self.bump();
 
         self.expect(&TokenKind::OpenDelim(Delimiter::Parenthesis))?;
@@ -2143,7 +2145,7 @@ impl<'a> Parser<'a> {
                     Err(err) => {
                         let span = token.uninterpolated_span();
                         self.bump();
-                        let guar = report_lit_error(self.sess, err, lit, span);
+                        let guar = report_lit_error(self.psess, err, lit, span);
                         // Pack possible quotes and prefixes from the original literal into
                         // the error literal's symbol so they can be pretty-printed faithfully.
                         let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None);
@@ -2236,7 +2238,7 @@ impl<'a> Parser<'a> {
         }
 
         if self.token.kind == token::Comma {
-            if !self.sess.source_map().is_multiline(prev_span.until(self.token.span)) {
+            if !self.psess.source_map().is_multiline(prev_span.until(self.token.span)) {
                 return Ok(());
             }
             let mut snapshot = self.create_snapshot_for_diagnostic();
@@ -2312,7 +2314,7 @@ impl<'a> Parser<'a> {
             let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
             let span = lo.to(self.prev_token.span);
 
-            self.sess.gated_spans.gate(sym::closure_lifetime_binder, span);
+            self.psess.gated_spans.gate(sym::closure_lifetime_binder, span);
 
             ClosureBinder::For { span, generic_params: lifetime_defs }
         } else {
@@ -2354,12 +2356,12 @@ impl<'a> Parser<'a> {
         match coroutine_kind {
             Some(CoroutineKind::Async { span, .. }) => {
                 // Feature-gate `async ||` closures.
-                self.sess.gated_spans.gate(sym::async_closure, span);
+                self.psess.gated_spans.gate(sym::async_closure, span);
             }
             Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => {
                 // Feature-gate `gen ||` and `async gen ||` closures.
                 // FIXME(gen_blocks): This perhaps should be a different gate.
-                self.sess.gated_spans.gate(sym::gen_blocks, span);
+                self.psess.gated_spans.gate(sym::gen_blocks, span);
             }
             None => {}
         }
@@ -2502,7 +2504,7 @@ impl<'a> Parser<'a> {
                 ExprKind::Block(_, None) => {
                     let guar = this.dcx().emit_err(errors::IfExpressionMissingCondition {
                         if_span: lo.with_neighbor(cond.span).shrink_to_hi(),
-                        block_span: self.sess.source_map().start_point(cond_span),
+                        block_span: self.psess.source_map().start_point(cond_span),
                     });
                     std::mem::replace(&mut cond, this.mk_expr_err(cond_span.shrink_to_hi(), guar))
                 }
@@ -2594,7 +2596,7 @@ impl<'a> Parser<'a> {
 
         if let ExprKind::Let(_, _, _, None) = cond.kind {
             // Remove the last feature gating of a `let` expression since it's stable.
-            self.sess.gated_spans.ungate_last(sym::let_chains, cond.span);
+            self.psess.gated_spans.ungate_last(sym::let_chains, cond.span);
         }
 
         Ok(cond)
@@ -2690,7 +2692,7 @@ impl<'a> Parser<'a> {
         attrs: AttrWrapper,
     ) {
         if !attrs.is_empty()
-            && let [x0 @ xn] | [x0, .., xn] = &*attrs.take_for_recovery(self.sess)
+            && let [x0 @ xn] | [x0, .., xn] = &*attrs.take_for_recovery(self.psess)
         {
             let attributes = x0.span.to(xn.span);
             let last = xn.span;
@@ -2787,7 +2789,7 @@ impl<'a> Parser<'a> {
             self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(kw::Await);
 
         if is_await {
-            self.sess.gated_spans.gate(sym::async_for_loop, self.prev_token.span);
+            self.psess.gated_spans.gate(sym::async_for_loop, self.prev_token.span);
         }
 
         let kind = if is_await { ForLoopKind::ForAwait } else { ForLoopKind::For };
@@ -3048,7 +3050,7 @@ impl<'a> Parser<'a> {
                     |x| {
                         // Don't gate twice
                         if !pat.contains_never_pattern() {
-                            this.sess.gated_spans.gate(sym::never_patterns, pat.span);
+                            this.psess.gated_spans.gate(sym::never_patterns, pat.span);
                         }
                         x
                     },
@@ -3103,7 +3105,7 @@ impl<'a> Parser<'a> {
                     this.expect_one_of(&[token::Comma], &[token::CloseDelim(Delimiter::Brace)])
                         .map_err(|mut err| {
                             if this.token == token::FatArrow {
-                                let sm = this.sess.source_map();
+                                let sm = this.psess.source_map();
                                 if let Ok(expr_lines) = sm.span_to_lines(expr_span)
                                     && let Ok(arm_start_lines) = sm.span_to_lines(arm_start_span)
                                     && arm_start_lines.lines[0].end_col
@@ -3227,10 +3229,10 @@ impl<'a> Parser<'a> {
         if has_let_expr {
             if does_not_have_bin_op {
                 // Remove the last feature gating of a `let` expression since it's stable.
-                self.sess.gated_spans.ungate_last(sym::let_chains, cond.span);
+                self.psess.gated_spans.ungate_last(sym::let_chains, cond.span);
             }
             let span = if_span.to(cond.span);
-            self.sess.gated_spans.gate(sym::if_let_guard, span);
+            self.psess.gated_spans.gate(sym::if_let_guard, span);
         }
         Ok(Some(cond))
     }
@@ -3321,7 +3323,7 @@ impl<'a> Parser<'a> {
             Err(self.dcx().create_err(errors::CatchAfterTry { span: self.prev_token.span }))
         } else {
             let span = span_lo.to(body.span);
-            self.sess.gated_spans.gate(sym::try_blocks, span);
+            self.psess.gated_spans.gate(sym::try_blocks, span);
             Ok(self.mk_expr_with_attrs(span, ExprKind::TryBlock(body), attrs))
         }
     }
@@ -3359,7 +3361,7 @@ impl<'a> Parser<'a> {
                 // `async` blocks are stable
             }
             GenBlockKind::Gen | GenBlockKind::AsyncGen => {
-                self.sess.gated_spans.gate(sym::gen_blocks, lo.to(self.prev_token.span));
+                self.psess.gated_spans.gate(sym::gen_blocks, lo.to(self.prev_token.span));
             }
         }
         let capture_clause = self.parse_capture_clause()?;
@@ -3876,7 +3878,7 @@ impl MutVisitor for CondChecker<'_> {
                             comparison: self.comparison,
                         }));
                 } else {
-                    self.parser.sess.gated_spans.gate(sym::let_chains, span);
+                    self.parser.psess.gated_spans.gate(sym::let_chains, span);
                 }
             }
             ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, _, _) => {
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index e059e707491..263b2a90643 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -420,7 +420,7 @@ impl<'a> Parser<'a> {
                         type_err.cancel();
 
                         let body_sp = pred_lo.to(snapshot.prev_token.span);
-                        let map = self.sess.source_map();
+                        let map = self.psess.source_map();
 
                         self.dcx().emit_err(WhereClauseBeforeTupleStructBody {
                             span: where_sp,
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index d8587f1340a..79492fe62ed 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -563,7 +563,7 @@ impl<'a> Parser<'a> {
 
         let constness = self.parse_constness(Case::Sensitive);
         if let Const::Yes(span) = constness {
-            self.sess.gated_spans.gate(sym::const_trait_impl, span);
+            self.psess.gated_spans.gate(sym::const_trait_impl, span);
         }
 
         // Parse stray `impl async Trait`
@@ -699,7 +699,7 @@ impl<'a> Parser<'a> {
             None
         };
         let span = span.to(self.prev_token.span);
-        self.sess.gated_spans.gate(sym::fn_delegation, span);
+        self.psess.gated_spans.gate(sym::fn_delegation, span);
 
         let ident = path.segments.last().map(|seg| seg.ident).unwrap_or(Ident::empty());
         Ok((
@@ -859,7 +859,7 @@ impl<'a> Parser<'a> {
         let unsafety = self.parse_unsafety(Case::Sensitive);
         // Parse optional `auto` prefix.
         let is_auto = if self.eat_keyword(kw::Auto) {
-            self.sess.gated_spans.gate(sym::auto_traits, self.prev_token.span);
+            self.psess.gated_spans.gate(sym::auto_traits, self.prev_token.span);
             IsAuto::Yes
         } else {
             IsAuto::No
@@ -894,7 +894,7 @@ impl<'a> Parser<'a> {
                 self.dcx().emit_err(errors::TraitAliasCannotBeUnsafe { span: whole_span });
             }
 
-            self.sess.gated_spans.gate(sym::trait_alias, whole_span);
+            self.psess.gated_spans.gate(sym::trait_alias, whole_span);
 
             Ok((ident, ItemKind::TraitAlias(generics, bounds)))
         } else {
@@ -1209,7 +1209,7 @@ impl<'a> Parser<'a> {
 
     fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &'static str) -> Option<T> {
         // FIXME(#100717): needs variant for each `ItemKind` (instead of using `ItemKind::descr()`)
-        let span = self.sess.source_map().guess_head_span(span);
+        let span = self.psess.source_map().guess_head_span(span);
         let descr = kind.descr();
         self.dcx().emit_err(errors::BadItemKind { span, descr, ctx });
         None
@@ -1332,7 +1332,7 @@ impl<'a> Parser<'a> {
         // Check the span for emptiness instead of the list of parameters in order to correctly
         // recognize and subsequently flag empty parameter lists (`<>`) as unstable.
         if !generics.span.is_empty() {
-            self.sess.gated_spans.gate(sym::generic_const_items, generics.span);
+            self.psess.gated_spans.gate(sym::generic_const_items, generics.span);
         }
 
         // Parse the type of a constant item. That is, the `":" $ty` fragment.
@@ -1366,7 +1366,7 @@ impl<'a> Parser<'a> {
                 name: ident.span,
                 body: expr.span,
                 sugg: if !after_where_clause.has_where_token {
-                    self.sess.source_map().span_to_snippet(expr.span).ok().map(|body| {
+                    self.psess.source_map().span_to_snippet(expr.span).ok().map(|body| {
                         errors::WhereClauseBeforeConstBodySugg {
                             left: before_where_clause.span.shrink_to_lo(),
                             snippet: body,
@@ -1401,7 +1401,7 @@ impl<'a> Parser<'a> {
         };
 
         if where_clause.has_where_token {
-            self.sess.gated_spans.gate(sym::generic_const_items, where_clause.span);
+            self.psess.gated_spans.gate(sym::generic_const_items, where_clause.span);
         }
 
         generics.where_clause = where_clause;
@@ -1898,7 +1898,7 @@ impl<'a> Parser<'a> {
 
     fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> {
         if let Err(err) = self.expect(&token::Colon) {
-            let sm = self.sess.source_map();
+            let sm = self.psess.source_map();
             let eq_typo = self.token.kind == token::Eq && self.look_ahead(1, |t| t.is_path_start());
             let semi_typo = self.token.kind == token::Semi
                 && self.look_ahead(1, |t| {
@@ -1970,7 +1970,7 @@ impl<'a> Parser<'a> {
     fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
         let (ident, is_raw) = self.ident_or_err(true)?;
         if ident.name == kw::Underscore {
-            self.sess.gated_spans.gate(sym::unnamed_fields, lo);
+            self.psess.gated_spans.gate(sym::unnamed_fields, lo);
         } else if matches!(is_raw, IdentIsRaw::No) && ident.is_reserved() {
             let snapshot = self.create_snapshot_for_diagnostic();
             let err = if self.check_fn_front_matter(false, Case::Sensitive) {
@@ -2080,7 +2080,7 @@ impl<'a> Parser<'a> {
             return self.unexpected();
         };
 
-        self.sess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
+        self.psess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span));
         Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: false })))
     }
 
@@ -2460,7 +2460,7 @@ impl<'a> Parser<'a> {
 
         match coroutine_kind {
             Some(CoroutineKind::Gen { span, .. }) | Some(CoroutineKind::AsyncGen { span, .. }) => {
-                self.sess.gated_spans.gate(sym::gen_blocks, span);
+                self.psess.gated_spans.gate(sym::gen_blocks, span);
             }
             Some(CoroutineKind::Async { .. }) | None => {}
         }
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 8542ea62310..12879dc429b 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -128,7 +128,7 @@ pub enum Recovery {
 
 #[derive(Clone)]
 pub struct Parser<'a> {
-    pub sess: &'a ParseSess,
+    pub psess: &'a ParseSess,
     /// The current token.
     pub token: Token,
     /// The spacing for the current token.
@@ -414,12 +414,12 @@ pub(super) fn token_descr(token: &Token) -> String {
 
 impl<'a> Parser<'a> {
     pub fn new(
-        sess: &'a ParseSess,
+        psess: &'a ParseSess,
         stream: TokenStream,
         subparser_name: Option<&'static str>,
     ) -> Self {
         let mut parser = Parser {
-            sess,
+            psess,
             token: Token::dummy(),
             token_spacing: Spacing::Alone,
             prev_token: Token::dummy(),
@@ -714,7 +714,7 @@ impl<'a> Parser<'a> {
         }
         match self.token.kind.break_two_token_op() {
             Some((first, second)) if first == expected => {
-                let first_span = self.sess.source_map().start_point(self.token.span);
+                let first_span = self.psess.source_map().start_point(self.token.span);
                 let second_span = self.token.span.with_lo(first_span.hi());
                 self.token = Token::new(first, first_span);
                 // Keep track of this token - if we end token capturing now,
@@ -1213,7 +1213,7 @@ impl<'a> Parser<'a> {
     fn parse_closure_constness(&mut self) -> Const {
         let constness = self.parse_constness_(Case::Sensitive, true);
         if let Const::Yes(span) = constness {
-            self.sess.gated_spans.gate(sym::const_closures, span);
+            self.psess.gated_spans.gate(sym::const_closures, span);
         }
         constness
     }
@@ -1234,9 +1234,9 @@ impl<'a> Parser<'a> {
     /// Parses inline const expressions.
     fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P<Expr>> {
         if pat {
-            self.sess.gated_spans.gate(sym::inline_const_pat, span);
+            self.psess.gated_spans.gate(sym::inline_const_pat, span);
         } else {
-            self.sess.gated_spans.gate(sym::inline_const, span);
+            self.psess.gated_spans.gate(sym::inline_const, span);
         }
         self.eat_keyword(kw::Const);
         let (attrs, blk) = self.parse_inner_attrs_and_block()?;
@@ -1521,7 +1521,7 @@ impl<'a> Parser<'a> {
 
 pub(crate) fn make_unclosed_delims_error(
     unmatched: UnmatchedDelim,
-    sess: &ParseSess,
+    psess: &ParseSess,
 ) -> Option<Diag<'_>> {
     // `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to
     // `unmatched_delims` only for error recovery in the `Parser`.
@@ -1530,7 +1530,7 @@ pub(crate) fn make_unclosed_delims_error(
     if let Some(sp) = unmatched.unclosed_span {
         spans.push(sp);
     };
-    let err = sess.dcx.create_err(MismatchedClosingDelimiter {
+    let err = psess.dcx.create_err(MismatchedClosingDelimiter {
         spans,
         delimiter: pprust::token_kind_to_string(&token::CloseDelim(found_delim)).to_string(),
         unmatched: unmatched.found_span,
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 7aeab6488a5..88ae1b5420f 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -470,7 +470,7 @@ impl<'a> Parser<'a> {
             self.parse_pat_range_to(form)? // `..=X`, `...X`, or `..X`.
         } else if self.eat(&token::Not) {
             // Parse `!`
-            self.sess.gated_spans.gate(sym::never_patterns, self.prev_token.span);
+            self.psess.gated_spans.gate(sym::never_patterns, self.prev_token.span);
             PatKind::Never
         } else if self.eat_keyword(kw::Underscore) {
             // Parse `_`
@@ -843,8 +843,8 @@ impl<'a> Parser<'a> {
         let mut err = self.dcx().struct_span_err(self.token.span, msg);
         err.span_label(self.token.span, format!("expected {expected}"));
 
-        let sp = self.sess.source_map().start_point(self.token.span);
-        if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
+        let sp = self.psess.source_map().start_point(self.token.span);
+        if let Some(sp) = self.psess.ambiguous_block_expr_parse.borrow().get(&sp) {
             err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp));
         }
 
@@ -1067,7 +1067,7 @@ impl<'a> Parser<'a> {
     fn parse_pat_struct(&mut self, qself: Option<P<QSelf>>, path: Path) -> PResult<'a, PatKind> {
         if qself.is_some() {
             // Feature gate the use of qualified paths in patterns
-            self.sess.gated_spans.gate(sym::more_qualified_paths, path.span);
+            self.psess.gated_spans.gate(sym::more_qualified_paths, path.span);
         }
         self.bump();
         let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| {
@@ -1096,7 +1096,7 @@ impl<'a> Parser<'a> {
             )
         })?;
         if qself.is_some() {
-            self.sess.gated_spans.gate(sym::more_qualified_paths, path.span);
+            self.psess.gated_spans.gate(sym::more_qualified_paths, path.span);
         }
         Ok(PatKind::TupleStruct(qself, path, fields))
     }
@@ -1143,7 +1143,7 @@ impl<'a> Parser<'a> {
             Ok(PatKind::Ident(BindingAnnotation::NONE, Ident::new(kw::Box, box_span), sub))
         } else {
             let pat = self.parse_pat_with_range_pat(false, None, None)?;
-            self.sess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span));
+            self.psess.gated_spans.gate(sym::box_patterns, box_span.to(self.prev_token.span));
             Ok(PatKind::Box(pat))
         }
     }
@@ -1192,15 +1192,15 @@ impl<'a> Parser<'a> {
                         .look_ahead(1, |t| if *t == token::Comma { Some(t.clone()) } else { None })
                     {
                         let nw_span = self
-                            .sess
+                            .psess
                             .source_map()
                             .span_extend_to_line(comma_tok.span)
                             .trim_start(comma_tok.span.shrink_to_lo())
-                            .map(|s| self.sess.source_map().span_until_non_whitespace(s));
+                            .map(|s| self.psess.source_map().span_until_non_whitespace(s));
                         first_etc_and_maybe_comma_span = nw_span.map(|s| etc_sp.to(s));
                     } else {
                         first_etc_and_maybe_comma_span =
-                            Some(self.sess.source_map().span_until_non_whitespace(etc_sp));
+                            Some(self.psess.source_map().span_until_non_whitespace(etc_sp));
                     }
                 }
 
@@ -1218,7 +1218,8 @@ impl<'a> Parser<'a> {
                 let mut comma_sp = None;
                 if self.token == token::Comma {
                     // Issue #49257
-                    let nw_span = self.sess.source_map().span_until_non_whitespace(self.token.span);
+                    let nw_span =
+                        self.psess.source_map().span_until_non_whitespace(self.token.span);
                     etc_sp = etc_sp.to(nw_span);
                     err.span_label(
                         etc_sp,
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 6e7bbe7e06d..545db5138a3 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -250,7 +250,7 @@ impl<'a> Parser<'a> {
                         self.dcx().emit_err(PathSingleColon {
                             span: self.prev_token.span,
                             type_ascription: self
-                                .sess
+                                .psess
                                 .unstable_features
                                 .is_nightly_build()
                                 .then_some(()),
@@ -322,7 +322,7 @@ impl<'a> Parser<'a> {
                             err = self.dcx().create_err(PathSingleColon {
                                 span: self.token.span,
                                 type_ascription: self
-                                    .sess
+                                    .psess
                                     .unstable_features
                                     .is_nightly_build()
                                     .then_some(()),
@@ -638,9 +638,9 @@ impl<'a> Parser<'a> {
                             && args.inputs.is_empty()
                             && matches!(args.output, ast::FnRetTy::Default(..))
                         {
-                            self.sess.gated_spans.gate(sym::return_type_notation, span);
+                            self.psess.gated_spans.gate(sym::return_type_notation, span);
                         } else {
-                            self.sess.gated_spans.gate(sym::associated_type_bounds, span);
+                            self.psess.gated_spans.gate(sym::associated_type_bounds, span);
                         }
                     }
                     let constraint =
@@ -675,7 +675,7 @@ impl<'a> Parser<'a> {
         let term = match arg {
             Some(GenericArg::Type(ty)) => ty.into(),
             Some(GenericArg::Const(c)) => {
-                self.sess.gated_spans.gate(sym::associated_const_equality, span);
+                self.psess.gated_spans.gate(sym::associated_const_equality, span);
                 c.into()
             }
             Some(GenericArg::Lifetime(lt)) => {
@@ -691,7 +691,7 @@ impl<'a> Parser<'a> {
                     .struct_span_err(after_eq.to(before_next), "missing type to the right of `=`");
                 if matches!(self.token.kind, token::Comma | token::Gt) {
                     err.span_suggestion(
-                        self.sess.source_map().next_point(eq).to(before_next),
+                        self.psess.source_map().next_point(eq).to(before_next),
                         "to constrain the associated type, add a type after `=`",
                         " TheType",
                         Applicability::HasPlaceholders,
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 65c0f7d49c1..73f5829adec 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -230,7 +230,7 @@ impl<'a> Parser<'a> {
     /// Also error if the previous token was a doc comment.
     fn error_outer_attrs(&self, attrs: AttrWrapper) {
         if !attrs.is_empty()
-            && let attrs @ [.., last] = &*attrs.take_for_recovery(self.sess)
+            && let attrs @ [.., last] = &*attrs.take_for_recovery(self.psess)
         {
             if last.is_doc_comment() {
                 self.dcx().emit_err(errors::DocCommentDoesNotDocumentAnything {
@@ -448,7 +448,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a block. No inner attributes are allowed.
-    pub(super) fn parse_block(&mut self) -> PResult<'a, P<Block>> {
+    pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
         let (attrs, block) = self.parse_inner_attrs_and_block()?;
         if let [.., last] = &*attrs {
             self.error_on_forbidden_inner_attr(
@@ -494,7 +494,7 @@ impl<'a> Parser<'a> {
             // Do not suggest `if foo println!("") {;}` (as would be seen in test for #46836).
             Ok(Some(Stmt { kind: StmtKind::Empty, .. })) => {}
             Ok(Some(stmt)) => {
-                let stmt_own_line = self.sess.source_map().is_line_before_span_empty(sp);
+                let stmt_own_line = self.psess.source_map().is_line_before_span_empty(sp);
                 let stmt_span = if stmt_own_line && self.eat(&token::Semi) {
                     // Expand the span to include the semicolon.
                     stmt.span.with_hi(self.prev_token.span.hi())
@@ -613,7 +613,7 @@ impl<'a> Parser<'a> {
                                     Applicability::MaybeIncorrect,
                                 );
                             }
-                            if self.sess.unstable_features.is_nightly_build() {
+                            if self.psess.unstable_features.is_nightly_build() {
                                 // FIXME(Nilstrieb): Remove this again after a few months.
                                 err.note("type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>");
                             }
@@ -787,13 +787,17 @@ impl<'a> Parser<'a> {
                             let suggest_eq = if self.token.kind == token::Dot
                                 && let _ = self.bump()
                                 && let mut snapshot = self.create_snapshot_for_diagnostic()
-                                && let Ok(_) = snapshot.parse_dot_suffix_expr(
-                                    colon_sp,
-                                    self.mk_expr_err(
+                                && let Ok(_) = snapshot
+                                    .parse_dot_suffix_expr(
                                         colon_sp,
-                                        self.dcx().delayed_bug("error during `:` -> `=` recovery"),
-                                    ),
-                                ) {
+                                        self.mk_expr_err(
+                                            colon_sp,
+                                            self.dcx()
+                                                .delayed_bug("error during `:` -> `=` recovery"),
+                                        ),
+                                    )
+                                    .map_err(Diag::cancel)
+                            {
                                 true
                             } else if let Some(op) = self.check_assoc_op()
                                 && op.node.can_continue_expr_unambiguously()
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index e3fe535bd5f..2385c18c089 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -397,7 +397,7 @@ impl<'a> Parser<'a> {
         let (fields, _recovered) =
             self.parse_record_struct_body(if is_union { "union" } else { "struct" }, lo, false)?;
         let span = lo.to(self.prev_token.span);
-        self.sess.gated_spans.gate(sym::unnamed_fields, span);
+        self.psess.gated_spans.gate(sym::unnamed_fields, span);
         let id = ast::DUMMY_NODE_ID;
         let kind =
             if is_union { TyKind::AnonUnion(id, fields) } else { TyKind::AnonStruct(id, fields) };
@@ -694,7 +694,7 @@ impl<'a> Parser<'a> {
 
         // parse dyn* types
         let syntax = if self.eat(&TokenKind::BinOp(token::Star)) {
-            self.sess.gated_spans.gate(sym::dyn_star, lo.to(self.prev_token.span));
+            self.psess.gated_spans.gate(sym::dyn_star, lo.to(self.prev_token.span));
             TraitObjectSyntax::DynStar
         } else {
             TraitObjectSyntax::Dyn
@@ -874,10 +874,10 @@ impl<'a> Parser<'a> {
             let tilde = self.prev_token.span;
             self.expect_keyword(kw::Const)?;
             let span = tilde.to(self.prev_token.span);
-            self.sess.gated_spans.gate(sym::const_trait_impl, span);
+            self.psess.gated_spans.gate(sym::const_trait_impl, span);
             BoundConstness::Maybe(span)
         } else if self.eat_keyword(kw::Const) {
-            self.sess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span);
+            self.psess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span);
             BoundConstness::Always(self.prev_token.span)
         } else {
             BoundConstness::Never
@@ -886,7 +886,7 @@ impl<'a> Parser<'a> {
         let asyncness = if self.token.uninterpolated_span().at_least_rust_2018()
             && self.eat_keyword(kw::Async)
         {
-            self.sess.gated_spans.gate(sym::async_closure, self.prev_token.span);
+            self.psess.gated_spans.gate(sym::async_closure, self.prev_token.span);
             BoundAsyncness::Async(self.prev_token.span)
         } else if self.may_recover()
             && self.token.uninterpolated_span().is_rust_2015()
@@ -897,7 +897,7 @@ impl<'a> Parser<'a> {
                 span: self.prev_token.span,
                 help: HelpUseLatestEdition::new(),
             });
-            self.sess.gated_spans.gate(sym::async_closure, self.prev_token.span);
+            self.psess.gated_spans.gate(sym::async_closure, self.prev_token.span);
             BoundAsyncness::Async(self.prev_token.span)
         } else {
             BoundAsyncness::Normal
@@ -906,7 +906,7 @@ impl<'a> Parser<'a> {
         let polarity = if self.eat(&token::Question) {
             BoundPolarity::Maybe(self.prev_token.span)
         } else if self.eat(&token::Not) {
-            self.sess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);
+            self.psess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);
             BoundPolarity::Negative(self.prev_token.span)
         } else {
             BoundPolarity::Positive
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 73c92708eb3..f88edf29dce 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -13,7 +13,7 @@ use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
 use rustc_session::parse::ParseSess;
 use rustc_span::{sym, Span, Symbol};
 
-pub fn check_attr(sess: &ParseSess, attr: &Attribute) {
+pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
     if attr.is_doc_comment() {
         return;
     }
@@ -24,11 +24,11 @@ pub fn check_attr(sess: &ParseSess, attr: &Attribute) {
     match attr_info {
         // `rustc_dummy` doesn't have any restrictions specific to built-in attributes.
         Some(BuiltinAttribute { name, template, .. }) if *name != sym::rustc_dummy => {
-            check_builtin_attribute(sess, attr, *name, *template)
+            check_builtin_attribute(psess, attr, *name, *template)
         }
         _ if let AttrArgs::Eq(..) = attr.get_normal_item().args => {
             // All key-value attributes are restricted to meta-item syntax.
-            parse_meta(sess, attr)
+            parse_meta(psess, attr)
                 .map_err(|err| {
                     err.emit();
                 })
@@ -38,7 +38,7 @@ pub fn check_attr(sess: &ParseSess, attr: &Attribute) {
     }
 }
 
-pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, MetaItem> {
+pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, MetaItem> {
     let item = attr.get_normal_item();
     Ok(MetaItem {
         span: attr.span,
@@ -46,8 +46,9 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta
         kind: match &item.args {
             AttrArgs::Empty => MetaItemKind::Word,
             AttrArgs::Delimited(DelimArgs { dspan, delim, tokens }) => {
-                check_meta_bad_delim(sess, *dspan, *delim);
-                let nmis = parse_in(sess, tokens.clone(), "meta list", |p| p.parse_meta_seq_top())?;
+                check_meta_bad_delim(psess, *dspan, *delim);
+                let nmis =
+                    parse_in(psess, tokens.clone(), "meta list", |p| p.parse_meta_seq_top())?;
                 MetaItemKind::List(nmis)
             }
             AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => {
@@ -56,7 +57,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta
                     let res = match res {
                         Ok(lit) => {
                             if token_lit.suffix.is_some() {
-                                let mut err = sess.dcx.struct_span_err(
+                                let mut err = psess.dcx.struct_span_err(
                                     expr.span,
                                     "suffixed literals are not allowed in attributes",
                                 );
@@ -70,7 +71,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta
                             }
                         }
                         Err(err) => {
-                            let guar = report_lit_error(sess, err, token_lit, expr.span);
+                            let guar = report_lit_error(psess, err, token_lit, expr.span);
                             let lit = ast::MetaItemLit {
                                 symbol: token_lit.symbol,
                                 suffix: token_lit.suffix,
@@ -89,7 +90,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta
                     //   the error because an earlier error will have already
                     //   been reported.
                     let msg = "attribute value must be a literal";
-                    let mut err = sess.dcx.struct_span_err(expr.span, msg);
+                    let mut err = psess.dcx.struct_span_err(expr.span, msg);
                     if let ast::ExprKind::Err(_) = expr.kind {
                         err.downgrade_to_delayed_bug();
                     }
@@ -101,21 +102,21 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta
     })
 }
 
-pub fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: Delimiter) {
+pub fn check_meta_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) {
     if let Delimiter::Parenthesis = delim {
         return;
     }
-    sess.dcx.emit_err(errors::MetaBadDelim {
+    psess.dcx.emit_err(errors::MetaBadDelim {
         span: span.entire(),
         sugg: errors::MetaBadDelimSugg { open: span.open, close: span.close },
     });
 }
 
-pub fn check_cfg_attr_bad_delim(sess: &ParseSess, span: DelimSpan, delim: Delimiter) {
+pub fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) {
     if let Delimiter::Parenthesis = delim {
         return;
     }
-    sess.dcx.emit_err(errors::CfgAttrBadDelim {
+    psess.dcx.emit_err(errors::CfgAttrBadDelim {
         span: span.entire(),
         sugg: errors::MetaBadDelimSugg { open: span.open, close: span.close },
     });
@@ -132,13 +133,13 @@ fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaIte
 }
 
 pub fn check_builtin_attribute(
-    sess: &ParseSess,
+    psess: &ParseSess,
     attr: &Attribute,
     name: Symbol,
     template: AttributeTemplate,
 ) {
-    match parse_meta(sess, attr) {
-        Ok(meta) => check_builtin_meta_item(sess, &meta, attr.style, name, template),
+    match parse_meta(psess, attr) {
+        Ok(meta) => check_builtin_meta_item(psess, &meta, attr.style, name, template),
         Err(err) => {
             err.emit();
         }
@@ -146,7 +147,7 @@ pub fn check_builtin_attribute(
 }
 
 pub fn check_builtin_meta_item(
-    sess: &ParseSess,
+    psess: &ParseSess,
     meta: &MetaItem,
     style: ast::AttrStyle,
     name: Symbol,
@@ -157,12 +158,12 @@ pub fn check_builtin_meta_item(
     let should_skip = |name| name == sym::cfg;
 
     if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) {
-        emit_malformed_attribute(sess, style, meta.span, name, template);
+        emit_malformed_attribute(psess, style, meta.span, name, template);
     }
 }
 
 fn emit_malformed_attribute(
-    sess: &ParseSess,
+    psess: &ParseSess,
     style: ast::AttrStyle,
     span: Span,
     name: Symbol,
@@ -204,9 +205,10 @@ fn emit_malformed_attribute(
     }
     suggestions.sort();
     if should_warn(name) {
-        sess.buffer_lint(ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, msg);
+        psess.buffer_lint(ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, msg);
     } else {
-        sess.dcx
+        psess
+            .dcx
             .struct_span_err(span, error_msg)
             .with_span_suggestions(
                 span,
@@ -223,12 +225,12 @@ fn emit_malformed_attribute(
 }
 
 pub fn emit_fatal_malformed_builtin_attribute(
-    sess: &ParseSess,
+    psess: &ParseSess,
     attr: &Attribute,
     name: Symbol,
 ) -> ! {
     let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").template;
-    emit_malformed_attribute(sess, attr.style, attr.span, name, template);
+    emit_malformed_attribute(psess, attr.style, attr.span, name, template);
     // This is fatal, otherwise it will likely cause a cascade of other errors
     // (and an error here is expected to be very rare).
     FatalError.raise()
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 04c0cf7436e..a99db9cb8cc 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1074,6 +1074,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
     /// of one item. Read the documentation of [`check_doc_inline`] for more information.
     ///
     /// [`check_doc_inline`]: Self::check_doc_inline
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn check_doc_attrs(
         &self,
         attr: &Attribute,
@@ -1756,6 +1757,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
     }
 
     /// Checks if the `#[repr]` attributes on `item` are valid.
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn check_repr(
         &self,
         attrs: &[Attribute],
@@ -2328,6 +2330,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
 
             let hir_sig = tcx.hir().fn_sig_by_hir_id(hir_id);
             if let Some(hir_sig) = hir_sig {
+                #[allow(rustc::diagnostic_outside_of_impl)] // FIXME
                 match terr {
                     TypeError::ArgumentMutability(idx) | TypeError::ArgumentSorts(_, idx) => {
                         if let Some(ty) = hir_sig.decl.inputs.get(idx) {
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index 02792491f5e..30a65d69c4e 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -77,6 +77,7 @@ impl<'tcx> CheckConstVisitor<'tcx> {
     }
 
     /// Emits an error when an unsupported expression is found in a const context.
+    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
     fn const_check_violated(&self, expr: NonConstExpr, span: Span) {
         let Self { tcx, def_id, const_kind } = *self;
 
diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs
index 4bfe6be5493..96893e58549 100644
--- a/compiler/rustc_passes/src/debugger_visualizer.rs
+++ b/compiler/rustc_passes/src/debugger_visualizer.rs
@@ -87,7 +87,7 @@ impl<'ast> rustc_ast::visit::Visitor<'ast> for DebuggerVisualizerCollector<'_> {
 
 /// Traverses and collects the debugger visualizers for a specific crate.
 fn debugger_visualizers(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec<DebuggerVisualizerFile> {
-    let resolver_and_krate = tcx.resolver_for_lowering(()).borrow();
+    let resolver_and_krate = tcx.resolver_for_lowering().borrow();
     let krate = &*resolver_and_krate.1;
 
     let mut visitor = DebuggerVisualizerCollector { sess: tcx.sess, visualizers: Vec::new() };
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index 97c70e327f0..5246389248e 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -114,6 +114,7 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
     }
 }
 
+#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
 fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> {
     if let Some((def_id, _)) = visitor.start_fn {
         Some((def_id.to_def_id(), EntryFnType::Start))
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 5f412bde2ee..69104a30495 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -7,7 +7,7 @@ use crate::fluent_generated as fluent;
 use rustc_ast::Label;
 use rustc_errors::{
     codes::*, AddToDiagnostic, Applicability, Diag, DiagCtxt, DiagSymbolList, EmissionGuarantee,
-    IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessageOp,
+    IntoDiagnostic, Level, MultiSpan, SubdiagMessageOp,
 };
 use rustc_hir::{self as hir, ExprKind, Target};
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@@ -1752,7 +1752,7 @@ pub struct UnusedVariableStringInterp {
 }
 
 impl AddToDiagnostic for UnusedVariableStringInterp {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs
index 02f56ecb10b..dd6c1166957 100644
--- a/compiler/rustc_passes/src/hir_id_validator.rs
+++ b/compiler/rustc_passes/src/hir_id_validator.rs
@@ -1,38 +1,26 @@
 use rustc_data_structures::sync::Lock;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::intravisit;
-use rustc_hir::{HirId, ItemLocalId};
+use rustc_hir::{intravisit, HirId, ItemLocalId};
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::TyCtxt;
 
 pub fn check_crate(tcx: TyCtxt<'_>) {
-    if tcx.sess.opts.unstable_opts.hir_stats {
-        crate::hir_stats::print_hir_stats(tcx);
-    }
+    let errors = Lock::new(Vec::new());
 
-    #[cfg(debug_assertions)]
-    {
-        let errors = Lock::new(Vec::new());
+    tcx.hir().par_for_each_module(|module_id| {
+        let mut v =
+            HirIdValidator { tcx, owner: None, hir_ids_seen: Default::default(), errors: &errors };
 
-        tcx.hir().par_for_each_module(|module_id| {
-            let mut v = HirIdValidator {
-                tcx,
-                owner: None,
-                hir_ids_seen: Default::default(),
-                errors: &errors,
-            };
+        tcx.hir().visit_item_likes_in_module(module_id, &mut v);
+    });
 
-            tcx.hir().visit_item_likes_in_module(module_id, &mut v);
-        });
+    let errors = errors.into_inner();
 
-        let errors = errors.into_inner();
-
-        if !errors.is_empty() {
-            let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2);
-            tcx.dcx().delayed_bug(message);
-        }
+    if !errors.is_empty() {
+        let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2);
+        tcx.dcx().delayed_bug(message);
     }
 }
 
@@ -90,7 +78,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> {
             self.error(|| {
                 format!(
                     "ItemLocalIds not assigned densely in {pretty_owner}. \
-                Max ItemLocalId = {max}, missing IDs = {missing_items:#?}; seen IDs = {seen_items:#?}"
+            Max ItemLocalId = {max}, missing IDs = {missing_items:#?}; seen IDs = {seen_items:#?}"
                 )
             });
         }
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index d3e3e183845..d1368267224 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -243,7 +243,7 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> {
 
 /// Traverses and collects all the lang items in all crates.
 fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
-    let resolver = tcx.resolver_for_lowering(()).borrow();
+    let resolver = tcx.resolver_for_lowering().borrow();
     let (resolver, krate) = &*resolver;
 
     // Initialize the collector.
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 7227b185f4d..e03052bcfed 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -28,6 +28,7 @@ mod debugger_visualizer;
 mod diagnostic_items;
 pub mod entry;
 mod errors;
+#[cfg(debug_assertions)]
 pub mod hir_id_validator;
 pub mod hir_stats;
 mod lang_items;
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 487407014d1..e5033e1f51f 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -86,7 +86,6 @@ use crate::errors;
 use self::LiveNodeKind::*;
 use self::VarKind::*;
 
-use rustc_ast::InlineAsmOptions;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir as hir;
 use rustc_hir::def::*;
@@ -416,6 +415,12 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
                 self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id));
             }
 
+            // Inline assembly may contain labels.
+            hir::ExprKind::InlineAsm(asm) if asm.contains_label() => {
+                self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id));
+                intravisit::walk_expr(self, expr);
+            }
+
             // otherwise, live nodes are not required:
             hir::ExprKind::Index(..)
             | hir::ExprKind::Field(..)
@@ -1045,20 +1050,53 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             | hir::ExprKind::Repeat(ref e, _) => self.propagate_through_expr(e, succ),
 
             hir::ExprKind::InlineAsm(asm) => {
-                // Handle non-returning asm
-                let mut succ = if asm.options.contains(InlineAsmOptions::NORETURN) {
-                    self.exit_ln
-                } else {
-                    succ
-                };
+                //
+                //     (inputs)
+                //        |
+                //        v
+                //     (outputs)
+                //    /         \
+                //    |         |
+                //    v         v
+                // (labels)(fallthrough)
+                //    |         |
+                //    v         v
+                // ( succ / exit_ln )
 
-                // Do a first pass for writing outputs only
+                // Handle non-returning asm
+                let mut succ =
+                    if self.typeck_results.expr_ty(expr).is_never() { self.exit_ln } else { succ };
+
+                // Do a first pass for labels only
+                if asm.contains_label() {
+                    let ln = self.live_node(expr.hir_id, expr.span);
+                    self.init_from_succ(ln, succ);
+                    for (op, _op_sp) in asm.operands.iter().rev() {
+                        match op {
+                            hir::InlineAsmOperand::Label { block } => {
+                                let label_ln = self.propagate_through_block(block, succ);
+                                self.merge_from_succ(ln, label_ln);
+                            }
+                            hir::InlineAsmOperand::In { .. }
+                            | hir::InlineAsmOperand::Out { .. }
+                            | hir::InlineAsmOperand::InOut { .. }
+                            | hir::InlineAsmOperand::SplitInOut { .. }
+                            | hir::InlineAsmOperand::Const { .. }
+                            | hir::InlineAsmOperand::SymFn { .. }
+                            | hir::InlineAsmOperand::SymStatic { .. } => {}
+                        }
+                    }
+                    succ = ln;
+                }
+
+                // Do a second pass for writing outputs only
                 for (op, _op_sp) in asm.operands.iter().rev() {
                     match op {
                         hir::InlineAsmOperand::In { .. }
                         | hir::InlineAsmOperand::Const { .. }
                         | hir::InlineAsmOperand::SymFn { .. }
-                        | hir::InlineAsmOperand::SymStatic { .. } => {}
+                        | hir::InlineAsmOperand::SymStatic { .. }
+                        | hir::InlineAsmOperand::Label { .. } => {}
                         hir::InlineAsmOperand::Out { expr, .. } => {
                             if let Some(expr) = expr {
                                 succ = self.write_place(expr, succ, ACC_WRITE);
@@ -1075,7 +1113,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                     }
                 }
 
-                // Then do a second pass for inputs
+                // Then do a third pass for inputs
                 for (op, _op_sp) in asm.operands.iter().rev() {
                     match op {
                         hir::InlineAsmOperand::In { expr, .. } => {
@@ -1097,7 +1135,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                         }
                         hir::InlineAsmOperand::Const { .. }
                         | hir::InlineAsmOperand::SymFn { .. }
-                        | hir::InlineAsmOperand::SymStatic { .. } => {}
+                        | hir::InlineAsmOperand::SymStatic { .. }
+                        | hir::InlineAsmOperand::Label { .. } => {}
                     }
                 }
                 succ
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index 0455d6d4acb..27c9c1306e6 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -237,7 +237,8 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
                 InlineAsmOperand::In { .. }
                 | InlineAsmOperand::Out { .. }
                 | InlineAsmOperand::InOut { .. }
-                | InlineAsmOperand::SplitInOut { .. } => Some(op_sp),
+                | InlineAsmOperand::SplitInOut { .. }
+                | InlineAsmOperand::Label { .. } => Some(op_sp),
             })
             .collect();
         if !unsupported_operands.is_empty() {
diff --git a/compiler/rustc_pattern_analysis/messages.ftl b/compiler/rustc_pattern_analysis/messages.ftl
index 827928f97d7..41a1d958f10 100644
--- a/compiler/rustc_pattern_analysis/messages.ftl
+++ b/compiler/rustc_pattern_analysis/messages.ftl
@@ -1,3 +1,11 @@
+pattern_analysis_excluside_range_missing_gap = multiple ranges are one apart
+    .label = this range doesn't match `{$gap}` because `..` is an exclusive range
+    .suggestion = use an inclusive range instead
+
+pattern_analysis_excluside_range_missing_max = exclusive range missing `{$max}`
+    .label = this range doesn't match `{$max}` because `..` is an exclusive range
+    .suggestion = use an inclusive range instead
+
 pattern_analysis_non_exhaustive_omitted_pattern = some variants are not matched explicitly
     .help = ensure that all variants are matched explicitly by adding the suggested match arms
     .note = the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found
diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs
index 767227619b0..69e294e47a5 100644
--- a/compiler/rustc_pattern_analysis/src/constructor.rs
+++ b/compiler/rustc_pattern_analysis/src/constructor.rs
@@ -192,7 +192,7 @@ impl fmt::Display for RangeEnd {
 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
 pub enum MaybeInfiniteInt {
     NegInfinity,
-    /// Encoded value. DO NOT CONSTRUCT BY HAND; use `new_finite`.
+    /// Encoded value. DO NOT CONSTRUCT BY HAND; use `new_finite_{int,uint}`.
     #[non_exhaustive]
     Finite(u128),
     /// The integer after `u128::MAX`. We need it to represent `x..=u128::MAX` as an exclusive range.
@@ -229,25 +229,22 @@ impl MaybeInfiniteInt {
     }
 
     /// Note: this will not turn a finite value into an infinite one or vice-versa.
-    pub fn minus_one(self) -> Self {
+    pub fn minus_one(self) -> Option<Self> {
         match self {
-            Finite(n) => match n.checked_sub(1) {
-                Some(m) => Finite(m),
-                None => panic!("Called `MaybeInfiniteInt::minus_one` on 0"),
-            },
-            JustAfterMax => Finite(u128::MAX),
-            x => x,
+            Finite(n) => n.checked_sub(1).map(Finite),
+            JustAfterMax => Some(Finite(u128::MAX)),
+            x => Some(x),
         }
     }
     /// Note: this will not turn a finite value into an infinite one or vice-versa.
-    pub fn plus_one(self) -> Self {
+    pub fn plus_one(self) -> Option<Self> {
         match self {
             Finite(n) => match n.checked_add(1) {
-                Some(m) => Finite(m),
-                None => JustAfterMax,
+                Some(m) => Some(Finite(m)),
+                None => Some(JustAfterMax),
             },
-            JustAfterMax => panic!("Called `MaybeInfiniteInt::plus_one` on u128::MAX+1"),
-            x => x,
+            JustAfterMax => None,
+            x => Some(x),
         }
     }
 }
@@ -268,18 +265,24 @@ impl IntRange {
     pub fn is_singleton(&self) -> bool {
         // Since `lo` and `hi` can't be the same `Infinity` and `plus_one` never changes from finite
         // to infinite, this correctly only detects ranges that contain exacly one `Finite(x)`.
-        self.lo.plus_one() == self.hi
+        self.lo.plus_one() == Some(self.hi)
     }
 
+    /// Construct a singleton range.
+    /// `x` must be a `Finite(_)` value.
     #[inline]
     pub fn from_singleton(x: MaybeInfiniteInt) -> IntRange {
-        IntRange { lo: x, hi: x.plus_one() }
+        // `unwrap()` is ok on a finite value
+        IntRange { lo: x, hi: x.plus_one().unwrap() }
     }
 
+    /// Construct a range with these boundaries.
+    /// `lo` must not be `PosInfinity` or `JustAfterMax`. `hi` must not be `NegInfinity`.
+    /// If `end` is `Included`, `hi` must also not be `JustAfterMax`.
     #[inline]
     pub fn from_range(lo: MaybeInfiniteInt, mut hi: MaybeInfiniteInt, end: RangeEnd) -> IntRange {
         if end == RangeEnd::Included {
-            hi = hi.plus_one();
+            hi = hi.plus_one().unwrap();
         }
         if lo >= hi {
             // This should have been caught earlier by E0030.
diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs
index 2d592b35159..e471b8abd73 100644
--- a/compiler/rustc_pattern_analysis/src/errors.rs
+++ b/compiler/rustc_pattern_analysis/src/errors.rs
@@ -1,4 +1,4 @@
-use rustc_errors::{AddToDiagnostic, Diag, EmissionGuarantee, SubdiagnosticMessageOp};
+use rustc_errors::{AddToDiagnostic, Diag, EmissionGuarantee, SubdiagMessageOp};
 use rustc_macros::{LintDiagnostic, Subdiagnostic};
 use rustc_middle::thir::Pat;
 use rustc_middle::ty::Ty;
@@ -62,7 +62,7 @@ pub struct Overlap<'tcx> {
 }
 
 impl<'tcx> AddToDiagnostic for Overlap<'tcx> {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _: F,
@@ -76,6 +76,57 @@ impl<'tcx> AddToDiagnostic for Overlap<'tcx> {
     }
 }
 
+#[derive(LintDiagnostic)]
+#[diag(pattern_analysis_excluside_range_missing_max)]
+pub struct ExclusiveRangeMissingMax<'tcx> {
+    #[label]
+    #[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")]
+    /// This is an exclusive range that looks like `lo..max` (i.e. doesn't match `max`).
+    pub first_range: Span,
+    /// Suggest `lo..=max` instead.
+    pub suggestion: String,
+    pub max: Pat<'tcx>,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(pattern_analysis_excluside_range_missing_gap)]
+pub struct ExclusiveRangeMissingGap<'tcx> {
+    #[label]
+    #[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")]
+    /// This is an exclusive range that looks like `lo..gap` (i.e. doesn't match `gap`).
+    pub first_range: Span,
+    pub gap: Pat<'tcx>,
+    /// Suggest `lo..=gap` instead.
+    pub suggestion: String,
+    #[subdiagnostic]
+    /// All these ranges skipped over `gap` which we think is probably a mistake.
+    pub gap_with: Vec<GappedRange<'tcx>>,
+}
+
+pub struct GappedRange<'tcx> {
+    pub span: Span,
+    pub gap: Pat<'tcx>,
+    pub first_range: Pat<'tcx>,
+}
+
+impl<'tcx> AddToDiagnostic for GappedRange<'tcx> {
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+        self,
+        diag: &mut Diag<'_, G>,
+        _: F,
+    ) {
+        let GappedRange { span, gap, first_range } = self;
+
+        // FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]`
+        // does not support `#[subdiagnostic(eager)]`...
+        let message = format!(
+            "this could appear to continue range `{first_range}`, but `{gap}` isn't matched by \
+            either of them"
+        );
+        diag.span_label(span, message);
+    }
+}
+
 #[derive(LintDiagnostic)]
 #[diag(pattern_analysis_non_exhaustive_omitted_pattern)]
 #[help]
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs
index 4b0955699fc..f632eaf7ea4 100644
--- a/compiler/rustc_pattern_analysis/src/lib.rs
+++ b/compiler/rustc_pattern_analysis/src/lib.rs
@@ -70,14 +70,8 @@ use rustc_middle::ty::Ty;
 use rustc_span::ErrorGuaranteed;
 
 use crate::constructor::{Constructor, ConstructorSet, IntRange};
-#[cfg(feature = "rustc")]
-use crate::lints::lint_nonexhaustive_missing_variants;
 use crate::pat::DeconstructedPat;
 use crate::pat_column::PatternColumn;
-#[cfg(feature = "rustc")]
-use crate::rustc::RustcMatchCheckCtxt;
-#[cfg(feature = "rustc")]
-use crate::usefulness::{compute_match_usefulness, ValidityConstraint};
 
 pub trait Captures<'a> {}
 impl<'a, T: ?Sized> Captures<'a> for T {}
@@ -145,6 +139,18 @@ pub trait TypeCx: Sized + fmt::Debug {
 
     /// The maximum pattern complexity limit was reached.
     fn complexity_exceeded(&self) -> Result<(), Self::Error>;
+
+    /// Lint that there is a gap `gap` between `pat` and all of `gapped_with` such that the gap is
+    /// not matched by another range. If `gapped_with` is empty, then `gap` is `T::MAX`. We only
+    /// detect singleton gaps.
+    /// The default implementation does nothing.
+    fn lint_non_contiguous_range_endpoints(
+        &self,
+        _pat: &DeconstructedPat<Self>,
+        _gap: IntRange,
+        _gapped_with: &[&DeconstructedPat<Self>],
+    ) {
+    }
 }
 
 /// The arm of a match expression.
@@ -167,11 +173,14 @@ impl<'p, Cx: TypeCx> Copy for MatchArm<'p, Cx> {}
 /// useful, and runs some lints.
 #[cfg(feature = "rustc")]
 pub fn analyze_match<'p, 'tcx>(
-    tycx: &RustcMatchCheckCtxt<'p, 'tcx>,
+    tycx: &rustc::RustcMatchCheckCtxt<'p, 'tcx>,
     arms: &[rustc::MatchArm<'p, 'tcx>],
     scrut_ty: Ty<'tcx>,
     pattern_complexity_limit: Option<usize>,
 ) -> Result<rustc::UsefulnessReport<'p, 'tcx>, ErrorGuaranteed> {
+    use lints::lint_nonexhaustive_missing_variants;
+    use usefulness::{compute_match_usefulness, ValidityConstraint};
+
     let scrut_ty = tycx.reveal_opaque_ty(scrut_ty);
     let scrut_validity = ValidityConstraint::from_bool(tycx.known_valid_scrutinee);
     let report =
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index 5f5bfa7154a..0085f0ab656 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -8,7 +8,7 @@ use rustc_index::{Idx, IndexVec};
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::{self, Const};
-use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange, PatRangeBoundary};
+use rustc_middle::thir::{self, FieldPat, Pat, PatKind, PatRange, PatRangeBoundary};
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::{self, FieldDef, OpaqueTypeKey, Ty, TyCtxt, TypeVisitableExt, VariantDef};
 use rustc_session::lint;
@@ -718,12 +718,12 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
                 let value = mir::Const::from_ty_const(c, cx.tcx);
                 lo = PatRangeBoundary::Finite(value);
             }
-            let hi = if matches!(range.hi, Finite(0)) {
+            let hi = if let Some(hi) = range.hi.minus_one() {
+                hi
+            } else {
                 // The range encodes `..ty::MIN`, so we can't convert it to an inclusive range.
                 end = rustc_hir::RangeEnd::Excluded;
                 range.hi
-            } else {
-                range.hi.minus_one()
             };
             let hi = cx.hoist_pat_range_bdy(hi, ty);
             PatKind::Range(Box::new(PatRange { lo, hi, end, ty: ty.inner() }))
@@ -900,6 +900,70 @@ impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
         let span = self.whole_match_span.unwrap_or(self.scrut_span);
         Err(self.tcx.dcx().span_err(span, "reached pattern complexity limit"))
     }
+
+    fn lint_non_contiguous_range_endpoints(
+        &self,
+        pat: &crate::pat::DeconstructedPat<Self>,
+        gap: IntRange,
+        gapped_with: &[&crate::pat::DeconstructedPat<Self>],
+    ) {
+        let Some(&thir_pat) = pat.data() else { return };
+        let thir::PatKind::Range(range) = &thir_pat.kind else { return };
+        // Only lint when the left range is an exclusive range.
+        if range.end != rustc_hir::RangeEnd::Excluded {
+            return;
+        }
+        // `pat` is an exclusive range like `lo..gap`. `gapped_with` contains ranges that start with
+        // `gap+1`.
+        let suggested_range: thir::Pat<'_> = {
+            // Suggest `lo..=gap` instead.
+            let mut suggested_range = thir_pat.clone();
+            let thir::PatKind::Range(range) = &mut suggested_range.kind else { unreachable!() };
+            range.end = rustc_hir::RangeEnd::Included;
+            suggested_range
+        };
+        let gap_as_pat = self.hoist_pat_range(&gap, *pat.ty());
+        if gapped_with.is_empty() {
+            // If `gapped_with` is empty, `gap == T::MAX`.
+            self.tcx.emit_node_span_lint(
+                lint::builtin::NON_CONTIGUOUS_RANGE_ENDPOINTS,
+                self.match_lint_level,
+                thir_pat.span,
+                errors::ExclusiveRangeMissingMax {
+                    // Point at this range.
+                    first_range: thir_pat.span,
+                    // That's the gap that isn't covered.
+                    max: gap_as_pat.clone(),
+                    // Suggest `lo..=max` instead.
+                    suggestion: suggested_range.to_string(),
+                },
+            );
+        } else {
+            self.tcx.emit_node_span_lint(
+                lint::builtin::NON_CONTIGUOUS_RANGE_ENDPOINTS,
+                self.match_lint_level,
+                thir_pat.span,
+                errors::ExclusiveRangeMissingGap {
+                    // Point at this range.
+                    first_range: thir_pat.span,
+                    // That's the gap that isn't covered.
+                    gap: gap_as_pat.clone(),
+                    // Suggest `lo..=gap` instead.
+                    suggestion: suggested_range.to_string(),
+                    // All these ranges skipped over `gap` which we think is probably a
+                    // mistake.
+                    gap_with: gapped_with
+                        .iter()
+                        .map(|pat| errors::GappedRange {
+                            span: pat.data().unwrap().span,
+                            gap: gap_as_pat.clone(),
+                            first_range: thir_pat.clone(),
+                        })
+                        .collect(),
+                },
+            );
+        }
+    }
 }
 
 /// Recursively expand this pattern into its subpatterns. Only useful for or-patterns.
diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs
index 0261768d916..a067bf1f0c2 100644
--- a/compiler/rustc_pattern_analysis/src/usefulness.rs
+++ b/compiler/rustc_pattern_analysis/src/usefulness.rs
@@ -1001,19 +1001,26 @@ impl<'p, Cx: TypeCx> PatStack<'p, Cx> {
     /// Only call if `ctor.is_covered_by(self.head().ctor())` is true.
     fn pop_head_constructor(
         &self,
+        cx: &Cx,
         ctor: &Constructor<Cx>,
         ctor_arity: usize,
         ctor_is_relevant: bool,
-    ) -> PatStack<'p, Cx> {
+    ) -> Result<PatStack<'p, Cx>, Cx::Error> {
         // We pop the head pattern and push the new fields extracted from the arguments of
         // `self.head()`.
         let mut new_pats = self.head().specialize(ctor, ctor_arity);
+        if new_pats.len() != ctor_arity {
+            return Err(cx.bug(format_args!(
+                "uncaught type error: pattern {:?} has inconsistent arity (expected arity {ctor_arity})",
+                self.head().as_pat().unwrap()
+            )));
+        }
         new_pats.extend_from_slice(&self.pats[1..]);
         // `ctor` is relevant for this row if it is the actual constructor of this row, or if the
         // row has a wildcard and `ctor` is relevant for wildcards.
         let ctor_is_relevant =
             !matches!(self.head().ctor(), Constructor::Wildcard) || ctor_is_relevant;
-        PatStack { pats: new_pats, relevant: self.relevant && ctor_is_relevant }
+        Ok(PatStack { pats: new_pats, relevant: self.relevant && ctor_is_relevant })
     }
 }
 
@@ -1083,18 +1090,19 @@ impl<'p, Cx: TypeCx> MatrixRow<'p, Cx> {
     /// Only call if `ctor.is_covered_by(self.head().ctor())` is true.
     fn pop_head_constructor(
         &self,
+        cx: &Cx,
         ctor: &Constructor<Cx>,
         ctor_arity: usize,
         ctor_is_relevant: bool,
         parent_row: usize,
-    ) -> MatrixRow<'p, Cx> {
-        MatrixRow {
-            pats: self.pats.pop_head_constructor(ctor, ctor_arity, ctor_is_relevant),
+    ) -> Result<MatrixRow<'p, Cx>, Cx::Error> {
+        Ok(MatrixRow {
+            pats: self.pats.pop_head_constructor(cx, ctor, ctor_arity, ctor_is_relevant)?,
             parent_row,
             is_under_guard: self.is_under_guard,
             useful: false,
             intersects: BitSet::new_empty(0), // Initialized in `Matrix::expand_and_push`.
-        }
+        })
     }
 }
 
@@ -1217,7 +1225,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
         };
         for (i, row) in self.rows().enumerate() {
             if ctor.is_covered_by(pcx.cx, row.head().ctor())? {
-                let new_row = row.pop_head_constructor(ctor, arity, ctor_is_relevant, i);
+                let new_row = row.pop_head_constructor(pcx.cx, ctor, arity, ctor_is_relevant, i)?;
                 matrix.expand_and_push(new_row);
             }
         }
@@ -1481,7 +1489,7 @@ impl<Cx: TypeCx> WitnessMatrix<Cx> {
 /// We can however get false negatives because exhaustiveness does not explore all cases. See the
 /// section on relevancy at the top of the file.
 fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
-    mcx: &mut UsefulnessCtxt<'_, Cx>,
+    cx: &Cx,
     overlap_range: IntRange,
     matrix: &Matrix<'p, Cx>,
     specialized_matrix: &Matrix<'p, Cx>,
@@ -1514,11 +1522,11 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
                     .map(|&(_, pat)| pat)
                     .collect();
                 if !overlaps_with.is_empty() {
-                    mcx.tycx.lint_overlapping_range_endpoints(pat, overlap_range, &overlaps_with);
+                    cx.lint_overlapping_range_endpoints(pat, overlap_range, &overlaps_with);
                 }
             }
             suffixes.push((child_row_id, pat))
-        } else if this_range.hi == overlap.plus_one() {
+        } else if Some(this_range.hi) == overlap.plus_one() {
             // `this_range` looks like `this_range.lo..=overlap`; it overlaps with any
             // ranges that look like `overlap..=hi`.
             if !suffixes.is_empty() {
@@ -1530,7 +1538,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
                     .map(|&(_, pat)| pat)
                     .collect();
                 if !overlaps_with.is_empty() {
-                    mcx.tycx.lint_overlapping_range_endpoints(pat, overlap_range, &overlaps_with);
+                    cx.lint_overlapping_range_endpoints(pat, overlap_range, &overlaps_with);
                 }
             }
             prefixes.push((child_row_id, pat))
@@ -1538,6 +1546,33 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
     }
 }
 
+/// Collect ranges that have a singleton gap between them.
+fn collect_non_contiguous_range_endpoints<'p, Cx: TypeCx>(
+    cx: &Cx,
+    gap_range: &IntRange,
+    matrix: &Matrix<'p, Cx>,
+) {
+    let gap = gap_range.lo;
+    // Ranges that look like `lo..gap`.
+    let mut onebefore: SmallVec<[_; 1]> = Default::default();
+    // Ranges that start on `gap+1` or singletons `gap+1`.
+    let mut oneafter: SmallVec<[_; 1]> = Default::default();
+    // Look through the column for ranges near the gap.
+    for pat in matrix.heads() {
+        let PatOrWild::Pat(pat) = pat else { continue };
+        let Constructor::IntRange(this_range) = pat.ctor() else { continue };
+        if gap == this_range.hi {
+            onebefore.push(pat)
+        } else if gap.plus_one() == Some(this_range.lo) {
+            oneafter.push(pat)
+        }
+    }
+
+    for pat_before in onebefore {
+        cx.lint_non_contiguous_range_endpoints(pat_before, *gap_range, oneafter.as_slice());
+    }
+}
+
 /// The core of the algorithm.
 ///
 /// This recursively computes witnesses of the non-exhaustiveness of `matrix` (if any). Also tracks
@@ -1618,13 +1653,24 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
                 && spec_matrix.rows.len() >= 2
                 && spec_matrix.rows.iter().any(|row| !row.intersects.is_empty())
             {
-                collect_overlapping_range_endpoints(mcx, overlap_range, matrix, &spec_matrix);
+                collect_overlapping_range_endpoints(mcx.tycx, overlap_range, matrix, &spec_matrix);
             }
         }
 
         matrix.unspecialize(spec_matrix);
     }
 
+    // Detect singleton gaps between ranges.
+    if missing_ctors.iter().any(|c| matches!(c, Constructor::IntRange(..))) {
+        for missing in &missing_ctors {
+            if let Constructor::IntRange(gap) = missing {
+                if gap.is_singleton() {
+                    collect_non_contiguous_range_endpoints(mcx.tycx, gap, matrix);
+                }
+            }
+        }
+    }
+
     // Record usefulness in the patterns.
     for row in matrix.rows() {
         if row.useful {
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 9d8a9f5fce3..fe359861681 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -11,6 +11,7 @@ extern crate tracing;
 
 mod errors;
 
+use rustc_ast::visit::{try_visit, VisitorResult};
 use rustc_ast::MacroDef;
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashSet;
@@ -67,17 +68,13 @@ impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> {
 /// manually. Second, it doesn't visit some type components like signatures of fn types, or traits
 /// in `impl Trait`, see individual comments in `DefIdVisitorSkeleton::visit_ty`.
 trait DefIdVisitor<'tcx> {
-    type BreakTy = ();
+    type Result: VisitorResult = ();
     const SHALLOW: bool = false;
     const SKIP_ASSOC_TYS: bool = false;
 
     fn tcx(&self) -> TyCtxt<'tcx>;
-    fn visit_def_id(
-        &mut self,
-        def_id: DefId,
-        kind: &str,
-        descr: &dyn fmt::Display,
-    ) -> ControlFlow<Self::BreakTy>;
+    fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
+    -> Self::Result;
 
     /// Not overridden, but used to actually visit types and traits.
     fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> {
@@ -87,25 +84,16 @@ trait DefIdVisitor<'tcx> {
             dummy: Default::default(),
         }
     }
-    fn visit(
-        &mut self,
-        ty_fragment: impl TypeVisitable<TyCtxt<'tcx>>,
-    ) -> ControlFlow<Self::BreakTy> {
+    fn visit(&mut self, ty_fragment: impl TypeVisitable<TyCtxt<'tcx>>) -> Self::Result {
         ty_fragment.visit_with(&mut self.skeleton())
     }
-    fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> Self::Result {
         self.skeleton().visit_trait(trait_ref)
     }
-    fn visit_predicates(
-        &mut self,
-        predicates: ty::GenericPredicates<'tcx>,
-    ) -> ControlFlow<Self::BreakTy> {
+    fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> Self::Result {
         self.skeleton().visit_clauses(predicates.predicates)
     }
-    fn visit_clauses(
-        &mut self,
-        clauses: &[(ty::Clause<'tcx>, Span)],
-    ) -> ControlFlow<Self::BreakTy> {
+    fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> Self::Result {
         self.skeleton().visit_clauses(clauses)
     }
 }
@@ -120,36 +108,42 @@ impl<'tcx, V> DefIdVisitorSkeleton<'_, 'tcx, V>
 where
     V: DefIdVisitor<'tcx> + ?Sized,
 {
-    fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<V::BreakTy> {
+    fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> V::Result {
         let TraitRef { def_id, args, .. } = trait_ref;
-        self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?;
-        if V::SHALLOW { ControlFlow::Continue(()) } else { args.visit_with(self) }
+        try_visit!(self.def_id_visitor.visit_def_id(
+            def_id,
+            "trait",
+            &trait_ref.print_only_trait_path()
+        ));
+        if V::SHALLOW { V::Result::output() } else { args.visit_with(self) }
     }
 
-    fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<V::BreakTy> {
+    fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> V::Result {
         let tcx = self.def_id_visitor.tcx();
         let (trait_ref, assoc_args) = projection.trait_ref_and_own_args(tcx);
-        self.visit_trait(trait_ref)?;
+        try_visit!(self.visit_trait(trait_ref));
         if V::SHALLOW {
-            ControlFlow::Continue(())
+            V::Result::output()
         } else {
-            assoc_args.iter().try_for_each(|arg| arg.visit_with(self))
+            V::Result::from_branch(
+                assoc_args.iter().try_for_each(|arg| arg.visit_with(self).branch()),
+            )
         }
     }
 
-    fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> ControlFlow<V::BreakTy> {
+    fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> V::Result {
         match clause.kind().skip_binder() {
             ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
                 self.visit_trait(trait_ref)
             }
             ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
-                term.visit_with(self)?;
+                try_visit!(term.visit_with(self));
                 self.visit_projection_ty(projection_ty)
             }
             ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => ty.visit_with(self),
-            ty::ClauseKind::RegionOutlives(..) => ControlFlow::Continue(()),
+            ty::ClauseKind::RegionOutlives(..) => V::Result::output(),
             ty::ClauseKind::ConstArgHasType(ct, ty) => {
-                ct.visit_with(self)?;
+                try_visit!(ct.visit_with(self));
                 ty.visit_with(self)
             }
             ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self),
@@ -157,8 +151,11 @@ where
         }
     }
 
-    fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> ControlFlow<V::BreakTy> {
-        clauses.into_iter().try_for_each(|&(clause, _span)| self.visit_clause(clause))
+    fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> V::Result {
+        for &(clause, _) in clauses {
+            try_visit!(self.visit_clause(clause));
+        }
+        V::Result::output()
     }
 }
 
@@ -166,13 +163,13 @@ impl<'tcx, V> TypeVisitor<TyCtxt<'tcx>> for DefIdVisitorSkeleton<'_, 'tcx, V>
 where
     V: DefIdVisitor<'tcx> + ?Sized,
 {
-    type BreakTy = V::BreakTy;
+    type Result = V::Result;
 
-    fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> Self::Result {
         self.visit_clause(p.as_clause().unwrap())
     }
 
-    fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<V::BreakTy> {
+    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
         let tcx = self.def_id_visitor.tcx();
         // GenericArgs are not visited here because they are visited below
         // in `super_visit_with`.
@@ -183,16 +180,16 @@ where
             | ty::Closure(def_id, ..)
             | ty::CoroutineClosure(def_id, ..)
             | ty::Coroutine(def_id, ..) => {
-                self.def_id_visitor.visit_def_id(def_id, "type", &ty)?;
+                try_visit!(self.def_id_visitor.visit_def_id(def_id, "type", &ty));
                 if V::SHALLOW {
-                    return ControlFlow::Continue(());
+                    return V::Result::output();
                 }
                 // Default type visitor doesn't visit signatures of fn types.
                 // Something like `fn() -> Priv {my_func}` is considered a private type even if
                 // `my_func` is public, so we need to visit signatures.
                 if let ty::FnDef(..) = ty.kind() {
                     // FIXME: this should probably use `args` from `FnDef`
-                    tcx.fn_sig(def_id).instantiate_identity().visit_with(self)?;
+                    try_visit!(tcx.fn_sig(def_id).instantiate_identity().visit_with(self));
                 }
                 // Inherent static methods don't have self type in args.
                 // Something like `fn() {my_method}` type of the method
@@ -200,7 +197,9 @@ where
                 // so we need to visit the self type additionally.
                 if let Some(assoc_item) = tcx.opt_associated_item(def_id) {
                     if let Some(impl_def_id) = assoc_item.impl_container(tcx) {
-                        tcx.type_of(impl_def_id).instantiate_identity().visit_with(self)?;
+                        try_visit!(
+                            tcx.type_of(impl_def_id).instantiate_identity().visit_with(self)
+                        );
                     }
                 }
             }
@@ -211,10 +210,10 @@ where
                     // as visible/reachable even if `Type` is private.
                     // Ideally, associated types should be instantiated in the same way as
                     // free type aliases, but this isn't done yet.
-                    return ControlFlow::Continue(());
+                    return V::Result::output();
                 }
 
-                self.def_id_visitor.visit_def_id(
+                try_visit!(self.def_id_visitor.visit_def_id(
                     data.def_id,
                     match kind {
                         ty::Inherent | ty::Projection => "associated type",
@@ -222,15 +221,17 @@ where
                         ty::Opaque => unreachable!(),
                     },
                     &LazyDefPathStr { def_id: data.def_id, tcx },
-                )?;
+                ));
 
                 // This will also visit args if necessary, so we don't need to recurse.
                 return if V::SHALLOW {
-                    ControlFlow::Continue(())
+                    V::Result::output()
                 } else if kind == ty::Projection {
                     self.visit_projection_ty(data)
                 } else {
-                    data.args.iter().try_for_each(|arg| arg.visit_with(self))
+                    V::Result::from_branch(
+                        data.args.iter().try_for_each(|arg| arg.visit_with(self).branch()),
+                    )
                 };
             }
             ty::Dynamic(predicates, ..) => {
@@ -245,7 +246,7 @@ where
                         }
                     };
                     let ty::ExistentialTraitRef { def_id, args: _ } = trait_ref;
-                    self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref)?;
+                    try_visit!(self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref));
                 }
             }
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
@@ -258,7 +259,7 @@ where
                     // through the trait list (default type visitor doesn't visit those traits).
                     // All traits in the list are considered the "primary" part of the type
                     // and are visited by shallow visitors.
-                    self.visit_clauses(tcx.explicit_item_bounds(def_id).skip_binder())?;
+                    try_visit!(self.visit_clauses(tcx.explicit_item_bounds(def_id).skip_binder()));
                 }
             }
             // These types don't have their own def-ids (but may have subcomponents
@@ -285,10 +286,10 @@ where
             }
         }
 
-        if V::SHALLOW { ControlFlow::Continue(()) } else { ty.super_visit_with(self) }
+        if V::SHALLOW { V::Result::output() } else { ty.super_visit_with(self) }
     }
 
-    fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_const(&mut self, c: Const<'tcx>) -> Self::Result {
         let tcx = self.def_id_visitor.tcx();
         tcx.expand_abstract_consts(c).super_visit_with(self)
     }
@@ -316,16 +317,10 @@ impl<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> DefIdVisitor<'tcx>
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
-    fn visit_def_id(
-        &mut self,
-        def_id: DefId,
-        _kind: &str,
-        _descr: &dyn fmt::Display,
-    ) -> ControlFlow<Self::BreakTy> {
+    fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) {
         if let Some(def_id) = def_id.as_local() {
             self.min = VL::new_min(self, def_id);
         }
-        ControlFlow::Continue(())
     }
 }
 
@@ -836,12 +831,7 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx>
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.ev.tcx
     }
-    fn visit_def_id(
-        &mut self,
-        def_id: DefId,
-        _kind: &str,
-        _descr: &dyn fmt::Display,
-    ) -> ControlFlow<Self::BreakTy> {
+    fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) {
         if let Some(def_id) = def_id.as_local() {
             // All effective visibilities except `reachable_through_impl_trait` are limited to
             // nominal visibility. If any type or trait is leaked farther than that, it will
@@ -850,7 +840,6 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx>
                 .then(|| self.ev.tcx.local_visibility(def_id));
             self.ev.update_eff_vis(def_id, self.effective_vis, max_vis, self.level);
         }
-        ControlFlow::Continue(())
     }
 }
 
@@ -1076,8 +1065,8 @@ impl<'tcx> TypePrivacyVisitor<'tcx> {
 }
 
 impl<'tcx> rustc_ty_utils::sig_types::SpannedTypeVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
-    type BreakTy = ();
-    fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> ControlFlow<()> {
+    type Result = ControlFlow<()>;
+    fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> Self::Result {
         self.span = span;
         value.visit_with(&mut self.skeleton())
     }
@@ -1233,6 +1222,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
 }
 
 impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
+    type Result = ControlFlow<()>;
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
@@ -1241,7 +1231,7 @@ impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
         def_id: DefId,
         kind: &str,
         descr: &dyn fmt::Display,
-    ) -> ControlFlow<Self::BreakTy> {
+    ) -> Self::Result {
         if self.check_def_id(def_id, kind, descr) {
             ControlFlow::Break(())
         } else {
@@ -1407,6 +1397,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
 }
 
 impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> {
+    type Result = ControlFlow<()>;
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
@@ -1415,7 +1406,7 @@ impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> {
         def_id: DefId,
         kind: &str,
         descr: &dyn fmt::Display,
-    ) -> ControlFlow<Self::BreakTy> {
+    ) -> Self::Result {
         if self.check_def_id(def_id, kind, descr) {
             ControlFlow::Break(())
         } else {
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 1b546bf9103..b06d75be390 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -17,6 +17,7 @@ use rustc_middle::dep_graph::{
 use rustc_middle::query::on_disk_cache::AbsoluteBytePos;
 use rustc_middle::query::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex};
 use rustc_middle::query::Key;
+use rustc_middle::ty::print::with_reduced_queries;
 use rustc_middle::ty::tls::{self, ImplicitCtxt};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};
@@ -304,6 +305,10 @@ pub(crate) fn create_query_frame<
     kind: DepKind,
     name: &'static str,
 ) -> QueryStackFrame {
+    // If reduced queries are requested, we may be printing a query stack due
+    // to a panic. Avoid using `default_span` and `def_kind` in that case.
+    let reduce_queries = with_reduced_queries();
+
     // Avoid calling queries while formatting the description
     let description = ty::print::with_no_queries!(do_describe(tcx, key));
     let description = if tcx.sess.verbose_internals() {
@@ -311,7 +316,7 @@ pub(crate) fn create_query_frame<
     } else {
         description
     };
-    let span = if kind == dep_graph::dep_kinds::def_span {
+    let span = if kind == dep_graph::dep_kinds::def_span || reduce_queries {
         // The `def_span` query is used to calculate `default_span`,
         // so exit to avoid infinite recursion.
         None
@@ -319,7 +324,7 @@ pub(crate) fn create_query_frame<
         Some(key.default_span(tcx))
     };
     let def_id = key.key_as_def_id();
-    let def_kind = if kind == dep_graph::dep_kinds::def_kind {
+    let def_kind = if kind == dep_graph::dep_kinds::def_kind || reduce_queries {
         // Try to avoid infinite recursion.
         None
     } else {
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 40517407ee6..3d9848395a2 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -285,9 +285,8 @@ where
                     let lock = query.query_state(qcx).active.get_shard_by_value(&key).lock();
 
                     match lock.get(&key) {
-                        Some(QueryResult::Poisoned) => {
-                            panic!("query '{}' not cached due to poisoning", query.name())
-                        }
+                        // The query we waited on panicked. Continue unwinding here.
+                        Some(QueryResult::Poisoned) => FatalError.raise(),
                         _ => panic!(
                             "query '{}' result must be in the cache or the query must be poisoned after a wait",
                             query.name()
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 1c4aeefcbcf..dd18ab7d9d2 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -25,6 +25,7 @@ use rustc_hir::def::{self, *};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
 use rustc_metadata::creader::LoadedMacro;
 use rustc_middle::metadata::ModChild;
+use rustc_middle::ty::Feed;
 use rustc_middle::{bug, ty};
 use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -407,7 +408,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
         // Top level use tree reuses the item's id and list stems reuse their parent
         // use tree's ids, so in both cases their visibilities are already filled.
         if nested && !list_stem {
-            self.r.feed_visibility(self.r.local_def_id(id), vis);
+            self.r.feed_visibility(self.r.feed(id), vis);
         }
 
         let mut prefix_iter = parent_prefix
@@ -632,7 +633,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
         &mut self,
         fields: &[ast::FieldDef],
         ident: Ident,
-        def_id: LocalDefId,
+        feed: Feed<'tcx, LocalDefId>,
         adt_res: Res,
         adt_vis: ty::Visibility,
         adt_span: Span,
@@ -643,7 +644,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
 
         // Define a name in the type namespace if it is not anonymous.
         self.r.define(parent, ident, TypeNS, (adt_res, adt_vis, adt_span, expansion));
-        self.r.feed_visibility(def_id, adt_vis);
+        self.r.feed_visibility(feed, adt_vis);
+        let def_id = feed.key();
 
         // Record field names for error reporting.
         self.insert_field_def_ids(def_id, fields);
@@ -653,14 +655,15 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             match &field.ty.kind {
                 ast::TyKind::AnonStruct(id, nested_fields)
                 | ast::TyKind::AnonUnion(id, nested_fields) => {
-                    let local_def_id = self.r.local_def_id(*id);
+                    let feed = self.r.feed(*id);
+                    let local_def_id = feed.key();
                     let def_id = local_def_id.to_def_id();
                     let def_kind = self.r.tcx.def_kind(local_def_id);
                     let res = Res::Def(def_kind, def_id);
                     self.build_reduced_graph_for_struct_variant(
                         &nested_fields,
                         Ident::empty(),
-                        local_def_id,
+                        feed,
                         res,
                         // Anonymous adts inherit visibility from their parent adts.
                         adt_vis,
@@ -680,12 +683,13 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
         let ident = item.ident;
         let sp = item.span;
         let vis = self.resolve_visibility(&item.vis);
-        let local_def_id = self.r.local_def_id(item.id);
+        let feed = self.r.feed(item.id);
+        let local_def_id = feed.key();
         let def_id = local_def_id.to_def_id();
         let def_kind = self.r.tcx.def_kind(def_id);
         let res = Res::Def(def_kind, def_id);
 
-        self.r.feed_visibility(local_def_id, vis);
+        self.r.feed_visibility(feed, vis);
 
         match item.kind {
             ItemKind::Use(ref use_tree) => {
@@ -762,7 +766,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
                 self.build_reduced_graph_for_struct_variant(
                     vdata.fields(),
                     ident,
-                    local_def_id,
+                    feed,
                     res,
                     vis,
                     sp,
@@ -795,10 +799,11 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
                         }
                         ret_fields.push(field_vis.to_def_id());
                     }
-                    let ctor_def_id = self.r.local_def_id(ctor_node_id);
+                    let feed = self.r.feed(ctor_node_id);
+                    let ctor_def_id = feed.key();
                     let ctor_res = self.res(ctor_def_id);
                     self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, sp, expansion));
-                    self.r.feed_visibility(ctor_def_id, ctor_vis);
+                    self.r.feed_visibility(feed, ctor_vis);
                     // We need the field visibility spans also for the constructor for E0603.
                     self.insert_field_visibilities_local(ctor_def_id.to_def_id(), vdata.fields());
 
@@ -812,7 +817,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
                 self.build_reduced_graph_for_struct_variant(
                     vdata.fields(),
                     ident,
-                    local_def_id,
+                    feed,
                     res,
                     vis,
                     sp,
@@ -919,7 +924,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
 
     /// Constructs the reduced graph for one foreign item.
     fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) {
-        let local_def_id = self.r.local_def_id(item.id);
+        let feed = self.r.feed(item.id);
+        let local_def_id = feed.key();
         let def_id = local_def_id.to_def_id();
         let ns = match item.kind {
             ForeignItemKind::Fn(..) => ValueNS,
@@ -931,7 +937,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
         let expansion = self.parent_scope.expansion;
         let vis = self.resolve_visibility(&item.vis);
         self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion));
-        self.r.feed_visibility(local_def_id, vis);
+        self.r.feed_visibility(feed, vis);
     }
 
     fn build_reduced_graph_for_block(&mut self, block: &Block) {
@@ -1218,7 +1224,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
     fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'a> {
         let parent_scope = self.parent_scope;
         let expansion = parent_scope.expansion;
-        let def_id = self.r.local_def_id(item.id);
+        let feed = self.r.feed(item.id);
+        let def_id = feed.key();
         let (res, ident, span, macro_rules) = match &item.kind {
             ItemKind::MacroDef(def) => (self.res(def_id), item.ident, item.span, def.macro_rules),
             ItemKind::Fn(..) => match self.proc_macro_stub(item) {
@@ -1269,7 +1276,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
                 self.r.check_reserved_macro_name(ident, res);
                 self.insert_unused_macro(ident, def_id, item.id);
             }
-            self.r.feed_visibility(def_id, vis);
+            self.r.feed_visibility(feed, vis);
             let scope = self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Binding(
                 self.r.arenas.alloc_macro_rules_binding(MacroRulesBinding {
                     parent_macro_rules_scope: parent_scope.macro_rules,
@@ -1293,7 +1300,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
                 self.insert_unused_macro(ident, def_id, item.id);
             }
             self.r.define(module, ident, MacroNS, (res, vis, span, expansion));
-            self.r.feed_visibility(def_id, vis);
+            self.r.feed_visibility(feed, vis);
             self.parent_scope.macro_rules
         }
     }
@@ -1385,7 +1392,8 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
         }
 
         let vis = self.resolve_visibility(&item.vis);
-        let local_def_id = self.r.local_def_id(item.id);
+        let feed = self.r.feed(item.id);
+        let local_def_id = feed.key();
         let def_id = local_def_id.to_def_id();
 
         if !(ctxt == AssocCtxt::Impl
@@ -1395,7 +1403,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             // Trait impl item visibility is inherited from its trait when not specified
             // explicitly. In that case we cannot determine it here in early resolve,
             // so we leave a hole in the visibility table to be filled later.
-            self.r.feed_visibility(local_def_id, vis);
+            self.r.feed_visibility(feed, vis);
         }
 
         if ctxt == AssocCtxt::Trait {
@@ -1469,7 +1477,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             self.visit_invoc(sf.id);
         } else {
             let vis = self.resolve_visibility(&sf.vis);
-            self.r.feed_visibility(self.r.local_def_id(sf.id), vis);
+            self.r.feed_visibility(self.r.feed(sf.id), vis);
             visit::walk_field_def(self, sf);
         }
     }
@@ -1487,10 +1495,11 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
         let ident = variant.ident;
 
         // Define a name in the type namespace.
-        let def_id = self.r.local_def_id(variant.id);
+        let feed = self.r.feed(variant.id);
+        let def_id = feed.key();
         let vis = self.resolve_visibility(&variant.vis);
         self.r.define(parent, ident, TypeNS, (self.res(def_id), vis, variant.span, expn_id));
-        self.r.feed_visibility(def_id, vis);
+        self.r.feed_visibility(feed, vis);
 
         // If the variant is marked as non_exhaustive then lower the visibility to within the crate.
         let ctor_vis =
@@ -1502,10 +1511,11 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
 
         // Define a constructor name in the value namespace.
         if let Some(ctor_node_id) = variant.data.ctor_node_id() {
-            let ctor_def_id = self.r.local_def_id(ctor_node_id);
+            let feed = self.r.feed(ctor_node_id);
+            let ctor_def_id = feed.key();
             let ctor_res = self.res(ctor_def_id);
             self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id));
-            self.r.feed_visibility(ctor_def_id, ctor_vis);
+            self.r.feed_visibility(feed, ctor_vis);
         }
 
         // Record field names for error reporting.
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 37cc50f6943..bf1ea2e2709 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -35,7 +35,7 @@ use rustc_data_structures::unord::UnordSet;
 use rustc_errors::{pluralize, MultiSpan};
 use rustc_hir::def::{DefKind, Res};
 use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES, UNUSED_IMPORTS};
-use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_session::lint::BuiltinLintDiag;
 use rustc_span::symbol::{kw, Ident};
 use rustc_span::{Span, DUMMY_SP};
 
@@ -137,6 +137,81 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
             self.check_import_as_underscore(item, *id);
         }
     }
+
+    fn report_unused_extern_crate_items(
+        &mut self,
+        maybe_unused_extern_crates: FxHashMap<ast::NodeId, Span>,
+    ) {
+        let tcx = self.r.tcx();
+        for extern_crate in &self.extern_crate_items {
+            let warn_if_unused = !extern_crate.ident.name.as_str().starts_with('_');
+
+            // If the crate is fully unused, we suggest removing it altogether.
+            // We do this in any edition.
+            if warn_if_unused {
+                if let Some(&span) = maybe_unused_extern_crates.get(&extern_crate.id) {
+                    self.r.lint_buffer.buffer_lint_with_diagnostic(
+                        UNUSED_EXTERN_CRATES,
+                        extern_crate.id,
+                        span,
+                        "unused extern crate",
+                        BuiltinLintDiag::UnusedExternCrate {
+                            removal_span: extern_crate.span_with_attributes,
+                        },
+                    );
+                    continue;
+                }
+            }
+
+            // If we are not in Rust 2018 edition, then we don't make any further
+            // suggestions.
+            if !tcx.sess.at_least_rust_2018() {
+                continue;
+            }
+
+            // If the extern crate has any attributes, they may have funky
+            // semantics we can't faithfully represent using `use` (most
+            // notably `#[macro_use]`). Ignore it.
+            if extern_crate.has_attrs {
+                continue;
+            }
+
+            // If the extern crate is renamed, then we cannot suggest replacing it with a use as this
+            // would not insert the new name into the prelude, where other imports in the crate may be
+            // expecting it.
+            if extern_crate.renames {
+                continue;
+            }
+
+            // If the extern crate isn't in the extern prelude,
+            // there is no way it can be written as a `use`.
+            if !self
+                .r
+                .extern_prelude
+                .get(&extern_crate.ident)
+                .is_some_and(|entry| !entry.introduced_by_item)
+            {
+                continue;
+            }
+
+            let vis_span = extern_crate
+                .vis_span
+                .find_ancestor_inside(extern_crate.span)
+                .unwrap_or(extern_crate.vis_span);
+            let ident_span = extern_crate
+                .ident
+                .span
+                .find_ancestor_inside(extern_crate.span)
+                .unwrap_or(extern_crate.ident.span);
+            self.r.lint_buffer.buffer_lint_with_diagnostic(
+                UNUSED_EXTERN_CRATES,
+                extern_crate.id,
+                extern_crate.span,
+                "`extern crate` is not idiomatic in the new edition",
+                BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span },
+            );
+        }
+    }
 }
 
 impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
@@ -335,6 +410,8 @@ impl Resolver<'_, '_> {
         };
         visit::walk_crate(&mut visitor, krate);
 
+        visitor.report_unused_extern_crate_items(maybe_unused_extern_crates);
+
         for unused in visitor.unused_imports.values() {
             let mut fixes = Vec::new();
             let spans = match calc_unused_spans(unused, &unused.use_tree, unused.use_tree_id) {
@@ -412,76 +489,7 @@ impl Resolver<'_, '_> {
                 unused.use_tree_id,
                 ms,
                 msg,
-                BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes, test_module_span),
-            );
-        }
-
-        for extern_crate in visitor.extern_crate_items {
-            let warn_if_unused = !extern_crate.ident.name.as_str().starts_with('_');
-
-            // If the crate is fully unused, we suggest removing it altogether.
-            // We do this in any edition.
-            if warn_if_unused {
-                if let Some(&span) = maybe_unused_extern_crates.get(&extern_crate.id) {
-                    visitor.r.lint_buffer.buffer_lint_with_diagnostic(
-                        UNUSED_EXTERN_CRATES,
-                        extern_crate.id,
-                        span,
-                        "unused extern crate",
-                        BuiltinLintDiagnostics::UnusedExternCrate {
-                            removal_span: extern_crate.span_with_attributes,
-                        },
-                    );
-                    continue;
-                }
-            }
-
-            // If we are not in Rust 2018 edition, then we don't make any further
-            // suggestions.
-            if !tcx.sess.at_least_rust_2018() {
-                continue;
-            }
-
-            // If the extern crate has any attributes, they may have funky
-            // semantics we can't faithfully represent using `use` (most
-            // notably `#[macro_use]`). Ignore it.
-            if extern_crate.has_attrs {
-                continue;
-            }
-
-            // If the extern crate is renamed, then we cannot suggest replacing it with a use as this
-            // would not insert the new name into the prelude, where other imports in the crate may be
-            // expecting it.
-            if extern_crate.renames {
-                continue;
-            }
-
-            // If the extern crate isn't in the extern prelude,
-            // there is no way it can be written as a `use`.
-            if !visitor
-                .r
-                .extern_prelude
-                .get(&extern_crate.ident)
-                .is_some_and(|entry| !entry.introduced_by_item)
-            {
-                continue;
-            }
-
-            let vis_span = extern_crate
-                .vis_span
-                .find_ancestor_inside(extern_crate.span)
-                .unwrap_or(extern_crate.vis_span);
-            let ident_span = extern_crate
-                .ident
-                .span
-                .find_ancestor_inside(extern_crate.span)
-                .unwrap_or(extern_crate.ident.span);
-            visitor.r.lint_buffer.buffer_lint_with_diagnostic(
-                UNUSED_EXTERN_CRATES,
-                extern_crate.id,
-                extern_crate.span,
-                "`extern crate` is not idiomatic in the new edition",
-                BuiltinLintDiagnostics::ExternCrateNotIdiomatic { vis_span, ident_span },
+                BuiltinLintDiag::UnusedImports(fix_msg.into(), fixes, test_module_span),
             );
         }
 
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 12bf462a6fd..bb3b902c0de 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -38,14 +38,16 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {
             "create_def(node_id={:?}, def_kind={:?}, parent_def={:?})",
             node_id, def_kind, parent_def
         );
-        self.resolver.create_def(
-            parent_def,
-            node_id,
-            name,
-            def_kind,
-            self.expansion.to_expn_id(),
-            span.with_parent(None),
-        )
+        self.resolver
+            .create_def(
+                parent_def,
+                node_id,
+                name,
+                def_kind,
+                self.expansion.to_expn_id(),
+                span.with_parent(None),
+            )
+            .def_id()
     }
 
     fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: LocalDefId, f: F) {
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index dc7dfa04d18..0bb2a69ae99 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -19,7 +19,7 @@ use rustc_middle::ty::TyCtxt;
 use rustc_session::lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE;
 use rustc_session::lint::builtin::AMBIGUOUS_GLOB_IMPORTS;
 use rustc_session::lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS;
-use rustc_session::lint::{AmbiguityErrorDiag, BuiltinLintDiagnostics};
+use rustc_session::lint::{AmbiguityErrorDiag, BuiltinLintDiag};
 use rustc_session::Session;
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::edition::Edition;
@@ -138,7 +138,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 CRATE_NODE_ID,
                 span_use,
                 msg,
-                BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
+                BuiltinLintDiag::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
             );
         }
 
@@ -153,7 +153,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     import.root_id,
                     ambiguity_error.ident.span,
                     diag.msg.to_string(),
-                    BuiltinLintDiagnostics::AmbiguousGlobImports { diag },
+                    BuiltinLintDiag::AmbiguousGlobImports { diag },
                 );
             } else {
                 let mut err = struct_span_code_err!(self.dcx(), diag.span, E0659, "{}", &diag.msg);
@@ -188,7 +188,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     &candidates,
                     if instead { Instead::Yes } else { Instead::No },
                     found_use,
-                    DiagnosticMode::Normal,
+                    DiagMode::Normal,
                     path,
                     "",
                 );
@@ -525,7 +525,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
         }
 
-        let diag = BuiltinLintDiagnostics::AbsPathWithModule(root_span);
+        let diag = BuiltinLintDiag::AbsPathWithModule(root_span);
         self.lint_buffer.buffer_lint_with_diagnostic(
             ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
             node_id,
@@ -723,7 +723,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         &import_suggestions,
                         Instead::No,
                         FoundUse::Yes,
-                        DiagnosticMode::Pattern,
+                        DiagMode::Pattern,
                         vec![],
                         "",
                     );
@@ -1444,7 +1444,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             &import_suggestions,
             Instead::No,
             found_use,
-            DiagnosticMode::Normal,
+            DiagMode::Normal,
             vec![],
             "",
         );
@@ -1736,7 +1736,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     }
 
     fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'a>) {
-        let PrivacyError { ident, binding, outermost_res, parent_scope, dedup_span } =
+        let PrivacyError { ident, binding, outermost_res, parent_scope, single_nested, dedup_span } =
             *privacy_error;
 
         let res = binding.res();
@@ -1775,7 +1775,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 &import_suggestions,
                 Instead::Yes,
                 FoundUse::Yes,
-                DiagnosticMode::Import,
+                DiagMode::Import { append: single_nested },
                 vec![],
                 "",
             );
@@ -2696,12 +2696,16 @@ enum FoundUse {
 }
 
 /// Whether a binding is part of a pattern or a use statement. Used for diagnostics.
-pub(crate) enum DiagnosticMode {
+pub(crate) enum DiagMode {
     Normal,
     /// The binding is part of a pattern
     Pattern,
     /// The binding is part of a use statement
-    Import,
+    Import {
+        /// `true` mean add the tips afterward for case `use a::{b,c}`,
+        /// rather than replacing within.
+        append: bool,
+    },
 }
 
 pub(crate) fn import_candidates(
@@ -2710,7 +2714,7 @@ pub(crate) fn import_candidates(
     // This is `None` if all placement locations are inside expansions
     use_placement_span: Option<Span>,
     candidates: &[ImportSuggestion],
-    mode: DiagnosticMode,
+    mode: DiagMode,
     append: &str,
 ) {
     show_candidates(
@@ -2726,6 +2730,8 @@ pub(crate) fn import_candidates(
     );
 }
 
+type PathString<'a> = (String, &'a str, Option<DefId>, &'a Option<String>, bool);
+
 /// When an entity with a given name is not available in scope, we search for
 /// entities with that name in all crates. This method allows outputting the
 /// results of this search in a programmer-friendly way. If any entities are
@@ -2738,7 +2744,7 @@ fn show_candidates(
     candidates: &[ImportSuggestion],
     instead: Instead,
     found_use: FoundUse,
-    mode: DiagnosticMode,
+    mode: DiagMode,
     path: Vec<Segment>,
     append: &str,
 ) -> bool {
@@ -2746,10 +2752,8 @@ fn show_candidates(
         return false;
     }
 
-    let mut accessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>, bool)> =
-        Vec::new();
-    let mut inaccessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>, bool)> =
-        Vec::new();
+    let mut accessible_path_strings: Vec<PathString<'_>> = Vec::new();
+    let mut inaccessible_path_strings: Vec<PathString<'_>> = Vec::new();
 
     candidates.iter().for_each(|c| {
         if c.accessible {
@@ -2799,7 +2803,7 @@ fn show_candidates(
             };
 
         let instead = if let Instead::Yes = instead { " instead" } else { "" };
-        let mut msg = if let DiagnosticMode::Pattern = mode {
+        let mut msg = if let DiagMode::Pattern = mode {
             format!(
                 "if you meant to match on {kind}{instead}{name}, use the full path in the pattern",
             )
@@ -2811,9 +2815,18 @@ fn show_candidates(
             err.note(note.clone());
         }
 
+        let append_candidates = |msg: &mut String, accessible_path_strings: Vec<PathString<'_>>| {
+            msg.push(':');
+
+            for candidate in accessible_path_strings {
+                msg.push('\n');
+                msg.push_str(&candidate.0);
+            }
+        };
+
         if let Some(span) = use_placement_span {
             let (add_use, trailing) = match mode {
-                DiagnosticMode::Pattern => {
+                DiagMode::Pattern => {
                     err.span_suggestions(
                         span,
                         msg,
@@ -2822,14 +2835,14 @@ fn show_candidates(
                     );
                     return true;
                 }
-                DiagnosticMode::Import => ("", ""),
-                DiagnosticMode::Normal => ("use ", ";\n"),
+                DiagMode::Import { .. } => ("", ""),
+                DiagMode::Normal => ("use ", ";\n"),
             };
             for candidate in &mut accessible_path_strings {
                 // produce an additional newline to separate the new use statement
                 // from the directly following item.
                 let additional_newline = if let FoundUse::No = found_use
-                    && let DiagnosticMode::Normal = mode
+                    && let DiagMode::Normal = mode
                 {
                     "\n"
                 } else {
@@ -2839,13 +2852,22 @@ fn show_candidates(
                     format!("{add_use}{}{append}{trailing}{additional_newline}", &candidate.0);
             }
 
-            err.span_suggestions_with_style(
-                span,
-                msg,
-                accessible_path_strings.into_iter().map(|a| a.0),
-                Applicability::MaybeIncorrect,
-                SuggestionStyle::ShowAlways,
-            );
+            match mode {
+                DiagMode::Import { append: true, .. } => {
+                    append_candidates(&mut msg, accessible_path_strings);
+                    err.span_help(span, msg);
+                }
+                _ => {
+                    err.span_suggestions_with_style(
+                        span,
+                        msg,
+                        accessible_path_strings.into_iter().map(|a| a.0),
+                        Applicability::MaybeIncorrect,
+                        SuggestionStyle::ShowAlways,
+                    );
+                }
+            }
+
             if let [first, .., last] = &path[..] {
                 let sp = first.ident.span.until(last.ident.span);
                 // Our suggestion is empty, so make sure the span is not empty (or we'd ICE).
@@ -2860,26 +2882,17 @@ fn show_candidates(
                 }
             }
         } else {
-            msg.push(':');
-
-            for candidate in accessible_path_strings {
-                msg.push('\n');
-                msg.push_str(&candidate.0);
-            }
-
+            append_candidates(&mut msg, accessible_path_strings);
             err.help(msg);
         }
         true
-    } else if !(inaccessible_path_strings.is_empty() || matches!(mode, DiagnosticMode::Import)) {
-        let prefix = if let DiagnosticMode::Pattern = mode {
-            "you might have meant to match on "
-        } else {
-            ""
-        };
+    } else if !(inaccessible_path_strings.is_empty() || matches!(mode, DiagMode::Import { .. })) {
+        let prefix =
+            if let DiagMode::Pattern = mode { "you might have meant to match on " } else { "" };
         if let [(name, descr, def_id, note, _)] = &inaccessible_path_strings[..] {
             let msg = format!(
                 "{prefix}{descr} `{name}`{} exists but is inaccessible",
-                if let DiagnosticMode::Pattern = mode { ", which" } else { "" }
+                if let DiagMode::Pattern = mode { ", which" } else { "" }
             );
 
             if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index c17ea00ec80..6518d9735ae 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -4,7 +4,7 @@ use rustc_hir::def::{DefKind, Namespace, NonMacroAttrKind, PartialRes, PerNS};
 use rustc_middle::bug;
 use rustc_middle::ty;
 use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK;
-use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_session::lint::BuiltinLintDiag;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext};
 use rustc_span::symbol::{kw, Ident};
@@ -530,7 +530,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                             ns.descr(),
                                             ident
                                         ),
-                                        BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(
+                                        BuiltinLintDiag::ProcMacroDeriveResolutionFallback(
                                             orig_ident.span,
                                         ),
                                     );
@@ -868,7 +868,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             .into_iter()
             .find_map(|binding| if binding == ignore_binding { None } else { binding });
 
-        if let Some(Finalize { path_span, report_private, used, .. }) = finalize {
+        if let Some(Finalize { path_span, report_private, used, root_span, .. }) = finalize {
             let Some(binding) = binding else {
                 return Err((Determined, Weak::No));
             };
@@ -881,6 +881,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         dedup_span: path_span,
                         outermost_res: None,
                         parent_scope: *parent_scope,
+                        single_nested: path_span != root_span,
                     });
                 } else {
                     return Err((Determined, Weak::No));
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 9bfca0f1798..ea08041f2aa 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -1,6 +1,6 @@
 //! A bunch of methods and structures more or less related to resolving imports.
 
-use crate::diagnostics::{import_candidates, DiagnosticMode, Suggestion};
+use crate::diagnostics::{import_candidates, DiagMode, Suggestion};
 use crate::errors::{
     CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
     CannotBeReexportedPrivateNS, CannotDetermineImportResolution, CannotGlobImportAllCrates,
@@ -8,8 +8,8 @@ use crate::errors::{
     ItemsInTraitsAreNotImportable,
 };
 use crate::Determinacy::{self, *};
-use crate::Namespace::*;
 use crate::{module_to_string, names_to_string, ImportSuggestion};
+use crate::{AmbiguityError, Namespace::*};
 use crate::{AmbiguityKind, BindingKey, ResolutionError, Resolver, Segment};
 use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet};
 use crate::{NameBinding, NameBindingData, NameBindingKind, PathResult, Used};
@@ -27,7 +27,7 @@ use rustc_session::lint::builtin::{
     AMBIGUOUS_GLOB_REEXPORTS, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE,
     UNUSED_IMPORTS,
 };
-use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_session::lint::BuiltinLintDiag;
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::hygiene::LocalExpnId;
 use rustc_span::symbol::{kw, Ident, Symbol};
@@ -538,7 +538,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             .chain(indeterminate_imports.iter().map(|i| (true, i)))
         {
             let unresolved_import_error = self.finalize_import(*import);
-
             // If this import is unresolved then create a dummy import
             // resolution for it so that later resolve stages won't complain.
             self.import_dummy_binding(*import, is_indeterminate);
@@ -618,7 +617,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             import.root_id,
                             import.root_span,
                             "ambiguous glob re-exports",
-                            BuiltinLintDiagnostics::AmbiguousGlobReexports {
+                            BuiltinLintDiag::AmbiguousGlobReexports {
                                 name: key.ident.to_string(),
                                 namespace: key.ns.descr().to_string(),
                                 first_reexport_span: import.root_span,
@@ -654,7 +653,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                 binding_id,
                                 binding.span,
                                 "private item shadows public glob re-export",
-                                BuiltinLintDiagnostics::HiddenGlobReexports {
+                                BuiltinLintDiag::HiddenGlobReexports {
                                     name: key.ident.name.to_string(),
                                     namespace: key.ns.descr().to_owned(),
                                     glob_reexport_span: glob_binding.span,
@@ -716,7 +715,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         &mut diag,
                         Some(err.span),
                         candidates,
-                        DiagnosticMode::Import,
+                        DiagMode::Import { append: false },
                         (source != target)
                             .then(|| format!(" as {target}"))
                             .as_deref()
@@ -728,7 +727,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             &mut diag,
                             None,
                             candidates,
-                            DiagnosticMode::Normal,
+                            DiagMode::Normal,
                             (source != target)
                                 .then(|| format!(" as {target}"))
                                 .as_deref()
@@ -856,7 +855,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(),
             _ => None,
         };
-        let prev_ambiguity_errors_len = self.ambiguity_errors.len();
+        let ambiguity_errors_len =
+            |errors: &Vec<AmbiguityError<'_>>| errors.iter().filter(|error| !error.warning).count();
+        let prev_ambiguity_errors_len = ambiguity_errors_len(&self.ambiguity_errors);
         let finalize = Finalize::with_root_span(import.root_id, import.span, import.root_span);
 
         // We'll provide more context to the privacy errors later, up to `len`.
@@ -870,7 +871,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             ignore_binding,
         );
 
-        let no_ambiguity = self.ambiguity_errors.len() == prev_ambiguity_errors_len;
+        let no_ambiguity =
+            ambiguity_errors_len(&self.ambiguity_errors) == prev_ambiguity_errors_len;
         import.vis.set(orig_vis);
         let module = match path_res {
             PathResult::Module(module) => {
@@ -1006,7 +1008,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             id,
                             import.span,
                             msg,
-                            BuiltinLintDiagnostics::RedundantImportVisibility {
+                            BuiltinLintDiag::RedundantImportVisibility {
                                 max_vis: max_vis.to_string(def_id, self.tcx),
                                 span: import.span,
                             },
@@ -1334,9 +1336,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
 
         let mut is_redundant = true;
-
         let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None };
-
         self.per_ns(|this, ns| {
             if is_redundant && let Ok(binding) = source_bindings[ns].get() {
                 if binding.res() == Res::Err {
@@ -1373,7 +1373,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 id,
                 import.span,
                 format!("the item `{source}` is imported redundantly"),
-                BuiltinLintDiagnostics::RedundantImport(redundant_spans, source),
+                BuiltinLintDiag::RedundantImport(redundant_spans, source),
             );
         }
     }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 85db8ba8618..d2aea0056b3 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -13,7 +13,7 @@ use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult};
 use crate::{ResolutionError, Resolver, Segment, UseError};
 
 use rustc_ast::ptr::P;
-use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
+use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
 use rustc_ast::*;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_errors::{
@@ -581,7 +581,7 @@ impl MaybeExported<'_> {
 }
 
 #[derive(Default)]
-struct DiagnosticMetadata<'ast> {
+struct DiagMetadata<'ast> {
     /// The current trait's associated items' ident, used for diagnostic suggestions.
     current_trait_assoc_items: Option<&'ast [P<AssocItem>]>,
 
@@ -674,7 +674,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
     current_trait_ref: Option<(Module<'a>, TraitRef)>,
 
     /// Fields used to add information to diagnostic errors.
-    diagnostic_metadata: Box<DiagnosticMetadata<'ast>>,
+    diag_metadata: Box<DiagMetadata<'ast>>,
 
     /// State used to know whether to ignore resolution errors for function bodies.
     ///
@@ -694,12 +694,12 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
         // as they do not correspond to actual code.
     }
     fn visit_item(&mut self, item: &'ast Item) {
-        let prev = replace(&mut self.diagnostic_metadata.current_item, Some(item));
+        let prev = replace(&mut self.diag_metadata.current_item, Some(item));
         // Always report errors in items we just entered.
         let old_ignore = replace(&mut self.in_func_body, false);
         self.with_lifetime_rib(LifetimeRibKind::Item, |this| this.resolve_item(item));
         self.in_func_body = old_ignore;
-        self.diagnostic_metadata.current_item = prev;
+        self.diag_metadata.current_item = prev;
     }
     fn visit_arm(&mut self, arm: &'ast Arm) {
         self.resolve_arm(arm);
@@ -716,10 +716,10 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
         self.resolve_expr(expr, None);
     }
     fn visit_pat(&mut self, p: &'ast Pat) {
-        let prev = self.diagnostic_metadata.current_pat;
-        self.diagnostic_metadata.current_pat = Some(p);
+        let prev = self.diag_metadata.current_pat;
+        self.diag_metadata.current_pat = Some(p);
         visit::walk_pat(self, p);
-        self.diagnostic_metadata.current_pat = prev;
+        self.diag_metadata.current_pat = prev;
     }
     fn visit_local(&mut self, local: &'ast Local) {
         let local_spans = match local.pat.kind {
@@ -731,13 +731,13 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
                 local.kind.init().map(|init| init.span),
             )),
         };
-        let original = replace(&mut self.diagnostic_metadata.current_let_binding, local_spans);
+        let original = replace(&mut self.diag_metadata.current_let_binding, local_spans);
         self.resolve_local(local);
-        self.diagnostic_metadata.current_let_binding = original;
+        self.diag_metadata.current_let_binding = original;
     }
     fn visit_ty(&mut self, ty: &'ast Ty) {
-        let prev = self.diagnostic_metadata.current_trait_object;
-        let prev_ty = self.diagnostic_metadata.current_type_path;
+        let prev = self.diag_metadata.current_trait_object;
+        let prev_ty = self.diag_metadata.current_type_path;
         match &ty.kind {
             TyKind::Ref(None, _) => {
                 // Elided lifetime in reference: we resolve as if there was some lifetime `'_` with
@@ -748,7 +748,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
                 visit::walk_ty(self, ty);
             }
             TyKind::Path(qself, path) => {
-                self.diagnostic_metadata.current_type_path = Some(ty);
+                self.diag_metadata.current_type_path = Some(ty);
                 self.smart_resolve_path(ty.id, qself, path, PathSource::Type);
 
                 // Check whether we should interpret this as a bare trait object.
@@ -795,7 +795,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
                 self.lifetime_elision_candidates = candidates;
             }
             TyKind::TraitObject(bounds, ..) => {
-                self.diagnostic_metadata.current_trait_object = Some(&bounds[..]);
+                self.diag_metadata.current_trait_object = Some(&bounds[..]);
                 visit::walk_ty(self, ty)
             }
             TyKind::BareFn(bare_fn) => {
@@ -842,8 +842,8 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
             }
             _ => visit::walk_ty(self, ty),
         }
-        self.diagnostic_metadata.current_trait_object = prev;
-        self.diagnostic_metadata.current_type_path = prev_ty;
+        self.diag_metadata.current_trait_object = prev;
+        self.diag_metadata.current_type_path = prev_ty;
     }
     fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef) {
         let span = tref.span.shrink_to_lo().to(tref.trait_ref.path.span.shrink_to_lo());
@@ -906,7 +906,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
         }
     }
     fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) {
-        let previous_value = self.diagnostic_metadata.current_function;
+        let previous_value = self.diag_metadata.current_function;
         match fn_kind {
             // Bail if the function is foreign, and thus cannot validly have
             // a body, or if there's no body for some other reason.
@@ -939,7 +939,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
                 return;
             }
             FnKind::Fn(..) => {
-                self.diagnostic_metadata.current_function = Some((fn_kind, sp));
+                self.diag_metadata.current_function = Some((fn_kind, sp));
             }
             // Do not update `current_function` for closures: it suggests `self` parameters.
             FnKind::Closure(..) => {}
@@ -1040,17 +1040,14 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
                 }
             })
         });
-        self.diagnostic_metadata.current_function = previous_value;
+        self.diag_metadata.current_function = previous_value;
     }
     fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::LifetimeCtxt) {
         self.resolve_lifetime(lifetime, use_ctxt)
     }
 
     fn visit_generics(&mut self, generics: &'ast Generics) {
-        self.visit_generic_params(
-            &generics.params,
-            self.diagnostic_metadata.current_self_item.is_some(),
-        );
+        self.visit_generic_params(&generics.params, self.diag_metadata.current_self_item.is_some());
         for p in &generics.where_clause.predicates {
             self.visit_where_predicate(p);
         }
@@ -1062,7 +1059,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
             ClosureBinder::For { generic_params, .. } => {
                 self.visit_generic_params(
                     generic_params,
-                    self.diagnostic_metadata.current_self_item.is_some(),
+                    self.diag_metadata.current_self_item.is_some(),
                 );
             }
         }
@@ -1070,7 +1067,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_generic_args, true);
+        let prev = replace(&mut self.diag_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
@@ -1101,7 +1098,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
                                 },
                             );
 
-                            self.diagnostic_metadata.currently_processing_generic_args = prev;
+                            self.diag_metadata.currently_processing_generic_args = prev;
                             return;
                         }
                     }
@@ -1114,7 +1111,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_generic_args = prev;
+        self.diag_metadata.currently_processing_generic_args = prev;
     }
 
     fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) {
@@ -1192,8 +1189,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
 
     fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
         debug!("visit_where_predicate {:?}", p);
-        let previous_value =
-            replace(&mut self.diagnostic_metadata.current_where_predicate, Some(p));
+        let previous_value = replace(&mut self.diag_metadata.current_where_predicate, Some(p));
         self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
             if let WherePredicate::BoundPredicate(WhereBoundPredicate {
                 ref bounded_ty,
@@ -1224,7 +1220,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
                 visit::walk_where_predicate(this, p);
             }
         });
-        self.diagnostic_metadata.current_where_predicate = previous_value;
+        self.diag_metadata.current_where_predicate = previous_value;
     }
 
     fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) {
@@ -1246,6 +1242,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
                     self.resolve_anon_const(anon_const, AnonConstKind::InlineConst);
                 }
                 InlineAsmOperand::Sym { sym } => self.visit_inline_asm_sym(sym),
+                InlineAsmOperand::Label { block } => self.visit_block(block),
             }
         }
     }
@@ -1297,7 +1294,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             lifetime_ribs: Vec::new(),
             lifetime_elision_candidates: None,
             current_trait_ref: None,
-            diagnostic_metadata: Default::default(),
+            diag_metadata: Default::default(),
             // errors at module scope should always be reported
             in_func_body: false,
             lifetime_uses: Default::default(),
@@ -1660,7 +1657,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                         node_id,
                         lifetime.ident.span,
                         msg,
-                        lint::BuiltinLintDiagnostics::AssociatedConstElidedLifetime {
+                        lint::BuiltinLintDiag::AssociatedConstElidedLifetime {
                             elided,
                             span: lifetime.ident.span,
                         },
@@ -1707,7 +1704,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     return;
                 }
                 LifetimeRibKind::ElisionFailure => {
-                    self.diagnostic_metadata.current_elision_failures.push(missing_lifetime);
+                    self.diag_metadata.current_elision_failures.push(missing_lifetime);
                     self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
                     return;
                 }
@@ -1911,7 +1908,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                         break;
                     }
                     LifetimeRibKind::ElisionFailure => {
-                        self.diagnostic_metadata.current_elision_failures.push(missing_lifetime);
+                        self.diag_metadata.current_elision_failures.push(missing_lifetime);
                         for id in node_ids {
                             self.record_lifetime_res(
                                 id,
@@ -1950,7 +1947,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     segment_id,
                     elided_lifetime_span,
                     "hidden lifetime parameters in types are deprecated",
-                    lint::BuiltinLintDiagnostics::ElidedLifetimesInPaths(
+                    lint::BuiltinLintDiag::ElidedLifetimesInPaths(
                         expected_lifetimes,
                         path_span,
                         !segment.has_generic_args,
@@ -2003,7 +2000,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         let elision_lifetime = self.resolve_fn_params(has_self, inputs);
         debug!(?elision_lifetime);
 
-        let outer_failures = take(&mut self.diagnostic_metadata.current_elision_failures);
+        let outer_failures = take(&mut self.diag_metadata.current_elision_failures);
         let output_rib = if let Ok(res) = elision_lifetime.as_ref() {
             self.r.lifetime_elision_allowed.insert(fn_id);
             LifetimeRibKind::Elided(*res)
@@ -2012,7 +2009,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         };
         self.with_lifetime_rib(output_rib, |this| visit::walk_fn_ret_ty(this, output_ty));
         let elision_failures =
-            replace(&mut self.diagnostic_metadata.current_elision_failures, outer_failures);
+            replace(&mut self.diag_metadata.current_elision_failures, outer_failures);
         if !elision_failures.is_empty() {
             let Err(failure_info) = elision_lifetime else { bug!() };
             self.report_missing_lifetime_specifiers(elision_failures, Some(failure_info));
@@ -2187,7 +2184,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         }
 
         let impl_self = self
-            .diagnostic_metadata
+            .diag_metadata
             .current_self_type
             .as_ref()
             .and_then(|ty| {
@@ -2385,7 +2382,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 items: ref impl_items,
                 ..
             }) => {
-                self.diagnostic_metadata.current_impl_items = Some(impl_items);
+                self.diag_metadata.current_impl_items = Some(impl_items);
                 self.resolve_implementation(
                     &item.attrs,
                     generics,
@@ -2394,7 +2391,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     item.id,
                     impl_items,
                 );
-                self.diagnostic_metadata.current_impl_items = None;
+                self.diag_metadata.current_impl_items = None;
             }
 
             ItemKind::Trait(box Trait { ref generics, ref bounds, ref items, .. }) => {
@@ -2597,10 +2594,19 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     let span = *entry.get();
                     let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span);
                     self.report_error(param.ident.span, err);
-                    if let GenericParamKind::Lifetime = param.kind {
-                        // Record lifetime res, so lowering knows there is something fishy.
-                        self.record_lifetime_param(param.id, LifetimeRes::Error);
-                    }
+                    let rib = match param.kind {
+                        GenericParamKind::Lifetime => {
+                            // Record lifetime res, so lowering knows there is something fishy.
+                            self.record_lifetime_param(param.id, LifetimeRes::Error);
+                            continue;
+                        }
+                        GenericParamKind::Type { .. } => &mut function_type_rib,
+                        GenericParamKind::Const { .. } => &mut function_value_rib,
+                    };
+
+                    // Taint the resolution in case of errors to prevent follow up errors in typeck
+                    self.r.record_partial_res(param.id, PartialRes::new(Res::Err));
+                    rib.bindings.insert(ident, Res::Err);
                     continue;
                 }
                 Entry::Vacant(entry) => {
@@ -2744,24 +2750,23 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
     fn with_current_self_type<T>(&mut self, self_type: &Ty, f: impl FnOnce(&mut Self) -> T) -> T {
         // Handle nested impls (inside fn bodies)
         let previous_value =
-            replace(&mut self.diagnostic_metadata.current_self_type, Some(self_type.clone()));
+            replace(&mut self.diag_metadata.current_self_type, Some(self_type.clone()));
         let result = f(self);
-        self.diagnostic_metadata.current_self_type = previous_value;
+        self.diag_metadata.current_self_type = previous_value;
         result
     }
 
     fn with_current_self_item<T>(&mut self, self_item: &Item, f: impl FnOnce(&mut Self) -> T) -> T {
-        let previous_value =
-            replace(&mut self.diagnostic_metadata.current_self_item, Some(self_item.id));
+        let previous_value = replace(&mut self.diag_metadata.current_self_item, Some(self_item.id));
         let result = f(self);
-        self.diagnostic_metadata.current_self_item = previous_value;
+        self.diag_metadata.current_self_item = previous_value;
         result
     }
 
     /// When evaluating a `trait` use its associated types' idents for suggestions in E0412.
     fn resolve_trait_items(&mut self, trait_items: &'ast [P<AssocItem>]) {
         let trait_assoc_items =
-            replace(&mut self.diagnostic_metadata.current_trait_assoc_items, Some(trait_items));
+            replace(&mut self.diag_metadata.current_trait_assoc_items, Some(trait_items));
 
         let walk_assoc_item =
             |this: &mut Self, generics: &Generics, kind, item: &'ast AssocItem| {
@@ -2818,7 +2823,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             };
         }
 
-        self.diagnostic_metadata.current_trait_assoc_items = trait_assoc_items;
+        self.diag_metadata.current_trait_assoc_items = trait_assoc_items;
     }
 
     /// This is called to resolve a trait reference from an `impl` (i.e., `impl Trait for Foo`).
@@ -2832,7 +2837,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         let mut new_id = None;
         if let Some(trait_ref) = opt_trait_ref {
             let path: Vec<_> = Segment::from_path(&trait_ref.path);
-            self.diagnostic_metadata.currently_processing_impl_trait =
+            self.diag_metadata.currently_processing_impl_trait =
                 Some((trait_ref.clone(), self_type.clone()));
             let res = self.smart_resolve_path_fragment(
                 &None,
@@ -2841,7 +2846,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 Finalize::new(trait_ref.ref_id, trait_ref.path.span),
                 RecordPartialRes::Yes,
             );
-            self.diagnostic_metadata.currently_processing_impl_trait = None;
+            self.diag_metadata.currently_processing_impl_trait = None;
             if let Some(def_id) = res.expect_full_res().opt_def_id() {
                 new_id = Some(def_id);
                 new_val = Some((self.r.expect_module(def_id), trait_ref.clone()));
@@ -3117,7 +3122,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 );
                 rustc_middle::ty::Visibility::Public
             };
-            this.r.feed_visibility(this.r.local_def_id(id), vis);
+            this.r.feed_visibility(this.r.feed(id), vis);
         };
 
         let Some(binding) = binding else {
@@ -3737,7 +3742,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
 
                 let def_id = this.parent_scope.module.nearest_parent_mod();
                 let instead = res.is_some();
-                let suggestion = if let Some((start, end)) = this.diagnostic_metadata.in_range
+                let suggestion = if let Some((start, end)) = this.diag_metadata.in_range
                     && path[0].ident.span.lo() == end.span.lo()
                 {
                     let mut sugg = ".";
@@ -3890,7 +3895,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         ) {
             Ok(Some(partial_res)) if let Some(res) = partial_res.full_res() => {
                 // if we also have an associated type that matches the ident, stash a suggestion
-                if let Some(items) = self.diagnostic_metadata.current_trait_assoc_items
+                if let Some(items) = self.diag_metadata.current_trait_assoc_items
                     && let [Segment { ident, .. }] = path
                     && items.iter().any(|item| {
                         item.ident == *ident && matches!(item.kind, AssocItemKind::Type(_))
@@ -3958,6 +3963,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             // Avoid recording definition of `A::B` in `<T as A>::B::C`.
             self.r.record_partial_res(node_id, partial_res);
             self.resolve_elided_lifetimes_in_path(partial_res, path, source, path_span);
+            self.lint_unused_qualifications(path, ns, finalize);
         }
 
         partial_res
@@ -4150,46 +4156,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             PathResult::Indeterminate => bug!("indeterminate path result in resolve_qpath"),
         };
 
-        if path.iter().all(|seg| !seg.ident.span.from_expansion()) {
-            let end_pos =
-                path.iter().position(|seg| seg.has_generic_args).map_or(path.len(), |pos| pos + 1);
-            let unqualified =
-                path[..end_pos].iter().enumerate().skip(1).rev().find_map(|(i, seg)| {
-                    // Preserve the current namespace for the final path segment, but use the type
-                    // namespace for all preceding segments
-                    //
-                    // e.g. for `std::env::args` check the `ValueNS` for `args` but the `TypeNS` for
-                    // `std` and `env`
-                    //
-                    // If the final path segment is beyond `end_pos` all the segments to check will
-                    // use the type namespace
-                    let ns = if i + 1 == path.len() { ns } else { TypeNS };
-                    let res = self.r.partial_res_map.get(&seg.id?)?.full_res()?;
-                    let binding = self.resolve_ident_in_lexical_scope(seg.ident, ns, None, None)?;
-
-                    (res == binding.res()).then_some(seg)
-                });
-
-            if let Some(unqualified) = unqualified {
-                self.r.lint_buffer.buffer_lint_with_diagnostic(
-                    lint::builtin::UNUSED_QUALIFICATIONS,
-                    finalize.node_id,
-                    finalize.path_span,
-                    "unnecessary qualification",
-                    lint::BuiltinLintDiagnostics::UnusedQualifications {
-                        removal_span: finalize.path_span.until(unqualified.ident.span),
-                    },
-                );
-            }
-        }
-
         Ok(Some(result))
     }
 
     fn with_resolved_label(&mut self, label: Option<Label>, id: NodeId, f: impl FnOnce(&mut Self)) {
         if let Some(label) = label {
             if label.ident.as_str().as_bytes()[1] != b'_' {
-                self.diagnostic_metadata.unused_labels.insert(id, label.ident.span);
+                self.diag_metadata.unused_labels.insert(id, label.ident.span);
             }
 
             if let Ok((_, orig_span)) = self.resolve_label(label.ident) {
@@ -4226,12 +4199,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             self.ribs[ValueNS].push(Rib::new(RibKind::Normal));
         }
 
-        let prev = self.diagnostic_metadata.current_block_could_be_bare_struct_literal.take();
+        let prev = self.diag_metadata.current_block_could_be_bare_struct_literal.take();
         if let (true, [Stmt { kind: StmtKind::Expr(expr), .. }]) =
             (block.could_be_bare_literal, &block.stmts[..])
             && let ExprKind::Type(..) = expr.kind
         {
-            self.diagnostic_metadata.current_block_could_be_bare_struct_literal = Some(block.span);
+            self.diag_metadata.current_block_could_be_bare_struct_literal = Some(block.span);
         }
         // Descend into the block.
         for stmt in &block.stmts {
@@ -4246,7 +4219,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
 
             self.visit_stmt(stmt);
         }
-        self.diagnostic_metadata.current_block_could_be_bare_struct_literal = prev;
+        self.diag_metadata.current_block_could_be_bare_struct_literal = prev;
 
         // Move back up.
         self.parent_scope.module = orig_module;
@@ -4353,7 +4326,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     Ok((node_id, _)) => {
                         // Since this res is a label, it is never read.
                         self.r.label_res_map.insert(expr.id, node_id);
-                        self.diagnostic_metadata.unused_labels.remove(&node_id);
+                        self.diag_metadata.unused_labels.remove(&node_id);
                     }
                     Err(error) => {
                         self.report_error(label.ident.span, error);
@@ -4377,9 +4350,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
 
             ExprKind::If(ref cond, ref then, ref opt_else) => {
                 self.with_rib(ValueNS, RibKind::Normal, |this| {
-                    let old = this.diagnostic_metadata.in_if_condition.replace(cond);
+                    let old = this.diag_metadata.in_if_condition.replace(cond);
                     this.visit_expr(cond);
-                    this.diagnostic_metadata.in_if_condition = old;
+                    this.diag_metadata.in_if_condition = old;
                     this.visit_block(then);
                 });
                 if let Some(expr) = opt_else {
@@ -4394,9 +4367,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             ExprKind::While(ref cond, ref block, label) => {
                 self.with_resolved_label(label, expr.id, |this| {
                     this.with_rib(ValueNS, RibKind::Normal, |this| {
-                        let old = this.diagnostic_metadata.in_if_condition.replace(cond);
+                        let old = this.diag_metadata.in_if_condition.replace(cond);
                         this.visit_expr(cond);
-                        this.diagnostic_metadata.in_if_condition = old;
+                        this.diag_metadata.in_if_condition = old;
                         this.visit_block(block);
                     })
                 });
@@ -4476,20 +4449,20 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 self.visit_expr(idx);
             }
             ExprKind::Assign(ref lhs, ref rhs, _) => {
-                if !self.diagnostic_metadata.is_assign_rhs {
-                    self.diagnostic_metadata.in_assignment = Some(expr);
+                if !self.diag_metadata.is_assign_rhs {
+                    self.diag_metadata.in_assignment = Some(expr);
                 }
                 self.visit_expr(lhs);
-                self.diagnostic_metadata.is_assign_rhs = true;
-                self.diagnostic_metadata.in_assignment = None;
+                self.diag_metadata.is_assign_rhs = true;
+                self.diag_metadata.in_assignment = None;
                 self.visit_expr(rhs);
-                self.diagnostic_metadata.is_assign_rhs = false;
+                self.diag_metadata.is_assign_rhs = false;
             }
             ExprKind::Range(Some(ref start), Some(ref end), RangeLimits::HalfOpen) => {
-                self.diagnostic_metadata.in_range = Some((start, end));
+                self.diag_metadata.in_range = Some((start, end));
                 self.resolve_expr(start, Some(expr));
                 self.resolve_expr(end, Some(expr));
-                self.diagnostic_metadata.in_range = None;
+                self.diag_metadata.in_range = None;
             }
             _ => {
                 visit::walk_expr(self, expr);
@@ -4661,6 +4634,42 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             self.r.doc_link_traits_in_scope = doc_link_traits_in_scope;
         }
     }
+
+    fn lint_unused_qualifications(&mut self, path: &[Segment], ns: Namespace, finalize: Finalize) {
+        if path.iter().any(|seg| seg.ident.span.from_expansion()) {
+            return;
+        }
+
+        let end_pos =
+            path.iter().position(|seg| seg.has_generic_args).map_or(path.len(), |pos| pos + 1);
+        let unqualified = path[..end_pos].iter().enumerate().skip(1).rev().find_map(|(i, seg)| {
+            // Preserve the current namespace for the final path segment, but use the type
+            // namespace for all preceding segments
+            //
+            // e.g. for `std::env::args` check the `ValueNS` for `args` but the `TypeNS` for
+            // `std` and `env`
+            //
+            // If the final path segment is beyond `end_pos` all the segments to check will
+            // use the type namespace
+            let ns = if i + 1 == path.len() { ns } else { TypeNS };
+            let res = self.r.partial_res_map.get(&seg.id?)?.full_res()?;
+            let binding = self.resolve_ident_in_lexical_scope(seg.ident, ns, None, None)?;
+
+            (res == binding.res()).then_some(seg)
+        });
+
+        if let Some(unqualified) = unqualified {
+            self.r.lint_buffer.buffer_lint_with_diagnostic(
+                lint::builtin::UNUSED_QUALIFICATIONS,
+                finalize.node_id,
+                finalize.path_span,
+                "unnecessary qualification",
+                lint::BuiltinLintDiag::UnusedQualifications {
+                    removal_span: path[0].ident.span.until(unqualified.ident.span),
+                },
+            );
+        }
+    }
 }
 
 /// Walks the whole crate in DFS order, visiting each item, counting the declared number of
@@ -4737,7 +4746,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let mut late_resolution_visitor = LateResolutionVisitor::new(self);
         late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
         visit::walk_crate(&mut late_resolution_visitor, krate);
-        for (id, span) in late_resolution_visitor.diagnostic_metadata.unused_labels.iter() {
+        for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() {
             self.lint_buffer.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label");
         }
     }
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index d008346af69..47f8cc56139 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -224,13 +224,13 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
             let item_ident = path.last().unwrap().ident;
             let item_span = item_ident.span;
             let (mod_prefix, mod_str, module, suggestion) = if path.len() == 1 {
-                debug!(?self.diagnostic_metadata.current_impl_items);
-                debug!(?self.diagnostic_metadata.current_function);
+                debug!(?self.diag_metadata.current_impl_items);
+                debug!(?self.diag_metadata.current_function);
                 let suggestion = if self.current_trait_ref.is_none()
-                    && let Some((fn_kind, _)) = self.diagnostic_metadata.current_function
+                    && let Some((fn_kind, _)) = self.diag_metadata.current_function
                     && let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt()
                     && let FnKind::Fn(_, _, sig, ..) = fn_kind
-                    && let Some(items) = self.diagnostic_metadata.current_impl_items
+                    && let Some(items) = self.diag_metadata.current_impl_items
                     && let Some(item) = items.iter().find(|i| {
                         i.ident.name == item_str.name
                             // Don't suggest if the item is in Fn signature arguments (#112590).
@@ -501,7 +501,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         err: &mut Diag<'_>,
         base_error: &BaseError,
     ) {
-        let Some(ty) = self.diagnostic_metadata.current_type_path else {
+        let Some(ty) = self.diag_metadata.current_type_path else {
             return;
         };
         let TyKind::Path(_, path) = &ty.kind else {
@@ -555,7 +555,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
             );
             if !self.self_value_is_available(path[0].ident.span) {
                 if let Some((FnKind::Fn(_, _, sig, ..), fn_span)) =
-                    &self.diagnostic_metadata.current_function
+                    &self.diag_metadata.current_function
                 {
                     let (span, sugg) = if let Some(param) = sig.decl.inputs.get(0) {
                         (param.span.shrink_to_lo(), "&self, ")
@@ -805,7 +805,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         ) = (source, res, is_macro)
         {
             if let Some(bounds @ [first_bound, .., last_bound]) =
-                self.diagnostic_metadata.current_trait_object
+                self.diag_metadata.current_trait_object
             {
                 fallback = true;
                 let spans: Vec<Span> = bounds
@@ -880,7 +880,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         let typo_sugg = typo_sugg.to_opt_suggestion();
         if !self.r.add_typo_suggestion(err, typo_sugg, ident_span) {
             fallback = true;
-            match self.diagnostic_metadata.current_let_binding {
+            match self.diag_metadata.current_let_binding {
                 Some((pat_sp, Some(ty_sp), None))
                     if ty_sp.contains(base_error.span) && base_error.could_be_expr =>
                 {
@@ -962,7 +962,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                                     Applicability::MaybeIncorrect,
                                 );
                                 // Do not lint against unused label when we suggest them.
-                                self.diagnostic_metadata.unused_labels.remove(node_id);
+                                self.diag_metadata.unused_labels.remove(node_id);
                             }
                         }
                     }
@@ -993,7 +993,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         }
         err.code(E0411);
         err.span_label(span, "`Self` is only available in impls, traits, and type definitions");
-        if let Some(item_kind) = self.diagnostic_metadata.current_item {
+        if let Some(item_kind) = self.diag_metadata.current_item {
             if !item_kind.ident.span.is_dummy() {
                 err.span_label(
                     item_kind.ident.span,
@@ -1031,7 +1031,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
             },
         );
         let is_assoc_fn = self.self_type_is_available();
-        if let Some((fn_kind, span)) = &self.diagnostic_metadata.current_function {
+        if let Some((fn_kind, span)) = &self.diag_metadata.current_function {
             // The current function has a `self` parameter, but we were unable to resolve
             // a reference to `self`. This can only happen if the `self` identifier we
             // are resolving came from a different hygiene context.
@@ -1077,7 +1077,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                     );
                 }
             }
-        } else if let Some(item_kind) = self.diagnostic_metadata.current_item {
+        } else if let Some(item_kind) = self.diag_metadata.current_item {
             err.span_label(
                 item_kind.ident.span,
                 format!(
@@ -1095,7 +1095,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         err: &mut Diag<'_>,
         path: &[Segment],
     ) {
-        let Some(pat) = self.diagnostic_metadata.current_pat else { return };
+        let Some(pat) = self.diag_metadata.current_pat else { return };
         let (bound, side, range) = match &pat.kind {
             ast::PatKind::Range(Some(bound), None, range) => (bound, Side::Start, range),
             ast::PatKind::Range(None, Some(bound), range) => (bound, Side::End, range),
@@ -1137,7 +1137,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         span: Span,
     ) {
         if let Some((trait_ref, self_ty)) =
-            self.diagnostic_metadata.currently_processing_impl_trait.clone()
+            self.diag_metadata.currently_processing_impl_trait.clone()
             && let TyKind::Path(_, self_ty_path) = &self_ty.kind
             && let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
                 self.resolve_path(&Segment::from_path(self_ty_path), Some(TypeNS), None)
@@ -1158,7 +1158,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
     }
 
     fn suggest_bare_struct_literal(&mut self, err: &mut Diag<'_>) {
-        if let Some(span) = self.diagnostic_metadata.current_block_could_be_bare_struct_literal {
+        if let Some(span) = self.diag_metadata.current_block_could_be_bare_struct_literal {
             err.multipart_suggestion(
                 "you might have meant to write a `struct` literal",
                 vec![
@@ -1195,7 +1195,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
             _ => return,
         };
 
-        let Some(item) = self.diagnostic_metadata.current_item else { return };
+        let Some(item) = self.diag_metadata.current_item else { return };
         let Some(generics) = item.kind.generics() else { return };
 
         let param = generics.params.iter().find_map(|param| {
@@ -1230,7 +1230,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
     ) -> bool {
         if let PathSource::Expr(_) = source
             && let Some(Expr { span: expr_span, kind: ExprKind::Assign(lhs, _, _), .. }) =
-                self.diagnostic_metadata.in_if_condition
+                self.diag_metadata.in_if_condition
         {
             // Icky heuristic so we don't suggest:
             // `if (i + 2) = 2` => `if let (i + 2) = 2` (approximately pattern)
@@ -1287,7 +1287,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                 bound_generic_params,
                 bounds,
                 span,
-            })) = self.diagnostic_metadata.current_where_predicate
+            })) = self.diag_metadata.current_where_predicate
             {
                 if !bound_generic_params.is_empty() {
                     return false;
@@ -2015,7 +2015,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         // Fields are generally expected in the same contexts as locals.
         if filter_fn(Res::Local(ast::DUMMY_NODE_ID)) {
             if let Some(node_id) =
-                self.diagnostic_metadata.current_self_type.as_ref().and_then(extract_node_id)
+                self.diag_metadata.current_self_type.as_ref().and_then(extract_node_id)
             {
                 // Look for a field with the same name in the current self_type.
                 if let Some(resolution) = self.r.partial_res_map.get(&node_id) {
@@ -2035,7 +2035,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
             }
         }
 
-        if let Some(items) = self.diagnostic_metadata.current_trait_assoc_items {
+        if let Some(items) = self.diag_metadata.current_trait_assoc_items {
             for assoc_item in items {
                 if assoc_item.ident == ident {
                     return Some(match &assoc_item.kind {
@@ -2250,8 +2250,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
     // try to give a suggestion for this pattern: `name = blah`, which is common in other languages
     // suggest `let name = blah` to introduce a new binding
     fn let_binding_suggestion(&mut self, err: &mut Diag<'_>, ident_span: Span) -> bool {
-        if let Some(Expr { kind: ExprKind::Assign(lhs, ..), .. }) =
-            self.diagnostic_metadata.in_assignment
+        if let Some(Expr { kind: ExprKind::Assign(lhs, ..), .. }) = self.diag_metadata.in_assignment
             && let ast::ExprKind::Path(None, ref path) = lhs.kind
         {
             if !ident_span.from_expansion() {
@@ -2502,10 +2501,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_generic_args && !single_uppercase_char {
+        if !self.diag_metadata.currently_processing_generic_args && !single_uppercase_char {
             return None;
         }
-        match (self.diagnostic_metadata.current_item, single_uppercase_char, self.diagnostic_metadata.currently_processing_generic_args) {
+        match (self.diag_metadata.current_item, single_uppercase_char, self.diag_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>()`
             }
@@ -2658,7 +2657,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                         param.id,
                         param.ident.span,
                         format!("lifetime parameter `{}` only used once", param.ident),
-                        lint::BuiltinLintDiagnostics::SingleUseLifetime {
+                        lint::BuiltinLintDiag::SingleUseLifetime {
                             param_span: param.ident.span,
                             use_span: Some((use_span, elidable)),
                             deletion_span,
@@ -2676,7 +2675,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                             param.id,
                             param.ident.span,
                             format!("lifetime parameter `{}` never used", param.ident),
-                            lint::BuiltinLintDiagnostics::SingleUseLifetime {
+                            lint::BuiltinLintDiag::SingleUseLifetime {
                                 param_span: param.ident.span,
                                 use_span: None,
                                 deletion_span,
@@ -3079,7 +3078,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                             || lt.kind == MissingLifetimeKind::Underscore)
                     {
                         let pre = if lt.kind == MissingLifetimeKind::Ampersand
-                            && let Some((kind, _span)) = self.diagnostic_metadata.current_function
+                            && let Some((kind, _span)) = self.diag_metadata.current_function
                             && let FnKind::Fn(_, _, sig, _, _, _) = kind
                             && !sig.decl.inputs.is_empty()
                             && let sugg = sig
@@ -3120,7 +3119,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                             "...or alternatively, you might want"
                         } else if (lt.kind == MissingLifetimeKind::Ampersand
                             || lt.kind == MissingLifetimeKind::Underscore)
-                            && let Some((kind, _span)) = self.diagnostic_metadata.current_function
+                            && let Some((kind, _span)) = self.diag_metadata.current_function
                             && let FnKind::Fn(_, _, sig, _, _, _) = kind
                             && let ast::FnRetTy::Ty(ret_ty) = &sig.decl.output
                             && !sig.decl.inputs.is_empty()
@@ -3180,7 +3179,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                         };
                         let mut owned_sugg = lt.kind == MissingLifetimeKind::Ampersand;
                         let mut sugg = vec![(lt.span, String::new())];
-                        if let Some((kind, _span)) = self.diagnostic_metadata.current_function
+                        if let Some((kind, _span)) = self.diag_metadata.current_function
                             && let FnKind::Fn(_, _, sig, _, _, _) = kind
                             && let ast::FnRetTy::Ty(ty) = &sig.decl.output
                         {
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 0434ff17193..ccb67ea78cf 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -52,8 +52,8 @@ use rustc_middle::metadata::ModChild;
 use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::query::Providers;
 use rustc_middle::span_bug;
-use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt};
-use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs};
+use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt, TyCtxtFeed};
+use rustc_middle::ty::{Feed, ResolverGlobalCtxt, ResolverOutputs};
 use rustc_query_system::ich::StableHashingContext;
 use rustc_session::lint::builtin::PRIVATE_MACRO_USE;
 use rustc_session::lint::LintBuffer;
@@ -729,6 +729,8 @@ struct PrivacyError<'a> {
     dedup_span: Span,
     outermost_res: Option<(Res, Ident)>,
     parent_scope: ParentScope<'a>,
+    /// Is the format `use a::{b,c}`?
+    single_nested: bool,
 }
 
 #[derive(Debug)]
@@ -1115,7 +1117,7 @@ pub struct Resolver<'a, 'tcx> {
 
     next_node_id: NodeId,
 
-    node_id_to_def_id: NodeMap<LocalDefId>,
+    node_id_to_def_id: NodeMap<Feed<'tcx, LocalDefId>>,
     def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>,
 
     /// Indices of unnamed struct or variant fields with unresolved attributes.
@@ -1231,11 +1233,19 @@ impl<'a, 'tcx> AsMut<Resolver<'a, 'tcx>> for Resolver<'a, 'tcx> {
 
 impl<'tcx> Resolver<'_, 'tcx> {
     fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
-        self.node_id_to_def_id.get(&node).copied()
+        self.opt_feed(node).map(|f| f.key())
     }
 
     fn local_def_id(&self, node: NodeId) -> LocalDefId {
-        self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`"))
+        self.feed(node).key()
+    }
+
+    fn opt_feed(&self, node: NodeId) -> Option<Feed<'tcx, LocalDefId>> {
+        self.node_id_to_def_id.get(&node).copied()
+    }
+
+    fn feed(&self, node: NodeId) -> Feed<'tcx, LocalDefId> {
+        self.opt_feed(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`"))
     }
 
     fn local_def_kind(&self, node: NodeId) -> DefKind {
@@ -1251,18 +1261,19 @@ impl<'tcx> Resolver<'_, 'tcx> {
         def_kind: DefKind,
         expn_id: ExpnId,
         span: Span,
-    ) -> LocalDefId {
+    ) -> TyCtxtFeed<'tcx, LocalDefId> {
         let data = def_kind.def_path_data(name);
         assert!(
             !self.node_id_to_def_id.contains_key(&node_id),
             "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
             node_id,
             data,
-            self.tcx.definitions_untracked().def_key(self.node_id_to_def_id[&node_id]),
+            self.tcx.definitions_untracked().def_key(self.node_id_to_def_id[&node_id].key()),
         );
 
         // FIXME: remove `def_span` body, pass in the right spans here and call `tcx.at().create_def()`
-        let def_id = self.tcx.create_def(parent, name, def_kind).def_id();
+        let feed = self.tcx.create_def(parent, name, def_kind);
+        let def_id = feed.def_id();
 
         // Create the definition.
         if expn_id != ExpnId::root() {
@@ -1279,11 +1290,11 @@ impl<'tcx> Resolver<'_, 'tcx> {
         // we don't need a mapping from `NodeId` to `LocalDefId`.
         if node_id != ast::DUMMY_NODE_ID {
             debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
-            self.node_id_to_def_id.insert(node_id, def_id);
+            self.node_id_to_def_id.insert(node_id, feed.downgrade());
         }
         assert_eq!(self.def_id_to_node_id.push(node_id), def_id);
 
-        def_id
+        feed
     }
 
     fn item_generics_num_lifetimes(&self, def_id: DefId) -> usize {
@@ -1331,7 +1342,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let mut def_id_to_node_id = IndexVec::default();
         assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), CRATE_DEF_ID);
         let mut node_id_to_def_id = NodeMap::default();
-        node_id_to_def_id.insert(CRATE_NODE_ID, CRATE_DEF_ID);
+        let crate_feed = tcx.create_local_crate_def_id(crate_span);
+
+        crate_feed.def_kind(DefKind::Mod);
+        let crate_feed = crate_feed.downgrade();
+        node_id_to_def_id.insert(CRATE_NODE_ID, crate_feed);
 
         let mut invocation_parents = FxHashMap::default();
         invocation_parents.insert(LocalExpnId::ROOT, (CRATE_DEF_ID, ImplTraitContext::Existential));
@@ -1482,7 +1497,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
         let root_parent_scope = ParentScope::module(graph_root, &resolver);
         resolver.invocation_parent_scopes.insert(LocalExpnId::ROOT, root_parent_scope);
-        resolver.feed_visibility(CRATE_DEF_ID, ty::Visibility::Public);
+        resolver.feed_visibility(crate_feed, ty::Visibility::Public);
 
         resolver
     }
@@ -1530,9 +1545,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         Default::default()
     }
 
-    fn feed_visibility(&mut self, def_id: LocalDefId, vis: ty::Visibility) {
-        self.tcx.feed_local_def_id(def_id).visibility(vis.to_def_id());
-        self.visibilities_for_hashing.push((def_id, vis));
+    fn feed_visibility(&mut self, feed: Feed<'tcx, LocalDefId>, vis: ty::Visibility) {
+        let feed = feed.upgrade(self.tcx);
+        feed.visibility(vis.to_def_id());
+        self.visibilities_for_hashing.push((feed.def_id(), vis));
     }
 
     pub fn into_outputs(self) -> ResolverOutputs {
@@ -1545,12 +1561,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let confused_type_with_std_module = self.confused_type_with_std_module;
         let effective_visibilities = self.effective_visibilities;
 
-        self.tcx.feed_local_crate().stripped_cfg_items(self.tcx.arena.alloc_from_iter(
-            self.stripped_cfg_items.into_iter().filter_map(|item| {
-                let parent_module = self.node_id_to_def_id.get(&item.parent_module)?.to_def_id();
-                Some(StrippedCfgItem { parent_module, name: item.name, cfg: item.cfg })
-            }),
-        ));
+        let stripped_cfg_items = Steal::new(
+            self.stripped_cfg_items
+                .into_iter()
+                .filter_map(|item| {
+                    let parent_module =
+                        self.node_id_to_def_id.get(&item.parent_module)?.key().to_def_id();
+                    Some(StrippedCfgItem { parent_module, name: item.name, cfg: item.cfg })
+                })
+                .collect(),
+        );
 
         let global_ctxt = ResolverGlobalCtxt {
             expn_that_defined,
@@ -1567,6 +1587,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             doc_link_resolutions: self.doc_link_resolutions,
             doc_link_traits_in_scope: self.doc_link_traits_in_scope,
             all_macro_rules: self.all_macro_rules,
+            stripped_cfg_items,
         };
         let ast_lowering = ty::ResolverAstLowering {
             legacy_const_generic_args: self.legacy_const_generic_args,
@@ -1576,7 +1597,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             lifetimes_res_map: self.lifetimes_res_map,
             extra_lifetime_params_map: self.extra_lifetime_params_map,
             next_node_id: self.next_node_id,
-            node_id_to_def_id: self.node_id_to_def_id,
+            node_id_to_def_id: self
+                .node_id_to_def_id
+                .into_items()
+                .map(|(k, f)| (k, f.key()))
+                .collect(),
             def_id_to_node_id: self.def_id_to_node_id,
             trait_map: self.trait_map,
             lifetime_elision_allowed: self.lifetime_elision_allowed,
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 3fccdec8aa0..c7bb2a573b1 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -27,7 +27,7 @@ use rustc_middle::ty::{TyCtxt, Visibility};
 use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES;
 use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE};
 use rustc_session::lint::builtin::{UNUSED_MACROS, UNUSED_MACRO_RULES};
-use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::parse::feature_err;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::{self, ExpnData, ExpnKind, LocalExpnId};
@@ -590,7 +590,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 _ => unreachable!(),
             };
             if soft_custom_inner_attributes_gate {
-                self.tcx.sess.parse_sess.buffer_lint(SOFT_UNSTABLE, path.span, node_id, msg);
+                self.tcx.sess.psess.buffer_lint(SOFT_UNSTABLE, path.span, node_id, msg);
             } else {
                 feature_err(&self.tcx.sess, sym::custom_inner_attributes, path.span, msg).emit();
             }
@@ -601,7 +601,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             && path.segments[0].ident.name == sym::diagnostic
             && path.segments[1].ident.name != sym::on_unimplemented
         {
-            self.tcx.sess.parse_sess.buffer_lint(
+            self.tcx.sess.psess.buffer_lint(
                 UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
                 path.segments[1].span(),
                 node_id,
@@ -810,7 +810,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             node_id,
                             ident.span,
                             "derive helper attribute is used before it is introduced",
-                            BuiltinLintDiagnostics::LegacyDeriveHelpers(binding.span),
+                            BuiltinLintDiag::LegacyDeriveHelpers(binding.span),
                         );
                     }
                 }
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index dadbcff6f68..61a220428b0 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1,6 +1,8 @@
 //! Contains infrastructure for configuring the compiler, including parsing
 //! command-line options.
 
+#![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
+
 pub use crate::options::*;
 
 use crate::errors::FileWriteFail;
@@ -146,8 +148,10 @@ pub enum LtoCli {
 /// unless the function has type parameters.
 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
 pub enum InstrumentCoverage {
-    /// Default `-C instrument-coverage` or `-C instrument-coverage=statement`
-    All,
+    /// `-C instrument-coverage=no` (or `off`, `false` etc.)
+    No,
+    /// `-C instrument-coverage` or `-C instrument-coverage=yes`
+    Yes,
     /// Additionally, instrument branches and output branch coverage.
     /// `-Zunstable-options -C instrument-coverage=branch`
     Branch,
@@ -155,8 +159,6 @@ pub enum InstrumentCoverage {
     ExceptUnusedGenerics,
     /// `-Zunstable-options -C instrument-coverage=except-unused-functions`
     ExceptUnusedFunctions,
-    /// `-C instrument-coverage=off` (or `no`, etc.)
-    Off,
 }
 
 /// Settings for `-Z instrument-xray` flag.
@@ -2468,9 +2470,7 @@ pub fn parse_externs(
             ));
             let adjusted_name = name.replace('-', "_");
             if is_ascii_ident(&adjusted_name) {
-                // FIXME: make this translatable
-                #[allow(rustc::diagnostic_outside_of_impl)]
-                #[allow(rustc::untranslatable_diagnostic)]
+                #[allow(rustc::diagnostic_outside_of_impl)] // FIXME
                 error.help(format!(
                     "consider replacing the dashes with underscores: `{adjusted_name}`"
                 ));
@@ -2722,7 +2722,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
     // This is what prevents them from being used on stable compilers.
     match cg.instrument_coverage {
         // Stable values:
-        InstrumentCoverage::All | InstrumentCoverage::Off => {}
+        InstrumentCoverage::Yes | InstrumentCoverage::No => {}
         // Unstable values:
         InstrumentCoverage::Branch
         | InstrumentCoverage::ExceptUnusedFunctions
@@ -2736,7 +2736,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
         }
     }
 
-    if cg.instrument_coverage != InstrumentCoverage::Off {
+    if cg.instrument_coverage != InstrumentCoverage::No {
         if cg.profile_generate.enabled() || cg.profile_use.is_some() {
             early_dcx.early_fatal(
                 "option `-C instrument-coverage` is not compatible with either `-C profile-use` \
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index 903d429d3a5..3c8ad27c07c 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -3,8 +3,8 @@ use std::num::NonZero;
 use rustc_ast::token;
 use rustc_ast::util::literal::LitError;
 use rustc_errors::{
-    codes::*, Diag, DiagCtxt, DiagnosticMessage, EmissionGuarantee, ErrorGuaranteed,
-    IntoDiagnostic, Level, MultiSpan,
+    codes::*, Diag, DiagCtxt, DiagMessage, EmissionGuarantee, ErrorGuaranteed, IntoDiagnostic,
+    Level, MultiSpan,
 };
 use rustc_macros::Diagnostic;
 use rustc_span::{Span, Symbol};
@@ -14,7 +14,7 @@ use crate::parse::ParseSess;
 
 pub struct FeatureGateError {
     pub span: MultiSpan,
-    pub explain: DiagnosticMessage,
+    pub explain: DiagMessage,
 }
 
 impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for FeatureGateError {
@@ -346,7 +346,7 @@ pub(crate) struct BinaryFloatLiteralNotSupported {
 }
 
 pub fn report_lit_error(
-    sess: &ParseSess,
+    psess: &ParseSess,
     err: LitError,
     lit: token::Lit,
     span: Span,
@@ -378,7 +378,7 @@ pub fn report_lit_error(
         valid.then(|| format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
     }
 
-    let dcx = &sess.dcx;
+    let dcx = &psess.dcx;
     match err {
         LitError::InvalidSuffix(suffix) => {
             dcx.emit_err(InvalidLiteralSuffix { span, kind: lit.kind.descr(), suffix })
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 42c9d5e10eb..93bef82e4ba 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -320,6 +320,7 @@ macro_rules! redirect_field {
 type OptionSetter<O> = fn(&mut O, v: Option<&str>) -> bool;
 type OptionDescrs<O> = &'static [(&'static str, OptionSetter<O>, &'static str, &'static str)];
 
+#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
 fn build_options<O: Default>(
     early_dcx: &EarlyDiagCtxt,
     matches: &getopts::Matches,
@@ -394,8 +395,7 @@ mod desc {
     pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of();
     pub const parse_optimization_fuel: &str = "crate=integer";
     pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`";
-    pub const parse_instrument_coverage: &str =
-        "`all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off`";
+    pub const parse_instrument_coverage: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc) or (unstable) one of `branch`, `except-unused-generics`, `except-unused-functions`";
     pub const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`";
     pub const parse_unpretty: &str = "`string` or `string=string`";
     pub const parse_treat_err_as_bug: &str = "either no value or a non-negative number";
@@ -918,18 +918,18 @@ mod parse {
         if v.is_some() {
             let mut bool_arg = false;
             if parse_bool(&mut bool_arg, v) {
-                *slot = if bool_arg { InstrumentCoverage::All } else { InstrumentCoverage::Off };
+                *slot = if bool_arg { InstrumentCoverage::Yes } else { InstrumentCoverage::No };
                 return true;
             }
         }
 
         let Some(v) = v else {
-            *slot = InstrumentCoverage::All;
+            *slot = InstrumentCoverage::Yes;
             return true;
         };
 
         *slot = match v {
-            "all" => InstrumentCoverage::All,
+            "all" => InstrumentCoverage::Yes,
             "branch" => InstrumentCoverage::Branch,
             "except-unused-generics" | "except_unused_generics" => {
                 InstrumentCoverage::ExceptUnusedGenerics
@@ -937,7 +937,7 @@ mod parse {
             "except-unused-functions" | "except_unused_functions" => {
                 InstrumentCoverage::ExceptUnusedFunctions
             }
-            "off" | "no" | "n" | "false" | "0" => InstrumentCoverage::Off,
+            "0" => InstrumentCoverage::No,
             _ => return false,
         };
         true
@@ -1444,15 +1444,15 @@ options! {
     inline_threshold: Option<u32> = (None, parse_opt_number, [TRACKED],
         "set the threshold for inlining a function"),
     #[rustc_lint_opt_deny_field_access("use `Session::instrument_coverage` instead of this field")]
-    instrument_coverage: InstrumentCoverage = (InstrumentCoverage::Off, parse_instrument_coverage, [TRACKED],
+    instrument_coverage: InstrumentCoverage = (InstrumentCoverage::No, parse_instrument_coverage, [TRACKED],
         "instrument the generated code to support LLVM source-based code coverage \
         reports (note, the compiler build config must include `profiler = true`); \
         implies `-C symbol-mangling-version=v0`. Optional values are:
-        `=all` (implicit value)
-        `=branch`
-        `=except-unused-generics`
-        `=except-unused-functions`
-        `=off` (default)"),
+        `=no` `=n` `=off` `=false` (default)
+        `=yes` `=y` `=on` `=true` (implicit value)
+        `=branch` (unstable)
+        `=except-unused-generics` (unstable)
+        `=except-unused-functions` (unstable)"),
     link_arg: (/* redirected to link_args */) = ((), parse_string_push, [UNTRACKED],
         "a single extra argument to append to the linker invocation (can be used several times)"),
     link_args: Vec<String> = (Vec::new(), parse_list, [UNTRACKED],
@@ -1565,6 +1565,8 @@ options! {
         "set options for branch target identification and pointer authentication on AArch64"),
     cf_protection: CFProtection = (CFProtection::None, parse_cfprotection, [TRACKED],
         "instrument control-flow architecture protection"),
+    check_cfg_all_expected: bool = (false, parse_bool, [UNTRACKED],
+        "show all expected values in check-cfg diagnostics (default: no)"),
     codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
         "the backend to use"),
     collapse_macro_debuginfo: CollapseMacroDebuginfo = (CollapseMacroDebuginfo::Unspecified,
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 9170b265748..398138d7e1f 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -7,7 +7,7 @@ use crate::errors::{
     SuggestUpgradeCompiler,
 };
 use crate::lint::{
-    builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId,
+    builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiag, Lint, LintId,
 };
 use crate::Session;
 use rustc_ast::node_id::NodeId;
@@ -15,8 +15,8 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
 use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc};
 use rustc_errors::emitter::{stderr_destination, HumanEmitter, SilentEmitter};
 use rustc_errors::{
-    fallback_fluent_bundle, ColorConfig, Diag, DiagCtxt, DiagnosticMessage, EmissionGuarantee,
-    MultiSpan, StashKey,
+    fallback_fluent_bundle, ColorConfig, Diag, DiagCtxt, DiagMessage, EmissionGuarantee, MultiSpan,
+    StashKey,
 };
 use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
 use rustc_span::edition::Edition;
@@ -85,7 +85,7 @@ pub fn feature_err(
     sess: &Session,
     feature: Symbol,
     span: impl Into<MultiSpan>,
-    explain: impl Into<DiagnosticMessage>,
+    explain: impl Into<DiagMessage>,
 ) -> Diag<'_> {
     feature_err_issue(sess, feature, span, GateIssue::Language, explain)
 }
@@ -100,19 +100,18 @@ pub fn feature_err_issue(
     feature: Symbol,
     span: impl Into<MultiSpan>,
     issue: GateIssue,
-    explain: impl Into<DiagnosticMessage>,
+    explain: impl Into<DiagMessage>,
 ) -> Diag<'_> {
     let span = span.into();
 
     // Cancel an earlier warning for this same error, if it exists.
     if let Some(span) = span.primary_span() {
-        if let Some(err) = sess.parse_sess.dcx.steal_non_err(span, StashKey::EarlySyntaxWarning) {
+        if let Some(err) = sess.psess.dcx.steal_non_err(span, StashKey::EarlySyntaxWarning) {
             err.cancel()
         }
     }
 
-    let mut err =
-        sess.parse_sess.dcx.create_err(FeatureGateError { span, explain: explain.into() });
+    let mut err = sess.psess.dcx.create_err(FeatureGateError { span, explain: explain.into() });
     add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false);
     err
 }
@@ -141,7 +140,7 @@ pub fn feature_warn_issue(
     issue: GateIssue,
     explain: &'static str,
 ) {
-    let mut err = sess.parse_sess.dcx.struct_span_warn(span, explain);
+    let mut err = sess.psess.dcx.struct_span_warn(span, explain);
     add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false);
 
     // Decorate this as a future-incompatibility lint as in rustc_middle::lint::lint_level
@@ -169,6 +168,7 @@ pub fn add_feature_diagnostics<G: EmissionGuarantee>(
 /// This variant allows you to control whether it is a library or language feature.
 /// Almost always, you want to use this for a language feature. If so, prefer
 /// `add_feature_diagnostics`.
+#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
 pub fn add_feature_diagnostics_for_issue<G: EmissionGuarantee>(
     err: &mut Diag<'_, G>,
     sess: &Session,
@@ -181,7 +181,7 @@ pub fn add_feature_diagnostics_for_issue<G: EmissionGuarantee>(
     }
 
     // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
-    if sess.parse_sess.unstable_features.is_nightly_build() {
+    if sess.psess.unstable_features.is_nightly_build() {
         if feature_from_cli {
             err.subdiagnostic(sess.dcx(), CliFeatureDiagnosticHelp { feature });
         } else {
@@ -233,9 +233,9 @@ pub struct ParseSess {
 
 impl ParseSess {
     /// Used for testing.
-    pub fn new(locale_resources: Vec<&'static str>, file_path_mapping: FilePathMapping) -> Self {
+    pub fn new(locale_resources: Vec<&'static str>) -> Self {
         let fallback_bundle = fallback_fluent_bundle(locale_resources, false);
-        let sm = Lrc::new(SourceMap::new(file_path_mapping));
+        let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
         let emitter = Box::new(
             HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle)
                 .sm(Some(sm.clone())),
@@ -266,14 +266,20 @@ impl ParseSess {
         }
     }
 
-    pub fn with_silent_emitter(fatal_note: String) -> Self {
-        let fallback_bundle = fallback_fluent_bundle(Vec::new(), false);
+    pub fn with_silent_emitter(locale_resources: Vec<&'static str>, fatal_note: String) -> Self {
+        let fallback_bundle = fallback_fluent_bundle(locale_resources, false);
         let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
-        let emitter =
-            Box::new(HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle));
+        let emitter = Box::new(HumanEmitter::new(
+            stderr_destination(ColorConfig::Auto),
+            fallback_bundle.clone(),
+        ));
         let fatal_dcx = DiagCtxt::new(emitter);
-        let dcx =
-            DiagCtxt::new(Box::new(SilentEmitter { fatal_dcx, fatal_note })).disable_warnings();
+        let dcx = DiagCtxt::new(Box::new(SilentEmitter {
+            fallback_bundle,
+            fatal_dcx,
+            fatal_note: Some(fatal_note),
+        }))
+        .disable_warnings();
         ParseSess::with_dcx(dcx, sm)
     }
 
@@ -291,7 +297,7 @@ impl ParseSess {
         lint: &'static Lint,
         span: impl Into<MultiSpan>,
         node_id: NodeId,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
     ) {
         self.buffered_lints.with_lock(|buffered_lints| {
             buffered_lints.push(BufferedEarlyLint {
@@ -299,7 +305,7 @@ impl ParseSess {
                 node_id,
                 msg: msg.into(),
                 lint_id: LintId::of(lint),
-                diagnostic: BuiltinLintDiagnostics::Normal,
+                diagnostic: BuiltinLintDiag::Normal,
             });
         });
     }
@@ -309,8 +315,8 @@ impl ParseSess {
         lint: &'static Lint,
         span: impl Into<MultiSpan>,
         node_id: NodeId,
-        msg: impl Into<DiagnosticMessage>,
-        diagnostic: BuiltinLintDiagnostics,
+        msg: impl Into<DiagMessage>,
+        diagnostic: BuiltinLintDiag,
     ) {
         self.buffered_lints.with_lock(|buffered_lints| {
             buffered_lints.push(BufferedEarlyLint {
diff --git a/compiler/rustc_session/src/search_paths.rs b/compiler/rustc_session/src/search_paths.rs
index 9b913c76998..32d5e430717 100644
--- a/compiler/rustc_session/src/search_paths.rs
+++ b/compiler/rustc_session/src/search_paths.rs
@@ -61,6 +61,7 @@ impl SearchPath {
             (PathKind::All, path)
         };
         if path.is_empty() {
+            #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
             early_dcx.early_fatal("empty search path given via `-L`");
         }
 
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 09fb6aa5d8f..ae1dbd13204 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -22,8 +22,8 @@ use rustc_errors::emitter::{stderr_destination, DynEmitter, HumanEmitter, HumanR
 use rustc_errors::json::JsonEmitter;
 use rustc_errors::registry::Registry;
 use rustc_errors::{
-    codes::*, fallback_fluent_bundle, Diag, DiagCtxt, DiagnosticMessage, ErrorGuaranteed,
-    FatalAbort, FluentBundle, IntoDiagnostic, LazyFallbackBundle, TerminalUrl,
+    codes::*, fallback_fluent_bundle, Diag, DiagCtxt, DiagMessage, ErrorGuaranteed, FatalAbort,
+    FluentBundle, IntoDiagnostic, LazyFallbackBundle, TerminalUrl,
 };
 use rustc_macros::HashStable_Generic;
 pub use rustc_span::def_id::StableCrateId;
@@ -146,7 +146,7 @@ pub struct Session {
     pub opts: config::Options,
     pub host_tlib_path: Lrc<SearchPath>,
     pub target_tlib_path: Lrc<SearchPath>,
-    pub parse_sess: ParseSess,
+    pub psess: ParseSess,
     pub sysroot: PathBuf,
     /// Input, input file path and output file path to this compilation process.
     pub io: CompilerIO,
@@ -312,6 +312,7 @@ impl Session {
     ) -> Diag<'a> {
         let mut err = self.dcx().create_err(err);
         if err.code.is_none() {
+            #[allow(rustc::diagnostic_outside_of_impl)]
             err.code(E0658);
         }
         add_feature_diagnostics(&mut err, self, feature);
@@ -336,12 +337,12 @@ impl Session {
 
     #[inline]
     pub fn dcx(&self) -> &DiagCtxt {
-        &self.parse_sess.dcx
+        &self.psess.dcx
     }
 
     #[inline]
     pub fn source_map(&self) -> &SourceMap {
-        self.parse_sess.source_map()
+        self.psess.source_map()
     }
 
     /// Returns `true` if internal lints should be added to the lint store - i.e. if
@@ -352,7 +353,7 @@ impl Session {
     }
 
     pub fn instrument_coverage(&self) -> bool {
-        self.opts.cg.instrument_coverage() != InstrumentCoverage::Off
+        self.opts.cg.instrument_coverage() != InstrumentCoverage::No
     }
 
     pub fn instrument_coverage_branch(&self) -> bool {
@@ -898,19 +899,6 @@ impl Session {
     }
 
     pub fn should_prefer_remapped_for_codegen(&self) -> bool {
-        // bail out, if any of the requested crate types aren't:
-        // "compiled executables or libraries"
-        for crate_type in &self.opts.crate_types {
-            match crate_type {
-                CrateType::Executable
-                | CrateType::Dylib
-                | CrateType::Rlib
-                | CrateType::Staticlib
-                | CrateType::Cdylib => continue,
-                CrateType::ProcMacro => return false,
-            }
-        }
-
         let has_split_debuginfo = match self.split_debuginfo() {
             SplitDebuginfo::Off => false,
             SplitDebuginfo::Packed => true,
@@ -1022,6 +1010,7 @@ fn default_emitter(
 
 // JUSTIFICATION: literally session construction
 #[allow(rustc::bad_opt_access)]
+#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
 pub fn build_session(
     early_dcx: EarlyDiagCtxt,
     sopts: config::Options,
@@ -1114,8 +1103,8 @@ pub fn build_session(
         None
     };
 
-    let mut parse_sess = ParseSess::with_dcx(dcx, source_map);
-    parse_sess.assume_incomplete_release = sopts.unstable_opts.assume_incomplete_release;
+    let mut psess = ParseSess::with_dcx(dcx, source_map);
+    psess.assume_incomplete_release = sopts.unstable_opts.assume_incomplete_release;
 
     let host_triple = config::host_triple();
     let target_triple = sopts.target_triple.triple();
@@ -1154,7 +1143,7 @@ pub fn build_session(
         opts: sopts,
         host_tlib_path,
         target_tlib_path,
-        parse_sess,
+        psess,
         sysroot,
         io,
         incr_comp_session: RwLock::new(IncrCompSession::NotInitialized),
@@ -1419,38 +1408,38 @@ impl EarlyDiagCtxt {
 
     #[allow(rustc::untranslatable_diagnostic)]
     #[allow(rustc::diagnostic_outside_of_impl)]
-    pub fn early_note(&self, msg: impl Into<DiagnosticMessage>) {
+    pub fn early_note(&self, msg: impl Into<DiagMessage>) {
         self.dcx.note(msg)
     }
 
     #[allow(rustc::untranslatable_diagnostic)]
     #[allow(rustc::diagnostic_outside_of_impl)]
-    pub fn early_help(&self, msg: impl Into<DiagnosticMessage>) {
+    pub fn early_help(&self, msg: impl Into<DiagMessage>) {
         self.dcx.struct_help(msg).emit()
     }
 
     #[allow(rustc::untranslatable_diagnostic)]
     #[allow(rustc::diagnostic_outside_of_impl)]
     #[must_use = "ErrorGuaranteed must be returned from `run_compiler` in order to exit with a non-zero status code"]
-    pub fn early_err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
+    pub fn early_err(&self, msg: impl Into<DiagMessage>) -> ErrorGuaranteed {
         self.dcx.err(msg)
     }
 
     #[allow(rustc::untranslatable_diagnostic)]
     #[allow(rustc::diagnostic_outside_of_impl)]
-    pub fn early_fatal(&self, msg: impl Into<DiagnosticMessage>) -> ! {
+    pub fn early_fatal(&self, msg: impl Into<DiagMessage>) -> ! {
         self.dcx.fatal(msg)
     }
 
     #[allow(rustc::untranslatable_diagnostic)]
     #[allow(rustc::diagnostic_outside_of_impl)]
-    pub fn early_struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> Diag<'_, FatalAbort> {
+    pub fn early_struct_fatal(&self, msg: impl Into<DiagMessage>) -> Diag<'_, FatalAbort> {
         self.dcx.struct_fatal(msg)
     }
 
     #[allow(rustc::untranslatable_diagnostic)]
     #[allow(rustc::diagnostic_outside_of_impl)]
-    pub fn early_warn(&self, msg: impl Into<DiagnosticMessage>) {
+    pub fn early_warn(&self, msg: impl Into<DiagMessage>) {
         self.dcx.warn(msg)
     }
 
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
index 501d6f7d304..003a9a59200 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
@@ -559,7 +559,8 @@ impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> {
             }
             InlineAsmOperand::Const { .. }
             | InlineAsmOperand::SymFn { .. }
-            | InlineAsmOperand::SymStatic { .. } => (None, None),
+            | InlineAsmOperand::SymStatic { .. }
+            | InlineAsmOperand::Label { .. } => (None, None),
         };
 
         stable_mir::mir::InlineAsmOperand { in_value, out_place, raw_rpr: format!("{self:?}") }
@@ -632,14 +633,15 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
                 operands,
                 options,
                 line_spans,
-                destination,
+                targets,
                 unwind,
             } => TerminatorKind::InlineAsm {
                 template: format!("{template:?}"),
                 operands: operands.iter().map(|operand| operand.stable(tables)).collect(),
                 options: format!("{options:?}"),
                 line_spans: format!("{line_spans:?}"),
-                destination: destination.map(|d| d.as_usize()),
+                // FIXME: Figure out how to do labels in SMIR
+                destination: targets.first().map(|d| d.as_usize()),
                 unwind: unwind.stable(tables),
             },
             mir::TerminatorKind::Yield { .. }
diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml
index 99de91a068a..98ed985738a 100644
--- a/compiler/rustc_span/Cargo.toml
+++ b/compiler/rustc_span/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 indexmap = { version = "2.0.0" }
+itoa = "1.0"
 md5 = { package = "md-5", version = "0.10.0" }
 rustc_arena = { path = "../rustc_arena" }
 rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 7e31cfc0662..80c4dcb6b18 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -187,7 +187,7 @@ symbols! {
         DecorateLint,
         Default,
         Deref,
-        DiagnosticMessage,
+        DiagMessage,
         DirBuilder,
         Display,
         DoubleEndedIterator,
@@ -304,7 +304,7 @@ symbols! {
         SpanCtxt,
         String,
         StructuralPartialEq,
-        SubdiagnosticMessage,
+        SubdiagMessage,
         Sync,
         T,
         Target,
@@ -399,6 +399,7 @@ symbols! {
         asm,
         asm_const,
         asm_experimental_arch,
+        asm_goto,
         asm_sym,
         asm_unwind,
         assert,
@@ -896,6 +897,7 @@ symbols! {
         generic_const_items,
         generic_param_attrs,
         get_context,
+        global_alloc_ty,
         global_allocator,
         global_asm,
         globs,
@@ -1525,6 +1527,7 @@ symbols! {
         rustc_inherit_overflow_checks,
         rustc_insignificant_dtor,
         rustc_intrinsic,
+        rustc_intrinsic_must_be_overridden,
         rustc_layout,
         rustc_layout_scalar_valid_range_end,
         rustc_layout_scalar_valid_range_start,
@@ -2324,13 +2327,15 @@ pub mod sym {
     ///
     /// The first few non-negative integers each have a static symbol and therefore
     /// are fast.
-    pub fn integer<N: TryInto<usize> + Copy + ToString>(n: N) -> Symbol {
+    pub fn integer<N: TryInto<usize> + Copy + itoa::Integer>(n: N) -> Symbol {
         if let Result::Ok(idx) = n.try_into() {
             if idx < 10 {
                 return Symbol::new(super::SYMBOL_DIGITS_BASE + idx as u32);
             }
         }
-        Symbol::intern(&n.to_string())
+        let mut buffer = itoa::Buffer::new();
+        let printed = buffer.format(n);
+        Symbol::intern(printed)
     }
 }
 
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 66177d551ba..f4967b94e93 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -814,7 +814,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
                     }
                 }
             },
-            "aarch64" => {
+            "aarch64" | "arm64ec" => {
                 let kind = if cx.target_spec().is_like_osx {
                     aarch64::AbiKind::DarwinPCS
                 } else if cx.target_spec().is_like_windows {
diff --git a/compiler/rustc_target/src/spec/base/avr_gnu.rs b/compiler/rustc_target/src/spec/base/avr_gnu.rs
index cd324c94bbe..1e410cea8d6 100644
--- a/compiler/rustc_target/src/spec/base/avr_gnu.rs
+++ b/compiler/rustc_target/src/spec/base/avr_gnu.rs
@@ -8,6 +8,7 @@ use object::elf;
 pub fn target(target_cpu: &'static str, mmcu: &'static str) -> Target {
     Target {
         arch: "avr".into(),
+        description: None,
         data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(),
         llvm_target: "avr-unknown-unknown".into(),
         pointer_width: 16,
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 0642290f109..3b6e15fad46 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1404,6 +1404,7 @@ supported_targets! {
     ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
     ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
     ("loongarch64-unknown-linux-gnu", loongarch64_unknown_linux_gnu),
+    ("loongarch64-unknown-linux-musl", loongarch64_unknown_linux_musl),
     ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu),
     ("csky-unknown-linux-gnuabiv2", csky_unknown_linux_gnuabiv2),
     ("csky-unknown-linux-gnuabiv2hf", csky_unknown_linux_gnuabiv2hf),
@@ -1564,6 +1565,7 @@ supported_targets! {
 
     ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
     ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc),
+    ("arm64ec-pc-windows-msvc", arm64ec_pc_windows_msvc),
     ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
     ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc),
     ("x86_64-win7-windows-msvc", x86_64_win7_windows_msvc),
@@ -1577,6 +1579,7 @@ supported_targets! {
     ("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
     ("wasm32-unknown-unknown", wasm32_unknown_unknown),
     ("wasm32-wasi", wasm32_wasi),
+    ("wasm32-wasip1", wasm32_wasip1),
     ("wasm32-wasip2", wasm32_wasip2),
     ("wasm32-wasi-preview1-threads", wasm32_wasi_preview1_threads),
     ("wasm64-unknown-unknown", wasm64_unknown_unknown),
@@ -1740,6 +1743,11 @@ impl TargetWarnings {
 pub struct Target {
     /// Target triple to pass to LLVM.
     pub llvm_target: StaticCow<str>,
+    /// A short description of the target including platform requirements,
+    /// for example "64-bit Linux (kernel 3.2+, glibc 2.17+)".
+    /// Optional for now, intended to be required in the future.
+    /// Part of #120745.
+    pub description: Option<StaticCow<str>>,
     /// Number of bits in a pointer. Influences the `target_pointer_width` `cfg` variable.
     pub pointer_width: u32,
     /// Architecture to use for ABI considerations. Valid options include: "x86",
@@ -2541,6 +2549,7 @@ impl Target {
 
         let mut base = Target {
             llvm_target: get_req_field("llvm-target")?.into(),
+            description: get_req_field("description").ok().map(Into::into),
             pointer_width: get_req_field("target-pointer-width")?
                 .parse::<u32>()
                 .map_err(|_| "target-pointer-width must be an integer".to_string())?,
@@ -3244,6 +3253,7 @@ impl ToJson for Target {
         }
 
         target_val!(llvm_target);
+        target_val!(description);
         d.insert("target-pointer-width".to_string(), self.pointer_width.to_string().to_json());
         target_val!(arch);
         target_val!(data_layout);
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
index 8e6c00b1255..05912d93689 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
@@ -15,6 +15,7 @@ pub fn target() -> Target {
         // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
         // correctly, we do too.
         llvm_target: macos_llvm_target(arch).into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
index f291ac5458d..6591d85384d 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
@@ -12,6 +12,7 @@ pub fn target() -> Target {
         // This is required for the target to pick the right
         // MACH-O commands, so we do too.
         llvm_target: ios_llvm_target(arch).into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
index 300e3014079..2b3967a76ca 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
@@ -8,6 +8,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: mac_catalyst_llvm_target(arch).into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
index 41760e9093f..c5c6b71023b 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
@@ -12,6 +12,7 @@ pub fn target() -> Target {
         // This is required for the simulator target to pick the right
         // MACH-O commands, so we do too.
         llvm_target: ios_sim_llvm_target(arch).into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
index e817308b685..1a292a524f6 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
@@ -5,6 +5,7 @@ pub fn target() -> Target {
     let arch = Arch::Arm64;
     Target {
         llvm_target: tvos_llvm_target(arch).into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
index c4aa8479279..0203b7cba93 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
@@ -5,6 +5,7 @@ pub fn target() -> Target {
     let arch = Arch::Arm64_sim;
     Target {
         llvm_target: tvos_sim_llvm_target(arch).into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
index c2cf2c4e96d..727a28b8566 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
@@ -5,6 +5,7 @@ pub fn target() -> Target {
     let base = opts("watchos", Arch::Arm64);
     Target {
         llvm_target: "aarch64-apple-watchos".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
index 96d43e6d27f..504035f8b0d 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
         // This is required for the simulator target to pick the right
         // MACH-O commands, so we do too.
         llvm_target: watchos_sim_llvm_target(arch).into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
index 739a9e4a3dc..da2f7ca4406 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
@@ -4,6 +4,7 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64_be-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
index 1b87c09e3fe..3226722be91 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
@@ -7,6 +7,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "aarch64_be-unknown-linux-gnu_ilp32".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs
index 02e156f19de..180bb3e552a 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs
@@ -4,6 +4,7 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64_be-unknown-netbsd".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs
index 5b4ffc08a57..df9dca16571 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs
@@ -4,6 +4,7 @@ pub fn target() -> Target {
     let base = base::solid::opts("asp3");
     Target {
         llvm_target: "aarch64-unknown-none".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
index db9a1808560..6f760f0e36a 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
@@ -6,6 +6,7 @@ use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-linux-android".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs
index 5a92225c496..221b550a3ac 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs
@@ -8,6 +8,7 @@ const LINKER_SCRIPT: &str = include_str!("./aarch64_nintendo_switch_freestanding
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-none".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs
index 1ea73814282..8ef6bea6768 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs
@@ -8,6 +8,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-pc-windows-gnu".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
index cbd1329726a..29c191fc9ab 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
@@ -7,6 +7,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-pc-windows-msvc".into(),
+        description: Some("ARM64 Windows MSVC".into()),
         pointer_width: 64,
         data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs
index 0ba91a54f1d..b4317508521 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-freebsd".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs
index 430a1c5e7f1..59ead79721b 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-fuchsia".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs
index 50813b81b8d..1a823400629 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-hermit".into(),
+        description: None,
         pointer_width: 64,
         arch: "aarch64".into(),
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs
index 634cb063a49..8344578d894 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs
@@ -11,6 +11,7 @@ pub fn target() -> Target {
         // LLVM does not currently have a separate illumos target,
         // so we still pass Solaris to it
         llvm_target: "aarch64-unknown-solaris2.11".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
index 5b3a2ffa599..dd29ef7b530 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
index 0ff5c8651e6..d1fe5ed863d 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-linux-gnu_ilp32".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
index d16ccd803a9..0a20c47d1ad 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
@@ -14,6 +14,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
index 1be27a51108..fdb5b8635b2 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
@@ -8,6 +8,7 @@ pub fn target() -> Target {
     Target {
         // LLVM 15 doesn't support OpenHarmony yet, use a linux target instead.
         llvm_target: "aarch64-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs
index 32a0816cf81..3aaebe85a0b 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-netbsd".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs
index 518597b3811..ca019a9a683 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs
@@ -31,6 +31,7 @@ pub fn target() -> Target {
     };
     Target {
         llvm_target: "aarch64-unknown-none".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs
index d56fbdbbe90..8f837865bfa 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs
@@ -25,6 +25,7 @@ pub fn target() -> Target {
     };
     Target {
         llvm_target: "aarch64-unknown-none".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs
index aeeaab3af32..3fb9fb7fd27 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-unknown".into(),
+        description: None,
         pointer_width: 64,
         // from: https://llvm.org/docs/LangRef.html#data-layout
         // e         = little endian
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs
index d5fca5c31a6..003f40c9803 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-openbsd".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs
index 844fed472a2..c50cb5a300d 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs
@@ -8,6 +8,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-unknown-redox".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs
index 204e9b061ce..1cb59879e47 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs
@@ -8,6 +8,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-unknown-none".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs
index 9ed6ed2651f..bf14f6950eb 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs
@@ -12,6 +12,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-unknown-windows".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs
index c64b2c7d113..8399e091c39 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs
@@ -7,6 +7,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-pc-windows-msvc".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs
index 48e142347d7..a26d41f81f0 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
index 59e6022d985..318764abab2 100644
--- a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
@@ -5,6 +5,7 @@ pub fn target() -> Target {
     let base = opts("watchos", Arch::Arm64_32);
     Target {
         llvm_target: "arm64_32-apple-watchos".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
index 5d1f81158b6..fd3a52d2f1f 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
@@ -15,6 +15,7 @@ pub fn target() -> Target {
         // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
         // correctly, we do too.
         llvm_target: macos_llvm_target(arch).into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
index 38657d7f1df..4d650921d39 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
@@ -12,6 +12,7 @@ pub fn target() -> Target {
         // This is required for the target to pick the right
         // MACH-O commands, so we do too.
         llvm_target: ios_llvm_target(arch).into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs
new file mode 100644
index 00000000000..f1af4d9a80e
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs
@@ -0,0 +1,21 @@
+use crate::spec::{add_link_args, base, LinkerFlavor, Lld, Target};
+
+pub fn target() -> Target {
+    let mut base = base::windows_msvc::opts();
+    base.max_atomic_width = Some(128);
+    base.features = "+v8a,+neon,+fp-armv8".into();
+    add_link_args(
+        &mut base.late_link_args,
+        LinkerFlavor::Msvc(Lld::No),
+        &["/machine:arm64ec", "softintrin.lib"],
+    );
+
+    Target {
+        llvm_target: "arm64ec-pc-windows-msvc".into(),
+        description: None,
+        pointer_width: 64,
+        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
+        arch: "arm64ec".into(),
+        options: base,
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs
index 43b27b414d8..a3563b19b13 100644
--- a/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, SanitizerSet, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "arm-linux-androideabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs
index e4fa54c4b75..1bd29d11cb4 100644
--- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "arm-unknown-linux-gnueabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs
index f379ea35ecb..b705d67ad5c 100644
--- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "arm-unknown-linux-gnueabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs
index f3d5ff89244..5f48330f673 100644
--- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs
@@ -6,6 +6,7 @@ pub fn target() -> Target {
         // to determine the calling convention and float ABI, and it doesn't
         // support the "musleabi" value.
         llvm_target: "arm-unknown-linux-gnueabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs
index f3e366d5993..6b94e673785 100644
--- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs
@@ -6,6 +6,7 @@ pub fn target() -> Target {
         // uses it to determine the calling convention and float ABI, and it
         // doesn't support the "musleabihf" value.
         llvm_target: "arm-unknown-linux-gnueabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs
index 07c7e1c5845..0cd8a7cdcb6 100644
--- a/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs
@@ -4,6 +4,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armeb-unknown-linux-gnueabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs
index 446efa90d09..6317bef0559 100644
--- a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs
@@ -6,6 +6,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
 pub fn target() -> Target {
     Target {
         llvm_target: "armebv7r-none-eabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs
index 0c9e99ff84b..13778ccb303 100644
--- a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs
@@ -6,6 +6,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
 pub fn target() -> Target {
     Target {
         llvm_target: "armebv7r-none-eabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs
index 44fdd3178af..e0f1756cdc2 100644
--- a/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs
@@ -14,6 +14,7 @@ use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target,
 pub fn target() -> Target {
     Target {
         llvm_target: "armv4t-none-eabi".into(),
+        description: None,
         pointer_width: 32,
         arch: "arm".into(),
         /* Data layout args are '-' separated:
diff --git a/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs
index 5ab753c3d61..94c9c77c252 100644
--- a/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv4t-unknown-linux-gnueabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs
index 5e23efecdbe..280aa3b84ca 100644
--- a/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs
@@ -5,6 +5,7 @@ use crate::spec::{base, cvs, FramePointer, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv5te-none-eabi".into(),
+        description: None,
         pointer_width: 32,
         arch: "arm".into(),
         /* Data layout args are '-' separated:
diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs
index 7155ab289c0..6a4cc7fb78e 100644
--- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv5te-unknown-linux-gnueabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs
index 3f25ab2bcc1..eb1c67650fc 100644
--- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs
@@ -7,6 +7,7 @@ pub fn target() -> Target {
         // uses it to determine the calling convention and float ABI, and LLVM
         // doesn't support the "musleabihf" value.
         llvm_target: "armv5te-unknown-linux-gnueabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs
index af6e3baa27a..6d20a9047de 100644
--- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv5te-unknown-linux-uclibcgnueabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs
index 70e40f60f22..1aec8e6681c 100644
--- a/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv6-unknown-freebsd-gnueabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs
index ca0db5e5640..86c8ade8b51 100644
--- a/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv6-unknown-netbsdelf-eabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs
index 23f4a5abf77..01a08283f82 100644
--- a/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs
+++ b/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs
@@ -12,6 +12,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "armv6k-none-eabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs
index bb3e574e32f..bfeca4bbc9e 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs
@@ -13,6 +13,7 @@ pub fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-march=armv7-a"]);
     Target {
         llvm_target: "armv7-none-linux-android".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
index 62c93603621..5f068edbaad 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
@@ -13,6 +13,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "thumbv7a-vita-eabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs
index 61b6d7a63e3..888eac89a98 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-freebsd-gnueabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs
index ad9fd773b8b..e04c9790164 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs
@@ -6,6 +6,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-linux-gnueabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs
index aad7977d504..401cef1f86c 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs
@@ -6,6 +6,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-linux-gnueabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs
index 7f30a5ad7d7..4792eb930d6 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs
@@ -11,6 +11,7 @@ pub fn target() -> Target {
         // to determine the calling convention and float ABI, and it doesn't
         // support the "musleabi" value.
         llvm_target: "armv7-unknown-linux-gnueabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs
index ec5c6419f63..948746235a7 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs
@@ -8,6 +8,7 @@ pub fn target() -> Target {
         // uses it to determine the calling convention and float ABI, and LLVM
         // doesn't support the "musleabihf" value.
         llvm_target: "armv7-unknown-linux-gnueabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs
index 9f2ac541ddc..62faf4b682a 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
     Target {
         // LLVM 15 doesn't support OpenHarmony yet, use a linux target instead.
         llvm_target: "armv7-unknown-linux-gnueabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs
index 212c80718f0..b33a6ec19ee 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs
@@ -7,6 +7,7 @@ pub fn target() -> Target {
     let base = base::linux_uclibc::opts();
     Target {
         llvm_target: "armv7-unknown-linux-gnueabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs
index f760ad9e79c..b64e325d760 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs
@@ -7,6 +7,7 @@ pub fn target() -> Target {
     let base = base::linux_uclibc::opts();
     Target {
         llvm_target: "armv7-unknown-linux-gnueabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs
index 7afdb87b62e..08efed615aa 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-netbsdelf-eabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs
index 0b4e64307d2..48721437c51 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-linux-gnueabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs
index 57d40d54c44..0c466f5a6c1 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs
@@ -4,6 +4,7 @@ pub fn target() -> Target {
     let base = base::solid::opts("asp3");
     Target {
         llvm_target: "armv7a-none-eabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs
index 3d21213c5ff..a109423f6d5 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs
@@ -4,6 +4,7 @@ pub fn target() -> Target {
     let base = base::solid::opts("asp3");
     Target {
         llvm_target: "armv7a-none-eabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs
index c5b61427e69..2680dda0305 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs
@@ -32,6 +32,7 @@ pub fn target() -> Target {
     };
     Target {
         llvm_target: "armv7a-none-eabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs
index ba3caad6a97..b26b560a5ee 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs
@@ -24,6 +24,7 @@ pub fn target() -> Target {
     };
     Target {
         llvm_target: "armv7a-none-eabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
index 7ed71c1ba6e..030f0ce4594 100644
--- a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
@@ -5,6 +5,7 @@ pub fn target() -> Target {
     let arch = Arch::Armv7k;
     Target {
         llvm_target: "armv7k-apple-watchos".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs
index 68b2527985a..b71de060ca6 100644
--- a/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs
@@ -5,6 +5,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
 pub fn target() -> Target {
     Target {
         llvm_target: "armv7r-none-eabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs
index 909765a310f..a03179a770f 100644
--- a/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs
@@ -5,6 +5,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
 pub fn target() -> Target {
     Target {
         llvm_target: "armv7r-none-eabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
index 44c624c4ebd..c8ce77b58be 100644
--- a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
@@ -5,6 +5,7 @@ pub fn target() -> Target {
     let arch = Arch::Armv7s;
     Target {
         llvm_target: ios_llvm_target(arch).into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs
index 28dba4f7f5d..f88b7e56c67 100644
--- a/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs
@@ -5,6 +5,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
 pub fn target() -> Target {
     Target {
         llvm_target: "armv8r-none-eabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs b/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs
index 91e091e237a..a6ac0f93c44 100644
--- a/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs
@@ -4,6 +4,7 @@ use crate::{abi::Endian, spec::base};
 pub fn target() -> Target {
     Target {
         llvm_target: "bpfeb".into(),
+        description: None,
         data_layout: "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         pointer_width: 64,
         arch: "bpf".into(),
diff --git a/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs b/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs
index 45ab750ead6..cee4d687daf 100644
--- a/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs
@@ -4,6 +4,7 @@ use crate::{abi::Endian, spec::base};
 pub fn target() -> Target {
     Target {
         llvm_target: "bpfel".into(),
+        description: None,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         pointer_width: 64,
         arch: "bpf".into(),
diff --git a/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs
index 14cd33a260a..4f0bd6c9ed4 100644
--- a/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs
+++ b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs
@@ -6,6 +6,7 @@ pub fn target() -> Target {
     Target {
         //https://github.com/llvm/llvm-project/blob/8b76aea8d8b1b71f6220bc2845abc749f18a19b7/clang/lib/Basic/Targets/CSKY.h
         llvm_target: "csky-unknown-linux-gnuabiv2".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32-v128:32:32-a:0:32-Fi32-n32".into(),
         arch: "csky".into(),
diff --git a/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs
index 0ce271c601c..d57c1d0c17f 100644
--- a/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs
+++ b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs
@@ -6,6 +6,7 @@ pub fn target() -> Target {
     Target {
         //https://github.com/llvm/llvm-project/blob/8b76aea8d8b1b71f6220bc2845abc749f18a19b7/clang/lib/Basic/Targets/CSKY.h
         llvm_target: "csky-unknown-linux-gnuabiv2".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32-v128:32:32-a:0:32-Fi32-n32".into(),
         arch: "csky".into(),
diff --git a/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs
index 98a5e7abd09..bae88e8546d 100644
--- a/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs
@@ -15,6 +15,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "hexagon-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 32,
         data_layout: concat!(
             "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32",
diff --git a/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs
index 205f195a701..907ff078257 100644
--- a/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs
@@ -3,6 +3,7 @@ use crate::spec::{PanicStrategy, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "hexagon-unknown-none-elf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: concat!(
             "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32",
diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
index d78acdbd1aa..cdd436ce34a 100644
--- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
@@ -11,6 +11,7 @@ pub fn target() -> Target {
         // This is required for the target to pick the right
         // MACH-O commands, so we do too.
         llvm_target: ios_sim_llvm_target(arch).into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:128-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
index ea8b919e748..e37cf4e5214 100644
--- a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
+++ b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOpt
 pub fn target() -> Target {
     Target {
         llvm_target: "i586-pc-unknown".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs
index 69bba4775b4..f72a4276d76 100644
--- a/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs
@@ -8,6 +8,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i586-unknown-netbsdelf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
index 25617b4436c..f4561d7ed58 100644
--- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
@@ -16,6 +16,7 @@ pub fn target() -> Target {
         //
         // While ld64 doesn't understand i686, LLVM does.
         llvm_target: macos_llvm_target(Arch::I686).into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:128-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
index 12ebf0c72f8..d16dfedd38f 100644
--- a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
@@ -15,6 +15,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-linux-android".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
index 11818034414..1b092045e4b 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
@@ -17,6 +17,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-gnu".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
index f4e33b88178..1a69e109fca 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
@@ -16,6 +16,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-gnu".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
index 9f1c8f4676c..0ba486417ff 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
@@ -23,6 +23,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-msvc".into(),
+        description: Some("32-bit MSVC (Windows 7+)".into()),
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
index d90f481c68c..f84886807c3 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-freebsd".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
index 330a390c981..af74539b4a1 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-haiku".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs
index c32f7177c1a..096337d0906 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-hurd-gnu".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
index 9bc38a72f4d..709265bde67 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
@@ -10,6 +10,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
index 4a82e0986c7..d86d0259cd9 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
@@ -23,6 +23,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
index ea72656607e..86d3404c219 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-netbsdelf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
index 945dc0f8967..4e3829f05f5 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-openbsd".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs
index 37d57c1cdf3..296acf35fdb 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs
@@ -78,6 +78,7 @@ pub fn target() -> Target {
     // remove -gnu and use the default one.
     Target {
         llvm_target: "i686-unknown-windows-gnu".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
index 0830033dc23..12c7c4c5a2d 100644
--- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
@@ -16,6 +16,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-gnu".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
index 534dd6ee54f..d04ec0012f2 100644
--- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
@@ -7,6 +7,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-msvc".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
index 35ad81dc052..081b4c5364c 100644
--- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
@@ -23,6 +23,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-msvc".into(),
+        description: Some("32-bit Windows 7 support".into()),
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
diff --git a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
index 30c2295e402..d554f717f25 100644
--- a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs
index 234270c999b..f69412bd509 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "loongarch64-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
         arch: "loongarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
new file mode 100644
index 00000000000..9f653174cf0
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
@@ -0,0 +1,19 @@
+use crate::spec::{base, Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        llvm_target: "loongarch64-unknown-linux-musl".into(),
+        description: None,
+        pointer_width: 64,
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+        arch: "loongarch64".into(),
+        options: TargetOptions {
+            cpu: "generic".into(),
+            features: "+f,+d".into(),
+            llvm_abiname: "lp64d".into(),
+            max_atomic_width: Some(64),
+            crt_static_default: false,
+            ..base::linux_musl::opts()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
index 3b1ea8e206f..370c7b39950 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
@@ -4,6 +4,7 @@ use crate::spec::{Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "loongarch64-unknown-none".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
         arch: "loongarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
index ab9300ef9c7..8e50a1c3009 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
@@ -4,6 +4,7 @@ use crate::spec::{Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "loongarch64-unknown-none".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
         arch: "loongarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs
index b54f5d753cc..9fe6760d9f3 100644
--- a/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs
@@ -8,6 +8,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "m68k-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16".into(),
         arch: "m68k".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
index 6191a6dfd41..96472c41da6 100644
--- a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
@@ -13,6 +13,7 @@ pub fn target() -> Target {
     Target {
         // LLVM doesn't recognize "muslabi64" yet.
         llvm_target: "mips64-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
         arch: "mips64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs
index e1131f07f26..6c767c57ffa 100644
--- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs
@@ -4,6 +4,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mips64-unknown-linux-gnuabi64".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
         arch: "mips64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs
index 147c1c22476..d2b6b4e4898 100644
--- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
     Target {
         // LLVM doesn't recognize "muslabi64" yet.
         llvm_target: "mips64-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
         arch: "mips64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs
index 4c612554d20..ef2458a563a 100644
--- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mips64el-unknown-linux-gnuabi64".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
         arch: "mips64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs
index d60404f0ce5..2983e957d4d 100644
--- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs
@@ -8,6 +8,7 @@ pub fn target() -> Target {
     Target {
         // LLVM doesn't recognize "muslabi64" yet.
         llvm_target: "mips64el-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
         arch: "mips64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs
index c49b89bbd46..d5a5540b326 100644
--- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs
@@ -4,6 +4,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mips-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs
index 92d2d9d84c1..6a13fb7b6bc 100644
--- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
     base.crt_static_default = false;
     Target {
         llvm_target: "mips-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs
index 51df0a974cb..1137a65c366 100644
--- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs
+++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs
@@ -4,6 +4,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mips-unknown-linux-uclibc".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs b/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs
index 75beb91b13a..88a6d08286e 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs
@@ -11,6 +11,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "mipsel-sony-psp".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs b/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs
index 12a66efdd46..3c97c279f1a 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs
@@ -3,6 +3,7 @@ use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target,
 pub fn target() -> Target {
     Target {
         llvm_target: "mipsel-sony-psx".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs
index c2e482148cd..cceeea43e17 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mipsel-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs
index 5eed050453d..3da9b70ba7f 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs
@@ -8,6 +8,7 @@ pub fn target() -> Target {
     base.crt_static_default = false;
     Target {
         llvm_target: "mipsel-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs
index 77e69119d16..14a8900c171 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mipsel-unknown-linux-uclibc".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs
index 706a1af3e15..f89ac1f08e1 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs
@@ -8,6 +8,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "mipsel-unknown-netbsd".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs
index 43b01e7a062..9c6bef4d771 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs
@@ -7,6 +7,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
 pub fn target() -> Target {
     Target {
         llvm_target: "mipsel-unknown-none".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs
index 59783882e18..0bda8634d8a 100644
--- a/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs
@@ -4,6 +4,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mipsisa32r6-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips32r6".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs
index c3d79412e1c..10b7b93d4ef 100644
--- a/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mipsisa32r6el-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips32r6".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs
index 2ae6e7521f9..945c237ef38 100644
--- a/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs
@@ -4,6 +4,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mipsisa64r6-unknown-linux-gnuabi64".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
         arch: "mips64r6".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs
index 31637e9f6d0..407431f685c 100644
--- a/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mipsisa64r6el-unknown-linux-gnuabi64".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
         arch: "mips64r6".into(),
diff --git a/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs b/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs
index 251fd2a0a7a..6f6503ea111 100644
--- a/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs
@@ -3,6 +3,7 @@ use crate::spec::{cvs, Cc, LinkerFlavor, PanicStrategy, RelocModel, Target, Targ
 pub fn target() -> Target {
     Target {
         llvm_target: "msp430-none-elf".into(),
+        description: None,
         pointer_width: 16,
         data_layout: "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16".into(),
         arch: "msp430".into(),
diff --git a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
index b0582b235b9..33b79a13359 100644
--- a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
+++ b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
@@ -5,6 +5,7 @@ pub fn target() -> Target {
         arch: "nvptx64".into(),
         data_layout: "e-i64:64-i128:128-v16:16-v32:32-n16:32:64".into(),
         llvm_target: "nvptx64-nvidia-cuda".into(),
+        description: None,
         pointer_width: 64,
 
         options: TargetOptions {
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs b/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs
index c512e4c7c48..6e156115f74 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs
@@ -10,6 +10,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-ibm-aix".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:a-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs
index e470ec05eff..27fbb6e3d81 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs
@@ -10,6 +10,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-unknown-freebsd".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:e-Fn32-i64:64-n32:64".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs
index 34e3184d348..11bbfe4baa2 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs
@@ -10,6 +10,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:e-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs
index 90df3c69684..5036df13694 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs
@@ -10,6 +10,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:e-Fn32-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs
index ebaeb04be31..f0813e50e03 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs
@@ -10,6 +10,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-unknown-openbsd".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:e-Fn32-i64:64-n32:64".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs
index e2085ba7ce3..2365b687f6d 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs
@@ -10,6 +10,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:e-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs
index b399d36d8b2..83c0a9a7f69 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64le-unknown-freebsd".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-Fn32-i64:64-n32:64".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs
index 194c3170e68..6041836f8fa 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64le-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-Fn32-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs
index 1f53e689598..a27a184aa88 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64le-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-Fn32-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs
index 6d094f9a367..31220adc0db 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs
@@ -13,6 +13,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-freebsd13.0".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: "powerpc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs
index 1600698da44..780824bed2a 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: "powerpc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs
index af0fbfebef2..302b06b3e93 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-linux-gnuspe".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: "powerpc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs
index 9b0ac4a0fc9..7f512824980 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: "powerpc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs
index bc2e239d9a5..41ea47fbb63 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-netbsd".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: "powerpc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs
index 081aaaea249..b57c980096a 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-openbsd".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: "powerpc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs
index e8bccc15385..7226d618465 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: "powerpc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs
index fa4ef098e03..847ff3799b0 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-linux-gnuspe".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: "powerpc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs
index 0be32cbd771..95d3aa29fac 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs
@@ -5,6 +5,7 @@ use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv32-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         arch: "riscv32".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
index cfa9990dac9..1c81da11de1 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
@@ -5,6 +5,7 @@ use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv32-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         arch: "riscv32".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs
index b80a5fbeacf..ad85186d216 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs
@@ -4,6 +4,7 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
+        description: None,
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs
index bf819de4133..43958df7ceb 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs
@@ -5,6 +5,7 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
+        description: None,
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs
index 6480facb137..60433837cf1 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs
@@ -4,6 +4,7 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
+        description: None,
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs
index 25f5c3bc2a6..6741d5224c9 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs
@@ -4,6 +4,7 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
+        description: None,
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs
index 55c6e4d16e5..4b49df632a1 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs
@@ -4,6 +4,7 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
+        description: None,
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs
index ed0591ad918..a295e060909 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs
@@ -4,6 +4,7 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
+        description: None,
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs b/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs
index 6c7c920bd18..15aa60f95a2 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs
@@ -4,6 +4,7 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
+        description: None,
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_none_elf.rs
index 9fb68874ac8..896ad1c04f8 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_none_elf.rs
@@ -4,6 +4,7 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
+        description: None,
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs b/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs
index 3aa9923ee4d..1707e067a48 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs
@@ -4,6 +4,7 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
+        description: None,
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs
index 13a621a6643..e23273f8c9f 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs
@@ -4,6 +4,7 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
+        description: None,
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
index 762197d7217..879deff2563 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
@@ -5,6 +5,7 @@ use crate::spec::{base, CodeModel, SanitizerSet, SplitDebuginfo, Target, TargetO
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-linux-android".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs
index 2c7878de812..ed0290d63a7 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, CodeModel, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-freebsd".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
index a29470c24fb..97873e93f68 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, CodeModel, SanitizerSet, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-fuchsia".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs
index b7e29d2da3d..40b3f196198 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, CodeModel, RelocModel, Target, TargetOptions, TlsModel};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-hermit".into(),
+        description: None,
         pointer_width: 64,
         arch: "riscv64".into(),
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs
index e71929a1904..fc7c8024ffb 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs
@@ -5,6 +5,7 @@ use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
index 8ea28d6b162..aa32149986f 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
@@ -5,6 +5,7 @@ use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs
index 43a313a9408..42d58535735 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, CodeModel, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-netbsd".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
index f29e224244e..89b0793375d 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
@@ -5,6 +5,7 @@ use crate::spec::{RelocModel, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
+        description: None,
         llvm_target: "riscv64".into(),
         pointer_width: 64,
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs
index 1f1da7d5a29..8f42bb5c1d2 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, CodeModel, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-openbsd".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs
index 0f1821c9985..78bfbe68565 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs
@@ -5,6 +5,7 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         llvm_target: "riscv64".into(),
+        description: None,
         pointer_width: 64,
         arch: "riscv64".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs
index 6fc410eb223..a982e145a8e 100644
--- a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs
@@ -18,6 +18,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "s390x-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64".into(),
         arch: "s390x".into(),
diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs
index 03772aab372..015abf2521b 100644
--- a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs
@@ -19,6 +19,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "s390x-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64".into(),
         arch: "s390x".into(),
diff --git a/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs
index 20ec9a84e8b..9df3c2167d7 100644
--- a/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "sparc64-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64-S128".into(),
         arch: "sparc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs
index c8c0fd2e134..305783883e2 100644
--- a/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "sparc64-unknown-netbsd".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64-S128".into(),
         arch: "sparc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs
index 82ce610066a..2878d27f5d4 100644
--- a/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs
@@ -10,6 +10,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "sparc64-unknown-openbsd".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64-S128".into(),
         arch: "sparc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs
index 548fbb9ed52..a2760ae93f2 100644
--- a/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs
@@ -10,6 +10,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "sparc-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-i64:64-f128:64-n32-S64".into(),
         arch: "sparc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs
index 7e908a0f365..c32e637a4a4 100644
--- a/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs
@@ -20,6 +20,7 @@ pub fn target() -> Target {
     Target {
         data_layout: "E-m:e-p:32:32-i64:64-f128:64-n32-S64".into(),
         llvm_target: "sparc-unknown-none-elf".into(),
+        description: None,
         pointer_width: 32,
         arch: "sparc".into(),
         options,
diff --git a/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs
index 16cd991dd28..2b6d2a4e49a 100644
--- a/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs
+++ b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs
@@ -12,6 +12,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "sparcv9-sun-solaris".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64-S128".into(),
         // Use "sparc64" instead of "sparcv9" here, since the former is already
diff --git a/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs
index 7b5c019b1bb..321b46d1d73 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs
@@ -15,6 +15,7 @@ use crate::spec::{cvs, FramePointer};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv4t-none-eabi".into(),
+        description: None,
         pointer_width: 32,
         arch: "arm".into(),
         /* Data layout args are '-' separated:
diff --git a/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs
index d9212afb084..d9901c647ab 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs
@@ -5,6 +5,7 @@ use crate::spec::{base, cvs, FramePointer, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv5te-none-eabi".into(),
+        description: None,
         pointer_width: 32,
         arch: "arm".into(),
         /* Data layout args are '-' separated:
diff --git a/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs
index ac076fb8864..c9878f172ae 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs
@@ -5,6 +5,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv6m-none-eabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs
index 128ac1dd179..bb2555bb1a5 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs
@@ -13,6 +13,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "thumbv7a-pc-windows-msvc".into(),
+        description: Some("ARM32 Windows MSVC".into()),
         pointer_width: 32,
         data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs
index 810ed6a2404..ce07626be3b 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, PanicStrategy, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv7a-pc-windows-msvc".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs
index 1752f1d9aac..f09ba2461a3 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs
@@ -14,6 +14,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv7em-none-eabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs
index c113c62fc1d..5aebfea45f0 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs
@@ -13,6 +13,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv7em-none-eabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs
index f9ab3ce1ad0..4e91765654c 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs
@@ -5,6 +5,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv7m-none-eabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs
index c07aa944d7e..8638f36a0fc 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs
@@ -13,6 +13,7 @@ pub fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-march=armv7-a"]);
     Target {
         llvm_target: "armv7-none-linux-android".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs
index b4045037c6a..20e1967c449 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs
@@ -9,6 +9,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-linux-gnueabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs
index 6ef30f10fe4..6be7c9f6a64 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs
@@ -12,6 +12,7 @@ pub fn target() -> Target {
         // uses it to determine the calling convention and float ABI, and LLVM
         // doesn't support the "musleabihf" value.
         llvm_target: "armv7-unknown-linux-gnueabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs
index bf62574867a..3a3cccd65a6 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs
@@ -5,6 +5,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv8m.base-none-eabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs
index 07fc7feade5..21c74af74d5 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs
@@ -6,6 +6,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv8m.main-none-eabi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs
index 61d4e8fc802..1baab520fd4 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs
@@ -6,6 +6,7 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv8m.main-none-eabihf".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs
index e9e874297d3..b6d5dae4f64 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs
@@ -24,6 +24,7 @@ pub fn target() -> Target {
     };
     Target {
         llvm_target: "wasm32-unknown-emscripten".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-S128-ni:1:10:20".into(),
         arch: "wasm32".into(),
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs
index 2a40d9c6637..94ded57d2f0 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs
@@ -47,6 +47,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "wasm32-unknown-unknown".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
         arch: "wasm32".into(),
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasi.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi.rs
index 6dbcb01ea43..2752125c009 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasi.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasi.rs
@@ -1,119 +1,11 @@
-//! The `wasm32-wasi` target is a new and still (as of April 2019) an
-//! experimental target. The definition in this file is likely to be tweaked
-//! over time and shouldn't be relied on too much.
+//! NB: This target is in the process of being renamed to
+//! `wasm32-wasip1`. For more information see:
 //!
-//! The `wasi` target is a proposal to define a standardized set of syscalls
-//! that WebAssembly files can interoperate with. This set of syscalls is
-//! intended to empower WebAssembly binaries with native capabilities such as
-//! filesystem access, network access, etc.
-//!
-//! You can see more about the proposal at <https://wasi.dev>.
-//!
-//! The Rust target definition here is interesting in a few ways. We want to
-//! serve two use cases here with this target:
-//!
-//! * First, we want Rust usage of the target to be as hassle-free as possible,
-//!   ideally avoiding the need to configure and install a local wasm32-wasi
-//!   toolchain.
-//!
-//! * Second, one of the primary use cases of LLVM's new wasm backend and the
-//!   wasm support in LLD is that any compiled language can interoperate with
-//!   any other. To that the `wasm32-wasi` target is the first with a viable C
-//!   standard library and sysroot common definition, so we want Rust and C/C++
-//!   code to interoperate when compiled to `wasm32-unknown-unknown`.
-//!
-//! You'll note, however, that the two goals above are somewhat at odds with one
-//! another. To attempt to solve both use cases in one go we define a target
-//! that (ab)uses the `crt-static` target feature to indicate which one you're
-//! in.
-//!
-//! ## No interop with C required
-//!
-//! By default the `crt-static` target feature is enabled, and when enabled
-//! this means that the bundled version of `libc.a` found in `liblibc.rlib`
-//! is used. This isn't intended really for interoperation with a C because it
-//! may be the case that Rust's bundled C library is incompatible with a
-//! foreign-compiled C library. In this use case, though, we use `rust-lld` and
-//! some copied crt startup object files to ensure that you can download the
-//! wasi target for Rust and you're off to the races, no further configuration
-//! necessary.
-//!
-//! All in all, by default, no external dependencies are required. You can
-//! compile `wasm32-wasi` binaries straight out of the box. You can't, however,
-//! reliably interoperate with C code in this mode (yet).
-//!
-//! ## Interop with C required
-//!
-//! For the second goal we repurpose the `target-feature` flag, meaning that
-//! you'll need to do a few things to have C/Rust code interoperate.
-//!
-//! 1. All Rust code needs to be compiled with `-C target-feature=-crt-static`,
-//!    indicating that the bundled C standard library in the Rust sysroot will
-//!    not be used.
-//!
-//! 2. If you're using rustc to build a linked artifact then you'll need to
-//!    specify `-C linker` to a `clang` binary that supports
-//!    `wasm32-wasi` and is configured with the `wasm32-wasi` sysroot. This
-//!    will cause Rust code to be linked against the libc.a that the specified
-//!    `clang` provides.
-//!
-//! 3. If you're building a staticlib and integrating Rust code elsewhere, then
-//!    compiling with `-C target-feature=-crt-static` is all you need to do.
-//!
-//! You can configure the linker via Cargo using the
-//! `CARGO_TARGET_WASM32_WASI_LINKER` env var. Be sure to also set
-//! `CC_wasm32-wasi` if any crates in the dependency graph are using the `cc`
-//! crate.
-//!
-//! ## Remember, this is all in flux
-//!
-//! The wasi target is **very** new in its specification. It's likely going to
-//! be a long effort to get it standardized and stable. We'll be following it as
-//! best we can with this target. Don't start relying on too much here unless
-//! you know what you're getting in to!
+//! * <https://github.com/rust-lang/compiler-team/issues/607>
+//! * <https://github.com/rust-lang/compiler-team/issues/695>
 
-use crate::spec::crt_objects;
-use crate::spec::LinkSelfContainedDefault;
-use crate::spec::{base, Cc, LinkerFlavor, Target};
+use crate::spec::Target;
 
 pub fn target() -> Target {
-    let mut options = base::wasm::options();
-
-    options.os = "wasi".into();
-    options.add_pre_link_args(LinkerFlavor::WasmLld(Cc::Yes), &["--target=wasm32-wasi"]);
-
-    options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained();
-    options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained();
-
-    // FIXME: Figure out cases in which WASM needs to link with a native toolchain.
-    options.link_self_contained = LinkSelfContainedDefault::True;
-
-    // Right now this is a bit of a workaround but we're currently saying that
-    // the target by default has a static crt which we're taking as a signal
-    // for "use the bundled crt". If that's turned off then the system's crt
-    // will be used, but this means that default usage of this target doesn't
-    // need an external compiler but it's still interoperable with an external
-    // compiler if configured correctly.
-    options.crt_static_default = true;
-    options.crt_static_respected = true;
-
-    // Allow `+crt-static` to create a "cdylib" output which is just a wasm file
-    // without a main function.
-    options.crt_static_allows_dylibs = true;
-
-    // WASI's `sys::args::init` function ignores its arguments; instead,
-    // `args::args()` makes the WASI API calls itself.
-    options.main_needs_argc_argv = false;
-
-    // And, WASI mangles the name of "main" to distinguish between different
-    // signatures.
-    options.entry_name = "__main_void".into();
-
-    Target {
-        llvm_target: "wasm32-wasi".into(),
-        pointer_width: 32,
-        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
-        arch: "wasm32".into(),
-        options,
-    }
+    super::wasm32_wasip1::target()
 }
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs
index 28ea4cc9ece..c04df5e6448 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs
@@ -125,6 +125,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "wasm32-wasi".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
         arch: "wasm32".into(),
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
new file mode 100644
index 00000000000..85c99c77e23
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
@@ -0,0 +1,58 @@
+//! The `wasm32-wasip1` enables compiling to WebAssembly using the first
+//! version of the WASI standard, called "preview1". This version of the
+//! standard was never formally specified and WASI has since evolved to a
+//! "preview2". This target in rustc uses the previous version of the proposal.
+//!
+//! This target uses the syscalls defined at
+//! <https://github.com/WebAssembly/WASI/tree/main/legacy/preview1>.
+//!
+//! Note that this target was historically called `wasm32-wasi` originally and
+//! was since renamed to `wasm32-wasip1` after the preview2 target was
+//! introduced.
+
+use crate::spec::crt_objects;
+use crate::spec::LinkSelfContainedDefault;
+use crate::spec::{base, Cc, LinkerFlavor, Target};
+
+pub fn target() -> Target {
+    let mut options = base::wasm::options();
+
+    options.os = "wasi".into();
+    options.add_pre_link_args(LinkerFlavor::WasmLld(Cc::Yes), &["--target=wasm32-wasi"]);
+
+    options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained();
+    options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained();
+
+    // FIXME: Figure out cases in which WASM needs to link with a native toolchain.
+    options.link_self_contained = LinkSelfContainedDefault::True;
+
+    // Right now this is a bit of a workaround but we're currently saying that
+    // the target by default has a static crt which we're taking as a signal
+    // for "use the bundled crt". If that's turned off then the system's crt
+    // will be used, but this means that default usage of this target doesn't
+    // need an external compiler but it's still interoperable with an external
+    // compiler if configured correctly.
+    options.crt_static_default = true;
+    options.crt_static_respected = true;
+
+    // Allow `+crt-static` to create a "cdylib" output which is just a wasm file
+    // without a main function.
+    options.crt_static_allows_dylibs = true;
+
+    // WASI's `sys::args::init` function ignores its arguments; instead,
+    // `args::args()` makes the WASI API calls itself.
+    options.main_needs_argc_argv = false;
+
+    // And, WASI mangles the name of "main" to distinguish between different
+    // signatures.
+    options.entry_name = "__main_void".into();
+
+    Target {
+        llvm_target: "wasm32-wasi".into(),
+        description: None,
+        pointer_width: 32,
+        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
+        arch: "wasm32".into(),
+        options,
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
index 30f7636f0bb..cd1b1c33ae4 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
@@ -56,6 +56,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "wasm32-unknown-unknown".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
         arch: "wasm32".into(),
diff --git a/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs
index 54c5ae8e203..866e80782e2 100644
--- a/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs
@@ -39,6 +39,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "wasm64-unknown-unknown".into(),
+        description: None,
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
         arch: "wasm64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
index 356c6721868..78907a12550 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
@@ -16,6 +16,7 @@ pub fn target() -> Target {
         // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
         // correctly, we do too.
         llvm_target: macos_llvm_target(arch).into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
index 5b34390141e..e40c7cf8ac1 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
@@ -10,6 +10,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: ios_sim_llvm_target(arch).into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
index e59f41185de..af375c58979 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
@@ -8,6 +8,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: mac_catalyst_llvm_target(arch).into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
index 95033699f1a..fe603d667b2 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
@@ -7,6 +7,7 @@ pub fn target() -> Target {
     let arch = Arch::X86_64_sim;
     Target {
         llvm_target: tvos_sim_llvm_target(arch).into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
index 806a58e980b..8032764f93d 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
@@ -5,6 +5,7 @@ pub fn target() -> Target {
     let arch = Arch::X86_64_sim;
     Target {
         llvm_target: watchos_sim_llvm_target(arch).into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs
index c38a1a08536..be40a7995bd 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs
@@ -74,6 +74,7 @@ pub fn target() -> Target {
     };
     Target {
         llvm_target: "x86_64-elf".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs
index 30b1ee73630..eb30838693e 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs
@@ -15,6 +15,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-linux-android".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs
index 0ef01597399..2253506df20 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-pc-unknown".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
index ade4dd6d431..df2fe6c2ace 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
@@ -12,6 +12,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-solaris".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs
index d6b44e7cfd4..ca65d3acb0f 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs
@@ -16,6 +16,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-gnu".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs
index b84a9a5a8a1..57519ccf0c1 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs
@@ -11,6 +11,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-gnu".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
index 51807bdba5d..c066c453feb 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
@@ -10,6 +10,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-msvc".into(),
+        description: Some("64-bit MSVC (Windows 7+)".into()),
         pointer_width: 64,
         data_layout:
             "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs
index 6c9d1147548..bb4744f2c57 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOpt
 pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 64,
         arch: "x86_64".into(),
         data_layout:
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs
index ce682bb8005..d5b148a8e74 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs
@@ -10,6 +10,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-dragonfly".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs
index 6d6940e7891..a99b908454b 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs
@@ -13,6 +13,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-freebsd".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
index 50139e5c1d8..8ced5051418 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
@@ -11,6 +11,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-fuchsia".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs
index c00c689f7ef..dc7c56d866e 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs
@@ -12,6 +12,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-haiku".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs
index fb46848ba8c..37ee1f7af1d 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-hermit".into(),
+        description: None,
         pointer_width: 64,
         arch: "x86_64".into(),
         data_layout:
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs
index 3e3f4921322..664312e0713 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs
@@ -12,6 +12,7 @@ pub fn target() -> Target {
         // LLVM does not currently have a separate illumos target,
         // so we still pass Solaris to it
         llvm_target: "x86_64-pc-solaris".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
index 646623668c6..c4b0b18ab23 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-l4re-uclibc".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
index 1510f3b390c..644c324050d 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
@@ -19,6 +19,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs
index d4b6519262e..4de9e9d3158 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs
@@ -14,6 +14,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-linux-gnux32".into(),
+        description: None,
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:128-n8:16:32:64-S128"
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
index c71dc65670c..4cb50e837f6 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
@@ -17,6 +17,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs
index c25105f6e35..fed9cbcffd0 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs
@@ -17,6 +17,7 @@ pub fn target() -> Target {
     Target {
         // LLVM 15 doesn't support OpenHarmony yet, use a linux target instead.
         llvm_target: "x86_64-unknown-linux-musl".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs
index 466498acb0b..175543b02a6 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs
@@ -18,6 +18,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-netbsd".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
index ceded7790a6..0bb5ea1594c 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
@@ -29,6 +29,7 @@ pub fn target() -> Target {
     };
     Target {
         llvm_target: "x86_64-unknown-none-elf".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs
index b542a569bbd..d0d16b8c8ee 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs
@@ -11,6 +11,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-openbsd".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs
index 550b7a3d282..b1feb8c2b37 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs
@@ -10,6 +10,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-redox".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
index 95847e57a0f..9bdadd73bc0 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
@@ -31,6 +31,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-windows".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs
index b37d33601e6..7d3884e521d 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs
@@ -15,6 +15,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-gnu".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs
index fe2b4c8e92d..a685530332a 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-msvc".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs
index fd26b6e8cae..813802e2320 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-win7-windows-msvc".into(),
+        description: Some("64-bit Windows 7 support".into()),
         pointer_width: 64,
         data_layout:
             "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs
index f7a78b48f95..e293d0eb3ce 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs
@@ -11,6 +11,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-linux-gnu".into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
index e0e4cb93e31..9aaaa894a93 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
@@ -34,6 +34,7 @@ pub fn target() -> Target {
         // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
         // correctly, we do too.
         llvm_target: macos_llvm_target(arch).into(),
+        description: None,
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index 2b7ac68c21d..c003982278e 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -377,10 +377,12 @@ const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability)] = &[
     // tidy-alphabetical-start
     ("d", Unstable(sym::loongarch_target_feature)),
     ("f", Unstable(sym::loongarch_target_feature)),
+    ("frecipe", Unstable(sym::loongarch_target_feature)),
     ("lasx", Unstable(sym::loongarch_target_feature)),
     ("lbt", Unstable(sym::loongarch_target_feature)),
     ("lsx", Unstable(sym::loongarch_target_feature)),
     ("lvz", Unstable(sym::loongarch_target_feature)),
+    ("relax", Unstable(sym::loongarch_target_feature)),
     ("ual", Unstable(sym::loongarch_target_feature)),
     // tidy-alphabetical-end
 ];
@@ -409,7 +411,7 @@ impl super::spec::Target {
     pub fn supported_target_features(&self) -> &'static [(&'static str, Stability)] {
         match &*self.arch {
             "arm" => ARM_ALLOWED_FEATURES,
-            "aarch64" => AARCH64_ALLOWED_FEATURES,
+            "aarch64" | "arm64ec" => AARCH64_ALLOWED_FEATURES,
             "x86" | "x86_64" => X86_ALLOWED_FEATURES,
             "hexagon" => HEXAGON_ALLOWED_FEATURES,
             "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_ALLOWED_FEATURES,
@@ -425,7 +427,7 @@ impl super::spec::Target {
 
     pub fn tied_target_features(&self) -> &'static [&'static [&'static str]] {
         match &*self.arch {
-            "aarch64" => AARCH64_TIED_FEATURES,
+            "aarch64" | "arm64ec" => AARCH64_TIED_FEATURES,
             _ => &[],
         }
     }
diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml
index 00ce9fbe758..3a58d41fcd0 100644
--- a/compiler/rustc_trait_selection/Cargo.toml
+++ b/compiler/rustc_trait_selection/Cargo.toml
@@ -8,6 +8,7 @@ edition = "2021"
 bitflags = "2.4.1"
 itertools = "0.11.0"
 rustc_ast = { path = "../rustc_ast" }
+rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 95667de79a6..e37640d0689 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -1,7 +1,7 @@
 use crate::fluent_generated as fluent;
 use rustc_errors::{
     codes::*, AddToDiagnostic, Applicability, Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic,
-    Level, SubdiagnosticMessageOp,
+    Level, SubdiagMessageOp,
 };
 use rustc_macros::Diagnostic;
 use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty};
@@ -101,7 +101,7 @@ pub enum AdjustSignatureBorrow {
 }
 
 impl AddToDiagnostic for AdjustSignatureBorrow {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index 7c1bfebef2c..fd3d62d1321 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -18,6 +18,7 @@
 #![allow(rustc::untranslatable_diagnostic)]
 #![feature(assert_matches)]
 #![feature(associated_type_bounds)]
+#![feature(associated_type_defaults)]
 #![feature(box_patterns)]
 #![feature(control_flow_enum)]
 #![feature(extract_if)]
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
index 98d28f10a54..22f52c27362 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
@@ -648,8 +648,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         }
 
         impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTermOrNotNameable<'_, 'tcx> {
-            type BreakTy = ();
-            fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+            type Result = ControlFlow<()>;
+            fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
                 match *t.kind() {
                     ty::Infer(ty::TyVar(vid)) => {
                         if let ty::TermKind::Ty(term) = self.term.unpack()
@@ -672,7 +672,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                 }
             }
 
-            fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+            fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {
                 match c.kind() {
                     ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
                         if let ty::TermKind::Const(term) = self.term.unpack()
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index 52b900af853..9e3e6a4676e 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -1,15 +1,16 @@
-/// An infrastructure to mechanically analyse proof trees.
-///
-/// It is unavoidable that this representation is somewhat
-/// lossy as it should hide quite a few semantically relevant things,
-/// e.g. canonicalization and the order of nested goals.
-///
-/// @lcnr: However, a lot of the weirdness here is not strictly necessary
-/// and could be improved in the future. This is mostly good enough for
-/// coherence right now and was annoying to implement, so I am leaving it
-/// as is until we start using it for something else.
-use std::ops::ControlFlow;
+//! An infrastructure to mechanically analyse proof trees.
+//!
+//! It is unavoidable that this representation is somewhat
+//! lossy as it should hide quite a few semantically relevant things,
+//! e.g. canonicalization and the order of nested goals.
+//!
+//! @lcnr: However, a lot of the weirdness here is not strictly necessary
+//! and could be improved in the future. This is mostly good enough for
+//! coherence right now and was annoying to implement, so I am leaving it
+//! as is until we start using it for something else.
 
+use rustc_ast_ir::try_visit;
+use rustc_ast_ir::visit::VisitorResult;
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::{inspect, QueryResult};
@@ -53,10 +54,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
     /// to also use it to compute the most relevant goal
     /// for fulfillment errors. Will do that once we actually
     /// need it.
-    pub fn visit_nested<V: ProofTreeVisitor<'tcx>>(
-        &self,
-        visitor: &mut V,
-    ) -> ControlFlow<V::BreakTy> {
+    pub fn visit_nested<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result {
         // HACK: An arbitrary cutoff to avoid dealing with overflow and cycles.
         if self.goal.depth <= 10 {
             let infcx = self.goal.infcx;
@@ -75,17 +73,18 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
                 for &goal in &instantiated_goals {
                     let (_, proof_tree) = infcx.evaluate_root_goal(goal, GenerateProofTree::Yes);
                     let proof_tree = proof_tree.unwrap();
-                    visitor.visit_goal(&InspectGoal::new(
+                    try_visit!(visitor.visit_goal(&InspectGoal::new(
                         infcx,
                         self.goal.depth + 1,
                         &proof_tree,
-                    ))?;
+                    )));
                 }
 
-                ControlFlow::Continue(())
-            })?;
+                V::Result::output()
+            })
+        } else {
+            V::Result::output()
         }
-        ControlFlow::Continue(())
     }
 }
 
@@ -202,9 +201,9 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
 
 /// The public API to interact with proof trees.
 pub trait ProofTreeVisitor<'tcx> {
-    type BreakTy;
+    type Result: VisitorResult = ();
 
-    fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow<Self::BreakTy>;
+    fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> Self::Result;
 }
 
 #[extension(pub trait ProofTreeInferCtxtExt<'tcx>)]
@@ -213,7 +212,7 @@ impl<'tcx> InferCtxt<'tcx> {
         &self,
         goal: Goal<'tcx, ty::Predicate<'tcx>>,
         visitor: &mut V,
-    ) -> ControlFlow<V::BreakTy> {
+    ) -> V::Result {
         self.probe(|_| {
             let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes);
             let proof_tree = proof_tree.unwrap();
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
index 248985715c2..ed839d14dc7 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
@@ -166,13 +166,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
         let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
         if !drcx.args_may_unify(
             goal.predicate.trait_ref(tcx).args,
-            impl_trait_header.skip_binder().trait_ref.args,
+            impl_trait_header.trait_ref.skip_binder().args,
         ) {
             return Err(NoSolution);
         }
 
         // We have to ignore negative impls when projecting.
-        let impl_polarity = impl_trait_header.skip_binder().polarity;
+        let impl_polarity = impl_trait_header.polarity;
         match impl_polarity {
             ty::ImplPolarity::Negative => return Err(NoSolution),
             ty::ImplPolarity::Reservation => {
@@ -183,7 +183,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
 
         ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
             let impl_args = ecx.fresh_args_for_item(impl_def_id);
-            let impl_trait_ref = impl_trait_header.instantiate(tcx, impl_args).trait_ref;
+            let impl_trait_ref = impl_trait_header.trait_ref.instantiate(tcx, impl_args);
 
             ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
 
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 80198ba39f9..281f5cc5685 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -47,14 +47,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
         if !drcx.args_may_unify(
             goal.predicate.trait_ref.args,
-            impl_trait_header.skip_binder().trait_ref.args,
+            impl_trait_header.trait_ref.skip_binder().args,
         ) {
             return Err(NoSolution);
         }
 
         // An upper bound of the certainty of this goal, used to lower the certainty
         // of reservation impl to ambiguous during coherence.
-        let impl_polarity = impl_trait_header.skip_binder().polarity;
+        let impl_polarity = impl_trait_header.polarity;
         let maximal_certainty = match impl_polarity {
             ty::ImplPolarity::Positive | ty::ImplPolarity::Negative => {
                 match impl_polarity == goal.predicate.polarity {
@@ -70,7 +70,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
 
         ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
             let impl_args = ecx.fresh_args_for_item(impl_def_id);
-            let impl_trait_ref = impl_trait_header.instantiate(tcx, impl_args).trait_ref;
+            let impl_trait_ref = impl_trait_header.trait_ref.instantiate(tcx, impl_args);
 
             ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
             let where_clause_bounds = tcx
@@ -102,7 +102,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
             if trait_clause.def_id() == goal.predicate.def_id()
                 && trait_clause.polarity() == goal.predicate.polarity
             {
-                // FIXME: Constness
                 ecx.probe_misc_candidate("assumption").enter(|ecx| {
                     let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause);
                     ecx.eq(
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 68111c4cc1f..2712ba19451 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -26,7 +26,6 @@ use rustc_infer::traits::{util, FulfillmentErrorCode, TraitEngine, TraitEngineEx
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal};
 use rustc_middle::traits::specialization_graph::OverlapMode;
-use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
@@ -207,7 +206,6 @@ fn overlap<'tcx>(
 
     let infcx = tcx
         .infer_ctxt()
-        .with_opaque_type_inference(DefiningAnchor::Bubble)
         .skip_leak_check(skip_leak_check.is_yes())
         .intercrate(true)
         .with_next_trait_solver(tcx.next_trait_solver_in_coherence())
@@ -474,7 +472,7 @@ fn plug_infer_with_placeholders<'tcx>(
     }
 
     impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for PlugInferWithPlaceholder<'_, 'tcx> {
-        fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        fn visit_ty(&mut self, ty: Ty<'tcx>) {
             let ty = self.infcx.shallow_resolve(ty);
             if ty.is_ty_var() {
                 let Ok(InferOk { value: (), obligations }) =
@@ -496,13 +494,12 @@ fn plug_infer_with_placeholders<'tcx>(
                     bug!("we always expect to be able to plug an infer var with placeholder")
                 };
                 assert_eq!(obligations, &[]);
-                ControlFlow::Continue(())
             } else {
-                ty.super_visit_with(self)
+                ty.super_visit_with(self);
             }
         }
 
-        fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+        fn visit_const(&mut self, ct: ty::Const<'tcx>) {
             let ct = self.infcx.shallow_resolve(ct);
             if ct.is_ct_infer() {
                 let Ok(InferOk { value: (), obligations }) =
@@ -519,13 +516,12 @@ fn plug_infer_with_placeholders<'tcx>(
                     bug!("we always expect to be able to plug an infer var with placeholder")
                 };
                 assert_eq!(obligations, &[]);
-                ControlFlow::Continue(())
             } else {
-                ct.super_visit_with(self)
+                ct.super_visit_with(self);
             }
         }
 
-        fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+        fn visit_region(&mut self, r: ty::Region<'tcx>) {
             if let ty::ReVar(vid) = *r {
                 let r = self
                     .infcx
@@ -555,7 +551,6 @@ fn plug_infer_with_placeholders<'tcx>(
                     assert_eq!(obligations, &[]);
                 }
             }
-            ControlFlow::Continue(())
         }
     }
 
@@ -868,12 +863,12 @@ impl<'tcx, F, E> TypeVisitor<TyCtxt<'tcx>> for OrphanChecker<'tcx, F>
 where
     F: FnMut(Ty<'tcx>) -> Result<Ty<'tcx>, E>,
 {
-    type BreakTy = OrphanCheckEarlyExit<'tcx, E>;
-    fn visit_region(&mut self, _r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+    type Result = ControlFlow<OrphanCheckEarlyExit<'tcx, E>>;
+    fn visit_region(&mut self, _r: ty::Region<'tcx>) -> Self::Result {
         ControlFlow::Continue(())
     }
 
-    fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
         // Need to lazily normalize here in with `-Znext-solver=coherence`.
         let ty = match (self.lazily_normalize_ty)(ty) {
             Ok(ty) => ty,
@@ -996,7 +991,7 @@ where
     /// As these should be quite rare as const arguments and especially rare as impl
     /// parameters, allowing uncovered const parameters in impls seems more useful
     /// than allowing `impl<T> Trait<local_fn_ptr, T> for i32` to compile.
-    fn visit_const(&mut self, _c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_const(&mut self, _c: ty::Const<'tcx>) -> Self::Result {
         ControlFlow::Continue(())
     }
 }
@@ -1026,18 +1021,17 @@ struct AmbiguityCausesVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
-    type BreakTy = !;
-    fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) {
         let infcx = goal.infcx();
         for cand in goal.candidates() {
-            cand.visit_nested(self)?;
+            cand.visit_nested(self);
         }
         // When searching for intercrate ambiguity causes, we only need to look
         // at ambiguous goals, as for others the coherence unknowable candidate
         // was irrelevant.
         match goal.result() {
             Ok(Certainty::Maybe(_)) => {}
-            Ok(Certainty::Yes) | Err(NoSolution) => return ControlFlow::Continue(()),
+            Ok(Certainty::Yes) | Err(NoSolution) => return,
         }
 
         let Goal { param_env, predicate } = goal.goal();
@@ -1054,7 +1048,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
             {
                 proj.projection_ty.trait_ref(infcx.tcx)
             }
-            _ => return ControlFlow::Continue(()),
+            _ => return,
         };
 
         // Add ambiguity causes for reservation impls.
@@ -1154,8 +1148,6 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
         if let Some(ambiguity_cause) = ambiguity_cause {
             self.causes.insert(ambiguity_cause);
         }
-
-        ControlFlow::Continue(())
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 189e1ba54bc..7f0f9a12d6a 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -17,7 +17,6 @@ use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitable, TypeVisitableExt, TypeVisitor};
 
 use rustc_span::Span;
-use std::ops::ControlFlow;
 
 use crate::traits::ObligationCtxt;
 
@@ -170,8 +169,7 @@ fn satisfied_from_param_env<'tcx>(
     }
 
     impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for Visitor<'a, 'tcx> {
-        type BreakTy = ();
-        fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+        fn visit_const(&mut self, c: ty::Const<'tcx>) {
             debug!("is_const_evaluatable: candidate={:?}", c);
             if self.infcx.probe(|_| {
                 let ocx = ObligationCtxt::new(self.infcx);
@@ -187,7 +185,7 @@ fn satisfied_from_param_env<'tcx>(
             }
 
             if let ty::ConstKind::Expr(e) = c.kind() {
-                e.visit_with(self)
+                e.visit_with(self);
             } else {
                 // FIXME(generic_const_exprs): This doesn't recurse into `<T as Trait<U>>::ASSOC`'s args.
                 // This is currently unobservable as `<T as Trait<{ U + 1 }>>::ASSOC` creates an anon const
@@ -196,7 +194,6 @@ fn satisfied_from_param_env<'tcx>(
                 // If we start allowing directly writing `ConstKind::Expr` without an intermediate anon const
                 // this will be incorrect. It might be worth investigating making `predicates_of` elaborate
                 // all of the `ConstEvaluatable` bounds rather than having a visitor here.
-                ControlFlow::Continue(())
             }
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 0796cb57d97..0515b09ae46 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -152,9 +152,9 @@ impl ArgKind {
 struct HasNumericInferVisitor;
 
 impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for HasNumericInferVisitor {
-    type BreakTy = ();
+    type Result = ControlFlow<()>;
 
-    fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
         if matches!(ty.kind(), ty::Infer(ty::FloatVar(_) | ty::IntVar(_))) {
             ControlFlow::Break(())
         } else {
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 de834b8fb64..1241227a5af 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1266,8 +1266,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     if has_custom_message {
                         err.note(msg);
                     } else {
-                        err.messages =
-                            vec![(rustc_errors::DiagnosticMessage::from(msg), Style::NoStyle)];
+                        err.messages = vec![(rustc_errors::DiagMessage::from(msg), Style::NoStyle)];
                     }
                     let mut file = None;
                     err.span_label(
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 62933bce76b..71fcc47dba3 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
@@ -19,6 +19,7 @@ use crate::traits::{
     ObligationCause, ObligationCauseCode, ObligationCtxt, Overflow, PredicateObligation,
     SelectionError, SignatureMismatch, TraitNotObjectSafe,
 };
+use core::ops::ControlFlow;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_errors::codes::*;
 use rustc_errors::{pluralize, struct_span_code_err, Applicability, MultiSpan, StringPart};
@@ -416,9 +417,59 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
                         let trait_predicate = bound_predicate.rebind(trait_predicate);
                         let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
-                        let trait_ref = trait_predicate.to_poly_trait_ref();
 
-                        if let Some(guar) = self.emit_specialized_closure_kind_error(&obligation, trait_ref) {
+                        // Let's use the root obligation as the main message, when we care about the
+                        // most general case ("X doesn't implement Pattern<'_>") over the case that
+                        // happened to fail ("char doesn't implement Fn(&mut char)").
+                        //
+                        // We rely on a few heuristics to identify cases where this root
+                        // obligation is more important than the leaf obligation:
+                        let (main_trait_predicate, o) = if let ty::PredicateKind::Clause(
+                            ty::ClauseKind::Trait(root_pred)
+                        ) = root_obligation.predicate.kind().skip_binder()
+                            && !trait_predicate.self_ty().skip_binder().has_escaping_bound_vars()
+                            && !root_pred.self_ty().has_escaping_bound_vars()
+                            // The type of the leaf predicate is (roughly) the same as the type
+                            // from the root predicate, as a proxy for "we care about the root"
+                            // FIXME: this doesn't account for trivial derefs, but works as a first
+                            // approximation.
+                            && (
+                                // `T: Trait` && `&&T: OtherTrait`, we want `OtherTrait`
+                                self.can_eq(
+                                    obligation.param_env,
+                                    trait_predicate.self_ty().skip_binder(),
+                                    root_pred.self_ty().peel_refs(),
+                                )
+                                // `&str: Iterator` && `&str: IntoIterator`, we want `IntoIterator`
+                                || self.can_eq(
+                                    obligation.param_env,
+                                    trait_predicate.self_ty().skip_binder(),
+                                    root_pred.self_ty(),
+                                )
+                            )
+                            // The leaf trait and the root trait are different, so as to avoid
+                            // talking about `&mut T: Trait` and instead remain talking about
+                            // `T: Trait` instead
+                            && trait_predicate.def_id() != root_pred.def_id()
+                            // The root trait is not `Unsize`, as to avoid talking about it in
+                            // `tests/ui/coercion/coerce-issue-49593-box-never.rs`.
+                            && Some(root_pred.def_id()) != self.tcx.lang_items().unsize_trait()
+                        {
+                            (
+                                self.resolve_vars_if_possible(
+                                    root_obligation.predicate.kind().rebind(root_pred),
+                                ),
+                                root_obligation,
+                            )
+                        } else {
+                            (trait_predicate, &obligation)
+                        };
+                        let trait_ref = main_trait_predicate.to_poly_trait_ref();
+
+                        if let Some(guar) = self.emit_specialized_closure_kind_error(
+                            &obligation,
+                            trait_ref,
+                        ) {
                             return guar;
                         }
 
@@ -459,8 +510,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             notes,
                             parent_label,
                             append_const_msg,
-                        } = self.on_unimplemented_note(trait_ref, &obligation, &mut long_ty_file);
-
+                        } = self.on_unimplemented_note(trait_ref, o, &mut long_ty_file);
                         let have_alt_message = message.is_some() || label.is_some();
                         let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id());
                         let is_unsize =
@@ -483,7 +533,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         };
 
                         let err_msg = self.get_standard_error_message(
-                            &trait_predicate,
+                            &main_trait_predicate,
                             message,
                             predicate_is_const,
                             append_const_msg,
@@ -1077,22 +1127,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         err: &mut Diag<'_>,
     ) -> bool {
         let span = obligation.cause.span;
-        struct V<'v> {
+        struct V {
             search_span: Span,
-            found: Option<&'v hir::Expr<'v>>,
         }
-        impl<'v> Visitor<'v> for V<'v> {
-            fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
+        impl<'v> Visitor<'v> for V {
+            type Result = ControlFlow<&'v hir::Expr<'v>>;
+            fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) -> Self::Result {
                 if let hir::ExprKind::Match(expr, _arms, hir::MatchSource::TryDesugar(_)) = ex.kind
+                    && ex.span.with_lo(ex.span.hi() - BytePos(1)).source_equal(self.search_span)
+                    && let hir::ExprKind::Call(_, [expr, ..]) = expr.kind
                 {
-                    if ex.span.with_lo(ex.span.hi() - BytePos(1)).source_equal(self.search_span) {
-                        if let hir::ExprKind::Call(_, [expr, ..]) = expr.kind {
-                            self.found = Some(expr);
-                            return;
-                        }
-                    }
+                    ControlFlow::Break(expr)
+                } else {
+                    hir::intravisit::walk_expr(self, ex)
                 }
-                hir::intravisit::walk_expr(self, ex);
             }
         }
         let hir_id = self.tcx.local_def_id_to_hir_id(obligation.cause.body_id);
@@ -1100,9 +1148,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) => body_id,
             _ => return false,
         };
-        let mut v = V { search_span: span, found: None };
-        v.visit_body(self.tcx.hir().body(*body_id));
-        let Some(expr) = v.found else {
+        let ControlFlow::Break(expr) =
+            (V { search_span: span }).visit_body(self.tcx.hir().body(*body_id))
+        else {
             return false;
         };
         let Some(typeck) = &self.typeck_results else {
@@ -1382,45 +1430,64 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
 #[extension(pub(super) trait InferCtxtPrivExt<'tcx>)]
 impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+    fn can_match_trait(
+        &self,
+        goal: ty::TraitPredicate<'tcx>,
+        assumption: ty::PolyTraitPredicate<'tcx>,
+    ) -> bool {
+        if goal.polarity != assumption.polarity() {
+            return false;
+        }
+
+        let trait_goal = goal.trait_ref;
+        let trait_assumption = self.instantiate_binder_with_fresh_vars(
+            DUMMY_SP,
+            infer::BoundRegionConversionTime::HigherRankedType,
+            assumption.to_poly_trait_ref(),
+        );
+
+        self.can_eq(ty::ParamEnv::empty(), trait_goal, trait_assumption)
+    }
+
+    fn can_match_projection(
+        &self,
+        goal: ty::ProjectionPredicate<'tcx>,
+        assumption: ty::PolyProjectionPredicate<'tcx>,
+    ) -> bool {
+        let assumption = self.instantiate_binder_with_fresh_vars(
+            DUMMY_SP,
+            infer::BoundRegionConversionTime::HigherRankedType,
+            assumption,
+        );
+
+        let param_env = ty::ParamEnv::empty();
+        self.can_eq(param_env, goal.projection_ty, assumption.projection_ty)
+            && self.can_eq(param_env, goal.term, assumption.term)
+    }
+
     // returns if `cond` not occurring implies that `error` does not occur - i.e., that
     // `error` occurring implies that `cond` occurs.
+    #[instrument(level = "debug", skip(self), ret)]
     fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool {
         if cond == error {
             return true;
         }
 
-        // FIXME: It should be possible to deal with `ForAll` in a cleaner way.
-        let bound_error = error.kind();
-        let (cond, error) = match (cond.kind().skip_binder(), bound_error.skip_binder()) {
-            (
-                ty::PredicateKind::Clause(ty::ClauseKind::Trait(..)),
-                ty::PredicateKind::Clause(ty::ClauseKind::Trait(error)),
-            ) => (cond, bound_error.rebind(error)),
-            _ => {
-                // FIXME: make this work in other cases too.
-                return false;
-            }
-        };
-
-        for pred in elaborate(self.tcx, std::iter::once(cond)) {
-            let bound_predicate = pred.kind();
-            if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(implication)) =
-                bound_predicate.skip_binder()
-            {
-                let error = error.to_poly_trait_ref();
-                let implication = bound_predicate.rebind(implication.trait_ref);
-                // FIXME: I'm just not taking associated types at all here.
-                // Eventually I'll need to implement param-env-aware
-                // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
-                let param_env = ty::ParamEnv::empty();
-                if self.can_sub(param_env, error, implication) {
-                    debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
-                    return true;
-                }
-            }
+        if let Some(error) = error.to_opt_poly_trait_pred() {
+            self.enter_forall(error, |error| {
+                elaborate(self.tcx, std::iter::once(cond))
+                    .filter_map(|implied| implied.to_opt_poly_trait_pred())
+                    .any(|implied| self.can_match_trait(error, implied))
+            })
+        } else if let Some(error) = error.to_opt_poly_projection_pred() {
+            self.enter_forall(error, |error| {
+                elaborate(self.tcx, std::iter::once(cond))
+                    .filter_map(|implied| implied.to_opt_poly_projection_pred())
+                    .any(|implied| self.can_match_projection(error, implied))
+            })
+        } else {
+            false
         }
-
-        false
     }
 
     #[instrument(skip(self), level = "debug")]
@@ -1839,13 +1906,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             .tcx
             .all_impls(trait_pred.def_id())
             .filter_map(|def_id| {
-                let imp = self.tcx.impl_trait_header(def_id).unwrap().skip_binder();
+                let imp = self.tcx.impl_trait_header(def_id).unwrap();
                 if imp.polarity == ty::ImplPolarity::Negative
                     || !self.tcx.is_user_visible_dep(def_id.krate)
                 {
                     return None;
                 }
-                let imp = imp.trait_ref;
+                let imp = imp.trait_ref.skip_binder();
 
                 self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false).map(
                     |similarity| ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id },
@@ -2029,12 +2096,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 .all_impls(def_id)
                 // Ignore automatically derived impls and `!Trait` impls.
                 .filter_map(|def_id| self.tcx.impl_trait_header(def_id))
-                .map(ty::EarlyBinder::instantiate_identity)
-                .filter(|header| {
-                    header.polarity != ty::ImplPolarity::Negative
-                        || self.tcx.is_automatically_derived(def_id)
+                .filter_map(|header| {
+                    (header.polarity != ty::ImplPolarity::Negative
+                        || self.tcx.is_automatically_derived(def_id))
+                    .then(|| header.trait_ref.instantiate_identity())
                 })
-                .map(|header| header.trait_ref)
                 .filter(|trait_ref| {
                     let self_ty = trait_ref.self_ty();
                     // Avoid mentioning type parameters.
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 32447aca390..cc8b8f72cf3 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -435,8 +435,8 @@ fn is_impossible_associated_item(
         trait_item_def_id: DefId,
     }
     impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for ReferencesOnlyParentGenerics<'tcx> {
-        type BreakTy = ();
-        fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        type Result = ControlFlow<()>;
+        fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
             // If this is a parameter from the trait item's own generics, then bail
             if let ty::Param(param) = t.kind()
                 && let param_def_id = self.generics.type_param(param, self.tcx).def_id
@@ -446,7 +446,7 @@ fn is_impossible_associated_item(
             }
             t.super_visit_with(self)
         }
-        fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+        fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
             if let ty::ReEarlyParam(param) = r.kind()
                 && let param_def_id = self.generics.region_param(&param, self.tcx).def_id
                 && self.tcx.parent(param_def_id) == self.trait_item_def_id
@@ -455,7 +455,7 @@ fn is_impossible_associated_item(
             }
             ControlFlow::Continue(())
         }
-        fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+        fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
             if let ty::ConstKind::Param(param) = ct.kind()
                 && let param_def_id = self.generics.const_param(&param, self.tcx).def_id
                 && self.tcx.parent(param_def_id) == self.trait_item_def_id
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 7b715984c2b..1816b98a636 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -834,9 +834,9 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
     }
 
     impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalSelfTypeVisitor<'tcx> {
-        type BreakTy = ();
+        type Result = ControlFlow<()>;
 
-        fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
             match t.kind() {
                 ty::Param(_) => {
                     if t == self.tcx.types.self_param {
@@ -887,7 +887,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
             }
         }
 
-        fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+        fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
             // Constants can only influence object safety if they are generic and reference `Self`.
             // This is only possible for unevaluated constants, so we walk these here.
             self.tcx.expand_abstract_consts(ct).super_visit_with(self)
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index e5f8e336860..c520e699bf5 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -18,8 +18,6 @@ use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableEx
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
 use rustc_span::DUMMY_SP;
 
-use std::ops::ControlFlow;
-
 use super::NoSolution;
 
 pub use rustc_middle::traits::query::NormalizationResult;
@@ -123,28 +121,23 @@ struct MaxEscapingBoundVarVisitor {
 }
 
 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxEscapingBoundVarVisitor {
-    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
-        &mut self,
-        t: &ty::Binder<'tcx, T>,
-    ) -> ControlFlow<Self::BreakTy> {
+    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
         self.outer_index.shift_in(1);
-        let result = t.super_visit_with(self);
+        t.super_visit_with(self);
         self.outer_index.shift_out(1);
-        result
     }
 
     #[inline]
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, t: Ty<'tcx>) {
         if t.outer_exclusive_binder() > self.outer_index {
             self.escaping = self
                 .escaping
                 .max(t.outer_exclusive_binder().as_usize() - self.outer_index.as_usize());
         }
-        ControlFlow::Continue(())
     }
 
     #[inline]
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_region(&mut self, r: ty::Region<'tcx>) {
         match *r {
             ty::ReBound(debruijn, _) if debruijn > self.outer_index => {
                 self.escaping =
@@ -152,16 +145,14 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxEscapingBoundVarVisitor {
             }
             _ => {}
         }
-        ControlFlow::Continue(())
     }
 
-    fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_const(&mut self, ct: ty::Const<'tcx>) {
         if ct.outer_exclusive_binder() > self.outer_index {
             self.escaping = self
                 .escaping
                 .max(ct.outer_exclusive_binder().as_usize() - self.outer_index.as_usize());
         }
-        ControlFlow::Continue(())
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 39f4ceda9f1..66f740b761d 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -562,7 +562,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // and so forth that we need to.
                 let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap();
                 if !drcx
-                    .args_may_unify(obligation_args, impl_trait_header.skip_binder().trait_ref.args)
+                    .args_may_unify(obligation_args, impl_trait_header.trait_ref.skip_binder().args)
                 {
                     return;
                 }
@@ -577,7 +577,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 if self.reject_fn_ptr_impls(
                     impl_def_id,
                     obligation,
-                    impl_trait_header.skip_binder().trait_ref.self_ty(),
+                    impl_trait_header.trait_ref.skip_binder().self_ty(),
                 ) {
                     return;
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 7dbea0cdb90..a6bd1ba9c3f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -42,7 +42,7 @@ use rustc_middle::ty::_match::MatchAgainstFreshVars;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
+use rustc_middle::ty::{self, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
 use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
 use rustc_span::symbol::sym;
 use rustc_span::Symbol;
@@ -2441,7 +2441,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
     fn match_impl(
         &mut self,
         impl_def_id: DefId,
-        impl_trait_header: EarlyBinder<ty::ImplTraitHeader<'tcx>>,
+        impl_trait_header: ty::ImplTraitHeader<'tcx>,
         obligation: &PolyTraitObligation<'tcx>,
     ) -> Result<Normalized<'tcx, GenericArgsRef<'tcx>>, ()> {
         let placeholder_obligation =
@@ -2450,8 +2450,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
 
         let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id);
 
-        let impl_trait_header = impl_trait_header.instantiate(self.tcx(), impl_args);
-        if impl_trait_header.references_error() {
+        let trait_ref = impl_trait_header.trait_ref.instantiate(self.tcx(), impl_args);
+        if trait_ref.references_error() {
             return Err(());
         }
 
@@ -2464,7 +2464,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                     obligation.param_env,
                     obligation.cause.clone(),
                     obligation.recursion_depth + 1,
-                    impl_trait_header.trait_ref,
+                    trait_ref,
                 )
             });
 
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index f5bc6c3ad2c..27dd8f26489 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -169,7 +169,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
         }
     }
 
-    let impl1_trait_header = tcx.impl_trait_header(impl1_def_id).unwrap().instantiate_identity();
+    let impl1_trait_header = tcx.impl_trait_header(impl1_def_id).unwrap();
 
     // We determine whether there's a subset relationship by:
     //
@@ -198,7 +198,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
     fulfill_implication(
         &infcx,
         penv,
-        impl1_trait_header.trait_ref,
+        impl1_trait_header.trait_ref.instantiate_identity(),
         impl1_def_id,
         impl2_def_id,
         |_, _| ObligationCause::dummy(),
diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs
index e6b42f15d51..b89406ca023 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs
@@ -53,9 +53,9 @@ impl<'tcx> Search<'tcx> {
 }
 
 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Search<'tcx> {
-    type BreakTy = Ty<'tcx>;
+    type Result = ControlFlow<Ty<'tcx>>;
 
-    fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
         debug!("Search visiting ty: {:?}", ty);
 
         let (adt_def, args) = match *ty.kind() {
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 6e01e0b76aa..3f433a9e919 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -127,7 +127,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
         }
 
         // Get components of trait alias.
-        let predicates = tcx.implied_predicates_of(trait_ref.def_id());
+        let predicates = tcx.super_predicates_of(trait_ref.def_id());
         debug!(?predicates);
 
         let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 15059bc6613..f89daf033f6 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -2,7 +2,9 @@ use crate::infer::InferCtxt;
 use crate::traits;
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{
+    self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
+};
 use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgsRef};
 use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
 use rustc_span::{Span, DUMMY_SP};
@@ -223,60 +225,87 @@ enum Elaborate {
     None,
 }
 
+/// Points the cause span of a super predicate at the relevant associated type.
+///
+/// Given a trait impl item:
+///
+/// ```ignore (incomplete)
+/// impl TargetTrait for TargetType {
+///    type Assoc = SomeType;
+/// }
+/// ```
+///
+/// And a super predicate of `TargetTrait` that has any of the following forms:
+///
+/// 1. `<OtherType as OtherTrait>::Assoc == <TargetType as TargetTrait>::Assoc`
+/// 2. `<<TargetType as TargetTrait>::Assoc as OtherTrait>::Assoc == OtherType`
+/// 3. `<TargetType as TargetTrait>::Assoc: OtherTrait`
+///
+/// Replace the span of the cause with the span of the associated item:
+///
+/// ```ignore (incomplete)
+/// impl TargetTrait for TargetType {
+///     type Assoc = SomeType;
+/// //               ^^^^^^^^ this span
+/// }
+/// ```
+///
+/// Note that bounds that can be expressed as associated item bounds are **not**
+/// super predicates. This means that form 2 and 3 from above are only relevant if
+/// the [`GenericArgsRef`] of the projection type are not its identity arguments.
 fn extend_cause_with_original_assoc_item_obligation<'tcx>(
     tcx: TyCtxt<'tcx>,
-    trait_ref: ty::TraitRef<'tcx>,
     item: Option<&hir::Item<'tcx>>,
     cause: &mut traits::ObligationCause<'tcx>,
     pred: ty::Predicate<'tcx>,
 ) {
-    debug!(
-        "extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}",
-        trait_ref, item, cause, pred
-    );
+    debug!(?item, ?cause, ?pred, "extended_cause_with_original_assoc_item_obligation");
     let (items, impl_def_id) = match item {
         Some(hir::Item { kind: hir::ItemKind::Impl(impl_), owner_id, .. }) => {
             (impl_.items, *owner_id)
         }
         _ => return,
     };
-    let fix_span =
-        |impl_item_ref: &hir::ImplItemRef| match tcx.hir().impl_item(impl_item_ref.id).kind {
-            hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::Type(ty) => ty.span,
-            _ => impl_item_ref.span,
-        };
+
+    let ty_to_impl_span = |ty: Ty<'_>| {
+        if let ty::Alias(ty::Projection, projection_ty) = ty.kind()
+            && let Some(&impl_item_id) =
+                tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.def_id)
+            && let Some(impl_item) =
+                items.iter().find(|item| item.id.owner_id.to_def_id() == impl_item_id)
+        {
+            Some(tcx.hir().impl_item(impl_item.id).expect_type().span)
+        } else {
+            None
+        }
+    };
 
     // It is fine to skip the binder as we don't care about regions here.
     match pred.kind().skip_binder() {
         ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) => {
-            // The obligation comes not from the current `impl` nor the `trait` being implemented,
-            // but rather from a "second order" obligation, where an associated type has a
-            // projection coming from another associated type. See
-            // `tests/ui/associated-types/point-at-type-on-obligation-failure.rs` and
-            // `traits-assoc-type-in-supertrait-bad.rs`.
-            if let Some(ty::Alias(ty::Projection, projection_ty)) =
-                proj.term.ty().map(|ty| ty.kind())
-                && let Some(&impl_item_id) =
-                    tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.def_id)
-                && let Some(impl_item_span) = items
-                    .iter()
-                    .find(|item| item.id.owner_id.to_def_id() == impl_item_id)
-                    .map(fix_span)
+            // Form 1: The obligation comes not from the current `impl` nor the `trait` being
+            // implemented, but rather from a "second order" obligation, where an associated
+            // type has a projection coming from another associated type.
+            // See `tests/ui/traits/assoc-type-in-superbad.rs` for an example.
+            if let Some(term_ty) = proj.term.ty()
+                && let Some(impl_item_span) = ty_to_impl_span(term_ty)
             {
                 cause.span = impl_item_span;
             }
+
+            // Form 2: A projection obligation for an associated item failed to be met.
+            // We overwrite the span from above to ensure that a bound like
+            // `Self::Assoc1: Trait<OtherAssoc = Self::Assoc2>` gets the same
+            // span for both obligations that it is lowered to.
+            if let Some(impl_item_span) = ty_to_impl_span(proj.self_ty()) {
+                cause.span = impl_item_span;
+            }
         }
+
         ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
-            // An associated item obligation born out of the `trait` failed to be met. An example
-            // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
+            // Form 3: A trait obligation for an associated item failed to be met.
             debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
-            if let ty::Alias(ty::Projection, ty::AliasTy { def_id, .. }) = *pred.self_ty().kind()
-                && let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&def_id)
-                && let Some(impl_item_span) = items
-                    .iter()
-                    .find(|item| item.id.owner_id.to_def_id() == impl_item_id)
-                    .map(fix_span)
-            {
+            if let Some(impl_item_span) = ty_to_impl_span(pred.self_ty()) {
                 cause.span = impl_item_span;
             }
         }
@@ -355,9 +384,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                     traits::ObligationCauseCode::DerivedObligation,
                 );
             }
-            extend_cause_with_original_assoc_item_obligation(
-                tcx, trait_ref, item, &mut cause, predicate,
-            );
+            extend_cause_with_original_assoc_item_obligation(tcx, item, &mut cause, predicate);
             traits::Obligation::with_depth(tcx, cause, depth, param_env, predicate)
         };
 
@@ -510,305 +537,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
     /// Pushes all the predicates needed to validate that `ty` is WF into `out`.
     #[instrument(level = "debug", skip(self))]
     fn compute(&mut self, arg: GenericArg<'tcx>) {
-        let mut walker = arg.walk();
-        let param_env = self.param_env;
-        let depth = self.recursion_depth;
-        while let Some(arg) = walker.next() {
-            debug!(?arg, ?self.out);
-            let ty = match arg.unpack() {
-                GenericArgKind::Type(ty) => ty,
-
-                // No WF constraints for lifetimes being present, any outlives
-                // obligations are handled by the parent (e.g. `ty::Ref`).
-                GenericArgKind::Lifetime(_) => continue,
-
-                GenericArgKind::Const(ct) => {
-                    match ct.kind() {
-                        ty::ConstKind::Unevaluated(uv) => {
-                            if !ct.has_escaping_bound_vars() {
-                                let obligations = self.nominal_obligations(uv.def, uv.args);
-                                self.out.extend(obligations);
-
-                                let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
-                                    ty::ClauseKind::ConstEvaluatable(ct),
-                                ));
-                                let cause = self.cause(traits::WellFormed(None));
-                                self.out.push(traits::Obligation::with_depth(
-                                    self.tcx(),
-                                    cause,
-                                    self.recursion_depth,
-                                    self.param_env,
-                                    predicate,
-                                ));
-                            }
-                        }
-                        ty::ConstKind::Infer(_) => {
-                            let cause = self.cause(traits::WellFormed(None));
-
-                            self.out.push(traits::Obligation::with_depth(
-                                self.tcx(),
-                                cause,
-                                self.recursion_depth,
-                                self.param_env,
-                                ty::Binder::dummy(ty::PredicateKind::Clause(
-                                    ty::ClauseKind::WellFormed(ct.into()),
-                                )),
-                            ));
-                        }
-                        ty::ConstKind::Expr(_) => {
-                            // FIXME(generic_const_exprs): this doesn't verify that given `Expr(N + 1)` the
-                            // trait bound `typeof(N): Add<typeof(1)>` holds. This is currently unnecessary
-                            // as `ConstKind::Expr` is only produced via normalization of `ConstKind::Unevaluated`
-                            // which means that the `DefId` would have been typeck'd elsewhere. However in
-                            // the future we may allow directly lowering to `ConstKind::Expr` in which case
-                            // we would not be proving bounds we should.
-
-                            let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
-                                ty::ClauseKind::ConstEvaluatable(ct),
-                            ));
-                            let cause = self.cause(traits::WellFormed(None));
-                            self.out.push(traits::Obligation::with_depth(
-                                self.tcx(),
-                                cause,
-                                self.recursion_depth,
-                                self.param_env,
-                                predicate,
-                            ));
-                        }
-
-                        ty::ConstKind::Error(_)
-                        | ty::ConstKind::Param(_)
-                        | ty::ConstKind::Bound(..)
-                        | ty::ConstKind::Placeholder(..) => {
-                            // These variants are trivially WF, so nothing to do here.
-                        }
-                        ty::ConstKind::Value(..) => {
-                            // FIXME: Enforce that values are structurally-matchable.
-                        }
-                    }
-                    continue;
-                }
-            };
-
-            debug!("wf bounds for ty={:?} ty.kind={:#?}", ty, ty.kind());
-
-            match *ty.kind() {
-                ty::Bool
-                | ty::Char
-                | ty::Int(..)
-                | ty::Uint(..)
-                | ty::Float(..)
-                | ty::Error(_)
-                | ty::Str
-                | ty::CoroutineWitness(..)
-                | ty::Never
-                | ty::Param(_)
-                | ty::Bound(..)
-                | ty::Placeholder(..)
-                | ty::Foreign(..) => {
-                    // WfScalar, WfParameter, etc
-                }
-
-                // Can only infer to `ty::Int(_) | ty::Uint(_)`.
-                ty::Infer(ty::IntVar(_)) => {}
-
-                // Can only infer to `ty::Float(_)`.
-                ty::Infer(ty::FloatVar(_)) => {}
-
-                ty::Slice(subty) => {
-                    self.require_sized(subty, traits::SliceOrArrayElem);
-                }
-
-                ty::Array(subty, _) => {
-                    self.require_sized(subty, traits::SliceOrArrayElem);
-                    // Note that we handle the len is implicitly checked while walking `arg`.
-                }
-
-                ty::Tuple(tys) => {
-                    if let Some((_last, rest)) = tys.split_last() {
-                        for &elem in rest {
-                            self.require_sized(elem, traits::TupleElem);
-                        }
-                    }
-                }
-
-                ty::RawPtr(_) => {
-                    // Simple cases that are WF if their type args are WF.
-                }
-
-                ty::Alias(ty::Projection, data) => {
-                    walker.skip_current_subtree(); // Subtree handled by compute_projection.
-                    self.compute_projection(data);
-                }
-                ty::Alias(ty::Inherent, data) => {
-                    walker.skip_current_subtree(); // Subtree handled by compute_inherent_projection.
-                    self.compute_inherent_projection(data);
-                }
-
-                ty::Adt(def, args) => {
-                    // WfNominalType
-                    let obligations = self.nominal_obligations(def.did(), args);
-                    self.out.extend(obligations);
-                }
-
-                ty::FnDef(did, args) => {
-                    let obligations = self.nominal_obligations(did, args);
-                    self.out.extend(obligations);
-                }
-
-                ty::Ref(r, rty, _) => {
-                    // WfReference
-                    if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
-                        let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
-                        self.out.push(traits::Obligation::with_depth(
-                            self.tcx(),
-                            cause,
-                            depth,
-                            param_env,
-                            ty::Binder::dummy(ty::PredicateKind::Clause(
-                                ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(rty, r)),
-                            )),
-                        ));
-                    }
-                }
-
-                ty::Coroutine(did, args, ..) => {
-                    // Walk ALL the types in the coroutine: this will
-                    // include the upvar types as well as the yield
-                    // type. Note that this is mildly distinct from
-                    // the closure case, where we have to be careful
-                    // about the signature of the closure. We don't
-                    // have the problem of implied bounds here since
-                    // coroutines don't take arguments.
-                    let obligations = self.nominal_obligations(did, args);
-                    self.out.extend(obligations);
-                }
-
-                ty::Closure(did, args) => {
-                    // Only check the upvar types for WF, not the rest
-                    // of the types within. This is needed because we
-                    // capture the signature and it may not be WF
-                    // without the implied bounds. Consider a closure
-                    // like `|x: &'a T|` -- it may be that `T: 'a` is
-                    // not known to hold in the creator's context (and
-                    // indeed the closure may not be invoked by its
-                    // creator, but rather turned to someone who *can*
-                    // verify that).
-                    //
-                    // The special treatment of closures here really
-                    // ought not to be necessary either; the problem
-                    // is related to #25860 -- there is no way for us
-                    // to express a fn type complete with the implied
-                    // bounds that it is assuming. I think in reality
-                    // the WF rules around fn are a bit messed up, and
-                    // that is the rot problem: `fn(&'a T)` should
-                    // probably always be WF, because it should be
-                    // shorthand for something like `where(T: 'a) {
-                    // fn(&'a T) }`, as discussed in #25860.
-                    walker.skip_current_subtree(); // subtree handled below
-                    // FIXME(eddyb) add the type to `walker` instead of recursing.
-                    self.compute(args.as_closure().tupled_upvars_ty().into());
-                    // Note that we cannot skip the generic types
-                    // types. Normally, within the fn
-                    // body where they are created, the generics will
-                    // always be WF, and outside of that fn body we
-                    // are not directly inspecting closure types
-                    // anyway, except via auto trait matching (which
-                    // only inspects the upvar types).
-                    // But when a closure is part of a type-alias-impl-trait
-                    // then the function that created the defining site may
-                    // have had more bounds available than the type alias
-                    // specifies. This may cause us to have a closure in the
-                    // hidden type that is not actually well formed and
-                    // can cause compiler crashes when the user abuses unsafe
-                    // code to procure such a closure.
-                    // See tests/ui/type-alias-impl-trait/wf_check_closures.rs
-                    let obligations = self.nominal_obligations(did, args);
-                    self.out.extend(obligations);
-                }
-
-                ty::CoroutineClosure(did, args) => {
-                    // See the above comments. The same apply to coroutine-closures.
-                    walker.skip_current_subtree();
-                    self.compute(args.as_coroutine_closure().tupled_upvars_ty().into());
-                    let obligations = self.nominal_obligations(did, args);
-                    self.out.extend(obligations);
-                }
-
-                ty::FnPtr(_) => {
-                    // let the loop iterate into the argument/return
-                    // types appearing in the fn signature
-                }
-
-                ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
-                    // All of the requirements on type parameters
-                    // have already been checked for `impl Trait` in
-                    // return position. We do need to check type-alias-impl-trait though.
-                    if self.tcx().is_type_alias_impl_trait(def_id) {
-                        let obligations = self.nominal_obligations(def_id, args);
-                        self.out.extend(obligations);
-                    }
-                }
-
-                ty::Alias(ty::Weak, ty::AliasTy { def_id, args, .. }) => {
-                    let obligations = self.nominal_obligations(def_id, args);
-                    self.out.extend(obligations);
-                }
-
-                ty::Dynamic(data, r, _) => {
-                    // WfObject
-                    //
-                    // Here, we defer WF checking due to higher-ranked
-                    // regions. This is perhaps not ideal.
-                    self.from_object_ty(ty, data, r);
-
-                    // FIXME(#27579) RFC also considers adding trait
-                    // obligations that don't refer to Self and
-                    // checking those
-
-                    let defer_to_coercion = self.tcx().features().object_safe_for_dispatch;
-
-                    if !defer_to_coercion {
-                        if let Some(principal) = data.principal_def_id() {
-                            self.out.push(traits::Obligation::with_depth(
-                                self.tcx(),
-                                self.cause(traits::WellFormed(None)),
-                                depth,
-                                param_env,
-                                ty::Binder::dummy(ty::PredicateKind::ObjectSafe(principal)),
-                            ));
-                        }
-                    }
-                }
-
-                // Inference variables are the complicated case, since we don't
-                // know what type they are. We do two things:
-                //
-                // 1. Check if they have been resolved, and if so proceed with
-                //    THAT type.
-                // 2. If not, we've at least simplified things (e.g., we went
-                //    from `Vec<$0>: WF` to `$0: WF`), so we can
-                //    register a pending obligation and keep
-                //    moving. (Goal is that an "inductive hypothesis"
-                //    is satisfied to ensure termination.)
-                // See also the comment on `fn obligations`, describing "livelock"
-                // prevention, which happens before this can be reached.
-                ty::Infer(_) => {
-                    let cause = self.cause(traits::WellFormed(None));
-                    self.out.push(traits::Obligation::with_depth(
-                        self.tcx(),
-                        cause,
-                        self.recursion_depth,
-                        param_env,
-                        ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
-                            ty.into(),
-                        ))),
-                    ));
-                }
-            }
-
-            debug!(?self.out);
-        }
+        arg.visit_with(self);
+        debug!(?self.out);
     }
 
     #[instrument(level = "debug", skip(self))]
@@ -908,6 +638,302 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
     }
 }
 
+impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
+    type Result = ();
+
+    fn visit_ty(&mut self, t: <TyCtxt<'tcx> as ty::Interner>::Ty) -> Self::Result {
+        debug!("wf bounds for t={:?} t.kind={:#?}", t, t.kind());
+
+        match *t.kind() {
+            ty::Bool
+            | ty::Char
+            | ty::Int(..)
+            | ty::Uint(..)
+            | ty::Float(..)
+            | ty::Error(_)
+            | ty::Str
+            | ty::CoroutineWitness(..)
+            | ty::Never
+            | ty::Param(_)
+            | ty::Bound(..)
+            | ty::Placeholder(..)
+            | ty::Foreign(..) => {
+                // WfScalar, WfParameter, etc
+            }
+
+            // Can only infer to `ty::Int(_) | ty::Uint(_)`.
+            ty::Infer(ty::IntVar(_)) => {}
+
+            // Can only infer to `ty::Float(_)`.
+            ty::Infer(ty::FloatVar(_)) => {}
+
+            ty::Slice(subty) => {
+                self.require_sized(subty, traits::SliceOrArrayElem);
+            }
+
+            ty::Array(subty, _) => {
+                self.require_sized(subty, traits::SliceOrArrayElem);
+                // Note that we handle the len is implicitly checked while walking `arg`.
+            }
+
+            ty::Tuple(tys) => {
+                if let Some((_last, rest)) = tys.split_last() {
+                    for &elem in rest {
+                        self.require_sized(elem, traits::TupleElem);
+                    }
+                }
+            }
+
+            ty::RawPtr(_) => {
+                // Simple cases that are WF if their type args are WF.
+            }
+
+            ty::Alias(ty::Projection, data) => {
+                self.compute_projection(data);
+                return; // Subtree handled by compute_projection.
+            }
+            ty::Alias(ty::Inherent, data) => {
+                self.compute_inherent_projection(data);
+                return; // Subtree handled by compute_inherent_projection.
+            }
+
+            ty::Adt(def, args) => {
+                // WfNominalType
+                let obligations = self.nominal_obligations(def.did(), args);
+                self.out.extend(obligations);
+            }
+
+            ty::FnDef(did, args) => {
+                let obligations = self.nominal_obligations(did, args);
+                self.out.extend(obligations);
+            }
+
+            ty::Ref(r, rty, _) => {
+                // WfReference
+                if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
+                    let cause = self.cause(traits::ReferenceOutlivesReferent(t));
+                    self.out.push(traits::Obligation::with_depth(
+                        self.tcx(),
+                        cause,
+                        self.recursion_depth,
+                        self.param_env,
+                        ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
+                            ty::OutlivesPredicate(rty, r),
+                        ))),
+                    ));
+                }
+            }
+
+            ty::Coroutine(did, args, ..) => {
+                // Walk ALL the types in the coroutine: this will
+                // include the upvar types as well as the yield
+                // type. Note that this is mildly distinct from
+                // the closure case, where we have to be careful
+                // about the signature of the closure. We don't
+                // have the problem of implied bounds here since
+                // coroutines don't take arguments.
+                let obligations = self.nominal_obligations(did, args);
+                self.out.extend(obligations);
+            }
+
+            ty::Closure(did, args) => {
+                // Note that we cannot skip the generic types
+                // types. Normally, within the fn
+                // body where they are created, the generics will
+                // always be WF, and outside of that fn body we
+                // are not directly inspecting closure types
+                // anyway, except via auto trait matching (which
+                // only inspects the upvar types).
+                // But when a closure is part of a type-alias-impl-trait
+                // then the function that created the defining site may
+                // have had more bounds available than the type alias
+                // specifies. This may cause us to have a closure in the
+                // hidden type that is not actually well formed and
+                // can cause compiler crashes when the user abuses unsafe
+                // code to procure such a closure.
+                // See tests/ui/type-alias-impl-trait/wf_check_closures.rs
+                let obligations = self.nominal_obligations(did, args);
+                self.out.extend(obligations);
+                // Only check the upvar types for WF, not the rest
+                // of the types within. This is needed because we
+                // capture the signature and it may not be WF
+                // without the implied bounds. Consider a closure
+                // like `|x: &'a T|` -- it may be that `T: 'a` is
+                // not known to hold in the creator's context (and
+                // indeed the closure may not be invoked by its
+                // creator, but rather turned to someone who *can*
+                // verify that).
+                //
+                // The special treatment of closures here really
+                // ought not to be necessary either; the problem
+                // is related to #25860 -- there is no way for us
+                // to express a fn type complete with the implied
+                // bounds that it is assuming. I think in reality
+                // the WF rules around fn are a bit messed up, and
+                // that is the rot problem: `fn(&'a T)` should
+                // probably always be WF, because it should be
+                // shorthand for something like `where(T: 'a) {
+                // fn(&'a T) }`, as discussed in #25860.
+                let upvars = args.as_closure().tupled_upvars_ty();
+                return upvars.visit_with(self);
+            }
+
+            ty::CoroutineClosure(did, args) => {
+                // See the above comments. The same apply to coroutine-closures.
+                let obligations = self.nominal_obligations(did, args);
+                self.out.extend(obligations);
+                let upvars = args.as_coroutine_closure().tupled_upvars_ty();
+                return upvars.visit_with(self);
+            }
+
+            ty::FnPtr(_) => {
+                // Let the visitor iterate into the argument/return
+                // types appearing in the fn signature.
+            }
+
+            ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
+                // All of the requirements on type parameters
+                // have already been checked for `impl Trait` in
+                // return position. We do need to check type-alias-impl-trait though.
+                if self.tcx().is_type_alias_impl_trait(def_id) {
+                    let obligations = self.nominal_obligations(def_id, args);
+                    self.out.extend(obligations);
+                }
+            }
+
+            ty::Alias(ty::Weak, ty::AliasTy { def_id, args, .. }) => {
+                let obligations = self.nominal_obligations(def_id, args);
+                self.out.extend(obligations);
+            }
+
+            ty::Dynamic(data, r, _) => {
+                // WfObject
+                //
+                // Here, we defer WF checking due to higher-ranked
+                // regions. This is perhaps not ideal.
+                self.from_object_ty(t, data, r);
+
+                // FIXME(#27579) RFC also considers adding trait
+                // obligations that don't refer to Self and
+                // checking those
+
+                let defer_to_coercion = self.tcx().features().object_safe_for_dispatch;
+
+                if !defer_to_coercion {
+                    if let Some(principal) = data.principal_def_id() {
+                        self.out.push(traits::Obligation::with_depth(
+                            self.tcx(),
+                            self.cause(traits::WellFormed(None)),
+                            self.recursion_depth,
+                            self.param_env,
+                            ty::Binder::dummy(ty::PredicateKind::ObjectSafe(principal)),
+                        ));
+                    }
+                }
+            }
+
+            // Inference variables are the complicated case, since we don't
+            // know what type they are. We do two things:
+            //
+            // 1. Check if they have been resolved, and if so proceed with
+            //    THAT type.
+            // 2. If not, we've at least simplified things (e.g., we went
+            //    from `Vec<$0>: WF` to `$0: WF`), so we can
+            //    register a pending obligation and keep
+            //    moving. (Goal is that an "inductive hypothesis"
+            //    is satisfied to ensure termination.)
+            // See also the comment on `fn obligations`, describing "livelock"
+            // prevention, which happens before this can be reached.
+            ty::Infer(_) => {
+                let cause = self.cause(traits::WellFormed(None));
+                self.out.push(traits::Obligation::with_depth(
+                    self.tcx(),
+                    cause,
+                    self.recursion_depth,
+                    self.param_env,
+                    ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
+                        t.into(),
+                    ))),
+                ));
+            }
+        }
+
+        t.super_visit_with(self)
+    }
+
+    fn visit_const(&mut self, c: <TyCtxt<'tcx> as ty::Interner>::Const) -> Self::Result {
+        match c.kind() {
+            ty::ConstKind::Unevaluated(uv) => {
+                if !c.has_escaping_bound_vars() {
+                    let obligations = self.nominal_obligations(uv.def, uv.args);
+                    self.out.extend(obligations);
+
+                    let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
+                        ty::ClauseKind::ConstEvaluatable(c),
+                    ));
+                    let cause = self.cause(traits::WellFormed(None));
+                    self.out.push(traits::Obligation::with_depth(
+                        self.tcx(),
+                        cause,
+                        self.recursion_depth,
+                        self.param_env,
+                        predicate,
+                    ));
+                }
+            }
+            ty::ConstKind::Infer(_) => {
+                let cause = self.cause(traits::WellFormed(None));
+
+                self.out.push(traits::Obligation::with_depth(
+                    self.tcx(),
+                    cause,
+                    self.recursion_depth,
+                    self.param_env,
+                    ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
+                        c.into(),
+                    ))),
+                ));
+            }
+            ty::ConstKind::Expr(_) => {
+                // FIXME(generic_const_exprs): this doesn't verify that given `Expr(N + 1)` the
+                // trait bound `typeof(N): Add<typeof(1)>` holds. This is currently unnecessary
+                // as `ConstKind::Expr` is only produced via normalization of `ConstKind::Unevaluated`
+                // which means that the `DefId` would have been typeck'd elsewhere. However in
+                // the future we may allow directly lowering to `ConstKind::Expr` in which case
+                // we would not be proving bounds we should.
+
+                let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
+                    ty::ClauseKind::ConstEvaluatable(c),
+                ));
+                let cause = self.cause(traits::WellFormed(None));
+                self.out.push(traits::Obligation::with_depth(
+                    self.tcx(),
+                    cause,
+                    self.recursion_depth,
+                    self.param_env,
+                    predicate,
+                ));
+            }
+
+            ty::ConstKind::Error(_)
+            | ty::ConstKind::Param(_)
+            | ty::ConstKind::Bound(..)
+            | ty::ConstKind::Placeholder(..) => {
+                // These variants are trivially WF, so nothing to do here.
+            }
+            ty::ConstKind::Value(..) => {
+                // FIXME: Enforce that values are structurally-matchable.
+            }
+        }
+
+        c.super_visit_with(self)
+    }
+
+    fn visit_predicate(&mut self, _p: <TyCtxt<'tcx> as ty::Interner>::Predicate) -> Self::Result {
+        bug!("predicate should not be checked for well-formedness");
+    }
+}
+
 /// Given an object type like `SomeTrait + Send`, computes the lifetime
 /// bounds that must hold on the elided self type. These are derived
 /// from the declarations of `SomeTrait`, `Send`, and friends -- if
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index f3fae63ecc7..b2b5c6cd909 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -6,7 +6,7 @@
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{FulfillmentErrorCode, TraitEngineExt as _};
 use rustc_middle::traits::CodegenObligationError;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::{
     ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, TraitEngineExt,
@@ -72,6 +72,13 @@ pub fn codegen_select_candidate<'tcx>(
 
     let impl_source = infcx.resolve_vars_if_possible(impl_source);
     let impl_source = infcx.tcx.erase_regions(impl_source);
+    if impl_source.has_infer() {
+        // Unused lifetimes on an impl get replaced with inference vars, but never resolved,
+        // causing the return value of a query to contain inference vars. We do not have a concept
+        // for this and will in fact ICE in stable hashing of the return value. So bail out instead.
+        infcx.tcx.dcx().has_errors().unwrap();
+        return Err(CodegenObligationError::FulfillmentError);
+    }
 
     Ok(&*tcx.arena.alloc(impl_source))
 }
diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml
index 066016231fa..3d0ad31747f 100644
--- a/compiler/rustc_transmute/Cargo.toml
+++ b/compiler/rustc_transmute/Cargo.toml
@@ -5,13 +5,14 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
-rustc_data_structures = { path = "../rustc_data_structures"}
-rustc_hir = { path = "../rustc_hir", optional = true}
-rustc_infer = { path = "../rustc_infer", optional = true}
-rustc_macros = { path = "../rustc_macros", optional = true}
-rustc_middle = { path = "../rustc_middle", optional = true}
-rustc_span = { path = "../rustc_span", optional = true}
-rustc_target = { path = "../rustc_target", optional = true}
+rustc_ast_ir = { path = "../rustc_ast_ir", optional = true }
+rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_hir = { path = "../rustc_hir", optional = true }
+rustc_infer = { path = "../rustc_infer", optional = true }
+rustc_macros = { path = "../rustc_macros", optional = true }
+rustc_middle = { path = "../rustc_middle", optional = true }
+rustc_span = { path = "../rustc_span", optional = true }
+rustc_target = { path = "../rustc_target", optional = true }
 tracing = "0.1"
 # tidy-alphabetical-end
 
@@ -23,6 +24,7 @@ rustc = [
     "rustc_middle",
     "rustc_span",
     "rustc_target",
+    "rustc_ast_ir",
 ]
 
 [dev-dependencies]
diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml
index f8eb82da8f6..2a30bd5d539 100644
--- a/compiler/rustc_ty_utils/Cargo.toml
+++ b/compiler/rustc_ty_utils/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 itertools = "0.11"
+rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 43042dbd366..a5328baadb5 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -452,7 +452,7 @@ fn adjust_for_rust_scalar<'tcx>(
             let no_alias = match kind {
                 PointerKind::SharedRef { frozen } => frozen,
                 PointerKind::MutableRef { unpin } => unpin && noalias_mut_ref,
-                PointerKind::Box { unpin } => unpin && noalias_for_box,
+                PointerKind::Box { unpin, global } => unpin && global && noalias_for_box,
             };
             // We can never add `noalias` in return position; that LLVM attribute has some very surprising semantics
             // (see <https://github.com/rust-lang/unsafe-code-guidelines/issues/385#issuecomment-1368055745>).
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index db37bec4b82..26d3370469a 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -4,7 +4,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, GenericArgs, ImplTraitInTraitData, Ty, TyCtxt};
+use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt};
 use rustc_span::symbol::kw;
 
 pub(crate) fn provide(providers: &mut Providers) {
@@ -284,48 +284,8 @@ fn associated_type_for_impl_trait_in_trait(
     // Copy defaultness of the containing function.
     trait_assoc_ty.defaultness(tcx.defaultness(fn_def_id));
 
-    // Copy type_of of the opaque.
-    trait_assoc_ty.type_of(ty::EarlyBinder::bind(Ty::new_opaque(
-        tcx,
-        opaque_ty_def_id.to_def_id(),
-        GenericArgs::identity_for_item(tcx, opaque_ty_def_id),
-    )));
-
     trait_assoc_ty.is_type_alias_impl_trait(false);
 
-    // Copy generics_of of the opaque type item but the trait is the parent.
-    trait_assoc_ty.generics_of({
-        let opaque_ty_generics = tcx.generics_of(opaque_ty_def_id);
-        let opaque_ty_parent_count = opaque_ty_generics.parent_count;
-        let mut params = opaque_ty_generics.params.clone();
-
-        let parent_generics = tcx.generics_of(trait_def_id);
-        let parent_count = parent_generics.parent_count + parent_generics.params.len();
-
-        let mut trait_fn_params = tcx.generics_of(fn_def_id).params.clone();
-
-        for param in &mut params {
-            param.index = param.index + parent_count as u32 + trait_fn_params.len() as u32
-                - opaque_ty_parent_count as u32;
-        }
-
-        trait_fn_params.extend(params);
-        params = trait_fn_params;
-
-        let param_def_id_to_index =
-            params.iter().map(|param| (param.def_id, param.index)).collect();
-
-        ty::Generics {
-            parent: Some(trait_def_id.to_def_id()),
-            parent_count,
-            params,
-            param_def_id_to_index,
-            has_self: opaque_ty_generics.has_self,
-            has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
-            host_effect_index: parent_generics.host_effect_index,
-        }
-    });
-
     // There are no inferred outlives for the synthesized associated type.
     trait_assoc_ty.inferred_outlives_of(&[]);
 
@@ -382,8 +342,9 @@ fn associated_type_for_impl_trait_in_impl(
     impl_assoc_ty.defaultness(tcx.defaultness(impl_fn_def_id));
 
     // Copy generics_of the trait's associated item but the impl as the parent.
-    // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) resolves to the trait instead of the impl
-    // generics.
+    // FIXME: This may be detrimental to diagnostics, as we resolve the early-bound vars
+    // here to paramswhose parent are items in the trait. We could synthesize new params
+    // here, but it seems overkill.
     impl_assoc_ty.generics_of({
         let trait_assoc_generics = tcx.generics_of(trait_assoc_def_id);
         let trait_assoc_parent_count = trait_assoc_generics.parent_count;
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 3f9bd509b08..87462963c27 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -71,7 +71,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
                     // the end of the list corresponding to the opaque's generics.
                     for param in &generics.params[tcx.generics_of(fn_def_id).params.len()..] {
                         let orig_lt =
-                            tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local());
+                            tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local());
                         if matches!(*orig_lt, ty::ReLateParam(..)) {
                             mapping.insert(
                                 orig_lt,
@@ -121,18 +121,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
             }
         }
         DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)),
-        DefKind::OpaqueTy => match tcx.def_kind(tcx.local_parent(def_id)) {
-            DefKind::TyAlias => ty::List::empty(),
-            DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)),
-            // Nested opaque types only occur in associated types:
-            // ` type Opaque<T> = impl Trait<&'static T, AssocTy = impl Nested>; `
-            // assumed_wf_types should include those of `Opaque<T>`, `Opaque<T>` itself
-            // and `&'static T`.
-            DefKind::OpaqueTy => bug!("unimplemented implied bounds for nested opaque types"),
-            def_kind => {
-                bug!("unimplemented implied bounds for opaque types with parent {def_kind:?}")
-            }
-        },
+        DefKind::OpaqueTy => bug!("implied bounds are not defined for opaques"),
         DefKind::Mod
         | DefKind::Struct
         | DefKind::Union
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 3e3bccce47f..381681fb1f4 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -1,5 +1,4 @@
 use rustc_errors::ErrorGuaranteed;
-use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::query::Providers;
@@ -28,8 +27,7 @@ fn resolve_instance<'tcx>(
             tcx.normalize_erasing_regions(param_env, args),
         )
     } else {
-        let def = if matches!(tcx.def_kind(def_id), DefKind::Fn) && tcx.intrinsic(def_id).is_some()
-        {
+        let def = if tcx.intrinsic(def_id).is_some() {
             debug!(" => intrinsic");
             ty::InstanceDef::Intrinsic(def_id)
         } else if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 86c7551882a..3dcc8382289 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -8,7 +8,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use rustc_span::Span;
 use rustc_trait_selection::traits::check_args_compatible;
-use std::ops::ControlFlow;
 
 use crate::errors::{DuplicateArg, NotParam};
 
@@ -22,11 +21,24 @@ struct OpaqueTypeCollector<'tcx> {
     seen: FxHashSet<LocalDefId>,
 
     span: Option<Span>,
+
+    mode: CollectionMode,
+}
+
+enum CollectionMode {
+    /// For impl trait in assoc types we only permit collecting them from
+    /// associated types of the same impl block.
+    ImplTraitInAssocTypes,
+    TypeAliasImplTraitTransition,
 }
 
 impl<'tcx> OpaqueTypeCollector<'tcx> {
     fn new(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self {
-        Self { tcx, opaques: Vec::new(), item, seen: Default::default(), span: None }
+        let mode = match tcx.def_kind(tcx.local_parent(item)) {
+            DefKind::Impl { of_trait: true } => CollectionMode::ImplTraitInAssocTypes,
+            _ => CollectionMode::TypeAliasImplTraitTransition,
+        };
+        Self { tcx, opaques: Vec::new(), item, seen: Default::default(), span: None, mode }
     }
 
     fn span(&self) -> Span {
@@ -129,7 +141,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
         trace!(?origin);
         match origin {
             rustc_hir::OpaqueTyOrigin::FnReturn(_) | rustc_hir::OpaqueTyOrigin::AsyncFn(_) => {}
-            rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => {
+            rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => {
                 if !in_assoc_ty {
                     if !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) {
                         return;
@@ -185,16 +197,15 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
 
 impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for OpaqueTypeCollector<'tcx> {
     #[instrument(skip(self), ret, level = "trace")]
-    fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> ControlFlow<!> {
+    fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) {
         self.visit_spanned(span, value);
-        ControlFlow::Continue(())
     }
 }
 
 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
     #[instrument(skip(self), ret, level = "trace")]
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
-        t.super_visit_with(self)?;
+    fn visit_ty(&mut self, t: Ty<'tcx>) {
+        t.super_visit_with(self);
         match t.kind() {
             ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
                 self.visit_opaque_ty(alias_ty);
@@ -203,7 +214,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
                 self.tcx
                     .type_of(alias_ty.def_id)
                     .instantiate(self.tcx, alias_ty.args)
-                    .visit_with(self)?;
+                    .visit_with(self);
             }
             ty::Alias(ty::Projection, alias_ty) => {
                 // This avoids having to do normalization of `Self::AssocTy` by only
@@ -235,11 +246,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
                             );
 
                             if check_args_compatible(self.tcx, assoc, impl_args) {
-                                return self
-                                    .tcx
+                                self.tcx
                                     .type_of(assoc.def_id)
                                     .instantiate(self.tcx, impl_args)
                                     .visit_with(self);
+                                return;
                             } else {
                                 self.tcx.dcx().span_delayed_bug(
                                     self.tcx.def_span(assoc.def_id),
@@ -251,8 +262,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
                 }
             }
             ty::Adt(def, _) if def.did().is_local() => {
+                if let CollectionMode::ImplTraitInAssocTypes = self.mode {
+                    return;
+                }
                 if !self.seen.insert(def.did().expect_local()) {
-                    return ControlFlow::Continue(());
+                    return;
                 }
                 for variant in def.variants().iter() {
                     for field in variant.fields.iter() {
@@ -271,95 +285,9 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
             }
             _ => trace!(kind=?t.kind()),
         }
-        ControlFlow::Continue(())
     }
 }
 
-struct ImplTraitInAssocTypeCollector<'tcx>(OpaqueTypeCollector<'tcx>);
-
-impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for ImplTraitInAssocTypeCollector<'tcx> {
-    #[instrument(skip(self), ret, level = "trace")]
-    fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> ControlFlow<!> {
-        let old = self.0.span;
-        self.0.span = Some(span);
-        value.visit_with(self);
-        self.0.span = old;
-
-        ControlFlow::Continue(())
-    }
-}
-
-impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInAssocTypeCollector<'tcx> {
-    #[instrument(skip(self), ret, level = "trace")]
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
-        t.super_visit_with(self)?;
-        match t.kind() {
-            ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
-                self.0.visit_opaque_ty(alias_ty);
-            }
-            ty::Alias(ty::Projection, alias_ty) => {
-                // This avoids having to do normalization of `Self::AssocTy` by only
-                // supporting the case of a method defining opaque types from assoc types
-                // in the same impl block.
-                let parent_trait_ref = self
-                    .0
-                    .parent_trait_ref()
-                    .expect("impl trait in assoc type collector used on non-assoc item");
-                // If the trait ref of the associated item and the impl differs,
-                // then we can't use the impl's identity args below, so
-                // just skip.
-                if alias_ty.trait_ref(self.0.tcx) == parent_trait_ref {
-                    let parent = self.0.parent().expect("we should have a parent here");
-
-                    for &assoc in self.0.tcx.associated_items(parent).in_definition_order() {
-                        trace!(?assoc);
-                        if assoc.trait_item_def_id != Some(alias_ty.def_id) {
-                            continue;
-                        }
-
-                        // If the type is further specializable, then the type_of
-                        // is not actually correct below.
-                        if !assoc.defaultness(self.0.tcx).is_final() {
-                            continue;
-                        }
-
-                        let impl_args = alias_ty.args.rebase_onto(
-                            self.0.tcx,
-                            parent_trait_ref.def_id,
-                            ty::GenericArgs::identity_for_item(self.0.tcx, parent),
-                        );
-
-                        if check_args_compatible(self.0.tcx, assoc, impl_args) {
-                            return self
-                                .0
-                                .tcx
-                                .type_of(assoc.def_id)
-                                .instantiate(self.0.tcx, impl_args)
-                                .visit_with(self);
-                        } else {
-                            self.0.tcx.dcx().span_bug(
-                                self.0.tcx.def_span(assoc.def_id),
-                                "item had incorrect args",
-                            );
-                        }
-                    }
-                }
-            }
-            _ => trace!(kind=?t.kind()),
-        }
-        ControlFlow::Continue(())
-    }
-}
-
-fn impl_trait_in_assoc_types_defined_by<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    item: LocalDefId,
-) -> &'tcx ty::List<LocalDefId> {
-    let mut collector = ImplTraitInAssocTypeCollector(OpaqueTypeCollector::new(tcx, item));
-    super::sig_types::walk_types(tcx, item, &mut collector);
-    tcx.mk_local_def_ids(&collector.0.opaques)
-}
-
 fn opaque_types_defined_by<'tcx>(
     tcx: TyCtxt<'tcx>,
     item: LocalDefId,
@@ -409,6 +337,5 @@ fn opaque_types_defined_by<'tcx>(
 }
 
 pub(super) fn provide(providers: &mut Providers) {
-    *providers =
-        Providers { opaque_types_defined_by, impl_trait_in_assoc_types_defined_by, ..*providers };
+    *providers = Providers { opaque_types_defined_by, ..*providers };
 }
diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs
index 38cc558380c..5527d853e30 100644
--- a/compiler/rustc_ty_utils/src/sig_types.rs
+++ b/compiler/rustc_ty_utils/src/sig_types.rs
@@ -1,27 +1,23 @@
 //! This module contains helpers for walking all types of
 //! a signature, while preserving spans as much as possible
 
-use std::ops::ControlFlow;
-
+use rustc_ast_ir::try_visit;
+use rustc_ast_ir::visit::VisitorResult;
 use rustc_hir::{def::DefKind, def_id::LocalDefId};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::Span;
 use rustc_type_ir::visit::TypeVisitable;
 
 pub trait SpannedTypeVisitor<'tcx> {
-    type BreakTy = !;
-    fn visit(
-        &mut self,
-        span: Span,
-        value: impl TypeVisitable<TyCtxt<'tcx>>,
-    ) -> ControlFlow<Self::BreakTy>;
+    type Result: VisitorResult = ();
+    fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> Self::Result;
 }
 
 pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
     tcx: TyCtxt<'tcx>,
     item: LocalDefId,
     visitor: &mut V,
-) -> ControlFlow<V::BreakTy> {
+) -> V::Result {
     let kind = tcx.def_kind(item);
     trace!(?kind);
     match kind {
@@ -30,12 +26,12 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
             let ty_sig = tcx.fn_sig(item).instantiate_identity();
             let hir_sig = tcx.hir_node_by_def_id(item).fn_decl().unwrap();
             // Walk over the inputs and outputs manually in order to get good spans for them.
-            visitor.visit(hir_sig.output.span(), ty_sig.output());
+            try_visit!(visitor.visit(hir_sig.output.span(), ty_sig.output()));
             for (hir, ty) in hir_sig.inputs.iter().zip(ty_sig.inputs().iter()) {
-                visitor.visit(hir.span, ty.map_bound(|x| *x))?;
+                try_visit!(visitor.visit(hir.span, ty.map_bound(|x| *x)));
             }
             for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
-                visitor.visit(span, pred)?;
+                try_visit!(visitor.visit(span, pred));
             }
         }
         // Walk over the type behind the alias
@@ -44,32 +40,32 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
         DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
             if let Some(ty) = tcx.hir_node_by_def_id(item).ty() {
                 // Associated types in traits don't necessarily have a type that we can visit
-                visitor.visit(ty.span, tcx.type_of(item).instantiate_identity())?;
+                try_visit!(visitor.visit(ty.span, tcx.type_of(item).instantiate_identity()));
             }
             for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
-                visitor.visit(span, pred)?;
+                try_visit!(visitor.visit(span, pred));
             }
         }
         DefKind::OpaqueTy => {
             for (pred, span) in tcx.explicit_item_bounds(item).instantiate_identity_iter_copied() {
-                visitor.visit(span, pred)?;
+                try_visit!(visitor.visit(span, pred));
             }
         }
         // Look at field types
         DefKind::Struct | DefKind::Union | DefKind::Enum => {
             let span = tcx.def_ident_span(item).unwrap();
             let ty = tcx.type_of(item).instantiate_identity();
-            visitor.visit(span, ty);
+            try_visit!(visitor.visit(span, ty));
             let ty::Adt(def, args) = ty.kind() else {
                 span_bug!(span, "invalid type for {kind:?}: {:#?}", ty.kind())
             };
             for field in def.all_fields() {
                 let span = tcx.def_ident_span(field.did).unwrap();
                 let ty = field.ty(tcx, args);
-                visitor.visit(span, ty);
+                try_visit!(visitor.visit(span, ty));
             }
             for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
-                visitor.visit(span, pred)?;
+                try_visit!(visitor.visit(span, pred));
             }
         }
         // These are not part of a public API, they can only appear as hidden types, and there
@@ -80,20 +76,20 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
             if of_trait {
                 let span = tcx.hir_node_by_def_id(item).expect_item().expect_impl().of_trait.unwrap().path.span;
                 let args = &tcx.impl_trait_ref(item).unwrap().instantiate_identity().args[1..];
-                visitor.visit(span, args)?;
+                try_visit!(visitor.visit(span, args));
             }
             let span = match tcx.hir_node_by_def_id(item).ty() {
                 Some(ty) => ty.span,
                 _ => tcx.def_span(item),
             };
-            visitor.visit(span, tcx.type_of(item).instantiate_identity());
+            try_visit!(visitor.visit(span, tcx.type_of(item).instantiate_identity()));
             for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
-                visitor.visit(span, pred)?;
+                try_visit!(visitor.visit(span, pred));
             }
         }
         DefKind::TraitAlias | DefKind::Trait => {
             for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
-                visitor.visit(span, pred)?;
+                try_visit!(visitor.visit(span, pred));
             }
         }
         | DefKind::Variant
@@ -116,5 +112,5 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
         | DefKind::Mod
         | DefKind::Use => {}
     }
-    ControlFlow::Continue(())
+    V::Result::output()
 }
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index b725eda33ce..2b6b91672c3 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -174,17 +174,13 @@ struct ImplTraitInTraitFinder<'a, 'tcx> {
 }
 
 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
-    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
-        &mut self,
-        binder: &ty::Binder<'tcx, T>,
-    ) -> std::ops::ControlFlow<Self::BreakTy> {
+    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, binder: &ty::Binder<'tcx, T>) {
         self.depth.shift_in(1);
-        let binder = binder.super_visit_with(self);
+        binder.super_visit_with(self);
         self.depth.shift_out(1);
-        binder
     }
 
-    fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, ty: Ty<'tcx>) {
         if let ty::Alias(ty::Projection, unshifted_alias_ty) = *ty.kind()
             && let Some(
                 ty::ImplTraitInTraitData::Trait { fn_def_id, .. }
@@ -259,10 +255,9 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<'
 
     let impl_ = tcx
         .impl_trait_header(def_id)
-        .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id))
-        .skip_binder();
+        .unwrap_or_else(|| bug!("issue33140_self_ty called on inherent impl {:?}", def_id));
 
-    let trait_ref = impl_.trait_ref;
+    let trait_ref = impl_.trait_ref.skip_binder();
     debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref);
 
     let is_marker_like = impl_.polarity == ty::ImplPolarity::Positive
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index 5bc2bfe2893..ad18ef24984 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -1,6 +1,7 @@
+use rustc_ast_ir::try_visit;
+use rustc_ast_ir::visit::VisitorResult;
 use std::fmt;
 use std::hash::Hash;
-use std::ops::ControlFlow;
 
 use crate::fold::{FallibleTypeFolder, TypeFoldable};
 use crate::visit::{TypeVisitable, TypeVisitor};
@@ -107,9 +108,9 @@ impl<I: Interner, V: TypeVisitable<I>> TypeVisitable<I> for Canonical<I, V>
 where
     I::CanonicalVars: TypeVisitable<I>,
 {
-    fn visit_with<F: TypeVisitor<I>>(&self, folder: &mut F) -> ControlFlow<F::BreakTy> {
-        self.value.visit_with(folder)?;
-        self.max_universe.visit_with(folder)?;
+    fn visit_with<F: TypeVisitor<I>>(&self, folder: &mut F) -> F::Result {
+        try_visit!(self.value.visit_with(folder));
+        try_visit!(self.max_universe.visit_with(folder));
         self.variables.visit_with(folder)
     }
 }
@@ -137,7 +138,7 @@ impl<I: Interner> TypeVisitable<I> for CanonicalVarInfo<I>
 where
     I::Ty: TypeVisitable<I>,
 {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
         self.kind.visit_with(visitor)
     }
 }
@@ -251,13 +252,13 @@ impl<I: Interner> TypeVisitable<I> for CanonicalVarKind<I>
 where
     I::Ty: TypeVisitable<I>,
 {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
         match self {
             CanonicalVarKind::Ty(_)
             | CanonicalVarKind::PlaceholderTy(_)
             | CanonicalVarKind::Region(_)
             | CanonicalVarKind::PlaceholderRegion(_)
-            | CanonicalVarKind::Effect => ControlFlow::Continue(()),
+            | CanonicalVarKind::Effect => V::Result::output(),
             CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => {
                 ty.visit_with(visitor)
             }
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 7d2c42a6dbe..373540de05e 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -4,8 +4,8 @@ use std::hash::Hash;
 
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
 use crate::{
-    BoundVar, BoundVars, CanonicalVarInfo, ConstKind, DebruijnIndex, DebugWithInfcx, RegionKind,
-    TyKind, UniverseIndex,
+    new, BoundVar, BoundVars, CanonicalVarInfo, ConstKind, DebugWithInfcx, RegionKind, TyKind,
+    UniverseIndex,
 };
 
 pub trait Interner: Sized {
@@ -34,7 +34,8 @@ pub trait Interner: Sized {
         + Into<Self::GenericArg>
         + IntoKind<Kind = TyKind<Self>>
         + TypeSuperVisitable<Self>
-        + Flags;
+        + Flags
+        + new::Ty<Self>;
     type Tys: Copy + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>;
     type AliasTy: Copy + DebugWithInfcx<Self> + Hash + Ord;
     type ParamTy: Copy + Debug + Hash + Ord;
@@ -56,7 +57,8 @@ pub trait Interner: Sized {
         + IntoKind<Kind = ConstKind<Self>>
         + ConstTy<Self>
         + TypeSuperVisitable<Self>
-        + Flags;
+        + Flags
+        + new::Const<Self>;
     type AliasConst: Copy + DebugWithInfcx<Self> + Hash + Ord;
     type PlaceholderConst: Copy + Debug + Hash + Ord + PlaceholderLike;
     type ParamConst: Copy + Debug + Hash + Ord;
@@ -71,7 +73,8 @@ pub trait Interner: Sized {
         + Ord
         + Into<Self::GenericArg>
         + IntoKind<Kind = RegionKind<Self>>
-        + Flags;
+        + Flags
+        + new::Region<Self>;
     type EarlyParamRegion: Copy + Debug + Hash + Ord;
     type LateParamRegion: Copy + Debug + Hash + Ord;
     type BoundRegion: Copy + Debug + Hash + Ord;
@@ -90,11 +93,6 @@ pub trait Interner: Sized {
     type ClosureKind: Copy + Debug + Hash + Eq;
 
     fn mk_canonical_var_infos(self, infos: &[CanonicalVarInfo<Self>]) -> Self::CanonicalVars;
-
-    // FIXME: We should not have all these constructors on `Interner`, but as functions on some trait.
-    fn mk_bound_ty(self, debruijn: DebruijnIndex, var: BoundVar) -> Self::Ty;
-    fn mk_bound_region(self, debruijn: DebruijnIndex, var: BoundVar) -> Self::Region;
-    fn mk_bound_const(self, debruijn: DebruijnIndex, var: BoundVar, ty: Self::Ty) -> Self::Const;
 }
 
 /// Common capabilities of placeholder kinds
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 94ccbcbd8a5..2ded1b956e5 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -21,12 +21,15 @@ use std::hash::Hash;
 #[cfg(not(feature = "nightly"))]
 use std::sync::Arc as Lrc;
 
+#[macro_use]
+pub mod visit;
+
 #[cfg(feature = "nightly")]
 pub mod codec;
 pub mod fold;
+pub mod new;
 pub mod ty_info;
 pub mod ty_kind;
-pub mod visit;
 
 #[macro_use]
 mod macros;
diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs
index 231546287d0..7dcc8851a43 100644
--- a/compiler/rustc_type_ir/src/macros.rs
+++ b/compiler/rustc_type_ir/src/macros.rs
@@ -25,9 +25,9 @@ macro_rules! TrivialTypeTraversalImpls {
                 fn visit_with<F: $crate::visit::TypeVisitor<I>>(
                     &self,
                     _: &mut F)
-                    -> ::std::ops::ControlFlow<F::BreakTy>
+                    -> F::Result
                 {
-                    ::std::ops::ControlFlow::Continue(())
+                    <F::Result as rustc_ast_ir::visit::VisitorResult>::output()
                 }
             }
         )+
diff --git a/compiler/rustc_type_ir/src/new.rs b/compiler/rustc_type_ir/src/new.rs
new file mode 100644
index 00000000000..e7e695e5908
--- /dev/null
+++ b/compiler/rustc_type_ir/src/new.rs
@@ -0,0 +1,13 @@
+use crate::{BoundVar, DebruijnIndex, Interner};
+
+pub trait Ty<I: Interner<Ty = Self>> {
+    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
+}
+
+pub trait Region<I: Interner<Region = Self>> {
+    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
+}
+
+pub trait Const<I: Interner<Const = Self>> {
+    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar, ty: I::Ty) -> Self;
+}
diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs
index 8c4d0fda6af..a0759f7df7f 100644
--- a/compiler/rustc_type_ir/src/predicate_kind.rs
+++ b/compiler/rustc_type_ir/src/predicate_kind.rs
@@ -1,5 +1,6 @@
+use rustc_ast_ir::try_visit;
+use rustc_ast_ir::visit::VisitorResult;
 use std::fmt;
-use std::ops::ControlFlow;
 
 use crate::fold::{FallibleTypeFolder, TypeFoldable};
 use crate::visit::{TypeVisitable, TypeVisitor};
@@ -91,14 +92,14 @@ where
     I::TypeOutlivesPredicate: TypeVisitable<I>,
     I::RegionOutlivesPredicate: TypeVisitable<I>,
 {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
         match self {
             ClauseKind::Trait(p) => p.visit_with(visitor),
             ClauseKind::RegionOutlives(p) => p.visit_with(visitor),
             ClauseKind::TypeOutlives(p) => p.visit_with(visitor),
             ClauseKind::Projection(p) => p.visit_with(visitor),
             ClauseKind::ConstArgHasType(c, t) => {
-                c.visit_with(visitor)?;
+                try_visit!(c.visit_with(visitor));
                 t.visit_with(visitor)
             }
             ClauseKind::WellFormed(p) => p.visit_with(visitor),
@@ -205,21 +206,21 @@ where
     I::NormalizesTo: TypeVisitable<I>,
     ClauseKind<I>: TypeVisitable<I>,
 {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
         match self {
             PredicateKind::Clause(p) => p.visit_with(visitor),
             PredicateKind::ObjectSafe(d) => d.visit_with(visitor),
             PredicateKind::Subtype(s) => s.visit_with(visitor),
             PredicateKind::Coerce(s) => s.visit_with(visitor),
             PredicateKind::ConstEquate(a, b) => {
-                a.visit_with(visitor)?;
+                try_visit!(a.visit_with(visitor));
                 b.visit_with(visitor)
             }
-            PredicateKind::Ambiguous => ControlFlow::Continue(()),
+            PredicateKind::Ambiguous => V::Result::output(),
             PredicateKind::NormalizesTo(p) => p.visit_with(visitor),
             PredicateKind::AliasRelate(a, b, d) => {
-                a.visit_with(visitor)?;
-                b.visit_with(visitor)?;
+                try_visit!(a.visit_with(visitor));
+                try_visit!(b.visit_with(visitor));
                 d.visit_with(visitor)
             }
         }
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 00f49a07f9d..de8f56618d0 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -1,3 +1,4 @@
+use rustc_ast_ir::try_visit;
 #[cfg(feature = "nightly")]
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 #[cfg(feature = "nightly")]
@@ -831,8 +832,8 @@ impl<I: Interner> TypeVisitable<I> for TypeAndMut<I>
 where
     I::Ty: TypeVisitable<I>,
 {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> std::ops::ControlFlow<V::BreakTy> {
-        self.ty.visit_with(visitor)?;
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
+        try_visit!(self.ty.visit_with(visitor));
         self.mutbl.visit_with(visitor)
     }
 }
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index 638fb9f7fa9..839e75dba4c 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -41,6 +41,8 @@
 //! - u.visit_with(visitor)
 //! ```
 
+use rustc_ast_ir::visit::VisitorResult;
+use rustc_ast_ir::{try_visit, walk_visitable_list};
 use rustc_index::{Idx, IndexVec};
 use std::fmt;
 use std::ops::ControlFlow;
@@ -63,7 +65,7 @@ pub trait TypeVisitable<I: Interner>: fmt::Debug + Clone {
     /// that calls a visitor method specifically for that type (such as
     /// `V::visit_ty`). This is where control transfers from `TypeVisitable` to
     /// `TypeVisitor`.
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result;
 }
 
 // This trait is implemented for types of interest.
@@ -74,7 +76,7 @@ pub trait TypeSuperVisitable<I: Interner>: TypeVisitable<I> {
     /// that method. For example, in `MyVisitor::visit_ty(ty)`, it is valid to
     /// call `ty.super_visit_with(self)`, but any other visiting should be done
     /// with `xyz.visit_with(self)`.
-    fn super_visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
+    fn super_visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result;
 }
 
 /// This trait is implemented for every visiting traversal. There is a visit
@@ -82,33 +84,30 @@ pub trait TypeSuperVisitable<I: Interner>: TypeVisitable<I> {
 /// that recurses into the type's fields in a non-custom fashion.
 pub trait TypeVisitor<I: Interner>: Sized {
     #[cfg(feature = "nightly")]
-    type BreakTy = !;
+    type Result: VisitorResult = ();
 
     #[cfg(not(feature = "nightly"))]
-    type BreakTy;
+    type Result: VisitorResult;
 
-    fn visit_binder<T: TypeVisitable<I>>(
-        &mut self,
-        t: &I::Binder<T>,
-    ) -> ControlFlow<Self::BreakTy> {
+    fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> Self::Result {
         t.super_visit_with(self)
     }
 
-    fn visit_ty(&mut self, t: I::Ty) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
         t.super_visit_with(self)
     }
 
     // The default region visitor is a no-op because `Region` is non-recursive
     // and has no `super_visit_with` method to call.
-    fn visit_region(&mut self, _r: I::Region) -> ControlFlow<Self::BreakTy> {
-        ControlFlow::Continue(())
+    fn visit_region(&mut self, _r: I::Region) -> Self::Result {
+        Self::Result::output()
     }
 
-    fn visit_const(&mut self, c: I::Const) -> ControlFlow<Self::BreakTy> {
+    fn visit_const(&mut self, c: I::Const) -> Self::Result {
         c.super_visit_with(self)
     }
 
-    fn visit_predicate(&mut self, p: I::Predicate) -> ControlFlow<Self::BreakTy> {
+    fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result {
         p.super_visit_with(self)
     }
 }
@@ -117,8 +116,8 @@ pub trait TypeVisitor<I: Interner>: Sized {
 // Traversal implementations.
 
 impl<I: Interner, T: TypeVisitable<I>, U: TypeVisitable<I>> TypeVisitable<I> for (T, U) {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.0.visit_with(visitor)?;
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
+        try_visit!(self.0.visit_with(visitor));
         self.1.visit_with(visitor)
     }
 }
@@ -126,24 +125,24 @@ impl<I: Interner, T: TypeVisitable<I>, U: TypeVisitable<I>> TypeVisitable<I> for
 impl<I: Interner, A: TypeVisitable<I>, B: TypeVisitable<I>, C: TypeVisitable<I>> TypeVisitable<I>
     for (A, B, C)
 {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.0.visit_with(visitor)?;
-        self.1.visit_with(visitor)?;
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
+        try_visit!(self.0.visit_with(visitor));
+        try_visit!(self.1.visit_with(visitor));
         self.2.visit_with(visitor)
     }
 }
 
 impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Option<T> {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
         match self {
             Some(v) => v.visit_with(visitor),
-            None => ControlFlow::Continue(()),
+            None => V::Result::output(),
         }
     }
 }
 
 impl<I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>> TypeVisitable<I> for Result<T, E> {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
         match self {
             Ok(v) => v.visit_with(visitor),
             Err(e) => e.visit_with(visitor),
@@ -152,20 +151,21 @@ impl<I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>> TypeVisitable<I> for
 }
 
 impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Lrc<T> {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
         (**self).visit_with(visitor)
     }
 }
 
 impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<T> {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
         (**self).visit_with(visitor)
     }
 }
 
 impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Vec<T> {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.iter().try_for_each(|t| t.visit_with(visitor))
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
+        walk_visitable_list!(visitor, self.iter());
+        V::Result::output()
     }
 }
 
@@ -173,20 +173,23 @@ impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Vec<T> {
 // case, because we can't return a new slice. But note that there are a couple
 // of trivial impls of `TypeFoldable` for specific slice types elsewhere.
 impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for &[T] {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.iter().try_for_each(|t| t.visit_with(visitor))
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
+        walk_visitable_list!(visitor, self.iter());
+        V::Result::output()
     }
 }
 
 impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<[T]> {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.iter().try_for_each(|t| t.visit_with(visitor))
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
+        walk_visitable_list!(visitor, self.iter());
+        V::Result::output()
     }
 }
 
 impl<I: Interner, T: TypeVisitable<I>, Ix: Idx> TypeVisitable<I> for IndexVec<Ix, T> {
-    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.iter().try_for_each(|t| t.visit_with(visitor))
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
+        walk_visitable_list!(visitor, self.iter());
+        V::Result::output()
     }
 }
 
@@ -366,12 +369,9 @@ impl std::fmt::Debug for HasTypeFlagsVisitor {
 // is important for anonymization of binders in `TyCtxt::erase_regions`. We
 // specifically detect this case in `visit_binder`.
 impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
-    type BreakTy = FoundFlags;
+    type Result = ControlFlow<FoundFlags>;
 
-    fn visit_binder<T: TypeVisitable<I>>(
-        &mut self,
-        t: &I::Binder<T>,
-    ) -> ControlFlow<Self::BreakTy> {
+    fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> Self::Result {
         // If we're looking for the HAS_BINDER_VARS flag, check if the
         // binder has vars. This won't be present in the binder's bound
         // value, so we need to check here too.
@@ -383,7 +383,7 @@ impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
     }
 
     #[inline]
-    fn visit_ty(&mut self, t: I::Ty) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
         // Note: no `super_visit_with` call.
         let flags = t.flags();
         if flags.intersects(self.flags) {
@@ -394,7 +394,7 @@ impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
     }
 
     #[inline]
-    fn visit_region(&mut self, r: I::Region) -> ControlFlow<Self::BreakTy> {
+    fn visit_region(&mut self, r: I::Region) -> Self::Result {
         // Note: no `super_visit_with` call, as usual for `Region`.
         let flags = r.flags();
         if flags.intersects(self.flags) {
@@ -405,7 +405,7 @@ impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
     }
 
     #[inline]
-    fn visit_const(&mut self, c: I::Const) -> ControlFlow<Self::BreakTy> {
+    fn visit_const(&mut self, c: I::Const) -> Self::Result {
         // Note: no `super_visit_with` call.
         if c.flags().intersects(self.flags) {
             ControlFlow::Break(FoundFlags)
@@ -415,7 +415,7 @@ impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
     }
 
     #[inline]
-    fn visit_predicate(&mut self, predicate: I::Predicate) -> ControlFlow<Self::BreakTy> {
+    fn visit_predicate(&mut self, predicate: I::Predicate) -> Self::Result {
         // Note: no `super_visit_with` call.
         if predicate.flags().intersects(self.flags) {
             ControlFlow::Break(FoundFlags)
@@ -459,12 +459,9 @@ struct HasEscapingVarsVisitor {
 }
 
 impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
-    type BreakTy = FoundEscapingVars;
+    type Result = ControlFlow<FoundEscapingVars>;
 
-    fn visit_binder<T: TypeVisitable<I>>(
-        &mut self,
-        t: &I::Binder<T>,
-    ) -> ControlFlow<Self::BreakTy> {
+    fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> Self::Result {
         self.outer_index.shift_in(1);
         let result = t.super_visit_with(self);
         self.outer_index.shift_out(1);
@@ -472,7 +469,7 @@ impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
     }
 
     #[inline]
-    fn visit_ty(&mut self, t: I::Ty) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
         // If the outer-exclusive-binder is *strictly greater* than
         // `outer_index`, that means that `t` contains some content
         // bound at `outer_index` or above (because
@@ -486,7 +483,7 @@ impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
     }
 
     #[inline]
-    fn visit_region(&mut self, r: I::Region) -> ControlFlow<Self::BreakTy> {
+    fn visit_region(&mut self, r: I::Region) -> Self::Result {
         // If the region is bound by `outer_index` or anything outside
         // of outer index, then it escapes the binders we have
         // visited.
@@ -497,7 +494,7 @@ impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
         }
     }
 
-    fn visit_const(&mut self, ct: I::Const) -> ControlFlow<Self::BreakTy> {
+    fn visit_const(&mut self, ct: I::Const) -> Self::Result {
         // If the outer-exclusive-binder is *strictly greater* than
         // `outer_index`, that means that `ct` contains some content
         // bound at `outer_index` or above (because
@@ -511,7 +508,7 @@ impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
     }
 
     #[inline]
-    fn visit_predicate(&mut self, predicate: I::Predicate) -> ControlFlow<Self::BreakTy> {
+    fn visit_predicate(&mut self, predicate: I::Predicate) -> Self::Result {
         if predicate.outer_exclusive_binder() > self.outer_index {
             ControlFlow::Break(FoundEscapingVars)
         } else {
@@ -523,9 +520,9 @@ impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
 struct HasErrorVisitor;
 
 impl<I: Interner> TypeVisitor<I> for HasErrorVisitor {
-    type BreakTy = I::ErrorGuaranteed;
+    type Result = ControlFlow<I::ErrorGuaranteed>;
 
-    fn visit_ty(&mut self, t: <I as Interner>::Ty) -> ControlFlow<Self::BreakTy> {
+    fn visit_ty(&mut self, t: <I as Interner>::Ty) -> Self::Result {
         if let ty::Error(guar) = t.kind() {
             ControlFlow::Break(guar)
         } else {
@@ -533,7 +530,7 @@ impl<I: Interner> TypeVisitor<I> for HasErrorVisitor {
         }
     }
 
-    fn visit_const(&mut self, c: <I as Interner>::Const) -> ControlFlow<Self::BreakTy> {
+    fn visit_const(&mut self, c: <I as Interner>::Const) -> Self::Result {
         if let ty::ConstKind::Error(guar) = c.kind() {
             ControlFlow::Break(guar)
         } else {
@@ -541,7 +538,7 @@ impl<I: Interner> TypeVisitor<I> for HasErrorVisitor {
         }
     }
 
-    fn visit_region(&mut self, r: <I as Interner>::Region) -> ControlFlow<Self::BreakTy> {
+    fn visit_region(&mut self, r: <I as Interner>::Region) -> Self::Result {
         if let ty::ReError(guar) = r.kind() {
             ControlFlow::Break(guar)
         } else {
diff --git a/config.example.toml b/config.example.toml
index cef33a7905a..c1939933850 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -300,6 +300,10 @@
 # This is only useful for verifying that rustc generates reproducible builds.
 #full-bootstrap = false
 
+# Set the bootstrap/download cache path. It is useful when building rust
+# repeatedly in a CI invironment.
+# bootstrap-cache-path = /shared/cache
+
 # Enable a build of the extended Rust tool set which is not only the compiler
 # but also tools such as Cargo. This will also produce "combined installers"
 # which are used to install Rust and Cargo together.
@@ -820,9 +824,9 @@
 # The full path to the musl libdir.
 #musl-libdir = musl-root/lib
 
-# The root location of the `wasm32-wasi` sysroot. Only used for the
-# `wasm32-wasi` target. If you are building wasm32-wasi target, make sure to
-# create a `[target.wasm32-wasi]` section and move this field there.
+# The root location of the `wasm32-wasip1` sysroot. Only used for WASI
+# related targets. Make sure to create a `[target.wasm32-wasip1]`
+# section and move this field there (or equivalent for the target being built).
 #wasi-root = <none> (path)
 
 # Used in testing for configuring where the QEMU images are located, you
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index 0b142939755..a5d28aa5252 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -50,6 +50,8 @@ extern "Rust" {
 #[unstable(feature = "allocator_api", issue = "32838")]
 #[derive(Copy, Clone, Default, Debug)]
 #[cfg(not(test))]
+// the compiler needs to know when a Box uses the global allocator vs a custom one
+#[cfg_attr(not(bootstrap), lang = "global_alloc_ty")]
 pub struct Global;
 
 #[cfg(test)]
@@ -385,6 +387,7 @@ pub const fn handle_alloc_error(layout: Layout) -> ! {
     }
 
     #[cfg(not(feature = "panic_immediate_abort"))]
+    #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
     unsafe {
         core::intrinsics::const_eval_select((layout,), ct_error, rt_error)
     }
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index b202d9250d5..2736e5ee6c5 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -2062,6 +2062,9 @@ impl<Args: Tuple, F: AsyncFn<Args> + ?Sized, A: Allocator> AsyncFn<Args> for Box
 #[unstable(feature = "coerce_unsized", issue = "18598")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {}
 
+// It is quite crucial that we only allow the `Global` allocator here.
+// Handling arbitrary custom allocators (which can affect the `Box` layout heavily!)
+// would need a lot of codegen and interpreter adjustments.
 #[unstable(feature = "dispatch_from_dyn", issue = "none")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T, Global> {}
 
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index 58ffa9710d3..e99c6220e20 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -624,6 +624,7 @@ impl<K, V> BTreeMap<K, V> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_btree_new", since = "1.66.0")]
+    #[inline]
     #[must_use]
     pub const fn new() -> BTreeMap<K, V> {
         BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(Global), _marker: PhantomData }
diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs
index dd8d6f6c7e6..4d9694d4beb 100644
--- a/library/alloc/src/raw_vec.rs
+++ b/library/alloc/src/raw_vec.rs
@@ -259,7 +259,7 @@ impl<T, A: Allocator> RawVec<T, A> {
         } else {
             // We could use Layout::array here which ensures the absence of isize and usize overflows
             // and could hypothetically handle differences between stride and size, but this memory
-            // has already been allocated so we know it can't overflow and currently rust does not
+            // has already been allocated so we know it can't overflow and currently Rust does not
             // support such types. So we can do better by skipping some checks and avoid an unwrap.
             const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) };
             unsafe {
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 084157b97ab..facfc9d208e 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -944,6 +944,21 @@ impl<T, A: Allocator> Rc<T, A> {
     /// is in fact equivalent to <code>[Rc::try_unwrap]\(this).[ok][Result::ok]()</code>.
     /// (Note that the same kind of equivalence does **not** hold true for
     /// [`Arc`](crate::sync::Arc), due to race conditions that do not apply to `Rc`!)
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::rc::Rc;
+    ///
+    /// let x = Rc::new(3);
+    /// assert_eq!(Rc::into_inner(x), Some(3));
+    ///
+    /// let x = Rc::new(4);
+    /// let y = Rc::clone(&x);
+    ///
+    /// assert_eq!(Rc::into_inner(y), None);
+    /// assert_eq!(Rc::into_inner(x), Some(4));
+    /// ```
     #[inline]
     #[stable(feature = "rc_into_inner", since = "1.70.0")]
     pub fn into_inner(this: Self) -> Option<T> {
@@ -1329,6 +1344,7 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
     /// let x_ptr = Rc::into_raw(x);
     /// assert_eq!(unsafe { &*x_ptr }, "hello");
     /// ```
+    #[must_use = "losing the pointer will leak memory"]
     #[stable(feature = "rc_raw", since = "1.17.0")]
     #[rustc_never_returns_null_ptr]
     pub fn into_raw(this: Self) -> *const T {
@@ -2970,7 +2986,7 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
     ///
     /// [`from_raw`]: Weak::from_raw
     /// [`as_ptr`]: Weak::as_ptr
-    #[must_use = "`self` will be dropped if the result is not used"]
+    #[must_use = "losing the pointer will leak memory"]
     #[stable(feature = "weak_into_raw", since = "1.45.0")]
     pub fn into_raw(self) -> *const T {
         let result = self.as_ptr();
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 00f47f5c6e0..80f0f2acc99 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -2719,7 +2719,7 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
     ///
     /// [`from_raw`]: Weak::from_raw
     /// [`as_ptr`]: Weak::as_ptr
-    #[must_use = "`self` will be dropped if the result is not used"]
+    #[must_use = "losing the pointer will leak memory"]
     #[stable(feature = "weak_into_raw", since = "1.45.0")]
     pub fn into_raw(self) -> *const T {
         let result = self.as_ptr();
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 7bd19875584..c0e934b3b1f 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1490,6 +1490,12 @@ impl<T, A: Allocator> Vec<T, A> {
     /// vec.insert(4, 5);
     /// assert_eq!(vec, [1, 4, 2, 3, 5]);
     /// ```
+    ///
+    /// # Time complexity
+    ///
+    /// Takes *O*([`Vec::len`]) time. All items after the insertion index must be
+    /// shifted to the right. In the worst case, all elements are shifted when
+    /// the insertion index is 0.
     #[cfg(not(no_global_oom_handling))]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(&mut self, index: usize, element: T) {
@@ -1913,6 +1919,13 @@ impl<T, A: Allocator> Vec<T, A> {
     /// vec.push(3);
     /// assert_eq!(vec, [1, 2, 3]);
     /// ```
+    ///
+    /// # Time complexity
+    ///
+    /// Takes amortized *O*(1) time. If the vector's length would exceed its
+    /// capacity after the push, *O*(*capacity*) time is taken to copy the
+    /// vector's elements to a larger allocation. This expensive operation is
+    /// offset by the *capacity* *O*(1) insertions it allows.
     #[cfg(not(no_global_oom_handling))]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -1961,6 +1974,10 @@ impl<T, A: Allocator> Vec<T, A> {
     /// }
     /// assert_eq!(from_iter_fallible(0..100), Ok(Vec::from_iter(0..100)));
     /// ```
+    ///
+    /// # Time complexity
+    ///
+    /// Takes *O*(1) time.
     #[inline]
     #[unstable(feature = "vec_push_within_capacity", issue = "100486")]
     pub fn push_within_capacity(&mut self, value: T) -> Result<(), T> {
@@ -1990,6 +2007,10 @@ impl<T, A: Allocator> Vec<T, A> {
     /// assert_eq!(vec.pop(), Some(3));
     /// assert_eq!(vec, [1, 2]);
     /// ```
+    ///
+    /// # Time complexity
+    ///
+    /// Takes *O*(1) time.
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pop(&mut self) -> Option<T> {
diff --git a/library/alloc/tests/task.rs b/library/alloc/tests/task.rs
index 0f8d9218980..034039a1eae 100644
--- a/library/alloc/tests/task.rs
+++ b/library/alloc/tests/task.rs
@@ -4,6 +4,7 @@ use alloc::task::{LocalWake, Wake};
 use core::task::{LocalWaker, Waker};
 
 #[test]
+#[cfg_attr(miri, should_panic)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it fails
 fn test_waker_will_wake_clone() {
     struct NoopWaker;
 
@@ -19,6 +20,7 @@ fn test_waker_will_wake_clone() {
 }
 
 #[test]
+#[cfg_attr(miri, should_panic)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it fails
 fn test_local_waker_will_wake_clone() {
     struct NoopWaker;
 
diff --git a/library/core/benches/lib.rs b/library/core/benches/lib.rs
index fdefc9a714e..4d14b930e41 100644
--- a/library/core/benches/lib.rs
+++ b/library/core/benches/lib.rs
@@ -16,6 +16,7 @@ mod char;
 mod fmt;
 mod hash;
 mod iter;
+mod net;
 mod num;
 mod ops;
 mod pattern;
diff --git a/library/core/benches/net/addr_parser.rs b/library/core/benches/net/addr_parser.rs
new file mode 100644
index 00000000000..b9406a9779d
--- /dev/null
+++ b/library/core/benches/net/addr_parser.rs
@@ -0,0 +1,78 @@
+use core::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
+use core::str::FromStr;
+
+use test::{black_box, Bencher};
+
+const IPV4_STR: &str = "192.168.0.1";
+const IPV4_STR_PORT: &str = "192.168.0.1:8080";
+
+const IPV6_STR_FULL: &str = "2001:db8:0:0:0:0:c0a8:1";
+const IPV6_STR_COMPRESS: &str = "2001:db8::c0a8:1";
+const IPV6_STR_V4: &str = "2001:db8::192.168.0.1";
+const IPV6_STR_PORT: &str = "[2001:db8::c0a8:1]:8080";
+const IPV6_STR_PORT_SCOPE_ID: &str = "[2001:db8::c0a8:1%1337]:8080";
+
+#[bench]
+fn bench_parse_ipv4(b: &mut Bencher) {
+    b.iter(|| Ipv4Addr::from_str(black_box(IPV4_STR)));
+}
+
+#[bench]
+fn bench_parse_ipv6_full(b: &mut Bencher) {
+    b.iter(|| Ipv6Addr::from_str(black_box(IPV6_STR_FULL)));
+}
+
+#[bench]
+fn bench_parse_ipv6_compress(b: &mut Bencher) {
+    b.iter(|| Ipv6Addr::from_str(black_box(IPV6_STR_COMPRESS)));
+}
+
+#[bench]
+fn bench_parse_ipv6_v4(b: &mut Bencher) {
+    b.iter(|| Ipv6Addr::from_str(black_box(IPV6_STR_V4)));
+}
+
+#[bench]
+fn bench_parse_ipaddr_v4(b: &mut Bencher) {
+    b.iter(|| IpAddr::from_str(black_box(IPV4_STR)));
+}
+
+#[bench]
+fn bench_parse_ipaddr_v6_full(b: &mut Bencher) {
+    b.iter(|| IpAddr::from_str(black_box(IPV6_STR_FULL)));
+}
+
+#[bench]
+fn bench_parse_ipaddr_v6_compress(b: &mut Bencher) {
+    b.iter(|| IpAddr::from_str(black_box(IPV6_STR_COMPRESS)));
+}
+
+#[bench]
+fn bench_parse_ipaddr_v6_v4(b: &mut Bencher) {
+    b.iter(|| IpAddr::from_str(black_box(IPV6_STR_V4)));
+}
+
+#[bench]
+fn bench_parse_socket_v4(b: &mut Bencher) {
+    b.iter(|| SocketAddrV4::from_str(black_box(IPV4_STR_PORT)));
+}
+
+#[bench]
+fn bench_parse_socket_v6(b: &mut Bencher) {
+    b.iter(|| SocketAddrV6::from_str(black_box(IPV6_STR_PORT)));
+}
+
+#[bench]
+fn bench_parse_socket_v6_scope_id(b: &mut Bencher) {
+    b.iter(|| SocketAddrV6::from_str(black_box(IPV6_STR_PORT_SCOPE_ID)));
+}
+
+#[bench]
+fn bench_parse_socketaddr_v4(b: &mut Bencher) {
+    b.iter(|| SocketAddr::from_str(black_box(IPV4_STR_PORT)));
+}
+
+#[bench]
+fn bench_parse_socketaddr_v6(b: &mut Bencher) {
+    b.iter(|| SocketAddr::from_str(black_box(IPV6_STR_PORT)));
+}
diff --git a/library/core/benches/net/mod.rs b/library/core/benches/net/mod.rs
new file mode 100644
index 00000000000..c29aed46ccd
--- /dev/null
+++ b/library/core/benches/net/mod.rs
@@ -0,0 +1 @@
+mod addr_parser;
diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs
index 8817ec0777b..31d6bc36fc8 100644
--- a/library/core/src/arch.rs
+++ b/library/core/src/arch.rs
@@ -6,10 +6,10 @@ pub use crate::core_arch::arch::*;
 
 /// Inline assembly.
 ///
-/// Refer to [rust by example] for a usage guide and the [reference] for
+/// Refer to [Rust By Example] for a usage guide and the [reference] for
 /// detailed information about the syntax and available options.
 ///
-/// [rust by example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html
+/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html
 /// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html
 #[stable(feature = "asm", since = "1.59.0")]
 #[rustc_builtin_macro]
@@ -19,10 +19,10 @@ pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) {
 
 /// Module-level inline assembly.
 ///
-/// Refer to [rust by example] for a usage guide and the [reference] for
+/// Refer to [Rust By Example] for a usage guide and the [reference] for
 /// detailed information about the syntax and available options.
 ///
-/// [rust by example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html
+/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html
 /// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html
 #[stable(feature = "global_asm", since = "1.59.0")]
 #[rustc_builtin_macro]
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index 42663ff2b53..8b5b48c59c2 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -360,6 +360,7 @@ where
     }
 }
 
+/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison).
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: PartialOrd, const N: usize> PartialOrd for [T; N] {
     #[inline]
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index a93b94867ce..65ae4831839 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -927,7 +927,7 @@ impl char {
     #[must_use]
     #[inline]
     pub(crate) fn is_grapheme_extended(self) -> bool {
-        unicode::Grapheme_Extend(self)
+        self > '\x7f' && unicode::Grapheme_Extend(self)
     }
 
     /// Returns `true` if this `char` has one of the general categories for numbers.
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index 85740dce866..63fd23ea9a9 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -466,10 +466,10 @@ pub trait Into<T>: Sized {
 /// Prefer using [`Into`] over using `From` when specifying trait bounds on a generic function.
 /// This way, types that directly implement [`Into`] can be used as arguments as well.
 ///
-/// The `From` is also very useful when performing error handling. When constructing a function
+/// The `From` trait is also very useful when performing error handling. When constructing a function
 /// that is capable of failing, the return type will generally be of the form `Result<T, E>`.
-/// The `From` trait simplifies error handling by allowing a function to return a single error type
-/// that encapsulate multiple error types. See the "Examples" section and [the book][book] for more
+/// `From` simplifies error handling by allowing a function to return a single error type
+/// that encapsulates multiple error types. See the "Examples" section and [the book][book] for more
 /// details.
 ///
 /// **Note: This trait must not fail**. The `From` trait is intended for perfect conversions.
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 20186a2de0f..0825281090c 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -428,10 +428,13 @@ impl CStr {
             unsafe { &*(bytes as *const [u8] as *const CStr) }
         }
 
+        #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
         // SAFETY: The const and runtime versions have identical behavior
         // unless the safety contract of `from_bytes_with_nul_unchecked` is
         // violated, which is UB.
-        unsafe { intrinsics::const_eval_select((bytes,), const_impl, rt_impl) }
+        unsafe {
+            intrinsics::const_eval_select((bytes,), const_impl, rt_impl)
+        }
     }
 
     /// Returns the inner pointer to this C string.
@@ -719,6 +722,9 @@ const unsafe fn const_strlen(ptr: *const c_char) -> usize {
         unsafe { strlen(s) }
     }
 
+    #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
     // SAFETY: the two functions always provide equivalent functionality
-    unsafe { intrinsics::const_eval_select((ptr,), strlen_ct, strlen_rt) }
+    unsafe {
+        intrinsics::const_eval_select((ptr,), strlen_ct, strlen_rt)
+    }
 }
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index e1b7b46a1ed..4016167d05c 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -201,14 +201,22 @@ pub trait Write {
         impl<W: Write + ?Sized> SpecWriteFmt for &mut W {
             #[inline]
             default fn spec_write_fmt(mut self, args: Arguments<'_>) -> Result {
-                write(&mut self, args)
+                if let Some(s) = args.as_const_str() {
+                    self.write_str(s)
+                } else {
+                    write(&mut self, args)
+                }
             }
         }
 
         impl<W: Write> SpecWriteFmt for &mut W {
             #[inline]
             fn spec_write_fmt(self, args: Arguments<'_>) -> Result {
-                write(self, args)
+                if let Some(s) = args.as_const_str() {
+                    self.write_str(s)
+                } else {
+                    write(self, args)
+                }
             }
         }
 
@@ -430,6 +438,14 @@ impl<'a> Arguments<'a> {
             _ => None,
         }
     }
+
+    /// Same as [`Arguments::as_str`], but will only return `Some(s)` if it can be determined at compile time.
+    #[must_use]
+    #[inline]
+    fn as_const_str(&self) -> Option<&'static str> {
+        let s = self.as_str();
+        if core::intrinsics::is_val_statically_known(s.is_some()) { s } else { None }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -633,6 +649,23 @@ pub use macros::Debug;
 /// [tostring]: ../../std/string/trait.ToString.html
 /// [tostring_function]: ../../std/string/trait.ToString.html#tymethod.to_string
 ///
+/// # Internationalization
+///
+/// Because a type can only have one `Display` implementation, it is often preferable
+/// to only implement `Display` when there is a single most "obvious" way that
+/// values can be formatted as text. This could mean formatting according to the
+/// "invariant" culture and "undefined" locale, or it could mean that the type
+/// display is designed for a specific culture/locale, such as developer logs.
+///
+/// If not all values have a justifiably canonical textual format or if you want
+/// to support alternative formats not covered by the standard set of possible
+/// [formatting traits], the most flexible approach is display adapters: methods
+/// like [`str::escape_default`] or [`Path::display`] which create a wrapper
+/// implementing `Display` to output the specific display format.
+///
+/// [formatting traits]: ../../std/fmt/index.html#formatting-traits
+/// [`Path::display`]: ../../std/path/struct.Path.html#method.display
+///
 /// # Examples
 ///
 /// Implementing `Display` on a type:
@@ -1582,8 +1615,9 @@ impl<'a> Formatter<'a> {
     /// assert_eq!(format!("{:0>8}", Foo(2)), "Foo 2");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
     pub fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result {
-        write(self.buf, fmt)
+        if let Some(s) = fmt.as_const_str() { self.buf.write_str(s) } else { write(self.buf, fmt) }
     }
 
     /// Flags for formatting
@@ -2272,8 +2306,13 @@ impl Write for Formatter<'_> {
         self.buf.write_char(c)
     }
 
+    #[inline]
     fn write_fmt(&mut self, args: Arguments<'_>) -> Result {
-        write(self.buf, args)
+        if let Some(s) = args.as_const_str() {
+            self.buf.write_str(s)
+        } else {
+            write(self.buf, args)
+        }
     }
 }
 
diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs
index af2e422e8a0..6dd3069034d 100644
--- a/library/core/src/future/future.rs
+++ b/library/core/src/future/future.rs
@@ -30,8 +30,7 @@ use crate::task::{Context, Poll};
 #[lang = "future_trait"]
 #[diagnostic::on_unimplemented(
     label = "`{Self}` is not a future",
-    message = "`{Self}` is not a future",
-    note = "{Self} must be a future or must implement `IntoFuture` to be awaited"
+    message = "`{Self}` is not a future"
 )]
 pub trait Future {
     /// The type of value produced on completion.
diff --git a/library/core/src/future/into_future.rs b/library/core/src/future/into_future.rs
index 38c654e76b4..eb5a9b72dd0 100644
--- a/library/core/src/future/into_future.rs
+++ b/library/core/src/future/into_future.rs
@@ -100,6 +100,11 @@ use crate::future::Future;
 /// ```
 #[stable(feature = "into_future", since = "1.64.0")]
 #[rustc_diagnostic_item = "IntoFuture"]
+#[diagnostic::on_unimplemented(
+    label = "`{Self}` is not a future",
+    message = "`{Self}` is not a future",
+    note = "{Self} must be a future or must implement `IntoFuture` to be awaited"
+)]
 pub trait IntoFuture {
     /// The output that the future will produce on completion.
     #[stable(feature = "into_future", since = "1.64.0")]
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 96e667d63c5..aff1c589e62 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -2499,9 +2499,8 @@ extern "rust-intrinsic" {
     #[rustc_nounwind]
     pub fn black_box<T>(dummy: T) -> T;
 
-    /// `ptr` must point to a vtable.
-    /// The intrinsic will return the size stored in that vtable.
     #[rustc_nounwind]
+    #[cfg(bootstrap)]
     pub fn vtable_size(ptr: *const ()) -> usize;
 
     /// `ptr` must point to a vtable.
@@ -2515,6 +2514,8 @@ extern "rust-intrinsic" {
     /// intrinsic will be replaced with a call to `called_in_const`. It gets
     /// replaced with a call to `called_at_rt` otherwise.
     ///
+    /// This function is safe to call, but note the stability concerns below.
+    ///
     /// # Type Requirements
     ///
     /// The two functions must be both function items. They cannot be function
@@ -2524,45 +2525,47 @@ extern "rust-intrinsic" {
     /// the two functions, therefore, both functions must accept the same type of
     /// arguments. Both functions must return RET.
     ///
-    /// # Safety
+    /// # Stability concerns
     ///
-    /// The two functions must behave observably equivalent. Safe code in other
-    /// crates may assume that calling a `const fn` at compile-time and at run-time
-    /// produces the same result. A function that produces a different result when
-    /// evaluated at run-time, or has any other observable side-effects, is
-    /// *unsound*.
+    /// Rust has not yet decided that `const fn` are allowed to tell whether
+    /// they run at compile-time or at runtime. Therefore, when using this
+    /// intrinsic anywhere that can be reached from stable, it is crucial that
+    /// the end-to-end behavior of the stable `const fn` is the same for both
+    /// modes of execution. (Here, Undefined Behavior is considered "the same"
+    /// as any other behavior, so if the function exhibits UB at runtime then
+    /// it may do whatever it wants at compile-time.)
     ///
     /// Here is an example of how this could cause a problem:
     /// ```no_run
     /// #![feature(const_eval_select)]
     /// #![feature(core_intrinsics)]
     /// # #![allow(internal_features)]
-    /// use std::hint::unreachable_unchecked;
+    /// # #![cfg_attr(bootstrap, allow(unused))]
     /// use std::intrinsics::const_eval_select;
     ///
-    /// // Crate A
+    /// // Standard library
+    /// # #[cfg(not(bootstrap))]
     /// pub const fn inconsistent() -> i32 {
     ///     fn runtime() -> i32 { 1 }
     ///     const fn compiletime() -> i32 { 2 }
     ///
-    ///     unsafe {
-    //          // ⚠ This code violates the required equivalence of `compiletime`
-    ///         // and `runtime`.
-    ///         const_eval_select((), compiletime, runtime)
-    ///     }
+    //      // ⚠ This code violates the required equivalence of `compiletime`
+    ///     // and `runtime`.
+    ///     const_eval_select((), compiletime, runtime)
     /// }
+    /// # #[cfg(bootstrap)]
+    /// # pub const fn inconsistent() -> i32 { 0 }
     ///
-    /// // Crate B
+    /// // User Crate
     /// const X: i32 = inconsistent();
     /// let x = inconsistent();
-    /// if x != X { unsafe { unreachable_unchecked(); }}
+    /// assert_eq!(x, X);
     /// ```
     ///
-    /// This code causes Undefined Behavior when being run, since the
-    /// `unreachable_unchecked` is actually being reached. The bug is in *crate A*,
-    /// which violates the principle that a `const fn` must behave the same at
-    /// compile-time and at run-time. The unsafe code in crate B is fine.
+    /// Currently such an assertion would always succeed; until Rust decides
+    /// otherwise, that principle should not be violated.
     #[rustc_const_unstable(feature = "const_eval_select", issue = "none")]
+    #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
     pub fn const_eval_select<ARG: Tuple, F, G, RET>(
         arg: ARG,
         called_in_const: F,
@@ -2681,6 +2684,17 @@ pub const unsafe fn const_allocate(_size: usize, _align: usize) -> *mut u8 {
 #[cfg_attr(bootstrap, inline)]
 pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {}
 
+/// `ptr` must point to a vtable.
+/// The intrinsic will return the size stored in that vtable.
+#[rustc_nounwind]
+#[unstable(feature = "core_intrinsics", issue = "none")]
+#[cfg_attr(not(bootstrap), rustc_intrinsic)]
+#[cfg_attr(not(bootstrap), rustc_intrinsic_must_be_overridden)]
+#[cfg(not(bootstrap))]
+pub unsafe fn vtable_size(_ptr: *const ()) -> usize {
+    unreachable!()
+}
+
 // Some functions are defined here because they accidentally got made
 // available in this module on stable. See <https://github.com/rust-lang/rust/issues/15702>.
 // (`transmute` also falls into this category, but it cannot be wrapped due to the
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index 0d1cf7941fb..d89801bce2b 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -236,6 +236,49 @@ pub trait FromIterator<A>: Sized {
 /// ```
 #[rustc_diagnostic_item = "IntoIterator"]
 #[rustc_skip_array_during_method_dispatch]
+#[rustc_on_unimplemented(
+    on(
+        _Self = "core::ops::range::RangeTo<Idx>",
+        label = "if you meant to iterate until a value, add a starting value",
+        note = "`..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a \
+              bounded `Range`: `0..end`"
+    ),
+    on(
+        _Self = "core::ops::range::RangeToInclusive<Idx>",
+        label = "if you meant to iterate until a value (including it), add a starting value",
+        note = "`..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant \
+              to have a bounded `RangeInclusive`: `0..=end`"
+    ),
+    on(
+        _Self = "[]",
+        label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`"
+    ),
+    on(_Self = "&[]", label = "`{Self}` is not an iterator; try calling `.iter()`"),
+    on(
+        _Self = "alloc::vec::Vec<T, A>",
+        label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`"
+    ),
+    on(
+        _Self = "&str",
+        label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
+    ),
+    on(
+        _Self = "alloc::string::String",
+        label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
+    ),
+    on(
+        _Self = "{integral}",
+        note = "if you want to iterate between `start` until a value `end`, use the exclusive range \
+              syntax `start..end` or the inclusive range syntax `start..=end`"
+    ),
+    on(
+        _Self = "{float}",
+        note = "if you want to iterate between `start` until a value `end`, use the exclusive range \
+              syntax `start..end` or the inclusive range syntax `start..=end`"
+    ),
+    label = "`{Self}` is not an iterator",
+    message = "`{Self}` is not an iterator"
+)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait IntoIterator {
     /// The type of the elements being iterated over.
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 3267cea38b7..e1904ed220c 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -28,42 +28,11 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
 #[rustc_on_unimplemented(
     on(
         _Self = "core::ops::range::RangeTo<Idx>",
-        label = "if you meant to iterate until a value, add a starting value",
-        note = "`..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a \
-              bounded `Range`: `0..end`"
+        note = "you might have meant to use a bounded `Range`"
     ),
     on(
         _Self = "core::ops::range::RangeToInclusive<Idx>",
-        label = "if you meant to iterate until a value (including it), add a starting value",
-        note = "`..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant \
-              to have a bounded `RangeInclusive`: `0..=end`"
-    ),
-    on(
-        _Self = "[]",
-        label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`"
-    ),
-    on(_Self = "&[]", label = "`{Self}` is not an iterator; try calling `.iter()`"),
-    on(
-        _Self = "alloc::vec::Vec<T, A>",
-        label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`"
-    ),
-    on(
-        _Self = "&str",
-        label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
-    ),
-    on(
-        _Self = "alloc::string::String",
-        label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
-    ),
-    on(
-        _Self = "{integral}",
-        note = "if you want to iterate between `start` until a value `end`, use the exclusive range \
-              syntax `start..end` or the inclusive range syntax `start..=end`"
-    ),
-    on(
-        _Self = "{float}",
-        note = "if you want to iterate between `start` until a value `end`, use the exclusive range \
-              syntax `start..end` or the inclusive range syntax `start..=end`"
+        note = "you might have meant to use a bounded `RangeInclusive`"
     ),
     label = "`{Self}` is not an iterator",
     message = "`{Self}` is not an iterator"
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 7b735d48bdf..0f7885769c2 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -202,6 +202,7 @@
 //
 // Language features:
 // tidy-alphabetical-start
+#![cfg_attr(bootstrap, feature(diagnostic_namespace))]
 #![cfg_attr(bootstrap, feature(platform_intrinsics))]
 #![feature(abi_unadjusted)]
 #![feature(adt_const_params)]
@@ -223,7 +224,6 @@
 #![feature(const_trait_impl)]
 #![feature(decl_macro)]
 #![feature(deprecated_suggestion)]
-#![feature(diagnostic_namespace)]
 #![feature(doc_cfg)]
 #![feature(doc_cfg_hide)]
 #![feature(doc_notable_trait)]
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index d818889f364..0ee7e190e3d 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -112,16 +112,19 @@ macro_rules! assert_ne {
     };
 }
 
-/// Asserts that an expression matches any of the given patterns.
+/// Asserts that an expression matches the provided pattern.
 ///
-/// Like in a `match` expression, the pattern can be optionally followed by `if`
-/// and a guard expression that has access to names bound by the pattern.
+/// This macro is generally preferable to `assert!(matches!(value, pattern))`, because it can print
+/// the debug representation of the actual value shape that did not meet expectations. In contrast,
+/// using [`assert!`] will only print that expectations were not met, but not why.
 ///
-/// On panic, this macro will print the value of the expression with its
-/// debug representation.
+/// The pattern syntax is exactly the same as found in a match arm and the `matches!` macro. The
+/// optional if guard can be used to add additional checks that must be true for the matched value,
+/// otherwise this macro will panic.
 ///
-/// Like [`assert!`], this macro has a second form, where a custom
-/// panic message can be provided.
+/// On panic, this macro will print the value of the expression with its debug representation.
+///
+/// Like [`assert!`], this macro has a second form, where a custom panic message can be provided.
 ///
 /// # Examples
 ///
@@ -130,13 +133,20 @@ macro_rules! assert_ne {
 ///
 /// use std::assert_matches::assert_matches;
 ///
-/// let a = 1u32.checked_add(2);
-/// let b = 1u32.checked_sub(2);
+/// let a = Some(345);
+/// let b = Some(56);
 /// assert_matches!(a, Some(_));
-/// assert_matches!(b, None);
+/// assert_matches!(b, Some(_));
 ///
-/// let c = Ok("abc".to_string());
-/// assert_matches!(c, Ok(x) | Err(x) if x.len() < 100);
+/// assert_matches!(a, Some(345));
+/// assert_matches!(a, Some(345) | None);
+///
+/// // assert_matches!(a, None); // panics
+/// // assert_matches!(b, Some(345)); // panics
+/// // assert_matches!(b, Some(345) | None); // panics
+///
+/// assert_matches!(a, Some(x) if x > 100);
+/// // assert_matches!(a, Some(x) if x < 100); // panics
 /// ```
 #[unstable(feature = "assert_matches", issue = "82775")]
 #[allow_internal_unstable(panic_internals)]
@@ -369,21 +379,25 @@ macro_rules! debug_assert_ne {
     };
 }
 
-/// Asserts that an expression matches any of the given patterns.
+/// Asserts that an expression matches the provided pattern.
 ///
-/// Like in a `match` expression, the pattern can be optionally followed by `if`
-/// and a guard expression that has access to names bound by the pattern.
+/// This macro is generally preferable to `debug_assert!(matches!(value, pattern))`, because it can
+/// print the debug representation of the actual value shape that did not meet expectations. In
+/// contrast, using [`debug_assert!`] will only print that expectations were not met, but not why.
 ///
-/// On panic, this macro will print the value of the expression with its
-/// debug representation.
+/// The pattern syntax is exactly the same as found in a match arm and the `matches!` macro. The
+/// optional if guard can be used to add additional checks that must be true for the matched value,
+/// otherwise this macro will panic.
 ///
-/// Unlike [`assert_matches!`], `debug_assert_matches!` statements are only
-/// enabled in non optimized builds by default. An optimized build will not
-/// execute `debug_assert_matches!` statements unless `-C debug-assertions` is
-/// passed to the compiler. This makes `debug_assert_matches!` useful for
-/// checks that are too expensive to be present in a release build but may be
-/// helpful during development. The result of expanding `debug_assert_matches!`
-/// is always type checked.
+/// On panic, this macro will print the value of the expression with its debug representation.
+///
+/// Like [`assert!`], this macro has a second form, where a custom panic message can be provided.
+///
+/// Unlike [`assert_matches!`], `debug_assert_matches!` statements are only enabled in non optimized
+/// builds by default. An optimized build will not execute `debug_assert_matches!` statements unless
+/// `-C debug-assertions` is passed to the compiler. This makes `debug_assert_matches!` useful for
+/// checks that are too expensive to be present in a release build but may be helpful during
+/// development. The result of expanding `debug_assert_matches!` is always type checked.
 ///
 /// # Examples
 ///
@@ -392,13 +406,20 @@ macro_rules! debug_assert_ne {
 ///
 /// use std::assert_matches::debug_assert_matches;
 ///
-/// let a = 1u32.checked_add(2);
-/// let b = 1u32.checked_sub(2);
+/// let a = Some(345);
+/// let b = Some(56);
 /// debug_assert_matches!(a, Some(_));
-/// debug_assert_matches!(b, None);
+/// debug_assert_matches!(b, Some(_));
 ///
-/// let c = Ok("abc".to_string());
-/// debug_assert_matches!(c, Ok(x) | Err(x) if x.len() < 100);
+/// debug_assert_matches!(a, Some(345));
+/// debug_assert_matches!(a, Some(345) | None);
+///
+/// // debug_assert_matches!(a, None); // panics
+/// // debug_assert_matches!(b, Some(345)); // panics
+/// // debug_assert_matches!(b, Some(345) | None); // panics
+///
+/// debug_assert_matches!(a, Some(x) if x > 100);
+/// // debug_assert_matches!(a, Some(x) if x < 100); // panics
 /// ```
 #[unstable(feature = "assert_matches", issue = "82775")]
 #[allow_internal_unstable(assert_matches)]
@@ -409,10 +430,15 @@ pub macro debug_assert_matches($($arg:tt)*) {
     }
 }
 
-/// Returns whether the given expression matches any of the given patterns.
+/// Returns whether the given expression matches the provided pattern.
 ///
-/// Like in a `match` expression, the pattern can be optionally followed by `if`
-/// and a guard expression that has access to names bound by the pattern.
+/// The pattern syntax is exactly the same as found in a match arm. The optional if guard can be
+/// used to add additional checks that must be true for the matched value, otherwise this macro will
+/// return `false`.
+///
+/// When testing that a value matches a pattern, it's generally preferable to use
+/// [`assert_matches!`] as it will print the debug representation of the value if the assertion
+/// fails.
 ///
 /// # Examples
 ///
@@ -1455,7 +1481,7 @@ pub(crate) mod builtin {
     /// script](https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script).
     ///
     /// When using the `include` macro to include stretches of documentation, remember that the
-    /// included file still needs to be a valid rust syntax. It is also possible to
+    /// included file still needs to be a valid Rust syntax. It is also possible to
     /// use the [`include_str`] macro as `#![doc = include_str!("...")]` (at the module level) or
     /// `#[doc = include_str!("...")]` (at the item level) to include documentation from a plain
     /// text or markdown file.
diff --git a/library/core/src/net/parser.rs b/library/core/src/net/parser.rs
index b9a1924d668..835ab9d73af 100644
--- a/library/core/src/net/parser.rs
+++ b/library/core/src/net/parser.rs
@@ -3,7 +3,7 @@
 //! This module is "publicly exported" through the `FromStr` implementations
 //! below.
 
-use crate::convert::TryInto;
+use crate::convert::{TryFrom, TryInto};
 use crate::error::Error;
 use crate::fmt;
 use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
@@ -104,36 +104,66 @@ impl<'a> Parser<'a> {
     // Read a number off the front of the input in the given radix, stopping
     // at the first non-digit character or eof. Fails if the number has more
     // digits than max_digits or if there is no number.
-    fn read_number<T: ReadNumberHelper>(
+    //
+    // INVARIANT: `max_digits` must be less than the number of digits that `u32`
+    // can represent.
+    fn read_number<T: ReadNumberHelper + TryFrom<u32>>(
         &mut self,
         radix: u32,
         max_digits: Option<usize>,
         allow_zero_prefix: bool,
     ) -> Option<T> {
-        self.read_atomically(move |p| {
-            let mut result = T::ZERO;
-            let mut digit_count = 0;
-            let has_leading_zero = p.peek_char() == Some('0');
+        // If max_digits.is_some(), then we are parsing a `u8` or `u16` and
+        // don't need to use checked arithmetic since it fits within a `u32`.
+        if let Some(max_digits) = max_digits {
+            // u32::MAX = 4_294_967_295u32, which is 10 digits long.
+            // `max_digits` must be less than 10 to not overflow a `u32`.
+            debug_assert!(max_digits < 10);
+
+            self.read_atomically(move |p| {
+                let mut result = 0_u32;
+                let mut digit_count = 0;
+                let has_leading_zero = p.peek_char() == Some('0');
+
+                while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) {
+                    result *= radix;
+                    result += digit;
+                    digit_count += 1;
 
-            while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) {
-                result = result.checked_mul(radix)?;
-                result = result.checked_add(digit)?;
-                digit_count += 1;
-                if let Some(max_digits) = max_digits {
                     if digit_count > max_digits {
                         return None;
                     }
                 }
-            }
 
-            if digit_count == 0 {
-                None
-            } else if !allow_zero_prefix && has_leading_zero && digit_count > 1 {
-                None
-            } else {
-                Some(result)
-            }
-        })
+                if digit_count == 0 {
+                    None
+                } else if !allow_zero_prefix && has_leading_zero && digit_count > 1 {
+                    None
+                } else {
+                    result.try_into().ok()
+                }
+            })
+        } else {
+            self.read_atomically(move |p| {
+                let mut result = T::ZERO;
+                let mut digit_count = 0;
+                let has_leading_zero = p.peek_char() == Some('0');
+
+                while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) {
+                    result = result.checked_mul(radix)?;
+                    result = result.checked_add(digit)?;
+                    digit_count += 1;
+                }
+
+                if digit_count == 0 {
+                    None
+                } else if !allow_zero_prefix && has_leading_zero && digit_count > 1 {
+                    None
+                } else {
+                    Some(result)
+                }
+            })
+        }
     }
 
     /// Read an IPv4 address.
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 47e16018a47..abdcb7099ca 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -1153,8 +1153,11 @@ impl f32 {
             // Stability concerns.
             unsafe { mem::transmute(x) }
         }
+        #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
         // SAFETY: We use internal implementations that either always work or fail at compile time.
-        unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
+        unsafe {
+            intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32)
+        }
     }
 
     /// Raw transmutation from `u32`.
@@ -1245,8 +1248,11 @@ impl f32 {
             // Stability concerns.
             unsafe { mem::transmute(x) }
         }
+        #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
         // SAFETY: We use internal implementations that either always work or fail at compile time.
-        unsafe { intrinsics::const_eval_select((v,), ct_u32_to_f32, rt_u32_to_f32) }
+        unsafe {
+            intrinsics::const_eval_select((v,), ct_u32_to_f32, rt_u32_to_f32)
+        }
     }
 
     /// Return the memory representation of this floating point number as a byte array in
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index cd69e758d28..f4d2a4f2167 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -1146,8 +1146,11 @@ impl f64 {
             // Stability concerns.
             unsafe { mem::transmute::<f64, u64>(rt) }
         }
+        #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
         // SAFETY: We use internal implementations that either always work or fail at compile time.
-        unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
+        unsafe {
+            intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64)
+        }
     }
 
     /// Raw transmutation from `u64`.
@@ -1243,8 +1246,11 @@ impl f64 {
             // Stability concerns.
             unsafe { mem::transmute::<u64, f64>(rt) }
         }
+        #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
         // SAFETY: We use internal implementations that either always work or fail at compile time.
-        unsafe { intrinsics::const_eval_select((v,), ct_u64_to_f64, rt_u64_to_f64) }
+        unsafe {
+            intrinsics::const_eval_select((v,), ct_u64_to_f64, rt_u64_to_f64)
+        }
     }
 
     /// Return the memory representation of this floating point number as a byte array in
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index 0819334b600..9e1184c8f5b 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -117,6 +117,7 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo
         panic_fmt(fmt);
     }
 
+    #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
     // SAFETY: const panic does not care about unwinding
     unsafe {
         super::intrinsics::const_eval_select((fmt, force_no_backtrace), comptime, runtime);
diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs
index 3eea065eef6..3508b0c7f23 100644
--- a/library/core/src/ptr/alignment.rs
+++ b/library/core/src/ptr/alignment.rs
@@ -3,7 +3,7 @@ use crate::num::NonZero;
 use crate::{cmp, fmt, hash, mem, num};
 
 /// A type storing a `usize` which is a power of two, and thus
-/// represents a possible alignment in the rust abstract machine.
+/// represents a possible alignment in the Rust abstract machine.
 ///
 /// Note that particularly large alignments, while representable in this type,
 /// are likely not to be supported by actual allocators and linkers.
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 85a56d37ab7..0c69bf2aef9 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -48,8 +48,11 @@ impl<T: ?Sized> *const T {
             }
         }
 
+        #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
         // SAFETY: The two versions are equivalent at runtime.
-        unsafe { const_eval_select((self as *const u8,), const_impl, runtime_impl) }
+        unsafe {
+            const_eval_select((self as *const u8,), const_impl, runtime_impl)
+        }
     }
 
     /// Casts to a pointer of another type.
@@ -806,6 +809,7 @@ impl<T: ?Sized> *const T {
     where
         T: Sized,
     {
+        #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
         // SAFETY: The comparison has no side-effects, and the intrinsic
         // does this check internally in the CTFE implementation.
         unsafe {
@@ -1322,9 +1326,7 @@ impl<T: ?Sized> *const T {
     /// `align`.
     ///
     /// If it is not possible to align the pointer, the implementation returns
-    /// `usize::MAX`. It is permissible for the implementation to *always*
-    /// return `usize::MAX`. Only your algorithm's performance can depend
-    /// on getting a usable offset here, not its correctness.
+    /// `usize::MAX`.
     ///
     /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
     /// used with the `wrapping_add` method.
@@ -1333,6 +1335,15 @@ impl<T: ?Sized> *const T {
     /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
     /// the returned offset is correct in all terms other than alignment.
     ///
+    /// When this is called during compile-time evaluation (which is unstable), the implementation
+    /// may return `usize::MAX` in cases where that can never happen at runtime. This is because the
+    /// actual alignment of pointers is not known yet during compile-time, so an offset with
+    /// guaranteed alignment can sometimes not be computed. For example, a buffer declared as `[u8;
+    /// N]` might be allocated at an odd or an even address, but at compile-time this is not yet
+    /// known, so the execution has to be correct for either choice. It is therefore impossible to
+    /// find an offset that is guaranteed to be 2-aligned. (This behavior is subject to change, as usual
+    /// for unstable APIs.)
+    ///
     /// # Panics
     ///
     /// The function panics if `align` is not a power-of-two.
@@ -1623,8 +1634,11 @@ impl<T: ?Sized> *const T {
             ptr.align_offset(align) == 0
         }
 
+        #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
         // SAFETY: The two versions are equivalent at runtime.
-        unsafe { const_eval_select((self.cast::<()>(), align), const_impl, runtime_impl) }
+        unsafe {
+            const_eval_select((self.cast::<()>(), align), const_impl, runtime_impl)
+        }
     }
 }
 
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 389e0d680a0..caa8ffb271d 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -796,6 +796,17 @@ pub const fn from_mut<T: ?Sized>(r: &mut T) -> *mut T {
 /// let slice = ptr::slice_from_raw_parts(raw_pointer, 3);
 /// assert_eq!(unsafe { &*slice }[2], 7);
 /// ```
+///
+/// You must ensure that the pointer is valid and not null before dereferencing
+/// the raw slice. A slice reference must never have a null pointer, even if it's empty.
+///
+/// ```rust,should_panic
+/// use std::ptr;
+/// let danger: *const [u8] = ptr::slice_from_raw_parts(ptr::null(), 0);
+/// unsafe {
+///     danger.as_ref().expect("references must not be null");
+/// }
+/// ```
 #[inline]
 #[stable(feature = "slice_from_raw_parts", since = "1.42.0")]
 #[rustc_const_stable(feature = "const_slice_from_raw_parts", since = "1.64.0")]
@@ -805,11 +816,13 @@ pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
     from_raw_parts(data.cast(), len)
 }
 
+/// Forms a raw mutable slice from a pointer and a length.
+///
+/// The `len` argument is the number of **elements**, not the number of bytes.
+///
 /// Performs the same functionality as [`slice_from_raw_parts`], except that a
 /// raw mutable slice is returned, as opposed to a raw immutable slice.
 ///
-/// See the documentation of [`slice_from_raw_parts`] for more details.
-///
 /// This function is safe, but actually using the return value is unsafe.
 /// See the documentation of [`slice::from_raw_parts_mut`] for slice safety requirements.
 ///
@@ -830,6 +843,17 @@ pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
 ///
 /// assert_eq!(unsafe { &*slice }[2], 99);
 /// ```
+///
+/// You must ensure that the pointer is valid and not null before dereferencing
+/// the raw slice. A slice reference must never have a null pointer, even if it's empty.
+///
+/// ```rust,should_panic
+/// use std::ptr;
+/// let danger: *mut [u8] = ptr::slice_from_raw_parts_mut(ptr::null_mut(), 0);
+/// unsafe {
+///     danger.as_mut().expect("references must not be null");
+/// }
+/// ```
 #[inline]
 #[stable(feature = "slice_from_raw_parts", since = "1.42.0")]
 #[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")]
@@ -995,6 +1019,7 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
         };
     }
 
+    #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
     // SAFETY: the caller must guarantee that `x` and `y` are
     // valid for writes and properly aligned.
     unsafe {
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 28ba26f5c16..5ce3b1f298c 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -48,8 +48,11 @@ impl<T: ?Sized> *mut T {
             }
         }
 
+        #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
         // SAFETY: The two versions are equivalent at runtime.
-        unsafe { const_eval_select((self as *mut u8,), const_impl, runtime_impl) }
+        unsafe {
+            const_eval_select((self as *mut u8,), const_impl, runtime_impl)
+        }
     }
 
     /// Casts to a pointer of another type.
@@ -1586,9 +1589,7 @@ impl<T: ?Sized> *mut T {
     /// `align`.
     ///
     /// If it is not possible to align the pointer, the implementation returns
-    /// `usize::MAX`. It is permissible for the implementation to *always*
-    /// return `usize::MAX`. Only your algorithm's performance can depend
-    /// on getting a usable offset here, not its correctness.
+    /// `usize::MAX`.
     ///
     /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
     /// used with the `wrapping_add` method.
@@ -1597,6 +1598,15 @@ impl<T: ?Sized> *mut T {
     /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
     /// the returned offset is correct in all terms other than alignment.
     ///
+    /// When this is called during compile-time evaluation (which is unstable), the implementation
+    /// may return `usize::MAX` in cases where that can never happen at runtime. This is because the
+    /// actual alignment of pointers is not known yet during compile-time, so an offset with
+    /// guaranteed alignment can sometimes not be computed. For example, a buffer declared as `[u8;
+    /// N]` might be allocated at an odd or an even address, but at compile-time this is not yet
+    /// known, so the execution has to be correct for either choice. It is therefore impossible to
+    /// find an offset that is guaranteed to be 2-aligned. (This behavior is subject to change, as usual
+    /// for unstable APIs.)
+    ///
     /// # Panics
     ///
     /// The function panics if `align` is not a power-of-two.
@@ -1896,8 +1906,11 @@ impl<T: ?Sized> *mut T {
             ptr.align_offset(align) == 0
         }
 
+        #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
         // SAFETY: The two versions are equivalent at runtime.
-        unsafe { const_eval_select((self.cast::<()>(), align), const_impl, runtime_impl) }
+        unsafe {
+            const_eval_select((self.cast::<()>(), align), const_impl, runtime_impl)
+        }
     }
 }
 
diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs
index e8b0010ba15..5bee4d55135 100644
--- a/library/core/src/slice/cmp.rs
+++ b/library/core/src/slice/cmp.rs
@@ -24,7 +24,7 @@ where
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Eq> Eq for [T] {}
 
-/// Implements comparison of vectors [lexicographically](Ord#lexicographical-comparison).
+/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> Ord for [T] {
     fn cmp(&self, other: &[T]) -> Ordering {
@@ -32,7 +32,7 @@ impl<T: Ord> Ord for [T] {
     }
 }
 
-/// Implements comparison of vectors [lexicographically](Ord#lexicographical-comparison).
+/// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison).
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: PartialOrd> PartialOrd for [T] {
     fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index 0e2d45c4ada..c771ea70472 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -35,6 +35,7 @@ where
 #[track_caller]
 #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
 const fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
+    #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
     // SAFETY: we are just panicking here
     unsafe {
         const_eval_select(
@@ -63,6 +64,7 @@ const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! {
 #[track_caller]
 #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
 const fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
+    #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
     // SAFETY: we are just panicking here
     unsafe {
         const_eval_select((index, len), slice_end_index_len_fail_ct, slice_end_index_len_fail_rt)
@@ -87,8 +89,11 @@ const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! {
 #[track_caller]
 #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
 const fn slice_index_order_fail(index: usize, end: usize) -> ! {
+    #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
     // SAFETY: we are just panicking here
-    unsafe { const_eval_select((index, end), slice_index_order_fail_ct, slice_index_order_fail_rt) }
+    unsafe {
+        const_eval_select((index, end), slice_index_order_fail_ct, slice_index_order_fail_rt)
+    }
 }
 
 // FIXME const-hack
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index aaedbed0d55..2d5e091feaa 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -23,7 +23,7 @@ use crate::slice;
     issue = "none",
     reason = "exposed from core to be reused in std; use the memchr crate"
 )]
-/// Pure rust memchr implementation, taken from rust-memchr
+/// Pure Rust memchr implementation, taken from rust-memchr
 pub mod memchr;
 
 #[unstable(
@@ -3786,11 +3786,8 @@ impl<T> [T] {
     /// maintained.
     ///
     /// This method splits the slice into three distinct slices: prefix, correctly aligned middle
-    /// slice of a new type, and the suffix slice. How exactly the slice is split up is not
-    /// specified; the middle part may be smaller than necessary. However, if this fails to return a
-    /// maximal middle part, that is because code is running in a context where performance does not
-    /// matter, such as a sanitizer attempting to find alignment bugs. Regular code running
-    /// in a default (debug or release) execution *will* return a maximal middle part.
+    /// slice of a new type, and the suffix slice. The middle part will be as big as possible under
+    /// the given alignment constraint and element size.
     ///
     /// This method has no purpose when either input element `T` or output element `U` are
     /// zero-sized and will return the original slice without splitting anything.
@@ -3854,11 +3851,8 @@ impl<T> [T] {
     /// types is maintained.
     ///
     /// This method splits the slice into three distinct slices: prefix, correctly aligned middle
-    /// slice of a new type, and the suffix slice. How exactly the slice is split up is not
-    /// specified; the middle part may be smaller than necessary. However, if this fails to return a
-    /// maximal middle part, that is because code is running in a context where performance does not
-    /// matter, such as a sanitizer attempting to find alignment bugs. Regular code running
-    /// in a default (debug or release) execution *will* return a maximal middle part.
+    /// slice of a new type, and the suffix slice. The middle part will be as big as possible under
+    /// the given alignment constraint and element size.
     ///
     /// This method has no purpose when either input element `T` or output element `U` are
     /// zero-sized and will return the original slice without splitting anything.
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index f965a50058b..4943bbc45d0 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -86,6 +86,7 @@ use iter::{MatchesInternal, SplitNInternal};
 #[rustc_allow_const_fn_unstable(const_eval_select)]
 #[cfg(not(feature = "panic_immediate_abort"))]
 const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
+    #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // on bootstrap bump, remove unsafe block
     // SAFETY: panics for both branches
     unsafe {
         crate::intrinsics::const_eval_select(
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 45193c11e1d..00e75ec9a25 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -1092,7 +1092,7 @@ impl AtomicBool {
 
     /// Returns a mutable pointer to the underlying [`bool`].
     ///
-    /// Doing non-atomic reads and writes on the resulting integer can be a data race.
+    /// Doing non-atomic reads and writes on the resulting boolean can be a data race.
     /// This method is mostly useful for FFI, where the function signature may use
     /// `*mut bool` instead of `&AtomicBool`.
     ///
@@ -2031,7 +2031,7 @@ impl<T> AtomicPtr<T> {
 
     /// Returns a mutable pointer to the underlying pointer.
     ///
-    /// Doing non-atomic reads and writes on the resulting integer can be a data race.
+    /// Doing non-atomic reads and writes on the resulting pointer can be a data race.
     /// This method is mostly useful for FFI, where the function signature may use
     /// `*mut *mut T` instead of `&AtomicPtr<T>`.
     ///
diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs
index fa02dd52e00..e8170c13ed2 100644
--- a/library/core/src/sync/exclusive.rs
+++ b/library/core/src/sync/exclusive.rs
@@ -19,7 +19,7 @@ use core::task::{Context, Poll};
 ///
 /// Certain constructs like [`Future`]s can only be used with _exclusive_ access,
 /// and are often `Send` but not `Sync`, so `Exclusive` can be used as hint to the
-/// rust compiler that something is `Sync` in practice.
+/// Rust compiler that something is `Sync` in practice.
 ///
 /// ## Examples
 /// Using a non-`Sync` future prevents the wrapping struct from being `Sync`
diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs
index b54f2db88ff..8a1ba436f72 100644
--- a/library/proc_macro/src/bridge/client.rs
+++ b/library/proc_macro/src/bridge/client.rs
@@ -209,7 +209,7 @@ impl<'a> scoped_cell::ApplyL<'a> for BridgeStateL {
 
 thread_local! {
     static BRIDGE_STATE: scoped_cell::ScopedCell<BridgeStateL> =
-        scoped_cell::ScopedCell::new(BridgeState::NotConnected);
+        const { scoped_cell::ScopedCell::new(BridgeState::NotConnected) };
 }
 
 impl BridgeState<'_> {
diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs
index 8736d1806fb..0dbd4bac85c 100644
--- a/library/proc_macro/src/bridge/server.rs
+++ b/library/proc_macro/src/bridge/server.rs
@@ -223,7 +223,7 @@ thread_local! {
     /// This is required as the thread-local state in the proc_macro client does
     /// not handle being re-entered, and will invalidate all `Symbol`s when
     /// entering a nested macro.
-    static ALREADY_RUNNING_SAME_THREAD: Cell<bool> = Cell::new(false);
+    static ALREADY_RUNNING_SAME_THREAD: Cell<bool> = const { Cell::new(false) };
 }
 
 /// Keep `ALREADY_RUNNING_SAME_THREAD` (see also its documentation)
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index e44da8e637e..8927e9a47fa 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -157,7 +157,7 @@ impl OsString {
     /// # Safety
     ///
     /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of
-    /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same rust version
+    /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version
     /// built for the same target platform.  For example, reconstructing an `OsString` from bytes sent
     /// over the network or stored in a file will likely violate these safety rules.
     ///
@@ -213,7 +213,7 @@ impl OsString {
     /// ASCII.
     ///
     /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should
-    /// be treated as opaque and only comparable within the same rust version built for the same
+    /// be treated as opaque and only comparable within the same Rust version built for the same
     /// target platform.  For example, sending the bytes over the network or storing it in a file
     /// will likely result in incompatible data.  See [`OsString`] for more encoding details
     /// and [`std::ffi`] for platform-specific, specified conversions.
@@ -747,7 +747,7 @@ impl OsStr {
     /// # Safety
     ///
     /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of
-    /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same rust version
+    /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version
     /// built for the same target platform.  For example, reconstructing an `OsStr` from bytes sent
     /// over the network or stored in a file will likely violate these safety rules.
     ///
@@ -955,7 +955,7 @@ impl OsStr {
     /// ASCII.
     ///
     /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should
-    /// be treated as opaque and only comparable within the same rust version built for the same
+    /// be treated as opaque and only comparable within the same Rust version built for the same
     /// target platform.  For example, sending the slice over the network or storing it in a file
     /// will likely result in incompatible byte slices.  See [`OsString`] for more encoding details
     /// and [`std::ffi`] for platform-specific, specified conversions.
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 694cc34cdc1..4373a1721e1 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -248,10 +248,10 @@ pub struct DirBuilder {
 ///
 /// ```no_run
 /// use std::fs;
-/// use std::net::SocketAddr;
 ///
 /// fn main() -> Result<(), Box<dyn std::error::Error + 'static>> {
-///     let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?;
+///     let data: Vec<u8> = fs::read("image.jpg")?;
+///     assert_eq!(data[0..3], [0xFF, 0xD8, 0xFF]);
 ///     Ok(())
 /// }
 /// ```
@@ -290,11 +290,11 @@ pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
 ///
 /// ```no_run
 /// use std::fs;
-/// use std::net::SocketAddr;
 /// use std::error::Error;
 ///
 /// fn main() -> Result<(), Box<dyn Error>> {
-///     let foo: SocketAddr = fs::read_to_string("address.txt")?.parse()?;
+///     let message: String = fs::read_to_string("message.txt")?;
+///     println!("{}", message);
 ///     Ok(())
 /// }
 /// ```
diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs
index 665d8602c08..2d13230ffba 100644
--- a/library/std/src/io/buffered/bufwriter.rs
+++ b/library/std/src/io/buffered/bufwriter.rs
@@ -554,35 +554,38 @@ impl<W: ?Sized + Write> Write for BufWriter<W> {
             // same underlying buffer, as otherwise the buffers wouldn't fit in memory). If the
             // computation overflows, then surely the input cannot fit in our buffer, so we forward
             // to the inner writer's `write_vectored` method to let it handle it appropriately.
-            let saturated_total_len =
-                bufs.iter().fold(0usize, |acc, b| acc.saturating_add(b.len()));
+            let mut saturated_total_len: usize = 0;
 
-            if saturated_total_len > self.spare_capacity() {
-                // Flush if the total length of the input exceeds our buffer's spare capacity.
-                // If we would have overflowed, this condition also holds, and we need to flush.
-                self.flush_buf()?;
+            for buf in bufs {
+                saturated_total_len = saturated_total_len.saturating_add(buf.len());
+
+                if saturated_total_len > self.spare_capacity() && !self.buf.is_empty() {
+                    // Flush if the total length of the input exceeds our buffer's spare capacity.
+                    // If we would have overflowed, this condition also holds, and we need to flush.
+                    self.flush_buf()?;
+                }
+
+                if saturated_total_len >= self.buf.capacity() {
+                    // Forward to our inner writer if the total length of the input is greater than or
+                    // equal to our buffer capacity. If we would have overflowed, this condition also
+                    // holds, and we punt to the inner writer.
+                    self.panicked = true;
+                    let r = self.get_mut().write_vectored(bufs);
+                    self.panicked = false;
+                    return r;
+                }
             }
 
-            if saturated_total_len >= self.buf.capacity() {
-                // Forward to our inner writer if the total length of the input is greater than or
-                // equal to our buffer capacity. If we would have overflowed, this condition also
-                // holds, and we punt to the inner writer.
-                self.panicked = true;
-                let r = self.get_mut().write_vectored(bufs);
-                self.panicked = false;
-                r
-            } else {
-                // `saturated_total_len < self.buf.capacity()` implies that we did not saturate.
+            // `saturated_total_len < self.buf.capacity()` implies that we did not saturate.
 
-                // SAFETY: We checked whether or not the spare capacity was large enough above. If
-                // it was, then we're safe already. If it wasn't, we flushed, making sufficient
-                // room for any input <= the buffer size, which includes this input.
-                unsafe {
-                    bufs.iter().for_each(|b| self.write_to_buffer_unchecked(b));
-                };
+            // SAFETY: We checked whether or not the spare capacity was large enough above. If
+            // it was, then we're safe already. If it wasn't, we flushed, making sufficient
+            // room for any input <= the buffer size, which includes this input.
+            unsafe {
+                bufs.iter().for_each(|b| self.write_to_buffer_unchecked(b));
+            };
 
-                Ok(saturated_total_len)
-            }
+            Ok(saturated_total_len)
         } else {
             let mut iter = bufs.iter();
             let mut total_written = if let Some(buf) = iter.by_ref().find(|&buf| !buf.is_empty()) {
diff --git a/library/std/src/io/buffered/linewritershim.rs b/library/std/src/io/buffered/linewritershim.rs
index 7eadfd41366..c3ac7855d44 100644
--- a/library/std/src/io/buffered/linewritershim.rs
+++ b/library/std/src/io/buffered/linewritershim.rs
@@ -175,6 +175,10 @@ impl<'a, W: ?Sized + Write> Write for LineWriterShim<'a, W> {
         }
 
         // Find the buffer containing the last newline
+        // FIXME: This is overly slow if there are very many bufs and none contain
+        // newlines. e.g. writev() on Linux only writes up to 1024 slices, so
+        // scanning the rest is wasted effort. This makes write_all_vectored()
+        // quadratic.
         let last_newline_buf_idx = bufs
             .iter()
             .enumerate()
@@ -215,9 +219,14 @@ impl<'a, W: ?Sized + Write> Write for LineWriterShim<'a, W> {
 
         // Don't try to reconstruct the exact amount written; just bail
         // in the event of a partial write
-        let lines_len = lines.iter().map(|buf| buf.len()).sum();
-        if flushed < lines_len {
-            return Ok(flushed);
+        let mut lines_len: usize = 0;
+        for buf in lines {
+            // With overlapping/duplicate slices the total length may in theory
+            // exceed usize::MAX
+            lines_len = lines_len.saturating_add(buf.len());
+            if flushed < lines_len {
+                return Ok(flushed);
+            }
         }
 
         // Now that the write has succeeded, buffer the rest (or as much of the
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 455de6d98ba..42fc0053030 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -128,8 +128,8 @@ impl Write for StdoutRaw {
     }
 
     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        let total = bufs.iter().map(|b| b.len()).sum();
-        handle_ebadf(self.0.write_vectored(bufs), total)
+        let total = || bufs.iter().map(|b| b.len()).sum();
+        handle_ebadf_lazy(self.0.write_vectored(bufs), total)
     }
 
     #[inline]
@@ -160,8 +160,8 @@ impl Write for StderrRaw {
     }
 
     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        let total = bufs.iter().map(|b| b.len()).sum();
-        handle_ebadf(self.0.write_vectored(bufs), total)
+        let total = || bufs.iter().map(|b| b.len()).sum();
+        handle_ebadf_lazy(self.0.write_vectored(bufs), total)
     }
 
     #[inline]
@@ -193,6 +193,13 @@ fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
     }
 }
 
+fn handle_ebadf_lazy<T>(r: io::Result<T>, default: impl FnOnce() -> T) -> io::Result<T> {
+    match r {
+        Err(ref e) if stdio::is_ebadf(e) => Ok(default()),
+        r => r,
+    }
+}
+
 /// A handle to the standard input stream of a process.
 ///
 /// Each handle is a shared reference to a global buffer of input data to this
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 288cce3aa08..55a5292a4a4 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -84,7 +84,7 @@
 //!
 //! # Contributing changes to the documentation
 //!
-//! Check out the rust contribution guidelines [here](
+//! Check out the Rust contribution guidelines [here](
 //! https://rustc-dev-guide.rust-lang.org/contributing.html#writing-documentation).
 //! The source for this documentation can be found on
 //! [GitHub](https://github.com/rust-lang/rust).
diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs
index b24b851a645..ec8b62f9687 100644
--- a/library/std/src/net/tcp/tests.rs
+++ b/library/std/src/net/tcp/tests.rs
@@ -544,30 +544,33 @@ fn close_readwrite_smoke() {
 }
 
 #[test]
+// FIXME: https://github.com/fortanix/rust-sgx/issues/110
 #[cfg_attr(target_env = "sgx", ignore)]
+// On windows, shutdown will not wake up blocking I/O operations.
+#[cfg_attr(windows, ignore)]
 fn close_read_wakes_up() {
     each_ip(&mut |addr| {
-        let a = t!(TcpListener::bind(&addr));
-        let (tx1, rx) = channel::<()>();
+        let listener = t!(TcpListener::bind(&addr));
         let _t = thread::spawn(move || {
-            let _s = t!(a.accept());
-            let _ = rx.recv();
+            let (stream, _) = t!(listener.accept());
+            stream
         });
 
-        let s = t!(TcpStream::connect(&addr));
-        let s2 = t!(s.try_clone());
-        let (tx, rx) = channel();
-        let _t = thread::spawn(move || {
-            let mut s2 = s2;
-            assert_eq!(t!(s2.read(&mut [0])), 0);
-            tx.send(()).unwrap();
-        });
-        // this should wake up the child thread
-        t!(s.shutdown(Shutdown::Read));
+        let mut stream = t!(TcpStream::connect(&addr));
+        let stream2 = t!(stream.try_clone());
 
-        // this test will never finish if the child doesn't wake up
-        rx.recv().unwrap();
-        drop(tx1);
+        let _t = thread::spawn(move || {
+            let stream2 = stream2;
+
+            // to make it more likely that `read` happens before `shutdown`
+            thread::sleep(Duration::from_millis(1000));
+
+            // this should wake up the reader up
+            t!(stream2.shutdown(Shutdown::Read));
+        });
+
+        // this `read` should get interrupted by `shutdown`
+        assert_eq!(t!(stream.read(&mut [0])), 0);
     })
 }
 
diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs
index 5ba8719e6ff..b0633fd7bfc 100644
--- a/library/std/src/os/unix/mod.rs
+++ b/library/std/src/os/unix/mod.rs
@@ -95,22 +95,6 @@ pub mod process;
 pub mod raw;
 pub mod thread;
 
-#[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")]
-#[cfg(any(
-    target_os = "android",
-    target_os = "linux",
-    target_os = "dragonfly",
-    target_os = "freebsd",
-    target_os = "ios",
-    target_os = "tvos",
-    target_os = "watchos",
-    target_os = "macos",
-    target_os = "netbsd",
-    target_os = "openbsd",
-    target_os = "nto",
-))]
-pub mod ucred;
-
 /// A prelude for conveniently writing platform-specific code.
 ///
 /// Includes all extension traits, and some important type definitions.
diff --git a/library/std/src/os/unix/net/mod.rs b/library/std/src/os/unix/net/mod.rs
index 6da3e350bf1..28c1188677b 100644
--- a/library/std/src/os/unix/net/mod.rs
+++ b/library/std/src/os/unix/net/mod.rs
@@ -12,6 +12,20 @@ mod listener;
 mod stream;
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests;
+#[cfg(any(
+    target_os = "android",
+    target_os = "linux",
+    target_os = "dragonfly",
+    target_os = "freebsd",
+    target_os = "ios",
+    target_os = "tvos",
+    target_os = "watchos",
+    target_os = "macos",
+    target_os = "netbsd",
+    target_os = "openbsd",
+    target_os = "nto",
+))]
+mod ucred;
 
 #[stable(feature = "unix_socket", since = "1.10.0")]
 pub use self::addr::*;
@@ -24,3 +38,18 @@ pub use self::datagram::*;
 pub use self::listener::*;
 #[stable(feature = "unix_socket", since = "1.10.0")]
 pub use self::stream::*;
+#[cfg(any(
+    target_os = "android",
+    target_os = "linux",
+    target_os = "dragonfly",
+    target_os = "freebsd",
+    target_os = "ios",
+    target_os = "tvos",
+    target_os = "watchos",
+    target_os = "macos",
+    target_os = "netbsd",
+    target_os = "openbsd",
+    target_os = "nto",
+))]
+#[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")]
+pub use self::ucred::*;
diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs
index b1cd504e219..069cb299e28 100644
--- a/library/std/src/os/unix/net/stream.rs
+++ b/library/std/src/os/unix/net/stream.rs
@@ -1,3 +1,16 @@
+#[cfg(any(
+    target_os = "android",
+    target_os = "linux",
+    target_os = "dragonfly",
+    target_os = "freebsd",
+    target_os = "ios",
+    target_os = "tvos",
+    target_os = "macos",
+    target_os = "watchos",
+    target_os = "netbsd",
+    target_os = "openbsd"
+))]
+use super::{peer_cred, UCred};
 #[cfg(any(doc, target_os = "android", target_os = "linux"))]
 use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary};
 use super::{sockaddr_un, SocketAddr};
@@ -5,40 +18,12 @@ use crate::fmt;
 use crate::io::{self, IoSlice, IoSliceMut};
 use crate::net::Shutdown;
 use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
-#[cfg(any(
-    target_os = "android",
-    target_os = "linux",
-    target_os = "dragonfly",
-    target_os = "freebsd",
-    target_os = "ios",
-    target_os = "tvos",
-    target_os = "macos",
-    target_os = "watchos",
-    target_os = "netbsd",
-    target_os = "openbsd"
-))]
-use crate::os::unix::ucred;
 use crate::path::Path;
 use crate::sys::cvt;
 use crate::sys::net::Socket;
 use crate::sys_common::{AsInner, FromInner};
 use crate::time::Duration;
 
-#[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")]
-#[cfg(any(
-    target_os = "android",
-    target_os = "linux",
-    target_os = "dragonfly",
-    target_os = "freebsd",
-    target_os = "ios",
-    target_os = "tvos",
-    target_os = "macos",
-    target_os = "watchos",
-    target_os = "netbsd",
-    target_os = "openbsd"
-))]
-pub use ucred::UCred;
-
 /// A Unix stream socket.
 ///
 /// # Examples
@@ -247,7 +232,7 @@ impl UnixStream {
         target_os = "openbsd"
     ))]
     pub fn peer_cred(&self) -> io::Result<UCred> {
-        ucred::peer_cred(self)
+        peer_cred(self)
     }
 
     /// Sets the read timeout for the socket.
diff --git a/library/std/src/os/unix/ucred.rs b/library/std/src/os/unix/net/ucred.rs
similarity index 95%
rename from library/std/src/os/unix/ucred.rs
rename to library/std/src/os/unix/net/ucred.rs
index 6efa74182cc..de09c93840a 100644
--- a/library/std/src/os/unix/ucred.rs
+++ b/library/std/src/os/unix/net/ucred.rs
@@ -1,5 +1,3 @@
-//! Unix peer credentials.
-
 // NOTE: Code in this file is heavily based on work done in PR 13 from the tokio-uds repository on
 //       GitHub.
 //
@@ -26,7 +24,7 @@ pub struct UCred {
 }
 
 #[cfg(any(target_os = "android", target_os = "linux"))]
-pub use self::impl_linux::peer_cred;
+pub(super) use self::impl_linux::peer_cred;
 
 #[cfg(any(
     target_os = "dragonfly",
@@ -34,13 +32,13 @@ pub use self::impl_linux::peer_cred;
     target_os = "openbsd",
     target_os = "netbsd"
 ))]
-pub use self::impl_bsd::peer_cred;
+pub(super) use self::impl_bsd::peer_cred;
 
 #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
-pub use self::impl_mac::peer_cred;
+pub(super) use self::impl_mac::peer_cred;
 
 #[cfg(any(target_os = "linux", target_os = "android"))]
-pub mod impl_linux {
+mod impl_linux {
     use super::UCred;
     use crate::os::unix::io::AsRawFd;
     use crate::os::unix::net::UnixStream;
@@ -82,7 +80,7 @@ pub mod impl_linux {
     target_os = "netbsd",
     target_os = "nto",
 ))]
-pub mod impl_bsd {
+mod impl_bsd {
     use super::UCred;
     use crate::io;
     use crate::os::unix::io::AsRawFd;
@@ -99,7 +97,7 @@ pub mod impl_bsd {
 }
 
 #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
-pub mod impl_mac {
+mod impl_mac {
     use super::UCred;
     use crate::os::unix::io::AsRawFd;
     use crate::os::unix::net::UnixStream;
diff --git a/library/std/src/os/unix/ucred/tests.rs b/library/std/src/os/unix/net/ucred/tests.rs
similarity index 100%
rename from library/std/src/os/unix/ucred/tests.rs
rename to library/std/src/os/unix/net/ucred/tests.rs
diff --git a/library/std/src/sys/locks/condvar/mod.rs b/library/std/src/sys/locks/condvar/mod.rs
index 126a42a2a4c..6849cacf88e 100644
--- a/library/std/src/sys/locks/condvar/mod.rs
+++ b/library/std/src/sys/locks/condvar/mod.rs
@@ -1,5 +1,6 @@
 cfg_if::cfg_if! {
     if #[cfg(any(
+        all(target_os = "windows", not(target_vendor="win7")),
         target_os = "linux",
         target_os = "android",
         target_os = "freebsd",
@@ -14,9 +15,9 @@ cfg_if::cfg_if! {
     } else if #[cfg(target_family = "unix")] {
         mod pthread;
         pub use pthread::Condvar;
-    } else if #[cfg(target_os = "windows")] {
-        mod windows;
-        pub use windows::Condvar;
+    } else if #[cfg(all(target_os = "windows", target_vendor = "win7"))] {
+        mod windows7;
+        pub use windows7::Condvar;
     } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
         mod sgx;
         pub use sgx::Condvar;
diff --git a/library/std/src/sys/locks/condvar/windows.rs b/library/std/src/sys/locks/condvar/windows7.rs
similarity index 100%
rename from library/std/src/sys/locks/condvar/windows.rs
rename to library/std/src/sys/locks/condvar/windows7.rs
diff --git a/library/std/src/sys/locks/mutex/futex.rs b/library/std/src/sys/locks/mutex/futex.rs
index c01229586c3..7427cae94d6 100644
--- a/library/std/src/sys/locks/mutex/futex.rs
+++ b/library/std/src/sys/locks/mutex/futex.rs
@@ -1,30 +1,42 @@
 use crate::sync::atomic::{
-    AtomicU32,
+    self,
     Ordering::{Acquire, Relaxed, Release},
 };
 use crate::sys::futex::{futex_wait, futex_wake};
 
-pub struct Mutex {
-    /// 0: unlocked
-    /// 1: locked, no other threads waiting
-    /// 2: locked, and other threads waiting (contended)
-    futex: AtomicU32,
+cfg_if::cfg_if! {
+if #[cfg(windows)] {
+    // On Windows we can have a smol futex
+    type Atomic = atomic::AtomicU8;
+    type State = u8;
+} else {
+    type Atomic = atomic::AtomicU32;
+    type State = u32;
 }
+}
+
+pub struct Mutex {
+    futex: Atomic,
+}
+
+const UNLOCKED: State = 0;
+const LOCKED: State = 1; // locked, no other threads waiting
+const CONTENDED: State = 2; // locked, and other threads waiting (contended)
 
 impl Mutex {
     #[inline]
     pub const fn new() -> Self {
-        Self { futex: AtomicU32::new(0) }
+        Self { futex: Atomic::new(UNLOCKED) }
     }
 
     #[inline]
     pub fn try_lock(&self) -> bool {
-        self.futex.compare_exchange(0, 1, Acquire, Relaxed).is_ok()
+        self.futex.compare_exchange(UNLOCKED, LOCKED, Acquire, Relaxed).is_ok()
     }
 
     #[inline]
     pub fn lock(&self) {
-        if self.futex.compare_exchange(0, 1, Acquire, Relaxed).is_err() {
+        if self.futex.compare_exchange(UNLOCKED, LOCKED, Acquire, Relaxed).is_err() {
             self.lock_contended();
         }
     }
@@ -36,8 +48,8 @@ impl Mutex {
 
         // If it's unlocked now, attempt to take the lock
         // without marking it as contended.
-        if state == 0 {
-            match self.futex.compare_exchange(0, 1, Acquire, Relaxed) {
+        if state == UNLOCKED {
+            match self.futex.compare_exchange(UNLOCKED, LOCKED, Acquire, Relaxed) {
                 Ok(_) => return, // Locked!
                 Err(s) => state = s,
             }
@@ -45,31 +57,31 @@ impl Mutex {
 
         loop {
             // Put the lock in contended state.
-            // We avoid an unnecessary write if it as already set to 2,
+            // We avoid an unnecessary write if it as already set to CONTENDED,
             // to be friendlier for the caches.
-            if state != 2 && self.futex.swap(2, Acquire) == 0 {
-                // We changed it from 0 to 2, so we just successfully locked it.
+            if state != CONTENDED && self.futex.swap(CONTENDED, Acquire) == UNLOCKED {
+                // We changed it from UNLOCKED to CONTENDED, so we just successfully locked it.
                 return;
             }
 
-            // Wait for the futex to change state, assuming it is still 2.
-            futex_wait(&self.futex, 2, None);
+            // Wait for the futex to change state, assuming it is still CONTENDED.
+            futex_wait(&self.futex, CONTENDED, None);
 
             // Spin again after waking up.
             state = self.spin();
         }
     }
 
-    fn spin(&self) -> u32 {
+    fn spin(&self) -> State {
         let mut spin = 100;
         loop {
             // We only use `load` (and not `swap` or `compare_exchange`)
             // while spinning, to be easier on the caches.
             let state = self.futex.load(Relaxed);
 
-            // We stop spinning when the mutex is unlocked (0),
-            // but also when it's contended (2).
-            if state != 1 || spin == 0 {
+            // We stop spinning when the mutex is UNLOCKED,
+            // but also when it's CONTENDED.
+            if state != LOCKED || spin == 0 {
                 return state;
             }
 
@@ -80,9 +92,9 @@ impl Mutex {
 
     #[inline]
     pub unsafe fn unlock(&self) {
-        if self.futex.swap(0, Release) == 2 {
+        if self.futex.swap(UNLOCKED, Release) == CONTENDED {
             // We only wake up one thread. When that thread locks the mutex, it
-            // will mark the mutex as contended (2) (see lock_contended above),
+            // will mark the mutex as CONTENDED (see lock_contended above),
             // which makes sure that any other waiting threads will also be
             // woken up eventually.
             self.wake();
diff --git a/library/std/src/sys/locks/mutex/mod.rs b/library/std/src/sys/locks/mutex/mod.rs
index 710cb91fb14..73d9bd273de 100644
--- a/library/std/src/sys/locks/mutex/mod.rs
+++ b/library/std/src/sys/locks/mutex/mod.rs
@@ -1,5 +1,6 @@
 cfg_if::cfg_if! {
     if #[cfg(any(
+        all(target_os = "windows", not(target_vendor = "win7")),
         target_os = "linux",
         target_os = "android",
         target_os = "freebsd",
@@ -19,9 +20,9 @@ cfg_if::cfg_if! {
     ))] {
         mod pthread;
         pub use pthread::{Mutex, raw};
-    } else if #[cfg(target_os = "windows")] {
-        mod windows;
-        pub use windows::{Mutex, raw};
+    } else if #[cfg(all(target_os = "windows", target_vendor = "win7"))] {
+        mod windows7;
+        pub use windows7::{Mutex, raw};
     } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
         mod sgx;
         pub use sgx::Mutex;
diff --git a/library/std/src/sys/locks/mutex/windows.rs b/library/std/src/sys/locks/mutex/windows7.rs
similarity index 100%
rename from library/std/src/sys/locks/mutex/windows.rs
rename to library/std/src/sys/locks/mutex/windows7.rs
diff --git a/library/std/src/sys/locks/rwlock/mod.rs b/library/std/src/sys/locks/rwlock/mod.rs
index 0564f1fe6fa..675931c64bd 100644
--- a/library/std/src/sys/locks/rwlock/mod.rs
+++ b/library/std/src/sys/locks/rwlock/mod.rs
@@ -1,5 +1,6 @@
 cfg_if::cfg_if! {
     if #[cfg(any(
+        all(target_os = "windows", not(target_vendor = "win7")),
         target_os = "linux",
         target_os = "android",
         target_os = "freebsd",
@@ -14,9 +15,9 @@ cfg_if::cfg_if! {
     } else if #[cfg(target_family = "unix")] {
         mod queue;
         pub use queue::RwLock;
-    } else if #[cfg(target_os = "windows")] {
-        mod windows;
-        pub use windows::RwLock;
+    } else if #[cfg(all(target_os = "windows", target_vendor = "win7"))] {
+        mod windows7;
+        pub use windows7::RwLock;
     } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
         mod sgx;
         pub use sgx::RwLock;
diff --git a/library/std/src/sys/locks/rwlock/windows.rs b/library/std/src/sys/locks/rwlock/windows7.rs
similarity index 100%
rename from library/std/src/sys/locks/rwlock/windows.rs
rename to library/std/src/sys/locks/rwlock/windows7.rs
diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs
index f289dafd8bc..319b835a768 100644
--- a/library/std/src/sys/pal/hermit/time.rs
+++ b/library/std/src/sys/pal/hermit/time.rs
@@ -179,7 +179,7 @@ impl Sub<Instant> for Instant {
     ///
     /// # Panics
     ///
-    /// Previous rust versions panicked when `other` was later than `self`. Currently this
+    /// Previous Rust versions panicked when `other` was later than `self`. Currently this
     /// method saturates. Future versions may reintroduce the panic in some circumstances.
     /// See [Monotonicity].
     ///
diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs
index afa92409404..584e17cd196 100644
--- a/library/std/src/sys/pal/windows/c.rs
+++ b/library/std/src/sys/pal/windows/c.rs
@@ -36,6 +36,7 @@ pub type LPVOID = *mut c_void;
 pub type LPWCH = *mut WCHAR;
 pub type LPWSTR = *mut WCHAR;
 
+#[cfg(target_vendor = "win7")]
 pub type PSRWLOCK = *mut SRWLOCK;
 
 pub type socklen_t = c_int;
@@ -50,7 +51,9 @@ pub const INVALID_HANDLE_VALUE: HANDLE = ::core::ptr::without_provenance_mut(-1i
 pub const EXIT_SUCCESS: u32 = 0;
 pub const EXIT_FAILURE: u32 = 1;
 
+#[cfg(target_vendor = "win7")]
 pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { Ptr: ptr::null_mut() };
+#[cfg(target_vendor = "win7")]
 pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { Ptr: ptr::null_mut() };
 pub const INIT_ONCE_STATIC_INIT: INIT_ONCE = INIT_ONCE { Ptr: ptr::null_mut() };
 
@@ -373,6 +376,7 @@ extern "system" {
         dwmilliseconds: u32,
     ) -> BOOL;
     pub fn WakeByAddressSingle(address: *const c_void);
+    pub fn WakeByAddressAll(address: *const c_void);
 }
 
 #[cfg(target_vendor = "win7")]
diff --git a/library/std/src/sys/pal/windows/futex.rs b/library/std/src/sys/pal/windows/futex.rs
new file mode 100644
index 00000000000..bc19c402d9c
--- /dev/null
+++ b/library/std/src/sys/pal/windows/futex.rs
@@ -0,0 +1,85 @@
+use super::api;
+use crate::sys::c;
+use crate::sys::dur2timeout;
+use core::ffi::c_void;
+use core::mem;
+use core::ptr;
+use core::sync::atomic::{
+    AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16,
+    AtomicU32, AtomicU64, AtomicU8, AtomicUsize,
+};
+use core::time::Duration;
+
+pub unsafe trait Waitable {
+    type Atomic;
+}
+macro_rules! unsafe_waitable_int {
+    ($(($int:ty, $atomic:ty)),*$(,)?) => {
+        $(
+            unsafe impl Waitable for $int {
+                type Atomic = $atomic;
+            }
+        )*
+    };
+}
+unsafe_waitable_int! {
+    (bool, AtomicBool),
+    (i8, AtomicI8),
+    (i16, AtomicI16),
+    (i32, AtomicI32),
+    (i64, AtomicI64),
+    (isize, AtomicIsize),
+    (u8, AtomicU8),
+    (u16, AtomicU16),
+    (u32, AtomicU32),
+    (u64, AtomicU64),
+    (usize, AtomicUsize),
+}
+unsafe impl<T> Waitable for *const T {
+    type Atomic = AtomicPtr<T>;
+}
+unsafe impl<T> Waitable for *mut T {
+    type Atomic = AtomicPtr<T>;
+}
+
+pub fn wait_on_address<W: Waitable>(
+    address: &W::Atomic,
+    compare: W,
+    timeout: Option<Duration>,
+) -> bool {
+    unsafe {
+        let addr = ptr::from_ref(address).cast::<c_void>();
+        let size = mem::size_of::<W>();
+        let compare_addr = ptr::addr_of!(compare).cast::<c_void>();
+        let timeout = timeout.map(dur2timeout).unwrap_or(c::INFINITE);
+        c::WaitOnAddress(addr, compare_addr, size, timeout) == c::TRUE
+    }
+}
+
+pub fn wake_by_address_single<T>(address: &T) {
+    unsafe {
+        let addr = ptr::from_ref(address).cast::<c_void>();
+        c::WakeByAddressSingle(addr);
+    }
+}
+
+pub fn wake_by_address_all<T>(address: &T) {
+    unsafe {
+        let addr = ptr::from_ref(address).cast::<c_void>();
+        c::WakeByAddressAll(addr);
+    }
+}
+
+pub fn futex_wait<W: Waitable>(futex: &W::Atomic, expected: W, timeout: Option<Duration>) -> bool {
+    // return false only on timeout
+    wait_on_address(futex, expected, timeout) || api::get_last_error().code != c::ERROR_TIMEOUT
+}
+
+pub fn futex_wake<T>(futex: &T) -> bool {
+    wake_by_address_single(futex);
+    false
+}
+
+pub fn futex_wake_all<T>(futex: &T) {
+    wake_by_address_all(futex)
+}
diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs
index a53c4034d06..6a561518fad 100644
--- a/library/std/src/sys/pal/windows/mod.rs
+++ b/library/std/src/sys/pal/windows/mod.rs
@@ -17,6 +17,8 @@ pub mod args;
 pub mod c;
 pub mod env;
 pub mod fs;
+#[cfg(not(target_vendor = "win7"))]
+pub mod futex;
 pub mod handle;
 pub mod io;
 pub mod net;
diff --git a/library/std/src/sys/pal/windows/thread.rs b/library/std/src/sys/pal/windows/thread.rs
index a8f1e9b726b..970bd9c6ce7 100644
--- a/library/std/src/sys/pal/windows/thread.rs
+++ b/library/std/src/sys/pal/windows/thread.rs
@@ -26,11 +26,8 @@ impl Thread {
     pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
         let p = Box::into_raw(Box::new(p));
 
-        // FIXME On UNIX, we guard against stack sizes that are too small but
-        // that's because pthreads enforces that stacks are at least
-        // PTHREAD_STACK_MIN bytes big. Windows has no such lower limit, it's
-        // just that below a certain threshold you can't do anything useful.
-        // That threshold is application and architecture-specific, however.
+        // CreateThread rounds up values for the stack size to the nearest page size (at least 4kb).
+        // If a value of zero is given then the default stack size is used instead.
         let ret = c::CreateThread(
             ptr::null_mut(),
             stack,
diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs
index efd06c8df6e..589a5fdad1d 100644
--- a/library/std/src/thread/tests.rs
+++ b/library/std/src/thread/tests.rs
@@ -70,7 +70,7 @@ fn test_named_thread_truncation() {
 }
 
 #[cfg(any(
-    target_os = "windows",
+    all(target_os = "windows", not(target_vendor = "win7")),
     target_os = "linux",
     target_os = "macos",
     target_os = "ios",
@@ -80,6 +80,7 @@ fn test_named_thread_truncation() {
 #[test]
 fn test_get_os_named_thread() {
     use crate::sys::thread::Thread;
+    // Spawn a new thread to avoid interfering with other tests running on this thread.
     let handler = thread::spawn(|| {
         let name = c"test me please";
         Thread::set_name(name);
@@ -423,3 +424,16 @@ fn scope_join_race() {
         });
     }
 }
+
+// Test that the smallest value for stack_size works on Windows.
+#[cfg(windows)]
+#[test]
+fn test_minimal_thread_stack() {
+    use crate::sync::atomic::AtomicU8;
+    static COUNT: AtomicU8 = AtomicU8::new(0);
+
+    let builder = thread::Builder::new().stack_size(1);
+    let before = builder.spawn(|| COUNT.fetch_add(1, Ordering::Relaxed)).unwrap().join().unwrap();
+    assert_eq!(before, 0);
+    assert_eq!(COUNT.load(Ordering::Relaxed), 1);
+}
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index 91c010ef2b5..6f1a354d28a 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -59,7 +59,7 @@ pub use core::time::TryFromFloatSecsError;
 /// experience time dilation (slow down or speed up), but it will never go
 /// backwards.
 /// As part of this non-guarantee it is also not specified whether system suspends count as
-/// elapsed time or not. The behavior varies across platforms and rust versions.
+/// elapsed time or not. The behavior varies across platforms and Rust versions.
 ///
 /// Instants are opaque types that can only be compared to one another. There is
 /// no method to get "the number of seconds" from an instant. Instead, it only
@@ -142,7 +142,7 @@ pub use core::time::TryFromFloatSecsError;
 /// where monotonicity is violated, or `Instant`s are subtracted in the wrong order.
 ///
 /// This workaround obscures programming errors where earlier and later instants are accidentally
-/// swapped. For this reason future rust versions may reintroduce panics.
+/// swapped. For this reason future Rust versions may reintroduce panics.
 ///
 /// [tier 1]: https://doc.rust-lang.org/rustc/platform-support.html
 /// [`duration_since`]: Instant::duration_since
@@ -290,7 +290,7 @@ impl Instant {
     ///
     /// # Panics
     ///
-    /// Previous rust versions panicked when `earlier` was later than `self`. Currently this
+    /// Previous Rust versions panicked when `earlier` was later than `self`. Currently this
     /// method saturates. Future versions may reintroduce the panic in some circumstances.
     /// See [Monotonicity].
     ///
@@ -365,7 +365,7 @@ impl Instant {
     ///
     /// # Panics
     ///
-    /// Previous rust versions panicked when the current time was earlier than self. Currently this
+    /// Previous Rust versions panicked when the current time was earlier than self. Currently this
     /// method returns a Duration of zero in that case. Future versions may reintroduce the panic.
     /// See [Monotonicity].
     ///
@@ -450,7 +450,7 @@ impl Sub<Instant> for Instant {
     ///
     /// # Panics
     ///
-    /// Previous rust versions panicked when `other` was later than `self`. Currently this
+    /// Previous Rust versions panicked when `other` was later than `self`. Currently this
     /// method saturates. Future versions may reintroduce the panic in some circumstances.
     /// See [Monotonicity].
     ///
diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs
index 2931ca6ead0..875c66e5fa3 100644
--- a/library/test/src/formatters/terse.rs
+++ b/library/test/src/formatters/terse.rs
@@ -23,6 +23,7 @@ pub(crate) struct TerseFormatter<T> {
     max_name_len: usize,
 
     test_count: usize,
+    test_column: usize,
     total_test_count: usize,
 }
 
@@ -39,6 +40,7 @@ impl<T: Write> TerseFormatter<T> {
             max_name_len,
             is_multithreaded,
             test_count: 0,
+            test_column: 0,
             total_test_count: 0, // initialized later, when write_run_start is called
         }
     }
@@ -47,8 +49,20 @@ impl<T: Write> TerseFormatter<T> {
         self.write_short_result(".", term::color::GREEN)
     }
 
-    pub fn write_failed(&mut self) -> io::Result<()> {
-        self.write_short_result("F", term::color::RED)
+    pub fn write_failed(&mut self, name: &str) -> io::Result<()> {
+        // Put failed tests on their own line and include the test name, so that it's faster
+        // to see which test failed without having to wait for them all to run.
+
+        // normally, we write the progress unconditionally, even if the previous line was cut short.
+        // but if this is the very first column, no short results will have been printed and we'll end up with *only* the progress on the line.
+        // avoid this.
+        if self.test_column != 0 {
+            self.write_progress()?;
+        }
+        self.test_count += 1;
+        self.write_plain(format!("{name} --- "))?;
+        self.write_pretty("FAILED", term::color::RED)?;
+        self.write_plain("\n")
     }
 
     pub fn write_ignored(&mut self) -> io::Result<()> {
@@ -65,15 +79,22 @@ impl<T: Write> TerseFormatter<T> {
         color: term::color::Color,
     ) -> io::Result<()> {
         self.write_pretty(result, color)?;
-        if self.test_count % QUIET_MODE_MAX_COLUMN == QUIET_MODE_MAX_COLUMN - 1 {
+        self.test_count += 1;
+        self.test_column += 1;
+        if self.test_column % QUIET_MODE_MAX_COLUMN == QUIET_MODE_MAX_COLUMN - 1 {
             // We insert a new line regularly in order to flush the
             // screen when dealing with line-buffered output (e.g., piping to
-            // `stamp` in the rust CI).
-            let out = format!(" {}/{}\n", self.test_count + 1, self.total_test_count);
-            self.write_plain(out)?;
+            // `stamp` in the Rust CI).
+            self.write_progress()?;
         }
 
-        self.test_count += 1;
+        Ok(())
+    }
+
+    fn write_progress(&mut self) -> io::Result<()> {
+        let out = format!(" {}/{}\n", self.test_count, self.total_test_count);
+        self.write_plain(out)?;
+        self.test_column = 0;
         Ok(())
     }
 
@@ -213,7 +234,7 @@ impl<T: Write> OutputFormatter for TerseFormatter<T> {
         match *result {
             TestResult::TrOk => self.write_ok(),
             TestResult::TrFailed | TestResult::TrFailedMsg(_) | TestResult::TrTimedFail => {
-                self.write_failed()
+                self.write_failed(desc.name.as_slice())
             }
             TestResult::TrIgnored => self.write_ignored(),
             TestResult::TrBench(ref bs) => {
diff --git a/library/test/src/types.rs b/library/test/src/types.rs
index 1a8ae889c8c..6a7035a8e29 100644
--- a/library/test/src/types.rs
+++ b/library/test/src/types.rs
@@ -13,7 +13,7 @@ pub use NamePadding::*;
 pub use TestFn::*;
 pub use TestName::*;
 
-/// Type of the test according to the [rust book](https://doc.rust-lang.org/cargo/guide/tests.html)
+/// Type of the test according to the [Rust book](https://doc.rust-lang.org/cargo/guide/tests.html)
 /// conventions.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub enum TestType {
diff --git a/rustfmt.toml b/rustfmt.toml
index e6cc298ec44..0b0674af8b4 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -37,7 +37,6 @@ ignore = [
     "src/tools/rustfmt",
 
     # these are ignored by a standard cargo fmt run
-    "compiler/rustc_codegen_cranelift/y.rs", # running rustfmt breaks this file
     "compiler/rustc_codegen_cranelift/scripts",
     "compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs", # uses edition 2024
 ]
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 0d604c0d3e5..6e49bcc9744 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -557,7 +557,9 @@ class RustBuild(object):
                 shutil.rmtree(bin_root)
 
             key = self.stage0_compiler.date
-            cache_dst = os.path.join(self.build_dir, "cache")
+            cache_dst = (self.get_toml('bootstrap-cache-path', 'build') or
+                os.path.join(self.build_dir, "cache"))
+
             rustc_cache = os.path.join(cache_dst, key)
             if not os.path.exists(rustc_cache):
                 os.makedirs(rustc_cache)
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index 8b65e8ff9c3..4257c0f7991 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -149,6 +149,7 @@ v("default-linker", "rust.default-linker", "the default linker")
 # (others are conditionally saved).
 o("manage-submodules", "build.submodules", "let the build manage the git submodules")
 o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of two (not recommended except for testing reproducible builds)")
+o("bootstrap-cache-path", "build.bootstrap-cache-path", "use provided path for the bootstrap cache")
 o("extended", "build.extended", "build an extended rust tool set")
 
 v("tools", None, "List of extended tools will be installed")
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 43ac71b112c..4bf50e19c3f 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -404,7 +404,7 @@ fn copy_self_contained_objects(
                 )
             })
             .join("lib")
-            .join(target.to_string().replace("-preview1", "").replace("p2", ""));
+            .join(target.to_string().replace("-preview1", "").replace("p2", "").replace("p1", ""));
         for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
             copy_and_stamp(
                 builder,
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 067dede904f..1090edc9c92 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -129,6 +129,7 @@ pub struct RustcDocs {
 impl Step for RustcDocs {
     type Output = Option<GeneratedTarball>;
     const DEFAULT: bool = true;
+    const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let builder = run.builder;
@@ -2035,10 +2036,26 @@ fn install_llvm_file(
         // If we have a symlink like libLLVM-18.so -> libLLVM.so.18.1, install the target of the
         // symlink, which is what will actually get loaded at runtime.
         builder.install(&t!(fs::canonicalize(source)), destination, 0o644);
+
+        let full_dest = destination.join(source.file_name().unwrap());
         if install_symlink {
-            // If requested, also install the symlink. This is used by download-ci-llvm.
-            let full_dest = destination.join(source.file_name().unwrap());
+            // For download-ci-llvm, also install the symlink, to match what LLVM does. Using a
+            // symlink is fine here, as this is not a rustup component.
             builder.copy(&source, &full_dest);
+        } else {
+            // Otherwise, replace the symlink with an equivalent linker script. This is used when
+            // projects like miri link against librustc_driver.so. We don't use a symlink, as
+            // these are not allowed inside rustup components.
+            let link = t!(fs::read_link(source));
+            let mut linker_script = t!(fs::File::create(full_dest));
+            t!(write!(linker_script, "INPUT({})\n", link.display()));
+
+            // We also want the linker script to have the same mtime as the source, otherwise it
+            // can trigger rebuilds.
+            let meta = t!(fs::metadata(source));
+            if let Ok(mtime) = meta.modified() {
+                t!(linker_script.set_modified(mtime));
+            }
         }
     } else {
         builder.install(&source, destination, 0o644);
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index a4903ce2353..c4235755ba8 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -797,7 +797,10 @@ impl Step for Rustc {
         cargo.rustdocflag("-Zunstable-options");
         cargo.rustdocflag("-Znormalize-docs");
         cargo.rustdocflag("--show-type-layout");
-        cargo.rustdocflag("--generate-link-to-definition");
+        // FIXME: `--generate-link-to-definition` tries to resolve cfged out code
+        // see https://github.com/rust-lang/rust/pull/122066#issuecomment-1983049222
+        // cargo.rustdocflag("--generate-link-to-definition");
+
         compile::rustc_cargo(builder, &mut cargo, target, compiler.stage);
         cargo.arg("-Zunstable-options");
         cargo.arg("-Zskip-rustdoc-fingerprint");
@@ -953,8 +956,10 @@ macro_rules! tool_doc {
                 cargo.rustdocflag("-Arustdoc::private-intra-doc-links");
                 cargo.rustdocflag("--enable-index-page");
                 cargo.rustdocflag("--show-type-layout");
-                cargo.rustdocflag("--generate-link-to-definition");
                 cargo.rustdocflag("-Zunstable-options");
+                // FIXME: `--generate-link-to-definition` tries to resolve cfged out code
+                // see https://github.com/rust-lang/rust/pull/122066#issuecomment-1983049222
+                // cargo.rustdocflag("--generate-link-to-definition");
 
                 let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc");
                 $(for krate in $crates {
diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs
index 700c3ee4fda..fc9f9789bd6 100644
--- a/src/bootstrap/src/core/build_steps/format.rs
+++ b/src/bootstrap/src/core/build_steps/format.rs
@@ -81,7 +81,7 @@ fn update_rustfmt_version(build: &Builder<'_>) {
 }
 
 /// Returns the Rust files modified between the `merge-base` of HEAD and
-/// rust-lang/master and what is now on the disk.
+/// rust-lang/master and what is now on the disk. Does not include removed files.
 ///
 /// Returns `None` if all files should be formatted.
 fn get_modified_rs_files(build: &Builder<'_>) -> Result<Option<Vec<String>>, String> {
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 875a4efae02..326f8f57173 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -161,6 +161,7 @@ pub struct Config {
     pub vendor: bool,
     pub target_config: HashMap<TargetSelection, Target>,
     pub full_bootstrap: bool,
+    pub bootstrap_cache_path: Option<PathBuf>,
     pub extended: bool,
     pub tools: Option<HashSet<String>>,
     pub sanitizers: bool,
@@ -827,6 +828,7 @@ define_config! {
         locked_deps: Option<bool> = "locked-deps",
         vendor: Option<bool> = "vendor",
         full_bootstrap: Option<bool> = "full-bootstrap",
+        bootstrap_cache_path: Option<PathBuf> = "bootstrap-cache-path",
         extended: Option<bool> = "extended",
         tools: Option<HashSet<String>> = "tools",
         verbose: Option<usize> = "verbose",
@@ -1389,6 +1391,7 @@ impl Config {
             locked_deps,
             vendor,
             full_bootstrap,
+            bootstrap_cache_path,
             extended,
             tools,
             verbose,
@@ -1477,6 +1480,7 @@ impl Config {
         config.reuse = reuse.map(PathBuf::from);
         config.submodules = submodules;
         config.android_ndk = android_ndk;
+        config.bootstrap_cache_path = bootstrap_cache_path;
         set(&mut config.low_priority, low_priority);
         set(&mut config.compiler_docs, compiler_docs);
         set(&mut config.library_docs_private_items, library_docs_private_items);
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index 185089a646b..27829eab937 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -578,7 +578,9 @@ impl Config {
             return;
         }
 
-        let cache_dst = self.out.join("cache");
+        let cache_dst =
+            self.bootstrap_cache_path.as_ref().cloned().unwrap_or_else(|| self.out.join("cache"));
+
         let cache_dir = cache_dst.join(key);
         if !cache_dir.exists() {
             t!(fs::create_dir_all(&cache_dir));
@@ -705,7 +707,9 @@ download-rustc = false
         let llvm_assertions = self.llvm_assertions;
 
         let cache_prefix = format!("llvm-{llvm_sha}-{llvm_assertions}");
-        let cache_dst = self.out.join("cache");
+        let cache_dst =
+            self.bootstrap_cache_path.as_ref().cloned().unwrap_or_else(|| self.out.join("cache"));
+
         let rustc_cache = cache_dst.join(cache_prefix);
         if !rustc_cache.exists() {
             t!(fs::create_dir_all(&rustc_cache));
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index f7748621d93..ab8f3c0d9e4 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -91,7 +91,7 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[
     /* Extra values not defined in the built-in targets yet, but used in std */
     (Some(Mode::Std), "target_env", Some(&["libnx", "p2"])),
     // (Some(Mode::Std), "target_os", Some(&[])),
-    (Some(Mode::Std), "target_arch", Some(&["spirv", "nvptx", "xtensa"])),
+    (Some(Mode::Std), "target_arch", Some(&["arm64ec", "spirv", "nvptx", "xtensa"])),
     /* Extra names used by dependencies */
     // FIXME: Used by serde_json, but we should not be triggering on external dependencies.
     (Some(Mode::Rustc), "no_btreemap_remove_entry", None),
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 9a50ad4437e..d166b84e51f 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -136,4 +136,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Info,
         summary: "`x install` now skips providing tarball sources (under 'build/dist' path) to speed up the installation process.",
     },
+    ChangeInfo {
+        change_id: 121976,
+        severity: ChangeSeverity::Info,
+        summary: "A new `boostrap-cache-path` option has been introduced which can be utilized to modify the cache path for bootstrap.",
+    },
 ];
diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs
index bfbb53f8c81..cbd01606a89 100644
--- a/src/bootstrap/src/utils/render_tests.rs
+++ b/src/bootstrap/src/utils/render_tests.rs
@@ -166,7 +166,7 @@ impl<'a> Renderer<'a> {
         println!();
     }
 
-    fn render_test_outcome_terse(&mut self, outcome: Outcome<'_>, _: &TestOutcome) {
+    fn render_test_outcome_terse(&mut self, outcome: Outcome<'_>, test: &TestOutcome) {
         if self.terse_tests_in_line != 0 && self.terse_tests_in_line % TERSE_TESTS_PER_LINE == 0 {
             if let Some(total) = self.tests_count {
                 let total = total.to_string();
@@ -178,7 +178,7 @@ impl<'a> Renderer<'a> {
         }
 
         self.terse_tests_in_line += 1;
-        self.builder.colored_stdout(|stdout| outcome.write_short(stdout)).unwrap();
+        self.builder.colored_stdout(|stdout| outcome.write_short(stdout, &test.name)).unwrap();
         let _ = std::io::stdout().flush();
     }
 
@@ -300,7 +300,7 @@ enum Outcome<'a> {
 }
 
 impl Outcome<'_> {
-    fn write_short(&self, writer: &mut dyn WriteColor) -> Result<(), std::io::Error> {
+    fn write_short(&self, writer: &mut dyn WriteColor, name: &str) -> Result<(), std::io::Error> {
         match self {
             Outcome::Ok => {
                 writer.set_color(ColorSpec::new().set_fg(Some(Color::Green)))?;
@@ -311,8 +311,11 @@ impl Outcome<'_> {
                 write!(writer, "b")?;
             }
             Outcome::Failed => {
+                // Put failed tests on their own line and include the test name, so that it's faster
+                // to see which test failed without having to wait for them all to run.
+                writeln!(writer)?;
                 writer.set_color(ColorSpec::new().set_fg(Some(Color::Red)))?;
-                write!(writer, "F")?;
+                writeln!(writer, "{name} ... F")?;
             }
             Outcome::Ignored { .. } => {
                 writer.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)))?;
diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
index 5f1fec74bed..e90141bb9a9 100644
--- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
@@ -112,6 +112,7 @@ ENV TARGETS=x86_64-unknown-fuchsia
 ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia
 ENV TARGETS=$TARGETS,wasm32-unknown-unknown
 ENV TARGETS=$TARGETS,wasm32-wasi
+ENV TARGETS=$TARGETS,wasm32-wasip1
 ENV TARGETS=$TARGETS,wasm32-wasi-preview1-threads
 ENV TARGETS=$TARGETS,sparcv9-sun-solaris
 ENV TARGETS=$TARGETS,x86_64-pc-solaris
@@ -135,7 +136,8 @@ ENV TARGETS=$TARGETS,x86_64-unknown-uefi
 RUN ln -s /usr/include/x86_64-linux-gnu/asm /usr/local/include/asm
 
 ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --disable-docs \
-  --set target.wasm32-wasi.wasi-root=/wasm32-wasi \
+  --set target.wasm32-wasi.wasi-root=/wasm32-wasip1 \
+  --set target.wasm32-wasip1.wasi-root=/wasm32-wasip1 \
   --set target.wasm32-wasi-preview1-threads.wasi-root=/wasm32-wasi-preview1-threads \
   --musl-root-armv7=/musl-armv7
 
diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
index 4b0d360686f..a2447494078 100755
--- a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
+++ b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh
@@ -15,7 +15,7 @@ make -j$(nproc) \
     CC="$bin/clang" \
     NM="$bin/llvm-nm" \
     AR="$bin/llvm-ar" \
-    INSTALL_DIR=/wasm32-wasi \
+    INSTALL_DIR=/wasm32-wasip1 \
     install
 
 cd ..
diff --git a/src/doc/rust.css b/src/doc/rust.css
index e0bf64c33bc..bd2e0b94518 100644
--- a/src/doc/rust.css
+++ b/src/doc/rust.css
@@ -5,12 +5,13 @@ body {
 	margin: 0 auto;
 	padding: 0 15px;
 	font-size: 18px;
-	color: #333;
+	color: #000;
 	line-height: 1.428571429;
 
 	-webkit-box-sizing: unset;
 	-moz-box-sizing: unset;
 	box-sizing: unset;
+	background: #fff;
 }
 @media (min-width: 768px) {
 	body {
@@ -39,7 +40,6 @@ h4, h5, h6 {
 	padding: 5px 10px;
 }
 h5, h6 {
-	color: black;
 	text-decoration: underline;
 }
 
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 90ac97f35f6..5a0168e30cb 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -18,6 +18,7 @@
     - [arm64e-apple-ios.md](platform-support/arm64e-apple-ios.md)
     - [arm64e-apple-darwin.md](platform-support/arm64e-apple-darwin.md)
     - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md)
+    - [arm64ec-pc-windows-msvc](platform-support/arm64ec-pc-windows-msvc.md)
     - [\*-apple-tvos](platform-support/apple-tvos.md)
     - [\*-apple-watchos\*](platform-support/apple-watchos.md)
     - [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md)
@@ -60,6 +61,7 @@
     - [\*-unknown-netbsd\*](platform-support/netbsd.md)
     - [*-unknown-openbsd](platform-support/openbsd.md)
     - [\*-unknown-uefi](platform-support/unknown-uefi.md)
+    - [wasm32-wasip1](platform-support/wasm32-wasip1.md)
     - [wasm32-wasi-preview1-threads](platform-support/wasm32-wasi-preview1-threads.md)
     - [wasm32-wasip2](platform-support/wasm32-wasip2.md)
     - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
diff --git a/src/doc/rustc/src/instrument-coverage.md b/src/doc/rustc/src/instrument-coverage.md
index 5b766318331..2f93252eddc 100644
--- a/src/doc/rustc/src/instrument-coverage.md
+++ b/src/doc/rustc/src/instrument-coverage.md
@@ -331,10 +331,29 @@ $ llvm-cov report \
 
 ## `-C instrument-coverage=<options>`
 
--   `-C instrument-coverage=all`: Instrument all functions, including unused functions and unused generics. (This is the same as `-C instrument-coverage`, with no value.)
--   `-C instrument-coverage=off`: Do not instrument any functions. (This is the same as simply not including the `-C instrument-coverage` option.)
--   `-Zunstable-options -C instrument-coverage=except-unused-generics`: Instrument all functions except unused generics.
--   `-Zunstable-options -C instrument-coverage=except-unused-functions`: Instrument only used (called) functions and instantiated generic functions.
+- `-C instrument-coverage=no` (or `n`/`off`/`false`):
+  Don't enable coverage instrumentation. No functions will be instrumented for coverage.
+  - This is the same as not using the `-C instrument-coverage` flag at all.
+- `-C instrument-coverage=yes` (or `y`/`on`/`true`):
+  Enable coverage instrumentation with the default behaviour.
+  Currently this instruments all functions, including unused functions and unused generics.
+  - This is the same as `-C instrument-coverage` with no value.
+
+### Other values
+
+- `-C instrument-coverage=all`:
+  Currently an alias for `yes`, but may behave differently in the future if
+  more fine-grained coverage options are added.
+  Using this value is currently not recommended.
+
+### Unstable values
+
+- `-Z unstable-options -C instrument-coverage=branch`:
+  Placeholder for potential branch coverage support in the future.
+- `-Z unstable-options -C instrument-coverage=except-unused-generics`:
+  Instrument all functions except unused generics.
+- `-Z unstable-options -C instrument-coverage=except-unused-functions`:
+  Instrument only used (called) functions and instantiated generic functions.
 
 ## Other references
 
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 5500dca9dc2..308e3235370 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -32,7 +32,7 @@ All tier 1 targets with host tools support the full standard library.
 
 target | notes
 -------|-------
-`aarch64-unknown-linux-gnu` | ARM64 Linux (kernel 4.1, glibc 2.17+) [^missing-stack-probes]
+`aarch64-unknown-linux-gnu` | ARM64 Linux (kernel 4.1, glibc 2.17+)
 `i686-pc-windows-gnu` | 32-bit MinGW (Windows 7+) [^windows-support] [^x86_32-floats-return-ABI]
 `i686-pc-windows-msvc` | 32-bit MSVC (Windows 7+) [^windows-support] [^x86_32-floats-return-ABI]
 `i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+) [^x86_32-floats-return-ABI]
@@ -41,10 +41,6 @@ target | notes
 `x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 7+) [^windows-support]
 `x86_64-unknown-linux-gnu` | 64-bit Linux (kernel 3.2+, glibc 2.17+)
 
-[^missing-stack-probes]: Stack probes support is missing on
-  `aarch64-unknown-linux-gnu`, but it's planned to be implemented in the near
-  future. The implementation is tracked on [issue #77071][77071].
-
 [^windows-support]: Only Windows 10 currently undergoes automated testing. Earlier versions of Windows rely on testing and support from the community.
 
 [^x86_32-floats-return-ABI]: Due to limitations of the C ABI, floating-point support on `i686` targets is non-compliant: floating-point return values are passed via an x87 register, so NaN payload bits can be lost. See [issue #114479][x86-32-float-issue].
@@ -94,7 +90,7 @@ target | notes
 -------|-------
 `aarch64-apple-darwin` | ARM64 macOS (11.0+, Big Sur+)
 `aarch64-pc-windows-msvc` | ARM64 Windows MSVC
-`aarch64-unknown-linux-musl` | ARM64 Linux with MUSL
+`aarch64-unknown-linux-musl` | ARM64 Linux with musl 1.2.3
 `arm-unknown-linux-gnueabi` | ARMv6 Linux (kernel 3.2, glibc 2.17)
 `arm-unknown-linux-gnueabihf` | ARMv6 Linux, hardfloat (kernel 3.2, glibc 2.17)
 `armv7-unknown-linux-gnueabihf` | ARMv7-A Linux, hardfloat (kernel 3.2, glibc 2.17)
@@ -106,7 +102,7 @@ target | notes
 `s390x-unknown-linux-gnu` | S390x Linux (kernel 3.2, glibc 2.17)
 `x86_64-unknown-freebsd` | 64-bit FreeBSD
 `x86_64-unknown-illumos` | illumos
-`x86_64-unknown-linux-musl` | 64-bit Linux with MUSL
+`x86_64-unknown-linux-musl` | 64-bit Linux with musl 1.2.3
 [`x86_64-unknown-netbsd`](platform-support/netbsd.md) | NetBSD/amd64
 
 ## Tier 2 without Host Tools
@@ -148,27 +144,28 @@ target | std | notes
 `aarch64-unknown-none` | * | Bare ARM64, hardfloat
 [`aarch64-unknown-uefi`](platform-support/unknown-uefi.md) | * | ARM64 UEFI
 [`arm-linux-androideabi`](platform-support/android.md) | ✓ | ARMv6 Android
-`arm-unknown-linux-musleabi` | ✓ | ARMv6 Linux with MUSL
-`arm-unknown-linux-musleabihf` | ✓ | ARMv6 Linux with MUSL, hardfloat
+`arm-unknown-linux-musleabi` | ✓ | ARMv6 Linux with musl 1.2.3
+`arm-unknown-linux-musleabihf` | ✓ | ARMv6 Linux with musl 1.2.3, hardfloat
 [`armebv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | Bare ARMv7-R, Big Endian
 [`armebv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | Bare ARMv7-R, Big Endian, hardfloat
 `armv5te-unknown-linux-gnueabi` | ✓ | ARMv5TE Linux (kernel 4.4, glibc 2.23)
-`armv5te-unknown-linux-musleabi` | ✓ | ARMv5TE Linux with MUSL
+`armv5te-unknown-linux-musleabi` | ✓ | ARMv5TE Linux with musl 1.2.3
 [`armv7-linux-androideabi`](platform-support/android.md) | ✓ | ARMv7-A Android
 `armv7-unknown-linux-gnueabi` | ✓ | ARMv7-A Linux (kernel 4.15, glibc 2.27)
-`armv7-unknown-linux-musleabi` | ✓ | ARMv7-A Linux with MUSL
-`armv7-unknown-linux-musleabihf` | ✓ | ARMv7-A Linux with MUSL, hardfloat
+`armv7-unknown-linux-musleabi` | ✓ | ARMv7-A Linux with musl 1.2.3
+`armv7-unknown-linux-musleabihf` | ✓ | ARMv7-A Linux with musl 1.2.3, hardfloat
 [`armv7-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | ARMv7-A OpenHarmony
 [`armv7a-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv7-A
 [`armv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | Bare ARMv7-R
 [`armv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | Bare ARMv7-R, hardfloat
 `i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE [^x86_32-floats-x87]
 `i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 3.2, glibc 2.17) [^x86_32-floats-x87]
-`i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL [^x86_32-floats-x87]
+`i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, musl 1.2.3 [^x86_32-floats-x87]
 [`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android [^x86_32-floats-return-ABI]
 `i686-unknown-freebsd` | ✓ | 32-bit FreeBSD [^x86_32-floats-return-ABI]
-`i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL [^x86_32-floats-return-ABI]
+`i686-unknown-linux-musl` | ✓ | 32-bit Linux with musl 1.2.3 [^x86_32-floats-return-ABI]
 [`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * | 32-bit UEFI
+[`loongarch64-unknown-linux-musl`](platform-support/loongarch-linux.md) | ? |  | LoongArch64 Linux (LP64D ABI) with musl 1.2.3
 [`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * |  | LoongArch64 Bare-metal (LP64D ABI)
 [`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * |  | LoongArch64 Bare-metal (LP64S ABI)
 [`nvptx64-nvidia-cuda`](platform-support/nvptx64-nvidia-cuda.md) | * | --emit=asm generates PTX code that [runs on NVIDIA GPUs]
@@ -192,7 +189,8 @@ target | std | notes
 [`thumbv8m.main-none-eabihf`](platform-support/arm-none-eabi.md) | * | Bare ARMv8-M Mainline, hardfloat
 `wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten
 `wasm32-unknown-unknown` | ✓ | WebAssembly
-`wasm32-wasi` | ✓ | WebAssembly with WASI
+`wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename])
+[`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASI
 [`wasm32-wasi-preview1-threads`](platform-support/wasm32-wasi-preview1-threads.md) | ✓ |  | WebAssembly with WASI Preview 1 and threads
 `x86_64-apple-ios` | ✓ | 64-bit x86 iOS
 [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX
@@ -207,6 +205,7 @@ target | std | notes
 [`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * | 64-bit UEFI
 
 [^x86_32-floats-x87]: Floating-point support on `i586` targets is non-compliant: the `x87` registers and instructions used for these targets do not provide IEEE-754-compliant behavior, in particular when it comes to rounding and NaN payload bits. See [issue #114479][x86-32-float-issue].
+[wasi-rename]: https://github.com/rust-lang/compiler-team/issues/607
 
 [Fortanix ABI]: https://edp.fortanix.com/
 
@@ -239,6 +238,7 @@ target | std | host | notes
 -------|:---:|:----:|-------
 [`arm64e-apple-ios`](platform-support/arm64e-apple-ios.md) | ✓ | | ARM64e Apple iOS
 [`arm64e-apple-darwin`](platform-support/arm64e-apple-darwin.md)  | ✓ | ✓ | ARM64e Apple Darwin
+[`arm64ec-pc-windows-msvc`](platform-support/arm64ec-pc-windows-msvc.md) | ? | | Arm64EC Windows MSVC
 `aarch64-apple-ios-macabi` | ? |  | Apple Catalyst on ARM64
 [`aarch64-apple-tvos`](platform-support/apple-tvos.md) | ? |  | ARM64 tvOS
 [`aarch64-apple-tvos-sim`](platform-support/apple-tvos.md) | ? |  | ARM64 tvOS Simulator
@@ -288,7 +288,7 @@ target | std | host | notes
 `csky-unknown-linux-gnuabiv2` | ✓ |  | C-SKY abiv2 Linux (little endian)
 `csky-unknown-linux-gnuabiv2hf` | ✓ |  | C-SKY abiv2 Linux, hardfloat (little endian)
 [`hexagon-unknown-none-elf`](platform-support/hexagon-unknown-none-elf.md)| * | | Bare Hexagon (v60+, HVX)
-[`hexagon-unknown-linux-musl`](platform-support/hexagon-unknown-linux-musl.md) | ✓ | | Hexagon Linux
+[`hexagon-unknown-linux-musl`](platform-support/hexagon-unknown-linux-musl.md) | ✓ | | Hexagon Linux with musl 1.2.3
 `i386-apple-ios` | ✓ |  | 32-bit x86 iOS [^x86_32-floats-return-ABI]
 [`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * |  | 32-bit x86 QNX Neutrino 7.0 RTOS  [^x86_32-floats-return-ABI]
 [`i586-unknown-netbsd`](platform-support/netbsd.md) | ✓ |  | 32-bit x86, restricted to Pentium
@@ -305,15 +305,15 @@ target | std | host | notes
 `i686-wrs-vxworks` | ? |  | [^x86_32-floats-return-ABI]
 [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? |  | Motorola 680x0 Linux
 `mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23)
-`mips-unknown-linux-musl` | ✓ |  | MIPS Linux with musl libc
+`mips-unknown-linux-musl` | ✓ |  | MIPS Linux with musl 1.2.3
 `mips-unknown-linux-uclibc` | ✓ |  | MIPS Linux with uClibc
-[`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? |  | MIPS64 for OpenWrt Linux MUSL
+[`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? |  | MIPS64 for OpenWrt Linux musl 1.2.3
 `mips64-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 Linux, N64 ABI (kernel 4.4, glibc 2.23)
-`mips64-unknown-linux-muslabi64` | ✓ |  | MIPS64 Linux, N64 ABI, musl libc
+`mips64-unknown-linux-muslabi64` | ✓ |  | MIPS64 Linux, N64 ABI, musl 1.2.3
 `mips64el-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 (little endian) Linux, N64 ABI (kernel 4.4, glibc 2.23)
-`mips64el-unknown-linux-muslabi64` | ✓ |  | MIPS64 (little endian) Linux, N64 ABI, musl libc
+`mips64el-unknown-linux-muslabi64` | ✓ |  | MIPS64 (little endian) Linux, N64 ABI, musl 1.2.3
 `mipsel-unknown-linux-gnu` | ✓ | ✓ | MIPS (little endian) Linux (kernel 4.4, glibc 2.23)
-`mipsel-unknown-linux-musl` | ✓ |  | MIPS (little endian) Linux with musl libc
+`mipsel-unknown-linux-musl` | ✓ |  | MIPS (little endian) Linux with musl 1.2.3
 [`mipsel-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | 32-bit MIPS (LE), requires mips32 cpu support
 `mipsel-sony-psp` | * |  | MIPS (LE) Sony PlayStation Portable (PSP)
 [`mipsel-sony-psx`](platform-support/mipsel-sony-psx.md) | * |  | MIPS (LE) Sony PlayStation 1 (PSX)
@@ -325,7 +325,7 @@ target | std | host | notes
 [`mipsisa64r6el-unknown-linux-gnuabi64`](platform-support/mips-release-6.md) | ✓ | ✓ | 64-bit MIPS Release 6 Little Endian
 `msp430-none-elf` | * |  | 16-bit MSP430 microcontrollers
 `powerpc-unknown-linux-gnuspe` | ✓ |  | PowerPC SPE Linux
-`powerpc-unknown-linux-musl` | ? |  |
+`powerpc-unknown-linux-musl` | ? |  | PowerPC Linux with musl 1.2.3
 [`powerpc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD 32-bit powerpc systems
 `powerpc-unknown-openbsd` | ? |  |
 `powerpc-wrs-vxworks-spe` | ? |  |
@@ -333,13 +333,13 @@ target | std | host | notes
 `powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv1 and ELFv2)
 `powerpc64le-unknown-freebsd` |   |   | PPC64LE FreeBSD
 `powerpc-unknown-freebsd` |   |   | PowerPC FreeBSD
-`powerpc64-unknown-linux-musl` | ? |  |
+`powerpc64-unknown-linux-musl` | ? |  | 64-bit PowerPC Linux with musl 1.2.3
 `powerpc64-wrs-vxworks` | ? |  |
-`powerpc64le-unknown-linux-musl` | ? |  |
+`powerpc64le-unknown-linux-musl` | ? |  | 64-bit PowerPC Linux with musl 1.2.3, Little Endian
 [`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64
 [`powerpc64-ibm-aix`](platform-support/aix.md) | ? |  | 64-bit AIX (7.2 and newer)
 `riscv32gc-unknown-linux-gnu` |   |   | RISC-V Linux (kernel 5.4, glibc 2.33)
-`riscv32gc-unknown-linux-musl` |   |   | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches)
+`riscv32gc-unknown-linux-musl` |   |   | RISC-V Linux (kernel 5.4, musl 1.2.3 + RISCV32 support patches)
 [`riscv32im-risc0-zkvm-elf`](platform-support/riscv32im-risc0-zkvm-elf.md) | ? |  | RISC Zero's zero-knowledge Virtual Machine (RV32IM ISA)
 [`riscv32imac-unknown-xous-elf`](platform-support/riscv32imac-unknown-xous-elf.md) | ? |  | RISC-V Xous (RV32IMAC ISA)
 [`riscv32imc-esp-espidf`](platform-support/esp-idf.md) | ✓ |  | RISC-V ESP-IDF
@@ -348,11 +348,11 @@ target | std | host | notes
 [`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ |   | RISC-V Hermit
 `riscv64gc-unknown-freebsd` |   |   | RISC-V FreeBSD
 `riscv64gc-unknown-fuchsia` |   |   | RISC-V Fuchsia
-`riscv64gc-unknown-linux-musl` |   |   | RISC-V Linux (kernel 4.20, musl 1.2.0)
+`riscv64gc-unknown-linux-musl` |   |   | RISC-V Linux (kernel 4.20, musl 1.2.3)
 [`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD
 [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64
 [`riscv64-linux-android`](platform-support/android.md) |   |   | RISC-V 64-bit Android
-`s390x-unknown-linux-musl` |  |  | S390x Linux (kernel 3.2, MUSL)
+`s390x-unknown-linux-musl` |  |  | S390x Linux (kernel 3.2, musl 1.2.3)
 `sparc-unknown-linux-gnu` | ✓ |  | 32-bit SPARC Linux
 [`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * |  | Bare 32-bit SPARC V7+
 [`sparc64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/sparc64
@@ -361,7 +361,7 @@ target | std | host | notes
 [`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * |  | Thumb-mode Bare ARMv5TE
 `thumbv7a-pc-windows-msvc` | ? |  |
 `thumbv7a-uwp-windows-msvc` | ✓ |  |
-`thumbv7neon-unknown-linux-musleabihf` | ? |  | Thumb2-mode ARMv7-A Linux with NEON, MUSL
+`thumbv7neon-unknown-linux-musleabihf` | ? |  | Thumb2-mode ARMv7-A Linux with NEON, musl 1.2.3
 [`wasm32-wasip2`](platform-support/wasm32-wasip2.md) | ✓ |  | WebAssembly
 [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? |  | WebAssembly
 `x86_64-apple-ios-macabi` | ✓ |  | Apple Catalyst on x86_64
@@ -370,7 +370,7 @@ target | std | host | notes
 [`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ |  | x86 64-bit QNX Neutrino 7.1 RTOS |
 [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
 `x86_64-pc-windows-msvc` | * |  | 64-bit Windows XP support
-[`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ |   | 64-bit Unikraft with musl
+[`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ |   | 64-bit Unikraft with musl 1.2.3
 `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD
 `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku
 [`x86_64-unknown-hermit`](platform-support/hermit.md) | ✓ |  | x86_64 Hermit
diff --git a/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md b/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md
new file mode 100644
index 00000000000..1bb2c677b08
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md
@@ -0,0 +1,69 @@
+# `arm64ec-pc-windows-msvc`
+
+**Tier: 3**
+
+Arm64EC ("Emulation Compatible") for mixed architecture (AArch64 and x86_64)
+applications on AArch64 Windows 11. See <https://learn.microsoft.com/en-us/windows/arm/arm64ec>.
+
+## Target maintainers
+
+- [@dpaoliello](https://github.com/dpaoliello)
+
+## Requirements
+
+Target only supports cross-compilation, `core` and `alloc` are supported but
+`std` is not.
+
+Builds Arm64EC static and dynamic libraries and executables which can be run on
+AArch64 Windows 11 devices. Arm64EC static libraries can also be linked into
+Arm64X dynamic libraries and executables.
+
+Uses `arm64ec` as its `target_arch` - code built for Arm64EC must be compatible
+with x86_64 code (e.g., same structure layouts, function signatures, etc.) but
+use AArch64 intrinsics.
+
+Only supported backend is LLVM 18 (or above).
+
+## Building the target
+
+You can build Rust with support for the targets by adding it to the `target`
+list in `config.toml` and disabling `std`:
+
+```toml
+[build]
+target = [ "arm64ec-pc-windows-msvc" ]
+
+[target.arm64ec-pc-windows-msvc]
+no-std = true
+```
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for this target. To compile for
+this target, you will either need to build Rust with the target enabled (see
+"Building the target" above), or build your own copy of `core` by using
+`build-std` or similar.
+
+## Testing
+
+Tests can be run on AArch64 Windows 11 devices.
+
+Since this is a `no_std` target, the Rust test suite is not supported.
+
+## Cross-compilation toolchains and C code
+
+C code can be built using the Arm64-targetting MSVC toolchain.
+
+To compile:
+
+```bash
+cl /arm64EC /c ...
+```
+
+To link:
+
+```bash
+link /MACHINE:ARM64EC ...
+```
+
+Further reading: <https://learn.microsoft.com/en-us/windows/arm/arm64ec-build>
diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1.md b/src/doc/rustc/src/platform-support/wasm32-wasip1.md
new file mode 100644
index 00000000000..71f8d281bc8
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/wasm32-wasip1.md
@@ -0,0 +1,119 @@
+# `wasm32-wasip1`
+
+**Tier: 2**
+
+The `wasm32-wasip1` target is a WebAssembly compilation target which
+assumes that the [WASIp1] (aka "WASI preview1") set of "syscalls" are available
+for use in the standard library. Historically this target in the Rust compiler
+was one of the first for WebAssembly where Rust and C code are explicitly
+intended to interoperate as well.
+
+There's a bit of history to the target and current development which is also
+worth explaining before going much further. Historically this target was
+originally called `wasm32-wasi` in both rustc and Clang. This was first added
+to Rust in 2019. In the intervening years leading up to 2024 the WASI standard
+continued to be developed and was eventually "rebased" on top of the [Component
+Model]. This was a large change to the WASI specification and was released as
+0.2.0 ("WASIp2" colloquially) in January 2024. The previous target's name in
+rustc, `wasm32-wasi`, was then renamed to `wasm32-wasip1`, to avoid
+confusion with this new target to be added to rustc as `wasm32-wasip2`.
+Some more context can be found in these MCPs:
+
+* [Rename wasm32-wasi target to wasm32-wasip1](https://github.com/rust-lang/compiler-team/issues/607)
+* [Smooth the renaming transition of wasm32-wasi](https://github.com/rust-lang/compiler-team/issues/695)
+
+At this point the `wasm32-wasip1` target is intended for historical
+compatibility with the first version of the WASI standard. As of now (January
+2024) the 0.2.0 target of WASI ("WASIp2") is relatively new. The state of
+WASI will likely change in few years after which point this documentation will
+probably receive another update.
+
+[WASI Preview1]: https://github.com/WebAssembly/WASI/tree/main/legacy/preview1
+[Component Model]: https://github.com/webassembly/component-model
+
+Today the `wasm32-wasip1` target will generate core WebAssembly modules
+which will import functions from the `wasi_snapshot_preview1` module for
+OS-related functionality (e.g. printing).
+
+## Target maintainers
+
+When this target was added to the compiler platform-specific documentation here
+was not maintained at that time. This means that the list below is not
+exhaustive and there are more interested parties in this target. That being
+said since when this document was last updated those interested in maintaining
+this target are:
+
+- Alex Crichton, https://github.com/alexcrichton
+
+## Requirements
+
+This target is cross-compiled. The target includes support for `std` itself,
+but not all of the standard library works. For example spawning a thread will
+always return an error (see the `wasm32-wasi-preview1-threads` target for
+example). Another example is that spawning a process will always return an
+error. Operations such as opening a file, however, will be implemented by
+calling WASI-defined APIs.
+
+The WASI targets for Rust are explicitly intended to interoperate with other
+languages compiled to WebAssembly, for example C/C++. Any ABI differences or
+mismatches are considered bugs that need to be fixed.
+
+By default the WASI targets in Rust ship in rustup with a precompiled copy of
+[`wasi-libc`] meaning that a WebAssembly-targetting-Clang is not required to
+use the WASI targets from Rust.  If there is no actual interoperation with C
+then `rustup target add wasm32-wasip1` is all that's needed to get
+started with WASI.
+
+Note that this behavior can be controlled with `-Clinker` and
+`-Clink-self-contained`, however. By specifying `clang` as a linker and
+disabling the `link-self-contained` option an external version of `libc.a` can
+be used instead.
+
+[`wasi-libc`]: https://github.com/WebAssembly/wasi-libc
+
+## Building the target
+
+To build this target a compiled version of [`wasi-libc`] is required to be
+present at build time. This can be installed through
+[`wasi-sdk`](https://github.com/WebAssembly/wasi-sdk) as well. This is the
+configured with:
+
+```toml
+[target.wasm32-wasip1]
+wasi-root = ".../wasi-libc/sysroot"
+```
+
+Additionally users will need to enable LLD when building Rust from source as
+LLVM's `wasm-ld` driver for LLD is required when linking WebAssembly code
+together.
+
+## Building Rust programs
+
+The `wasm32-wasip1` target is shipped with rustup so users can install
+the target with:
+
+```text
+rustup target add wasm32-wasip1
+```
+
+> **Note**: the `wasm32-wasip1` target is new and may only be available
+> on nightly by the time you're reading this. If `wasm32-wasip1` isn't
+> available on stable Rust then `wasm32-wasi` should be available instead.
+
+Rust programs can be built for that target:
+
+```text
+rustc --target wasm32-wasip1 your-code.rs
+```
+
+## Cross-compilation
+
+This target can be cross-compiled from any hosts.
+
+## Testing
+
+Currently the WASI target is not tested in rust-lang/rust CI. This means that
+tests in the repository are not guaranteed to pass. This is theoretically
+possibly by installing a standalone WebAssembly runtime and using it as a
+"runner" for all tests, but there are various failures that will need to be
+waded through to adjust tests to work on the WASI target.
diff --git a/src/doc/unstable-book/src/language-features/asm-goto.md b/src/doc/unstable-book/src/language-features/asm-goto.md
new file mode 100644
index 00000000000..d72eb7c0c6e
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/asm-goto.md
@@ -0,0 +1,30 @@
+# `asm_goto`
+
+The tracking issue for this feature is: [#119364]
+
+[#119364]: https://github.com/rust-lang/rust/issues/119364
+
+------------------------
+
+This feature adds a `label <block>` operand type to `asm!`.
+
+Example:
+```rust,ignore (partial-example, x86-only)
+
+unsafe {
+    asm!(
+        "jmp {}",
+        label {
+            println!("Jumped from asm!");
+        }
+    );
+}
+```
+
+The block must have unit type or diverge.
+
+When `label <block>` is used together with `noreturn` option, it means that the
+assembly will not fallthrough. It's allowed to jump to a label within the
+assembly. In this case, the entire `asm!` expression will have an unit type as
+opposed to diverging, if not all label blocks diverge. The `asm!` expression
+still diverges if `noreturn` option is used and all label blocks diverge.
diff --git a/src/doc/unstable-book/src/language-features/diagnostic-namespace.md b/src/doc/unstable-book/src/language-features/diagnostic-namespace.md
deleted file mode 100644
index 7c46811a27a..00000000000
--- a/src/doc/unstable-book/src/language-features/diagnostic-namespace.md
+++ /dev/null
@@ -1,84 +0,0 @@
-# `diagnostic_namespace`
-
-The tracking issue for this feature is: [#111996]
-
-[#111996]: https://github.com/rust-lang/rust/issues/111996
-
-------------------------
-
-The `diagnostic_namespace` feature permits customization of compilation errors.
-
-## diagnostic::on_unimplemented
-
-With [#114452] support for `diagnostic::on_unimplemented` was added.
-
-When used on a trait declaration, the following options are available:
-
-* `message` to customize the primary error message
-* `note` to add a customized note message to an error message
-* `label` to customize the label part of the error message
-
-The attribute will hint to the compiler to use these in error messages:
-```rust
-// some library
-#![feature(diagnostic_namespace)]
-
-#[diagnostic::on_unimplemented(
-    message = "cannot insert element",
-    label = "cannot be put into a table",
-    note = "see <link> for more information about the Table api"
-)]
-pub trait Element {
-    // ...
-}
-```
-
-```rust,compile_fail,E0277
-# #![feature(diagnostic_namespace)]
-#
-# #[diagnostic::on_unimplemented(
-#    message = "cannot insert element",
-#    label = "cannot be put into a table",
-#    note = "see <link> for more information about the Table api"
-# )]
-# pub trait Element {
-#    // ...
-# }
-# struct Table;
-# impl Table {
-#    fn insert<T: Element>(&self, element: T) {
-#        // ..
-#    }
-# }
-# fn main() {
-#    let table = Table;
-#    let element = ();
-// user code
-table.insert(element);
-# }
-```
-
-```text
-error[E0277]: cannot insert element
-  --> src/main.rs:24:18
-   |
-24 |     table.insert(element);
-   |           ------ ^^^^^^^ cannot be put into a table
-   |           |
-   |           required by a bound introduced by this call
-   |
-   = help: the trait `Element` is not implemented for `<type>`
-   = note: see <link> for more information about the Table api
-note: required by a bound in `Table::insert`
-  --> src/main.rs:15:18
-   |
-15 |     fn insert<T: Element>(&self, element: T) {
-   |                  ^^^^^^^ required by this bound in `Table::insert`
-
-For more information about this error, try `rustc --explain E0277`.
-```
-
-See [RFC 3368] for more information.
-
-[#114452]: https://github.com/rust-lang/rust/pull/114452
-[RFC 3368]: https://github.com/rust-lang/rfcs/blob/master/text/3368-diagnostic-attribute-namespace.md
diff --git a/src/doc/unstable-book/src/language-features/intrinsics.md b/src/doc/unstable-book/src/language-features/intrinsics.md
index 1a8c1c0b36a..02a009d56d3 100644
--- a/src/doc/unstable-book/src/language-features/intrinsics.md
+++ b/src/doc/unstable-book/src/language-features/intrinsics.md
@@ -52,12 +52,23 @@ with any regular function.
 Various intrinsics have native MIR operations that they correspond to. Instead of requiring
 backends to implement both the intrinsic and the MIR operation, the `lower_intrinsics` pass
 will convert the calls to the MIR operation. Backends do not need to know about these intrinsics
-at all.
+at all. These intrinsics only make sense without a body, and can either be declared as a "rust-intrinsic"
+or as a `#[rustc_intrinsic]`. The body is never used, as calls to the intrinsic do not exist
+anymore after MIR analyses.
 
 ## Intrinsics without fallback logic
 
 These must be implemented by all backends.
 
+### `#[rustc_intrinsic]` declarations
+
+These are written like intrinsics with fallback bodies, but the body is irrelevant.
+Use `loop {}` for the body or call the intrinsic recursively and add
+`#[rustc_intrinsic_must_be_overridden]` to the function to ensure that backends don't
+invoke the body.
+
+### Legacy extern ABI based intrinsics
+
 These are imported as if they were FFI functions, with the special
 `rust-intrinsic` ABI. For example, if one was in a freestanding
 context, but wished to be able to `transmute` between types, and
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 0445daf0d4d..277db90df9a 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -130,18 +130,18 @@ impl Cfg {
     ///
     /// Equivalent to `attr::cfg_matches`.
     // FIXME: Actually make use of `features`.
-    pub(crate) fn matches(&self, parse_sess: &ParseSess, features: Option<&Features>) -> bool {
+    pub(crate) fn matches(&self, psess: &ParseSess, features: Option<&Features>) -> bool {
         match *self {
             Cfg::False => false,
             Cfg::True => true,
-            Cfg::Not(ref child) => !child.matches(parse_sess, features),
+            Cfg::Not(ref child) => !child.matches(psess, features),
             Cfg::All(ref sub_cfgs) => {
-                sub_cfgs.iter().all(|sub_cfg| sub_cfg.matches(parse_sess, features))
+                sub_cfgs.iter().all(|sub_cfg| sub_cfg.matches(psess, features))
             }
             Cfg::Any(ref sub_cfgs) => {
-                sub_cfgs.iter().any(|sub_cfg| sub_cfg.matches(parse_sess, features))
+                sub_cfgs.iter().any(|sub_cfg| sub_cfg.matches(psess, features))
             }
-            Cfg::Cfg(name, value) => parse_sess.config.contains(&(name, value)),
+            Cfg::Cfg(name, value) => psess.config.contains(&(name, value)),
         }
     }
 
diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs
index b6880cfc60f..5ac1b742c38 100644
--- a/src/librustdoc/clean/render_macro_matchers.rs
+++ b/src/librustdoc/clean/render_macro_matchers.rs
@@ -4,7 +4,6 @@ use rustc_ast_pretty::pprust::state::State as Printer;
 use rustc_ast_pretty::pprust::PrintState;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::parse::ParseSess;
-use rustc_span::source_map::FilePathMapping;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::Span;
 
@@ -63,11 +62,10 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option<String
     let snippet = source_map.span_to_snippet(span).ok()?;
 
     // Create a Parser.
-    let sess =
-        ParseSess::new(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), FilePathMapping::empty());
+    let psess = ParseSess::new(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec());
     let file_name = source_map.span_to_filename(span);
     let mut parser =
-        match rustc_parse::maybe_new_parser_from_source_str(&sess, file_name, snippet.clone()) {
+        match rustc_parse::maybe_new_parser_from_source_str(&psess, file_name, snippet.clone()) {
             Ok(parser) => parser,
             Err(errs) => {
                 errs.into_iter().for_each(|err| err.cancel());
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 9ba79cf5d29..80a30ac2727 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -263,7 +263,7 @@ pub(crate) fn create_config(
         file_loader: None,
         locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES,
         lint_caps,
-        parse_sess_created: None,
+        psess_created: None,
         hash_untracked_state: None,
         register_lints: Some(Box::new(crate::lint::register_lints)),
         override_queries: Some(|_sess, providers| {
@@ -314,21 +314,10 @@ pub(crate) fn run_global_ctxt(
     // typeck function bodies or run the default rustc lints.
     // (see `override_queries` in the `config`)
 
-    // HACK(jynelson) this calls an _extremely_ limited subset of `typeck`
-    // and might break if queries change their assumptions in the future.
-    tcx.sess.time("type_collecting", || {
-        tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
-    });
-
     // NOTE: These are copy/pasted from typeck/lib.rs and should be kept in sync with those changes.
     let _ = tcx.sess.time("wf_checking", || {
         tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
     });
-    tcx.sess.time("item_types_checking", || {
-        tcx.hir().for_each_module(|module| {
-            let _ = tcx.ensure().check_mod_type_wf(module);
-        });
-    });
 
     if let Some(guar) = tcx.dcx().has_errors() {
         return Err(guar);
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 3d92444364f..d446b781bf1 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -102,7 +102,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
         file_loader: None,
         locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES,
         lint_caps,
-        parse_sess_created: None,
+        psess_created: None,
         hash_untracked_state: None,
         register_lints: Some(Box::new(crate::lint::register_lints)),
         override_queries: None,
@@ -131,7 +131,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
                         options,
                         false,
                         opts,
-                        Some(compiler.sess.parse_sess.clone_source_map()),
+                        Some(compiler.sess.psess.clone_source_map()),
                         None,
                         enable_per_target_ignores,
                     );
@@ -585,13 +585,13 @@ pub(crate) fn make_test(
 
             // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
             let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
-            let sess = ParseSess::with_dcx(dcx, sm);
+            let psess = ParseSess::with_dcx(dcx, sm);
 
             let mut found_main = false;
             let mut found_extern_crate = crate_name.is_none();
             let mut found_macro = false;
 
-            let mut parser = match maybe_new_parser_from_source_str(&sess, filename, source) {
+            let mut parser = match maybe_new_parser_from_source_str(&psess, filename, source) {
                 Ok(p) => p,
                 Err(errs) => {
                     errs.into_iter().for_each(|err| err.cancel());
@@ -646,7 +646,7 @@ pub(crate) fn make_test(
             // dcx. Any errors in the tests will be reported when the test file is compiled,
             // Note that we still need to cancel the errors above otherwise `Diag` will panic on
             // drop.
-            sess.dcx.reset_err_count();
+            psess.dcx.reset_err_count();
 
             (found_main, found_extern_crate, found_macro)
         })
@@ -770,9 +770,9 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
             let emitter = HumanEmitter::new(Box::new(io::sink()), fallback_bundle);
 
             let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
-            let sess = ParseSess::with_dcx(dcx, sm);
+            let psess = ParseSess::with_dcx(dcx, sm);
             let mut parser =
-                match maybe_new_parser_from_source_str(&sess, filename, source.to_owned()) {
+                match maybe_new_parser_from_source_str(&psess, filename, source.to_owned()) {
                     Ok(p) => p,
                     Err(errs) => {
                         errs.into_iter().for_each(|err| err.cancel());
@@ -1233,7 +1233,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
     ) {
         let ast_attrs = self.tcx.hir().attrs(self.tcx.local_def_id_to_hir_id(def_id));
         if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) {
-            if !cfg.matches(&self.sess.parse_sess, Some(self.tcx.features())) {
+            if !cfg.matches(&self.sess.psess, Some(self.tcx.features())) {
                 return;
             }
         }
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index e8b250648bc..64f0e096cd0 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -27,7 +27,7 @@
 //! ```
 
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{Diag, DiagnosticMessage};
+use rustc_errors::{Diag, DiagMessage};
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::TyCtxt;
 pub(crate) use rustc_resolve::rustdoc::main_body_opts;
@@ -828,7 +828,7 @@ impl<'tcx> ExtraInfo<'tcx> {
         ExtraInfo { def_id, sp, tcx }
     }
 
-    fn error_invalid_codeblock_attr(&self, msg: impl Into<DiagnosticMessage>) {
+    fn error_invalid_codeblock_attr(&self, msg: impl Into<DiagMessage>) {
         if let Some(def_id) = self.def_id.as_local() {
             self.tcx.node_span_lint(
                 crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
@@ -842,7 +842,7 @@ impl<'tcx> ExtraInfo<'tcx> {
 
     fn error_invalid_codeblock_attr_with_help(
         &self,
-        msg: impl Into<DiagnosticMessage>,
+        msg: impl Into<DiagMessage>,
         f: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
     ) {
         if let Some(def_id) = self.def_id.as_local() {
@@ -952,7 +952,7 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> {
         Self { inner: data.char_indices().peekable(), data, is_in_attribute_block: false, extra }
     }
 
-    fn emit_error(&self, err: impl Into<DiagnosticMessage>) {
+    fn emit_error(&self, err: impl Into<DiagMessage>) {
         if let Some(extra) = self.extra {
             extra.error_invalid_codeblock_attr(err);
         }
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 33837fe5652..39d27b104cd 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -179,21 +179,14 @@ pub fn main() {
     rustc_driver::init_logger(&early_dcx, rustc_log::LoggerConfig::from_env("RUSTDOC_LOG"));
 
     let exit_code = rustc_driver::catch_with_exit_code(|| {
-        let args = env::args_os()
-            .enumerate()
-            .map(|(i, arg)| {
-                arg.into_string().unwrap_or_else(|arg| {
-                    early_dcx.early_fatal(format!("argument {i} is not valid Unicode: {arg:?}"))
-                })
-            })
-            .collect::<Vec<_>>();
-        main_args(&mut early_dcx, &args, using_internal_features)
+        let at_args = rustc_driver::args::raw_args(&early_dcx)?;
+        main_args(&mut early_dcx, &at_args, using_internal_features)
     });
     process::exit(exit_code);
 }
 
 fn init_logging(early_dcx: &EarlyDiagCtxt) {
-    let color_logs = match std::env::var("RUSTDOC_LOG_COLOR").as_deref() {
+    let color_logs = match env::var("RUSTDOC_LOG_COLOR").as_deref() {
         Ok("always") => true,
         Ok("never") => false,
         Ok("auto") | Err(VarError::NotPresent) => io::stdout().is_terminal(),
@@ -705,7 +698,7 @@ fn main_args(
     // the compiler with @empty_file as argv[0] and no more arguments.
     let at_args = at_args.get(1..).unwrap_or_default();
 
-    let args = rustc_driver::args::arg_expand_all(early_dcx, at_args);
+    let args = rustc_driver::args::arg_expand_all(early_dcx, at_args)?;
 
     let mut options = getopts::Options::new();
     for option in opts() {
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 33bdbbe1b94..a5f5fca3d15 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -8,7 +8,7 @@ use rustc_data_structures::{
     fx::{FxHashMap, FxHashSet},
     intern::Interned,
 };
-use rustc_errors::{Applicability, Diag, DiagnosticMessage};
+use rustc_errors::{Applicability, Diag, DiagMessage};
 use rustc_hir::def::Namespace::*;
 use rustc_hir::def::{DefKind, Namespace, PerNS};
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
@@ -1674,7 +1674,7 @@ impl Suggestion {
 fn report_diagnostic(
     tcx: TyCtxt<'_>,
     lint: &'static Lint,
-    msg: impl Into<DiagnosticMessage> + Display,
+    msg: impl Into<DiagMessage> + Display,
     DiagnosticInfo { item, ori_link: _, dox, link_range }: &DiagnosticInfo<'_>,
     decorate: impl FnOnce(&mut Diag<'_, ()>, Option<rustc_span::Span>, MarkdownLinkRange),
 ) {
@@ -2010,7 +2010,7 @@ fn disambiguator_error(
     cx: &DocContext<'_>,
     mut diag_info: DiagnosticInfo<'_>,
     disambiguator_range: MarkdownLinkRange,
-    msg: impl Into<DiagnosticMessage> + Display,
+    msg: impl Into<DiagMessage> + Display,
 ) {
     diag_info.link_range = disambiguator_range;
     report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, _sp, _link_range| {
diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs
index 5145d8babef..7b81b5e63be 100644
--- a/src/librustdoc/passes/lint/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs
@@ -44,7 +44,7 @@ fn check_rust_syntax(
     let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
     let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
     let source = dox[code_block.code].to_owned();
-    let sess = ParseSess::with_dcx(dcx, sm);
+    let psess = ParseSess::with_dcx(dcx, sm);
 
     let edition = code_block.lang_string.edition.unwrap_or_else(|| cx.tcx.sess.edition());
     let expn_data =
@@ -56,7 +56,7 @@ fn check_rust_syntax(
         parse_stream_from_source_str(
             FileName::Custom(String::from("doctest")),
             source,
-            &sess,
+            &psess,
             Some(span),
         )
         .is_empty()
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index f0975fc0823..067bf4054da 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -148,6 +148,7 @@ static TARGETS: &[&str] = &[
     "wasm32-unknown-emscripten",
     "wasm32-unknown-unknown",
     "wasm32-wasi",
+    "wasm32-wasip1",
     "wasm32-wasi-preview1-threads",
     "x86_64-apple-darwin",
     "x86_64-apple-ios",
diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs
index b91dc38e924..a3c857b0268 100644
--- a/src/tools/build_helper/src/git.rs
+++ b/src/tools/build_helper/src/git.rs
@@ -113,6 +113,7 @@ pub fn get_git_merge_base(
 
 /// Returns the files that have been modified in the current branch compared to the master branch.
 /// The `extensions` parameter can be used to filter the files by their extension.
+/// Does not include removed files.
 /// If `extensions` is empty, all files will be returned.
 pub fn get_git_modified_files(
     config: &GitConfig<'_>,
@@ -125,13 +126,19 @@ pub fn get_git_modified_files(
     if let Some(git_dir) = git_dir {
         git.current_dir(git_dir);
     }
-    let files = output_result(git.args(["diff-index", "--name-only", merge_base.trim()]))?
+    let files = output_result(git.args(["diff-index", "--name-status", merge_base.trim()]))?
         .lines()
-        .map(|s| s.trim().to_owned())
-        .filter(|f| {
-            Path::new(f).extension().map_or(false, |ext| {
+        .filter_map(|f| {
+            let (status, name) = f.trim().split_once(char::is_whitespace).unwrap();
+            if status == "D" {
+                None
+            } else if Path::new(name).extension().map_or(false, |ext| {
                 extensions.is_empty() || extensions.contains(&ext.to_str().unwrap())
-            })
+            }) {
+                Some(name.to_owned())
+            } else {
+                None
+            }
         })
         .collect();
     Ok(Some(files))
diff --git a/src/tools/cargo b/src/tools/cargo
index f772ec0224d..a4c63fe5388 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit f772ec0224d3755ce52ac5128a80319fb2eb45d0
+Subproject commit a4c63fe5388beaa09e5f91196c86addab0a03580
diff --git a/src/tools/clippy/.github/driver.sh b/src/tools/clippy/.github/driver.sh
index 11fd6b5c79e..2eafdd0fbc8 100755
--- a/src/tools/clippy/.github/driver.sh
+++ b/src/tools/clippy/.github/driver.sh
@@ -50,11 +50,11 @@ diff -u normalized.stderr tests/ui/double_neg.stderr
 
 # make sure "clippy-driver --rustc --arg" and "rustc --arg" behave the same
 SYSROOT=$(rustc --print sysroot)
-diff -u <(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver --rustc --version --verbose) <(rustc --version --verbose)
+diff -u <(./target/debug/clippy-driver --rustc --version --verbose) <(rustc --version --verbose)
 
 echo "fn main() {}" >target/driver_test.rs
 # we can't run 2 rustcs on the same file at the same time
-CLIPPY=$(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver ./target/driver_test.rs --rustc)
+CLIPPY=$(./target/debug/clippy-driver ./target/driver_test.rs --rustc)
 RUSTC=$(rustc ./target/driver_test.rs)
 diff -u <($CLIPPY) <($RUSTC)
 
diff --git a/src/tools/clippy/.github/workflows/clippy.yml b/src/tools/clippy/.github/workflows/clippy.yml
index 5ba960db66d..603f91a910b 100644
--- a/src/tools/clippy/.github/workflows/clippy.yml
+++ b/src/tools/clippy/.github/workflows/clippy.yml
@@ -44,11 +44,6 @@ jobs:
       run: rustup show active-toolchain
 
     # Run
-    - name: Set LD_LIBRARY_PATH (Linux)
-      run: |
-        SYSROOT=$(rustc --print sysroot)
-        echo "LD_LIBRARY_PATH=${SYSROOT}/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" >> $GITHUB_ENV
-
     - name: Build
       run: cargo build --tests --features deny-warnings,internal
 
@@ -72,6 +67,6 @@ jobs:
       working-directory: clippy_dev
 
     - name: Test clippy-driver
-      run: bash .github/driver.sh
-      env:
-        OS: ${{ runner.os }}
+      run: |
+        TOOLCHAIN=$(rustup show active-toolchain | cut -f1 -d' ')
+        rustup run $TOOLCHAIN bash .github/driver.sh
diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml
index 012797e5ca7..0bc28c1f9d9 100644
--- a/src/tools/clippy/.github/workflows/clippy_bors.yml
+++ b/src/tools/clippy/.github/workflows/clippy_bors.yml
@@ -59,7 +59,7 @@ jobs:
           host: i686-unknown-linux-gnu
         - os: windows-latest
           host: x86_64-pc-windows-msvc
-        - os: macos-latest
+        - os: macos-13
           host: x86_64-apple-darwin
 
     runs-on: ${{ matrix.os }}
@@ -87,23 +87,6 @@ jobs:
         rustup show active-toolchain
 
     # Run
-    - name: Set LD_LIBRARY_PATH (Linux)
-      if: runner.os == 'Linux'
-      run: |
-        SYSROOT=$(rustc --print sysroot)
-        echo "LD_LIBRARY_PATH=${SYSROOT}/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" >> $GITHUB_ENV
-    - name: Link rustc dylib (MacOS)
-      if: runner.os == 'macOS'
-      run: |
-        SYSROOT=$(rustc --print sysroot)
-        sudo mkdir -p /usr/local/lib
-        sudo find "${SYSROOT}/lib" -maxdepth 1 -name '*dylib' -exec ln -s {} /usr/local/lib \;
-    - name: Set PATH (Windows)
-      if: runner.os == 'Windows'
-      run: |
-        SYSROOT=$(rustc --print sysroot)
-        echo "$SYSROOT/bin" >> $GITHUB_PATH
-
     - name: Build
       run: cargo build --tests --features deny-warnings,internal
 
@@ -136,7 +119,9 @@ jobs:
       working-directory: clippy_dev
 
     - name: Test clippy-driver
-      run: bash .github/driver.sh
+      run: |
+        TOOLCHAIN=$(rustup show active-toolchain | cut -f1 -d' ')
+        rustup run $TOOLCHAIN bash .github/driver.sh
       env:
         OS: ${{ runner.os }}
 
@@ -236,11 +221,6 @@ jobs:
     - name: Install toolchain
       run: rustup show active-toolchain
 
-    - name: Set LD_LIBRARY_PATH
-      run: |
-        SYSROOT=$(rustc --print sysroot)
-        echo "LD_LIBRARY_PATH=${SYSROOT}/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" >> $GITHUB_ENV
-
     # Download
     - name: Download target dir
       uses: actions/download-artifact@v3
@@ -254,8 +234,8 @@ jobs:
     # Run
     - name: Test ${{ matrix.integration }}
       run: |
-        RUSTUP_TOOLCHAIN="$(rustup show active-toolchain | grep -o -E "nightly-[0-9]{4}-[0-9]{2}-[0-9]{2}")" \
-          $CARGO_TARGET_DIR/debug/integration --show-output
+          TOOLCHAIN=$(rustup show active-toolchain | cut -f1 -d' ')
+          rustup run $TOOLCHAIN $CARGO_TARGET_DIR/debug/integration --show-output
       env:
         INTEGRATION: ${{ matrix.integration }}
 
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index f0b01742deb..d3b2c0a7bf6 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -5046,6 +5046,7 @@ Released 2018-09-13
 [`assertions_on_result_states`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_result_states
 [`assign_op_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_op_pattern
 [`assign_ops`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_ops
+[`assigning_clones`]: https://rust-lang.github.io/rust-clippy/master/index.html#assigning_clones
 [`async_yields_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#async_yields_async
 [`await_holding_invalid_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type
 [`await_holding_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_lock
@@ -5423,6 +5424,7 @@ Released 2018-09-13
 [`missing_spin_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_spin_loop
 [`missing_trait_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_trait_methods
 [`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes
+[`mixed_attributes_style`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_attributes_style
 [`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals
 [`mixed_read_write_in_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_read_write_in_expression
 [`mod_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#mod_module_files
@@ -5816,74 +5818,74 @@ Released 2018-09-13
 [`zst_offset`]: https://rust-lang.github.io/rust-clippy/master/index.html#zst_offset
 <!-- end autogenerated links to lint list -->
 <!-- begin autogenerated links to configuration documentation -->
+[`absolute-paths-allowed-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-allowed-crates
+[`absolute-paths-max-segments`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-max-segments
+[`accept-comment-above-attributes`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-attributes
+[`accept-comment-above-statement`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-statement
+[`allow-comparison-to-zero`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-comparison-to-zero
+[`allow-dbg-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-dbg-in-tests
+[`allow-expect-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-expect-in-tests
+[`allow-mixed-uninlined-format-args`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-mixed-uninlined-format-args
+[`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings
+[`allow-print-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-print-in-tests
+[`allow-private-module-inception`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-private-module-inception
+[`allow-unwrap-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-in-tests
+[`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles
+[`allowed-duplicate-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-duplicate-crates
+[`allowed-idents-below-min-chars`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-idents-below-min-chars
+[`allowed-scripts`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-scripts
+[`allowed-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-wildcard-imports
 [`arithmetic-side-effects-allowed`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed
 [`arithmetic-side-effects-allowed-binary`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed-binary
 [`arithmetic-side-effects-allowed-unary`]: https://doc.rust-lang.org/clippy/lint_configuration.html#arithmetic-side-effects-allowed-unary
-[`avoid-breaking-exported-api`]: https://doc.rust-lang.org/clippy/lint_configuration.html#avoid-breaking-exported-api
-[`msrv`]: https://doc.rust-lang.org/clippy/lint_configuration.html#msrv
-[`cognitive-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cognitive-complexity-threshold
-[`excessive-nesting-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#excessive-nesting-threshold
-[`disallowed-names`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-names
-[`semicolon-inside-block-ignore-singleline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-inside-block-ignore-singleline
-[`semicolon-outside-block-ignore-multiline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-outside-block-ignore-multiline
-[`doc-valid-idents`]: https://doc.rust-lang.org/clippy/lint_configuration.html#doc-valid-idents
-[`too-many-arguments-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-arguments-threshold
-[`type-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#type-complexity-threshold
-[`single-char-binding-names-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#single-char-binding-names-threshold
-[`too-large-for-stack`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-large-for-stack
-[`enum-variant-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enum-variant-name-threshold
-[`struct-field-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#struct-field-name-threshold
-[`enum-variant-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enum-variant-size-threshold
-[`verbose-bit-mask-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#verbose-bit-mask-threshold
-[`literal-representation-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#literal-representation-threshold
-[`trivial-copy-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#trivial-copy-size-limit
-[`pass-by-value-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pass-by-value-size-limit
-[`too-many-lines-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-lines-threshold
 [`array-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#array-size-threshold
-[`stack-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#stack-size-threshold
-[`vec-box-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#vec-box-size-threshold
-[`max-trait-bounds`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-trait-bounds
-[`max-struct-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-struct-bools
-[`max-fn-params-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-fn-params-bools
-[`warn-on-all-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#warn-on-all-wildcard-imports
+[`avoid-breaking-exported-api`]: https://doc.rust-lang.org/clippy/lint_configuration.html#avoid-breaking-exported-api
+[`await-holding-invalid-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#await-holding-invalid-types
+[`cargo-ignore-publish`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cargo-ignore-publish
+[`check-private-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-private-items
+[`cognitive-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cognitive-complexity-threshold
 [`disallowed-macros`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-macros
 [`disallowed-methods`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-methods
+[`disallowed-names`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-names
 [`disallowed-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-types
+[`doc-valid-idents`]: https://doc.rust-lang.org/clippy/lint_configuration.html#doc-valid-idents
+[`enable-raw-pointer-heuristic-for-send`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enable-raw-pointer-heuristic-for-send
+[`enforce-iter-loop-reborrow`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforce-iter-loop-reborrow
+[`enforced-import-renames`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforced-import-renames
+[`enum-variant-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enum-variant-name-threshold
+[`enum-variant-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enum-variant-size-threshold
+[`excessive-nesting-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#excessive-nesting-threshold
+[`future-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#future-size-threshold
+[`ignore-interior-mutability`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-interior-mutability
+[`large-error-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-threshold
+[`literal-representation-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#literal-representation-threshold
+[`matches-for-let-else`]: https://doc.rust-lang.org/clippy/lint_configuration.html#matches-for-let-else
+[`max-fn-params-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-fn-params-bools
+[`max-include-file-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-include-file-size
+[`max-struct-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-struct-bools
+[`max-suggested-slice-pattern-length`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-suggested-slice-pattern-length
+[`max-trait-bounds`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-trait-bounds
+[`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold
+[`missing-docs-in-crate-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#missing-docs-in-crate-items
+[`msrv`]: https://doc.rust-lang.org/clippy/lint_configuration.html#msrv
+[`pass-by-value-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pass-by-value-size-limit
+[`pub-underscore-fields-behavior`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pub-underscore-fields-behavior
+[`semicolon-inside-block-ignore-singleline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-inside-block-ignore-singleline
+[`semicolon-outside-block-ignore-multiline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-outside-block-ignore-multiline
+[`single-char-binding-names-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#single-char-binding-names-threshold
+[`stack-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#stack-size-threshold
+[`standard-macro-braces`]: https://doc.rust-lang.org/clippy/lint_configuration.html#standard-macro-braces
+[`struct-field-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#struct-field-name-threshold
+[`suppress-restriction-lint-in-const`]: https://doc.rust-lang.org/clippy/lint_configuration.html#suppress-restriction-lint-in-const
+[`too-large-for-stack`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-large-for-stack
+[`too-many-arguments-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-arguments-threshold
+[`too-many-lines-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-lines-threshold
+[`trivial-copy-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#trivial-copy-size-limit
+[`type-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#type-complexity-threshold
+[`unnecessary-box-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unnecessary-box-size
 [`unreadable-literal-lint-fractions`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unreadable-literal-lint-fractions
 [`upper-case-acronyms-aggressive`]: https://doc.rust-lang.org/clippy/lint_configuration.html#upper-case-acronyms-aggressive
-[`matches-for-let-else`]: https://doc.rust-lang.org/clippy/lint_configuration.html#matches-for-let-else
-[`cargo-ignore-publish`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cargo-ignore-publish
-[`standard-macro-braces`]: https://doc.rust-lang.org/clippy/lint_configuration.html#standard-macro-braces
-[`enforced-import-renames`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforced-import-renames
-[`allowed-scripts`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-scripts
-[`enable-raw-pointer-heuristic-for-send`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enable-raw-pointer-heuristic-for-send
-[`max-suggested-slice-pattern-length`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-suggested-slice-pattern-length
-[`await-holding-invalid-types`]: https://doc.rust-lang.org/clippy/lint_configuration.html#await-holding-invalid-types
-[`max-include-file-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-include-file-size
-[`allow-expect-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-expect-in-tests
-[`allow-unwrap-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-in-tests
-[`allow-dbg-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-dbg-in-tests
-[`allow-print-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-print-in-tests
-[`large-error-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-threshold
-[`ignore-interior-mutability`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-interior-mutability
-[`allow-mixed-uninlined-format-args`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-mixed-uninlined-format-args
-[`suppress-restriction-lint-in-const`]: https://doc.rust-lang.org/clippy/lint_configuration.html#suppress-restriction-lint-in-const
-[`missing-docs-in-crate-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#missing-docs-in-crate-items
-[`future-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#future-size-threshold
-[`unnecessary-box-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unnecessary-box-size
-[`allow-private-module-inception`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-private-module-inception
-[`allowed-idents-below-min-chars`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-idents-below-min-chars
-[`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold
-[`accept-comment-above-statement`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-statement
-[`accept-comment-above-attributes`]: https://doc.rust-lang.org/clippy/lint_configuration.html#accept-comment-above-attributes
-[`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings
-[`absolute-paths-max-segments`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-max-segments
-[`absolute-paths-allowed-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-allowed-crates
-[`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles
-[`allowed-duplicate-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-duplicate-crates
-[`enforce-iter-loop-reborrow`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforce-iter-loop-reborrow
-[`check-private-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-private-items
-[`pub-underscore-fields-behavior`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pub-underscore-fields-behavior
-[`allow-comparison-to-zero`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-comparison-to-zero
-[`allowed-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-wildcard-imports
+[`vec-box-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#vec-box-size-threshold
+[`verbose-bit-mask-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#verbose-bit-mask-threshold
+[`warn-on-all-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#warn-on-all-wildcard-imports
 <!-- end autogenerated links to configuration documentation -->
diff --git a/src/tools/clippy/book/src/development/trait_checking.md b/src/tools/clippy/book/src/development/trait_checking.md
index fb263922cf8..b7d229ccc19 100644
--- a/src/tools/clippy/book/src/development/trait_checking.md
+++ b/src/tools/clippy/book/src/development/trait_checking.md
@@ -94,6 +94,53 @@ impl LateLintPass<'_> for CheckTokioAsyncReadExtTrait {
 }
 ```
 
+## Creating Types Programmatically
+
+Traits are often generic over a type parameter, e.g. `Borrow<T>` is generic
+over `T`. Rust allows us to implement a trait for a specific type. For example,
+we can implement `Borrow<[u8]>` for a hypothetical type `Foo`. Let's suppose
+that we would like to find whether our type actually implements `Borrow<[u8]>`.
+
+To do so, we can use the same `implements_trait` function as above, and supply
+a type parameter that represents `[u8]`. Since `[u8]` is a specialization of
+`[T]`, we can use the  [`Ty::new_slice`][new_slice] method to create a type
+that represents `[T]` and supply `u8` as a type parameter.
+To create a `ty::Ty` programmatically, we rely on `Ty::new_*` methods. These
+methods create a `TyKind` and then wrap it in a `Ty` struct. This means we
+have access to all the primitive types, such as `Ty::new_char`,
+`Ty::new_bool`, `Ty::new_int`, etc. We can also create more complex types,
+such as slices, tuples, and references out of these basic building blocks.
+
+For trait checking, it is not enough to create the types, we need to convert
+them into [GenericArg]. In rustc, a generic is an entity that the compiler
+understands and has three kinds, type, const and lifetime. By calling
+`.into()` on a constructed [Ty], we wrap the type into a generic which can
+then be used by the query system to decide whether the specialized trait
+is implemented.
+
+The following code demonstrates how to do this:
+
+```rust
+
+use rustc_middle::ty::Ty;
+use clippy_utils::ty::implements_trait;
+use rustc_span::symbol::sym;
+
+let ty = todo!("Get the `Foo` type to check for a trait implementation");
+let borrow_id = cx.tcx.get_diagnostic_item(sym::Borrow).unwrap(); // avoid unwrap in real code
+let slice_of_bytes_t = Ty::new_slice(cx.tcx, cx.tcx.types.u8);
+let generic_param = slice_of_bytes_t.into();
+if implements_trait(cx, ty, borrow_id, &[generic_param]) {
+    todo!("Rest of lint implementation")
+}
+```
+
+In essence, the [Ty] struct allows us to create types programmatically in a
+representation that can be used by the compiler and the query engine. We then
+use the `rustc_middle::Ty` of the type we are interested in, and query the
+compiler to see if it indeed implements the trait we are interested in.
+
+
 [DefId]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html
 [diagnostic_items]: https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html
 [lang_items]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/lang_items/struct.LanguageItems.html
@@ -102,4 +149,7 @@ impl LateLintPass<'_> for CheckTokioAsyncReadExtTrait {
 [symbol]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Symbol.html
 [symbol_index]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_span/symbol/sym/index.html
 [TyCtxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html
+[Ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html
 [rust]: https://github.com/rust-lang/rust
+[new_slice]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.new_slice
+[GenericArg]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.GenericArg.html
diff --git a/src/tools/clippy/book/src/development/type_checking.md b/src/tools/clippy/book/src/development/type_checking.md
index dc29ab5d08d..136b3fd0270 100644
--- a/src/tools/clippy/book/src/development/type_checking.md
+++ b/src/tools/clippy/book/src/development/type_checking.md
@@ -123,6 +123,22 @@ the [`TypeckResults::node_type()`][node_type] method inside of bodies.
 
 > **Warning**: Don't use `hir_ty_to_ty` inside of bodies, because this can cause ICEs.
 
+## Creating Types programmatically
+
+A common usecase for creating types programmatically is when we want to check if a type implements a trait (see
+[Trait Checking](trait_checking.md)).
+
+Here's an example of how to create a `Ty` for a slice of `u8`, i.e. `[u8]`
+
+```rust
+use rustc_middle::ty::Ty;
+// assume we have access to a LateContext
+let ty = Ty::new_slice(cx.tcx, Ty::new_u8());
+```
+
+In general, we rely on `Ty::new_*` methods. These methods define the basic building-blocks that the
+type-system and trait-system use to define and understand the written code.
+
 ## Useful Links
 
 Below are some useful links to further explore the concepts covered
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index 214a60d3bfd..a985346b3c0 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -10,6 +10,192 @@ and lints affected.
 
 ---
 
+## `absolute-paths-allowed-crates`
+Which crates to allow absolute paths from
+
+**Default Value:** `[]`
+
+---
+**Affected lints:**
+* [`absolute_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths)
+
+
+## `absolute-paths-max-segments`
+The maximum number of segments a path can have before being linted, anything above this will
+be linted.
+
+**Default Value:** `2`
+
+---
+**Affected lints:**
+* [`absolute_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths)
+
+
+## `accept-comment-above-attributes`
+Whether to accept a safety comment to be placed above the attributes for the `unsafe` block
+
+**Default Value:** `true`
+
+---
+**Affected lints:**
+* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks)
+
+
+## `accept-comment-above-statement`
+Whether to accept a safety comment to be placed above the statement containing the `unsafe` block
+
+**Default Value:** `true`
+
+---
+**Affected lints:**
+* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks)
+
+
+## `allow-comparison-to-zero`
+Don't lint when comparing the result of a modulo operation to zero.
+
+**Default Value:** `true`
+
+---
+**Affected lints:**
+* [`modulo_arithmetic`](https://rust-lang.github.io/rust-clippy/master/index.html#modulo_arithmetic)
+
+
+## `allow-dbg-in-tests`
+Whether `dbg!` should be allowed in test functions or `#[cfg(test)]`
+
+**Default Value:** `false`
+
+---
+**Affected lints:**
+* [`dbg_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro)
+
+
+## `allow-expect-in-tests`
+Whether `expect` should be allowed in test functions or `#[cfg(test)]`
+
+**Default Value:** `false`
+
+---
+**Affected lints:**
+* [`expect_used`](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used)
+
+
+## `allow-mixed-uninlined-format-args`
+Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)`
+
+**Default Value:** `true`
+
+---
+**Affected lints:**
+* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args)
+
+
+## `allow-one-hash-in-raw-strings`
+Whether to allow `r#""#` when `r""` can be used
+
+**Default Value:** `false`
+
+---
+**Affected lints:**
+* [`unnecessary_raw_string_hashes`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_raw_string_hashes)
+
+
+## `allow-print-in-tests`
+Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]`
+
+**Default Value:** `false`
+
+---
+**Affected lints:**
+* [`print_stderr`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr)
+* [`print_stdout`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout)
+
+
+## `allow-private-module-inception`
+Whether to allow module inception if it's not public.
+
+**Default Value:** `false`
+
+---
+**Affected lints:**
+* [`module_inception`](https://rust-lang.github.io/rust-clippy/master/index.html#module_inception)
+
+
+## `allow-unwrap-in-tests`
+Whether `unwrap` should be allowed in test functions or `#[cfg(test)]`
+
+**Default Value:** `false`
+
+---
+**Affected lints:**
+* [`unwrap_used`](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used)
+
+
+## `allowed-dotfiles`
+Additional dotfiles (files or directories starting with a dot) to allow
+
+**Default Value:** `[]`
+
+---
+**Affected lints:**
+* [`path_ends_with_ext`](https://rust-lang.github.io/rust-clippy/master/index.html#path_ends_with_ext)
+
+
+## `allowed-duplicate-crates`
+A list of crate names to allow duplicates of
+
+**Default Value:** `[]`
+
+---
+**Affected lints:**
+* [`multiple_crate_versions`](https://rust-lang.github.io/rust-clippy/master/index.html#multiple_crate_versions)
+
+
+## `allowed-idents-below-min-chars`
+Allowed names below the minimum allowed characters. The value `".."` can be used as part of
+the list to indicate, that the configured values should be appended to the default
+configuration of Clippy. By default, any configuration will replace the default value.
+
+**Default Value:** `["j", "z", "i", "y", "n", "x", "w"]`
+
+---
+**Affected lints:**
+* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars)
+
+
+## `allowed-scripts`
+The list of unicode scripts allowed to be used in the scope.
+
+**Default Value:** `["Latin"]`
+
+---
+**Affected lints:**
+* [`disallowed_script_idents`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents)
+
+
+## `allowed-wildcard-imports`
+List of path segments allowed to have wildcard imports.
+
+#### Example
+
+```toml
+allowed-wildcard-imports = [ "utils", "common" ]
+```
+
+#### Noteworthy
+
+1. This configuration has no effects if used with `warn_on_all_wildcard_imports = true`.
+2. Paths with any segment that containing the word 'prelude'
+are already allowed by default.
+
+**Default Value:** `[]`
+
+---
+**Affected lints:**
+* [`wildcard_imports`](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports)
+
+
 ## `arithmetic-side-effects-allowed`
 Suppress checking of the passed type names in all types of operations.
 
@@ -72,6 +258,17 @@ arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
 * [`arithmetic_side_effects`](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects)
 
 
+## `array-size-threshold`
+The maximum allowed size for arrays on the stack
+
+**Default Value:** `512000`
+
+---
+**Affected lints:**
+* [`large_const_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays)
+* [`large_stack_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays)
+
+
 ## `avoid-breaking-exported-api`
 Suppress lints whenever the suggested change would cause breakage for other crates.
 
@@ -79,79 +276,55 @@ Suppress lints whenever the suggested change would cause breakage for other crat
 
 ---
 **Affected lints:**
+* [`box_collection`](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection)
 * [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names)
 * [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value)
+* [`linkedlist`](https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist)
+* [`option_option`](https://rust-lang.github.io/rust-clippy/master/index.html#option_option)
+* [`rc_buffer`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer)
+* [`rc_mutex`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex)
+* [`redundant_allocation`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation)
+* [`single_call_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#single_call_fn)
 * [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref)
+* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns)
 * [`unnecessary_wraps`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps)
 * [`unused_self`](https://rust-lang.github.io/rust-clippy/master/index.html#unused_self)
 * [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms)
-* [`wrong_self_convention`](https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention)
-* [`box_collection`](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection)
-* [`redundant_allocation`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation)
-* [`rc_buffer`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer)
 * [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box)
-* [`option_option`](https://rust-lang.github.io/rust-clippy/master/index.html#option_option)
-* [`linkedlist`](https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist)
-* [`rc_mutex`](https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex)
-* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns)
-* [`single_call_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#single_call_fn)
+* [`wrong_self_convention`](https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention)
 
 
-## `msrv`
-The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
+## `await-holding-invalid-types`
+
+
+**Default Value:** `[]`
 
 ---
 **Affected lints:**
-* [`manual_split_once`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once)
-* [`manual_str_repeat`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat)
-* [`cloned_instead_of_copied`](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied)
-* [`redundant_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names)
-* [`option_map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or)
-* [`redundant_static_lifetimes`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes)
-* [`filter_map_next`](https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next)
-* [`checked_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions)
-* [`manual_range_contains`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains)
-* [`use_self`](https://rust-lang.github.io/rust-clippy/master/index.html#use_self)
-* [`mem_replace_with_default`](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default)
-* [`manual_non_exhaustive`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive)
-* [`option_as_ref_deref`](https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref)
-* [`map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or)
-* [`match_like_matches_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro)
-* [`manual_strip`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip)
-* [`missing_const_for_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn)
-* [`unnested_or_patterns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns)
-* [`from_over_into`](https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into)
-* [`ptr_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr)
-* [`if_then_some_else_none`](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none)
-* [`approx_constant`](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant)
-* [`deprecated_cfg_attr`](https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr)
-* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice)
-* [`map_clone`](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone)
-* [`borrow_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr)
-* [`manual_bits`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits)
-* [`err_expect`](https://rust-lang.github.io/rust-clippy/master/index.html#err_expect)
-* [`cast_abs_to_unsigned`](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned)
-* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args)
-* [`manual_clamp`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp)
-* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else)
-* [`unchecked_duration_subtraction`](https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction)
-* [`collapsible_str_replace`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace)
-* [`seek_from_current`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current)
-* [`seek_rewind`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_rewind)
-* [`unnecessary_lazy_evaluations`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations)
-* [`transmute_ptr_to_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref)
-* [`almost_complete_range`](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range)
-* [`needless_borrow`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow)
-* [`derivable_impls`](https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls)
-* [`manual_is_ascii_check`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check)
-* [`manual_rem_euclid`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid)
-* [`manual_retain`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain)
-* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds)
-* [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions)
-* [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold)
-* [`manual_hash_one`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one)
-* [`iter_kv_map`](https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map)
-* [`manual_c_str_literals`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals)
+* [`await_holding_invalid_type`](https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type)
+
+
+## `cargo-ignore-publish`
+For internal testing only, ignores the current `publish` settings in the Cargo manifest.
+
+**Default Value:** `false`
+
+---
+**Affected lints:**
+* [`cargo_common_metadata`](https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata)
+
+
+## `check-private-items`
+Whether to also run the listed lints on private items.
+
+**Default Value:** `false`
+
+---
+**Affected lints:**
+* [`missing_errors_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc)
+* [`missing_panics_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc)
+* [`missing_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc)
+* [`unnecessary_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc)
 
 
 ## `cognitive-complexity-threshold`
@@ -164,253 +337,6 @@ The maximum cognitive complexity a function can have
 * [`cognitive_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity)
 
 
-## `excessive-nesting-threshold`
-The maximum amount of nesting a block can reside in
-
-**Default Value:** `0`
-
----
-**Affected lints:**
-* [`excessive_nesting`](https://rust-lang.github.io/rust-clippy/master/index.html#excessive_nesting)
-
-
-## `disallowed-names`
-The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value
-`".."` can be used as part of the list to indicate that the configured values should be appended to the
-default configuration of Clippy. By default, any configuration will replace the default value.
-
-**Default Value:** `["foo", "baz", "quux"]`
-
----
-**Affected lints:**
-* [`disallowed_names`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names)
-
-
-## `semicolon-inside-block-ignore-singleline`
-Whether to lint only if it's multiline.
-
-**Default Value:** `false`
-
----
-**Affected lints:**
-* [`semicolon_inside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block)
-
-
-## `semicolon-outside-block-ignore-multiline`
-Whether to lint only if it's singleline.
-
-**Default Value:** `false`
-
----
-**Affected lints:**
-* [`semicolon_outside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block)
-
-
-## `doc-valid-idents`
-The list of words this lint should not consider as identifiers needing ticks. The value
-`".."` can be used as part of the list to indicate, that the configured values should be appended to the
-default configuration of Clippy. By default, any configuration will replace the default value. For example:
-* `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`.
-* `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list.
-
-**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "WebGL", "WebGL2", "WebGPU", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]`
-
----
-**Affected lints:**
-* [`doc_markdown`](https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown)
-
-
-## `too-many-arguments-threshold`
-The maximum number of argument a function or method can have
-
-**Default Value:** `7`
-
----
-**Affected lints:**
-* [`too_many_arguments`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments)
-
-
-## `type-complexity-threshold`
-The maximum complexity a type can have
-
-**Default Value:** `250`
-
----
-**Affected lints:**
-* [`type_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity)
-
-
-## `single-char-binding-names-threshold`
-The maximum number of single char bindings a scope may have
-
-**Default Value:** `4`
-
----
-**Affected lints:**
-* [`many_single_char_names`](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names)
-
-
-## `too-large-for-stack`
-The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap
-
-**Default Value:** `200`
-
----
-**Affected lints:**
-* [`boxed_local`](https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local)
-* [`useless_vec`](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec)
-
-
-## `enum-variant-name-threshold`
-The minimum number of enum variants for the lints about variant names to trigger
-
-**Default Value:** `3`
-
----
-**Affected lints:**
-* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names)
-
-
-## `struct-field-name-threshold`
-The minimum number of struct fields for the lints about field names to trigger
-
-**Default Value:** `3`
-
----
-**Affected lints:**
-* [`struct_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_field_names)
-
-
-## `enum-variant-size-threshold`
-The maximum size of an enum's variant to avoid box suggestion
-
-**Default Value:** `200`
-
----
-**Affected lints:**
-* [`large_enum_variant`](https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant)
-
-
-## `verbose-bit-mask-threshold`
-The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros'
-
-**Default Value:** `1`
-
----
-**Affected lints:**
-* [`verbose_bit_mask`](https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask)
-
-
-## `literal-representation-threshold`
-The lower bound for linting decimal literals
-
-**Default Value:** `16384`
-
----
-**Affected lints:**
-* [`decimal_literal_representation`](https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation)
-
-
-## `trivial-copy-size-limit`
-The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by
-reference. By default there is no limit
-
----
-**Affected lints:**
-* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref)
-
-
-## `pass-by-value-size-limit`
-The minimum size (in bytes) to consider a type for passing by reference instead of by value.
-
-**Default Value:** `256`
-
----
-**Affected lints:**
-* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value)
-
-
-## `too-many-lines-threshold`
-The maximum number of lines a function or method can have
-
-**Default Value:** `100`
-
----
-**Affected lints:**
-* [`too_many_lines`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines)
-
-
-## `array-size-threshold`
-The maximum allowed size for arrays on the stack
-
-**Default Value:** `512000`
-
----
-**Affected lints:**
-* [`large_stack_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays)
-* [`large_const_arrays`](https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays)
-
-
-## `stack-size-threshold`
-The maximum allowed stack size for functions in bytes
-
-**Default Value:** `512000`
-
----
-**Affected lints:**
-* [`large_stack_frames`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames)
-
-
-## `vec-box-size-threshold`
-The size of the boxed type in bytes, where boxing in a `Vec` is allowed
-
-**Default Value:** `4096`
-
----
-**Affected lints:**
-* [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box)
-
-
-## `max-trait-bounds`
-The maximum number of bounds a trait can have to be linted
-
-**Default Value:** `3`
-
----
-**Affected lints:**
-* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds)
-
-
-## `max-struct-bools`
-The maximum number of bool fields a struct can have
-
-**Default Value:** `3`
-
----
-**Affected lints:**
-* [`struct_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools)
-
-
-## `max-fn-params-bools`
-The maximum number of bool parameters a function can have
-
-**Default Value:** `3`
-
----
-**Affected lints:**
-* [`fn_params_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools)
-
-
-## `warn-on-all-wildcard-imports`
-Whether to allow certain wildcard imports (prelude, super in tests).
-
-**Default Value:** `false`
-
----
-**Affected lints:**
-* [`wildcard_imports`](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports)
-
-
 ## `disallowed-macros`
 The list of disallowed macros, written as fully qualified paths.
 
@@ -431,6 +357,18 @@ The list of disallowed methods, written as fully qualified paths.
 * [`disallowed_methods`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods)
 
 
+## `disallowed-names`
+The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value
+`".."` can be used as part of the list to indicate that the configured values should be appended to the
+default configuration of Clippy. By default, any configuration will replace the default value.
+
+**Default Value:** `["foo", "baz", "quux"]`
+
+---
+**Affected lints:**
+* [`disallowed_names`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names)
+
+
 ## `disallowed-types`
 The list of disallowed types, written as fully qualified paths.
 
@@ -441,79 +379,18 @@ The list of disallowed types, written as fully qualified paths.
 * [`disallowed_types`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types)
 
 
-## `unreadable-literal-lint-fractions`
-Should the fraction of a decimal be linted to include separators.
+## `doc-valid-idents`
+The list of words this lint should not consider as identifiers needing ticks. The value
+`".."` can be used as part of the list to indicate, that the configured values should be appended to the
+default configuration of Clippy. By default, any configuration will replace the default value. For example:
+* `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`.
+* `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list.
 
-**Default Value:** `true`
+**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "WebGL", "WebGL2", "WebGPU", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]`
 
 ---
 **Affected lints:**
-* [`unreadable_literal`](https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal)
-
-
-## `upper-case-acronyms-aggressive`
-Enables verbose mode. Triggers if there is more than one uppercase char next to each other
-
-**Default Value:** `false`
-
----
-**Affected lints:**
-* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms)
-
-
-## `matches-for-let-else`
-Whether the matches should be considered by the lint, and whether there should
-be filtering for common types.
-
-**Default Value:** `"WellKnownTypes"`
-
----
-**Affected lints:**
-* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else)
-
-
-## `cargo-ignore-publish`
-For internal testing only, ignores the current `publish` settings in the Cargo manifest.
-
-**Default Value:** `false`
-
----
-**Affected lints:**
-* [`cargo_common_metadata`](https://rust-lang.github.io/rust-clippy/master/index.html#cargo_common_metadata)
-
-
-## `standard-macro-braces`
-Enforce the named macros always use the braces specified.
-
-A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro
-could be used with a full path two `MacroMatcher`s have to be added one with the full path
-`crate_name::macro_name` and one with just the macro name.
-
-**Default Value:** `[]`
-
----
-**Affected lints:**
-* [`nonstandard_macro_braces`](https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces)
-
-
-## `enforced-import-renames`
-The list of imports to always rename, a fully qualified path followed by the rename.
-
-**Default Value:** `[]`
-
----
-**Affected lints:**
-* [`missing_enforced_import_renames`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames)
-
-
-## `allowed-scripts`
-The list of unicode scripts allowed to be used in the scope.
-
-**Default Value:** `["Latin"]`
-
----
-**Affected lints:**
-* [`disallowed_script_idents`](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents)
+* [`doc_markdown`](https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown)
 
 
 ## `enable-raw-pointer-heuristic-for-send`
@@ -526,259 +403,6 @@ Whether to apply the raw pointer heuristic to determine if a type is `Send`.
 * [`non_send_fields_in_send_ty`](https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty)
 
 
-## `max-suggested-slice-pattern-length`
-When Clippy suggests using a slice pattern, this is the maximum number of elements allowed in
-the slice pattern that is suggested. If more elements are necessary, the lint is suppressed.
-For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
-
-**Default Value:** `3`
-
----
-**Affected lints:**
-* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice)
-
-
-## `await-holding-invalid-types`
-
-
-**Default Value:** `[]`
-
----
-**Affected lints:**
-* [`await_holding_invalid_type`](https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type)
-
-
-## `max-include-file-size`
-The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes
-
-**Default Value:** `1000000`
-
----
-**Affected lints:**
-* [`large_include_file`](https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file)
-
-
-## `allow-expect-in-tests`
-Whether `expect` should be allowed in test functions or `#[cfg(test)]`
-
-**Default Value:** `false`
-
----
-**Affected lints:**
-* [`expect_used`](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used)
-
-
-## `allow-unwrap-in-tests`
-Whether `unwrap` should be allowed in test functions or `#[cfg(test)]`
-
-**Default Value:** `false`
-
----
-**Affected lints:**
-* [`unwrap_used`](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used)
-
-
-## `allow-dbg-in-tests`
-Whether `dbg!` should be allowed in test functions or `#[cfg(test)]`
-
-**Default Value:** `false`
-
----
-**Affected lints:**
-* [`dbg_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro)
-
-
-## `allow-print-in-tests`
-Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]`
-
-**Default Value:** `false`
-
----
-**Affected lints:**
-* [`print_stdout`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout)
-* [`print_stderr`](https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr)
-
-
-## `large-error-threshold`
-The maximum size of the `Err`-variant in a `Result` returned from a function
-
-**Default Value:** `128`
-
----
-**Affected lints:**
-* [`result_large_err`](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err)
-
-
-## `ignore-interior-mutability`
-A list of paths to types that should be treated like `Arc`, i.e. ignored but
-for the generic parameters for determining interior mutability
-
-**Default Value:** `["bytes::Bytes"]`
-
----
-**Affected lints:**
-* [`mutable_key_type`](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type)
-* [`ifs_same_cond`](https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond)
-
-
-## `allow-mixed-uninlined-format-args`
-Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)`
-
-**Default Value:** `true`
-
----
-**Affected lints:**
-* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args)
-
-
-## `suppress-restriction-lint-in-const`
-Whether to suppress a restriction lint in constant code. In same
-cases the restructured operation might not be unavoidable, as the
-suggested counterparts are unavailable in constant code. This
-configuration will cause restriction lints to trigger even
-if no suggestion can be made.
-
-**Default Value:** `false`
-
----
-**Affected lints:**
-* [`indexing_slicing`](https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing)
-
-
-## `missing-docs-in-crate-items`
-Whether to **only** check for missing documentation in items visible within the current
-crate. For example, `pub(crate)` items.
-
-**Default Value:** `false`
-
----
-**Affected lints:**
-* [`missing_docs_in_private_items`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items)
-
-
-## `future-size-threshold`
-The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint
-
-**Default Value:** `16384`
-
----
-**Affected lints:**
-* [`large_futures`](https://rust-lang.github.io/rust-clippy/master/index.html#large_futures)
-
-
-## `unnecessary-box-size`
-The byte size a `T` in `Box<T>` can have, below which it triggers the `clippy::unnecessary_box` lint
-
-**Default Value:** `128`
-
----
-**Affected lints:**
-* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns)
-
-
-## `allow-private-module-inception`
-Whether to allow module inception if it's not public.
-
-**Default Value:** `false`
-
----
-**Affected lints:**
-* [`module_inception`](https://rust-lang.github.io/rust-clippy/master/index.html#module_inception)
-
-
-## `allowed-idents-below-min-chars`
-Allowed names below the minimum allowed characters. The value `".."` can be used as part of
-the list to indicate, that the configured values should be appended to the default
-configuration of Clippy. By default, any configuration will replace the default value.
-
-**Default Value:** `["j", "z", "i", "y", "n", "x", "w"]`
-
----
-**Affected lints:**
-* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars)
-
-
-## `min-ident-chars-threshold`
-Minimum chars an ident can have, anything below or equal to this will be linted.
-
-**Default Value:** `1`
-
----
-**Affected lints:**
-* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars)
-
-
-## `accept-comment-above-statement`
-Whether to accept a safety comment to be placed above the statement containing the `unsafe` block
-
-**Default Value:** `true`
-
----
-**Affected lints:**
-* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks)
-
-
-## `accept-comment-above-attributes`
-Whether to accept a safety comment to be placed above the attributes for the `unsafe` block
-
-**Default Value:** `true`
-
----
-**Affected lints:**
-* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks)
-
-
-## `allow-one-hash-in-raw-strings`
-Whether to allow `r#""#` when `r""` can be used
-
-**Default Value:** `false`
-
----
-**Affected lints:**
-* [`unnecessary_raw_string_hashes`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_raw_string_hashes)
-
-
-## `absolute-paths-max-segments`
-The maximum number of segments a path can have before being linted, anything above this will
-be linted.
-
-**Default Value:** `2`
-
----
-**Affected lints:**
-* [`absolute_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths)
-
-
-## `absolute-paths-allowed-crates`
-Which crates to allow absolute paths from
-
-**Default Value:** `[]`
-
----
-**Affected lints:**
-* [`absolute_paths`](https://rust-lang.github.io/rust-clippy/master/index.html#absolute_paths)
-
-
-## `allowed-dotfiles`
-Additional dotfiles (files or directories starting with a dot) to allow
-
-**Default Value:** `[]`
-
----
-**Affected lints:**
-* [`path_ends_with_ext`](https://rust-lang.github.io/rust-clippy/master/index.html#path_ends_with_ext)
-
-
-## `allowed-duplicate-crates`
-A list of crate names to allow duplicates of
-
-**Default Value:** `[]`
-
----
-**Affected lints:**
-* [`multiple_crate_versions`](https://rust-lang.github.io/rust-clippy/master/index.html#multiple_crate_versions)
-
-
 ## `enforce-iter-loop-reborrow`
 Whether to recommend using implicit into iter for reborrowed values.
 
@@ -805,17 +429,237 @@ for _ in &mut *rmvec {}
 * [`explicit_iter_loop`](https://rust-lang.github.io/rust-clippy/master/index.html#explicit_iter_loop)
 
 
-## `check-private-items`
-Whether to also run the listed lints on private items.
+## `enforced-import-renames`
+The list of imports to always rename, a fully qualified path followed by the rename.
+
+**Default Value:** `[]`
+
+---
+**Affected lints:**
+* [`missing_enforced_import_renames`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames)
+
+
+## `enum-variant-name-threshold`
+The minimum number of enum variants for the lints about variant names to trigger
+
+**Default Value:** `3`
+
+---
+**Affected lints:**
+* [`enum_variant_names`](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names)
+
+
+## `enum-variant-size-threshold`
+The maximum size of an enum's variant to avoid box suggestion
+
+**Default Value:** `200`
+
+---
+**Affected lints:**
+* [`large_enum_variant`](https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant)
+
+
+## `excessive-nesting-threshold`
+The maximum amount of nesting a block can reside in
+
+**Default Value:** `0`
+
+---
+**Affected lints:**
+* [`excessive_nesting`](https://rust-lang.github.io/rust-clippy/master/index.html#excessive_nesting)
+
+
+## `future-size-threshold`
+The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint
+
+**Default Value:** `16384`
+
+---
+**Affected lints:**
+* [`large_futures`](https://rust-lang.github.io/rust-clippy/master/index.html#large_futures)
+
+
+## `ignore-interior-mutability`
+A list of paths to types that should be treated like `Arc`, i.e. ignored but
+for the generic parameters for determining interior mutability
+
+**Default Value:** `["bytes::Bytes"]`
+
+---
+**Affected lints:**
+* [`ifs_same_cond`](https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond)
+* [`mutable_key_type`](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type)
+
+
+## `large-error-threshold`
+The maximum size of the `Err`-variant in a `Result` returned from a function
+
+**Default Value:** `128`
+
+---
+**Affected lints:**
+* [`result_large_err`](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err)
+
+
+## `literal-representation-threshold`
+The lower bound for linting decimal literals
+
+**Default Value:** `16384`
+
+---
+**Affected lints:**
+* [`decimal_literal_representation`](https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation)
+
+
+## `matches-for-let-else`
+Whether the matches should be considered by the lint, and whether there should
+be filtering for common types.
+
+**Default Value:** `"WellKnownTypes"`
+
+---
+**Affected lints:**
+* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else)
+
+
+## `max-fn-params-bools`
+The maximum number of bool parameters a function can have
+
+**Default Value:** `3`
+
+---
+**Affected lints:**
+* [`fn_params_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools)
+
+
+## `max-include-file-size`
+The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes
+
+**Default Value:** `1000000`
+
+---
+**Affected lints:**
+* [`large_include_file`](https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file)
+
+
+## `max-struct-bools`
+The maximum number of bool fields a struct can have
+
+**Default Value:** `3`
+
+---
+**Affected lints:**
+* [`struct_excessive_bools`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools)
+
+
+## `max-suggested-slice-pattern-length`
+When Clippy suggests using a slice pattern, this is the maximum number of elements allowed in
+the slice pattern that is suggested. If more elements are necessary, the lint is suppressed.
+For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
+
+**Default Value:** `3`
+
+---
+**Affected lints:**
+* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice)
+
+
+## `max-trait-bounds`
+The maximum number of bounds a trait can have to be linted
+
+**Default Value:** `3`
+
+---
+**Affected lints:**
+* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds)
+
+
+## `min-ident-chars-threshold`
+Minimum chars an ident can have, anything below or equal to this will be linted.
+
+**Default Value:** `1`
+
+---
+**Affected lints:**
+* [`min_ident_chars`](https://rust-lang.github.io/rust-clippy/master/index.html#min_ident_chars)
+
+
+## `missing-docs-in-crate-items`
+Whether to **only** check for missing documentation in items visible within the current
+crate. For example, `pub(crate)` items.
 
 **Default Value:** `false`
 
 ---
 **Affected lints:**
-* [`missing_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc)
-* [`unnecessary_safety_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc)
-* [`missing_panics_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc)
-* [`missing_errors_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc)
+* [`missing_docs_in_private_items`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items)
+
+
+## `msrv`
+The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
+
+---
+**Affected lints:**
+* [`almost_complete_range`](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range)
+* [`approx_constant`](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant)
+* [`borrow_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr)
+* [`cast_abs_to_unsigned`](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned)
+* [`checked_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions)
+* [`cloned_instead_of_copied`](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied)
+* [`collapsible_str_replace`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace)
+* [`deprecated_cfg_attr`](https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr)
+* [`derivable_impls`](https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls)
+* [`err_expect`](https://rust-lang.github.io/rust-clippy/master/index.html#err_expect)
+* [`filter_map_next`](https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next)
+* [`from_over_into`](https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into)
+* [`if_then_some_else_none`](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none)
+* [`index_refutable_slice`](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice)
+* [`iter_kv_map`](https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map)
+* [`manual_bits`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits)
+* [`manual_c_str_literals`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals)
+* [`manual_clamp`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp)
+* [`manual_hash_one`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one)
+* [`manual_is_ascii_check`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check)
+* [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else)
+* [`manual_non_exhaustive`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive)
+* [`manual_range_contains`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains)
+* [`manual_rem_euclid`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid)
+* [`manual_retain`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain)
+* [`manual_split_once`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once)
+* [`manual_str_repeat`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat)
+* [`manual_strip`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip)
+* [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold)
+* [`map_clone`](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone)
+* [`map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or)
+* [`match_like_matches_macro`](https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro)
+* [`mem_replace_with_default`](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default)
+* [`missing_const_for_fn`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn)
+* [`needless_borrow`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow)
+* [`option_as_ref_deref`](https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref)
+* [`option_map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or)
+* [`ptr_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr)
+* [`redundant_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names)
+* [`redundant_static_lifetimes`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes)
+* [`seek_from_current`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current)
+* [`seek_rewind`](https://rust-lang.github.io/rust-clippy/master/index.html#seek_rewind)
+* [`transmute_ptr_to_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref)
+* [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions)
+* [`type_repetition_in_bounds`](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds)
+* [`unchecked_duration_subtraction`](https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction)
+* [`uninlined_format_args`](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args)
+* [`unnecessary_lazy_evaluations`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations)
+* [`unnested_or_patterns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns)
+* [`use_self`](https://rust-lang.github.io/rust-clippy/master/index.html#use_self)
+
+
+## `pass-by-value-size-limit`
+The minimum size (in bytes) to consider a type for passing by reference instead of by value.
+
+**Default Value:** `256`
+
+---
+**Affected lints:**
+* [`large_types_passed_by_value`](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value)
 
 
 ## `pub-underscore-fields-behavior`
@@ -829,32 +673,188 @@ exported visibility, or whether they are marked as "pub".
 * [`pub_underscore_fields`](https://rust-lang.github.io/rust-clippy/master/index.html#pub_underscore_fields)
 
 
-## `allow-comparison-to-zero`
-Don't lint when comparing the result of a modulo operation to zero.
+## `semicolon-inside-block-ignore-singleline`
+Whether to lint only if it's multiline.
+
+**Default Value:** `false`
+
+---
+**Affected lints:**
+* [`semicolon_inside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_inside_block)
+
+
+## `semicolon-outside-block-ignore-multiline`
+Whether to lint only if it's singleline.
+
+**Default Value:** `false`
+
+---
+**Affected lints:**
+* [`semicolon_outside_block`](https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_outside_block)
+
+
+## `single-char-binding-names-threshold`
+The maximum number of single char bindings a scope may have
+
+**Default Value:** `4`
+
+---
+**Affected lints:**
+* [`many_single_char_names`](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names)
+
+
+## `stack-size-threshold`
+The maximum allowed stack size for functions in bytes
+
+**Default Value:** `512000`
+
+---
+**Affected lints:**
+* [`large_stack_frames`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames)
+
+
+## `standard-macro-braces`
+Enforce the named macros always use the braces specified.
+
+A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro
+could be used with a full path two `MacroMatcher`s have to be added one with the full path
+`crate_name::macro_name` and one with just the macro name.
+
+**Default Value:** `[]`
+
+---
+**Affected lints:**
+* [`nonstandard_macro_braces`](https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces)
+
+
+## `struct-field-name-threshold`
+The minimum number of struct fields for the lints about field names to trigger
+
+**Default Value:** `3`
+
+---
+**Affected lints:**
+* [`struct_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#struct_field_names)
+
+
+## `suppress-restriction-lint-in-const`
+Whether to suppress a restriction lint in constant code. In same
+cases the restructured operation might not be unavoidable, as the
+suggested counterparts are unavailable in constant code. This
+configuration will cause restriction lints to trigger even
+if no suggestion can be made.
+
+**Default Value:** `false`
+
+---
+**Affected lints:**
+* [`indexing_slicing`](https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing)
+
+
+## `too-large-for-stack`
+The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap
+
+**Default Value:** `200`
+
+---
+**Affected lints:**
+* [`boxed_local`](https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local)
+* [`useless_vec`](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec)
+
+
+## `too-many-arguments-threshold`
+The maximum number of argument a function or method can have
+
+**Default Value:** `7`
+
+---
+**Affected lints:**
+* [`too_many_arguments`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments)
+
+
+## `too-many-lines-threshold`
+The maximum number of lines a function or method can have
+
+**Default Value:** `100`
+
+---
+**Affected lints:**
+* [`too_many_lines`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines)
+
+
+## `trivial-copy-size-limit`
+The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by
+reference. By default there is no limit
+
+---
+**Affected lints:**
+* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref)
+
+
+## `type-complexity-threshold`
+The maximum complexity a type can have
+
+**Default Value:** `250`
+
+---
+**Affected lints:**
+* [`type_complexity`](https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity)
+
+
+## `unnecessary-box-size`
+The byte size a `T` in `Box<T>` can have, below which it triggers the `clippy::unnecessary_box` lint
+
+**Default Value:** `128`
+
+---
+**Affected lints:**
+* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns)
+
+
+## `unreadable-literal-lint-fractions`
+Should the fraction of a decimal be linted to include separators.
 
 **Default Value:** `true`
 
 ---
 **Affected lints:**
-* [`modulo_arithmetic`](https://rust-lang.github.io/rust-clippy/master/index.html#modulo_arithmetic)
+* [`unreadable_literal`](https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal)
 
 
-## `allowed-wildcard-imports`
-List of path segments allowed to have wildcard imports.
+## `upper-case-acronyms-aggressive`
+Enables verbose mode. Triggers if there is more than one uppercase char next to each other
 
-#### Example
+**Default Value:** `false`
 
-```toml
-allowed-wildcard-imports = [ "utils", "common" ]
-```
+---
+**Affected lints:**
+* [`upper_case_acronyms`](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms)
 
-#### Noteworthy
 
-1. This configuration has no effects if used with `warn_on_all_wildcard_imports = true`.
-2. Paths with any segment that containing the word 'prelude'
-are already allowed by default.
+## `vec-box-size-threshold`
+The size of the boxed type in bytes, where boxing in a `Vec` is allowed
 
-**Default Value:** `[]`
+**Default Value:** `4096`
+
+---
+**Affected lints:**
+* [`vec_box`](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box)
+
+
+## `verbose-bit-mask-threshold`
+The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros'
+
+**Default Value:** `1`
+
+---
+**Affected lints:**
+* [`verbose_bit_mask`](https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask)
+
+
+## `warn-on-all-wildcard-imports`
+Whether to allow certain wildcard imports (prelude, super in tests).
+
+**Default Value:** `false`
 
 ---
 **Affected lints:**
diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs
index b781259ad96..673b6328b39 100644
--- a/src/tools/clippy/clippy_config/src/conf.rs
+++ b/src/tools/clippy/clippy_config/src/conf.rs
@@ -193,7 +193,7 @@ macro_rules! define_Conf {
         }
 
         pub fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
-            vec![
+            let mut sorted = vec![
                 $(
                     {
                         let deprecation_reason = wrap_option!($($dep)?);
@@ -206,7 +206,9 @@ macro_rules! define_Conf {
                         )
                     },
                 )+
-            ]
+            ];
+            sorted.sort_by(|a, b| a.name.cmp(&b.name));
+            sorted
         }
     };
 }
diff --git a/src/tools/clippy/clippy_config/src/lib.rs b/src/tools/clippy/clippy_config/src/lib.rs
index 3d5002f1780..01e2aa6e0a6 100644
--- a/src/tools/clippy/clippy_config/src/lib.rs
+++ b/src/tools/clippy/clippy_config/src/lib.rs
@@ -5,7 +5,7 @@
     clippy::must_use_candidate,
     clippy::missing_panics_doc,
     rustc::diagnostic_outside_of_impl,
-    rustc::untranslatable_diagnostic,
+    rustc::untranslatable_diagnostic
 )]
 
 extern crate rustc_ast;
diff --git a/src/tools/clippy/clippy_config/src/metadata.rs b/src/tools/clippy/clippy_config/src/metadata.rs
index 3ba2796e18d..400887185e8 100644
--- a/src/tools/clippy/clippy_config/src/metadata.rs
+++ b/src/tools/clippy/clippy_config/src/metadata.rs
@@ -26,9 +26,11 @@ impl ClippyConfiguration {
         doc_comment: &'static str,
         deprecation_reason: Option<&'static str>,
     ) -> Self {
-        let (lints, doc) = parse_config_field_doc(doc_comment)
+        let (mut lints, doc) = parse_config_field_doc(doc_comment)
             .unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string()));
 
+        lints.sort();
+
         Self {
             name: to_kebab(name),
             lints,
diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_config/src/msrvs.rs
index f4389db627d..a8a32f7ed20 100644
--- a/src/tools/clippy/clippy_config/src/msrvs.rs
+++ b/src/tools/clippy/clippy_config/src/msrvs.rs
@@ -24,6 +24,7 @@ msrv_aliases! {
     1,68,0 { PATH_MAIN_SEPARATOR_STR }
     1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS }
     1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE }
+    1,59,0 { THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST }
     1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY }
     1,55,0 { SEEK_REWIND }
     1,54,0 { INTO_KEYS }
diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
new file mode 100644
index 00000000000..b1c552c7a8d
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
@@ -0,0 +1,322 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::macros::HirNode;
+use clippy_utils::sugg::Sugg;
+use clippy_utils::{is_trait_method, path_to_local};
+use rustc_errors::Applicability;
+use rustc_hir::{self as hir, Expr, ExprKind, Node};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{self, Instance, Mutability};
+use rustc_session::declare_lint_pass;
+use rustc_span::def_id::DefId;
+use rustc_span::symbol::sym;
+use rustc_span::ExpnKind;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for code like `foo = bar.clone();`
+    ///
+    /// ### Why is this bad?
+    /// Custom `Clone::clone_from()` or `ToOwned::clone_into` implementations allow the objects
+    /// to share resources and therefore avoid allocations.
+    ///
+    /// ### Example
+    /// ```rust
+    /// struct Thing;
+    ///
+    /// impl Clone for Thing {
+    ///     fn clone(&self) -> Self { todo!() }
+    ///     fn clone_from(&mut self, other: &Self) { todo!() }
+    /// }
+    ///
+    /// pub fn assign_to_ref(a: &mut Thing, b: Thing) {
+    ///     *a = b.clone();
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// struct Thing;
+    /// impl Clone for Thing {
+    ///     fn clone(&self) -> Self { todo!() }
+    ///     fn clone_from(&mut self, other: &Self) { todo!() }
+    /// }
+    ///
+    /// pub fn assign_to_ref(a: &mut Thing, b: Thing) {
+    ///     a.clone_from(&b);
+    /// }
+    /// ```
+    #[clippy::version = "1.77.0"]
+    pub ASSIGNING_CLONES,
+    perf,
+    "assigning the result of cloning may be inefficient"
+}
+declare_lint_pass!(AssigningClones => [ASSIGNING_CLONES]);
+
+impl<'tcx> LateLintPass<'tcx> for AssigningClones {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, assign_expr: &'tcx hir::Expr<'_>) {
+        // Do not fire the lint in macros
+        let expn_data = assign_expr.span().ctxt().outer_expn_data();
+        match expn_data.kind {
+            ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) | ExpnKind::Macro(..) => return,
+            ExpnKind::Root => {},
+        }
+
+        let ExprKind::Assign(lhs, rhs, _span) = assign_expr.kind else {
+            return;
+        };
+
+        let Some(call) = extract_call(cx, rhs) else {
+            return;
+        };
+
+        if is_ok_to_suggest(cx, lhs, &call) {
+            suggest(cx, assign_expr, lhs, &call);
+        }
+    }
+}
+
+// Try to resolve the call to `Clone::clone` or `ToOwned::to_owned`.
+fn extract_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<CallCandidate<'tcx>> {
+    let fn_def_id = clippy_utils::fn_def_id(cx, expr)?;
+
+    // Fast paths to only check method calls without arguments or function calls with a single argument
+    let (target, kind, resolved_method) = match expr.kind {
+        ExprKind::MethodCall(path, receiver, [], _span) => {
+            let args = cx.typeck_results().node_args(expr.hir_id);
+
+            // If we could not resolve the method, don't apply the lint
+            let Ok(Some(resolved_method)) = Instance::resolve(cx.tcx, cx.param_env, fn_def_id, args) else {
+                return None;
+            };
+            if is_trait_method(cx, expr, sym::Clone) && path.ident.name == sym::clone {
+                (TargetTrait::Clone, CallKind::MethodCall { receiver }, resolved_method)
+            } else if is_trait_method(cx, expr, sym::ToOwned) && path.ident.name.as_str() == "to_owned" {
+                (TargetTrait::ToOwned, CallKind::MethodCall { receiver }, resolved_method)
+            } else {
+                return None;
+            }
+        },
+        ExprKind::Call(function, [arg]) => {
+            let kind = cx.typeck_results().node_type(function.hir_id).kind();
+
+            // If we could not resolve the method, don't apply the lint
+            let Ok(Some(resolved_method)) = (match kind {
+                ty::FnDef(_, args) => Instance::resolve(cx.tcx, cx.param_env, fn_def_id, args),
+                _ => Ok(None),
+            }) else {
+                return None;
+            };
+            if cx.tcx.is_diagnostic_item(sym::to_owned_method, fn_def_id) {
+                (
+                    TargetTrait::ToOwned,
+                    CallKind::FunctionCall { self_arg: arg },
+                    resolved_method,
+                )
+            } else if let Some(trait_did) = cx.tcx.trait_of_item(fn_def_id)
+                && cx.tcx.is_diagnostic_item(sym::Clone, trait_did)
+            {
+                (
+                    TargetTrait::Clone,
+                    CallKind::FunctionCall { self_arg: arg },
+                    resolved_method,
+                )
+            } else {
+                return None;
+            }
+        },
+        _ => return None,
+    };
+
+    Some(CallCandidate {
+        target,
+        kind,
+        method_def_id: resolved_method.def_id(),
+    })
+}
+
+// Return true if we find that the called method has a custom implementation and isn't derived or
+// provided by default by the corresponding trait.
+fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallCandidate<'tcx>) -> bool {
+    // If the left-hand side is a local variable, it might be uninitialized at this point.
+    // In that case we do not want to suggest the lint.
+    if let Some(local) = path_to_local(lhs) {
+        // TODO: This check currently bails if the local variable has no initializer.
+        // That is overly conservative - the lint should fire even if there was no initializer,
+        // but the variable has been initialized before `lhs` was evaluated.
+        if let Some(Node::Local(local)) = cx.tcx.hir().parent_id_iter(local).next().map(|p| cx.tcx.hir_node(p))
+            && local.init.is_none()
+        {
+            return false;
+        }
+    }
+
+    let Some(impl_block) = cx.tcx.impl_of_method(call.method_def_id) else {
+        return false;
+    };
+
+    // If the method implementation comes from #[derive(Clone)], then don't suggest the lint.
+    // Automatically generated Clone impls do not currently override `clone_from`.
+    // See e.g. https://github.com/rust-lang/rust/pull/98445#issuecomment-1190681305 for more details.
+    if cx.tcx.is_builtin_derived(impl_block) {
+        return false;
+    }
+
+    // Find the function for which we want to check that it is implemented.
+    let provided_fn = match call.target {
+        TargetTrait::Clone => cx.tcx.get_diagnostic_item(sym::Clone).and_then(|clone| {
+            cx.tcx
+                .provided_trait_methods(clone)
+                .find(|item| item.name == sym::clone_from)
+        }),
+        TargetTrait::ToOwned => cx.tcx.get_diagnostic_item(sym::ToOwned).and_then(|to_owned| {
+            cx.tcx
+                .provided_trait_methods(to_owned)
+                .find(|item| item.name.as_str() == "clone_into")
+        }),
+    };
+    let Some(provided_fn) = provided_fn else {
+        return false;
+    };
+
+    // Now take a look if the impl block defines an implementation for the method that we're interested
+    // in. If not, then we're using a default implementation, which is not interesting, so we will
+    // not suggest the lint.
+    let implemented_fns = cx.tcx.impl_item_implementor_ids(impl_block);
+    implemented_fns.contains_key(&provided_fn.def_id)
+}
+
+fn suggest<'tcx>(
+    cx: &LateContext<'tcx>,
+    assign_expr: &hir::Expr<'tcx>,
+    lhs: &hir::Expr<'tcx>,
+    call: &CallCandidate<'tcx>,
+) {
+    span_lint_and_then(cx, ASSIGNING_CLONES, assign_expr.span, call.message(), |diag| {
+        let mut applicability = Applicability::MachineApplicable;
+
+        diag.span_suggestion(
+            assign_expr.span,
+            call.suggestion_msg(),
+            call.suggested_replacement(cx, lhs, &mut applicability),
+            applicability,
+        );
+    });
+}
+
+#[derive(Copy, Clone, Debug)]
+enum CallKind<'tcx> {
+    MethodCall { receiver: &'tcx Expr<'tcx> },
+    FunctionCall { self_arg: &'tcx Expr<'tcx> },
+}
+
+#[derive(Copy, Clone, Debug)]
+enum TargetTrait {
+    Clone,
+    ToOwned,
+}
+
+#[derive(Debug)]
+struct CallCandidate<'tcx> {
+    target: TargetTrait,
+    kind: CallKind<'tcx>,
+    // DefId of the called method from an impl block that implements the target trait
+    method_def_id: DefId,
+}
+
+impl<'tcx> CallCandidate<'tcx> {
+    #[inline]
+    fn message(&self) -> &'static str {
+        match self.target {
+            TargetTrait::Clone => "assigning the result of `Clone::clone()` may be inefficient",
+            TargetTrait::ToOwned => "assigning the result of `ToOwned::to_owned()` may be inefficient",
+        }
+    }
+
+    #[inline]
+    fn suggestion_msg(&self) -> &'static str {
+        match self.target {
+            TargetTrait::Clone => "use `clone_from()`",
+            TargetTrait::ToOwned => "use `clone_into()`",
+        }
+    }
+
+    fn suggested_replacement(
+        &self,
+        cx: &LateContext<'tcx>,
+        lhs: &hir::Expr<'tcx>,
+        applicability: &mut Applicability,
+    ) -> String {
+        match self.target {
+            TargetTrait::Clone => {
+                match self.kind {
+                    CallKind::MethodCall { receiver } => {
+                        let receiver_sugg = if let ExprKind::Unary(hir::UnOp::Deref, ref_expr) = lhs.kind {
+                            // `*lhs = self_expr.clone();` -> `lhs.clone_from(self_expr)`
+                            Sugg::hir_with_applicability(cx, ref_expr, "_", applicability)
+                        } else {
+                            // `lhs = self_expr.clone();` -> `lhs.clone_from(self_expr)`
+                            Sugg::hir_with_applicability(cx, lhs, "_", applicability)
+                        }
+                        .maybe_par();
+
+                        // Determine whether we need to reference the argument to clone_from().
+                        let clone_receiver_type = cx.typeck_results().expr_ty(receiver);
+                        let clone_receiver_adj_type = cx.typeck_results().expr_ty_adjusted(receiver);
+                        let mut arg_sugg = Sugg::hir_with_applicability(cx, receiver, "_", applicability);
+                        if clone_receiver_type != clone_receiver_adj_type {
+                            // The receiver may have been a value type, so we need to add an `&` to
+                            // be sure the argument to clone_from will be a reference.
+                            arg_sugg = arg_sugg.addr();
+                        };
+
+                        format!("{receiver_sugg}.clone_from({arg_sugg})")
+                    },
+                    CallKind::FunctionCall { self_arg, .. } => {
+                        let self_sugg = if let ExprKind::Unary(hir::UnOp::Deref, ref_expr) = lhs.kind {
+                            // `*lhs = Clone::clone(self_expr);` -> `Clone::clone_from(lhs, self_expr)`
+                            Sugg::hir_with_applicability(cx, ref_expr, "_", applicability)
+                        } else {
+                            // `lhs = Clone::clone(self_expr);` -> `Clone::clone_from(&mut lhs, self_expr)`
+                            Sugg::hir_with_applicability(cx, lhs, "_", applicability).mut_addr()
+                        };
+                        // The RHS had to be exactly correct before the call, there is no auto-deref for function calls.
+                        let rhs_sugg = Sugg::hir_with_applicability(cx, self_arg, "_", applicability);
+
+                        format!("Clone::clone_from({self_sugg}, {rhs_sugg})")
+                    },
+                }
+            },
+            TargetTrait::ToOwned => {
+                let rhs_sugg = if let ExprKind::Unary(hir::UnOp::Deref, ref_expr) = lhs.kind {
+                    // `*lhs = rhs.to_owned()` -> `rhs.clone_into(lhs)`
+                    // `*lhs = ToOwned::to_owned(rhs)` -> `ToOwned::clone_into(rhs, lhs)`
+                    let sugg = Sugg::hir_with_applicability(cx, ref_expr, "_", applicability).maybe_par();
+                    let inner_type = cx.typeck_results().expr_ty(ref_expr);
+                    // If after unwrapping the dereference, the type is not a mutable reference, we add &mut to make it
+                    // deref to a mutable reference.
+                    if matches!(inner_type.kind(), ty::Ref(_, _, Mutability::Mut)) {
+                        sugg
+                    } else {
+                        sugg.mut_addr()
+                    }
+                } else {
+                    // `lhs = rhs.to_owned()` -> `rhs.clone_into(&mut lhs)`
+                    // `lhs = ToOwned::to_owned(rhs)` -> `ToOwned::clone_into(rhs, &mut lhs)`
+                    Sugg::hir_with_applicability(cx, lhs, "_", applicability)
+                        .maybe_par()
+                        .mut_addr()
+                };
+
+                match self.kind {
+                    CallKind::MethodCall { receiver } => {
+                        let receiver_sugg = Sugg::hir_with_applicability(cx, receiver, "_", applicability);
+                        format!("{receiver_sugg}.clone_into({rhs_sugg})")
+                    },
+                    CallKind::FunctionCall { self_arg, .. } => {
+                        let self_sugg = Sugg::hir_with_applicability(cx, self_arg, "_", applicability);
+                        format!("ToOwned::clone_into({self_sugg}, {rhs_sugg})")
+                    },
+                }
+            },
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
deleted file mode 100644
index f2937d51340..00000000000
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ /dev/null
@@ -1,1210 +0,0 @@
-//! checks for attributes
-
-use clippy_config::msrvs::{self, Msrv};
-use clippy_utils::diagnostics::{
-    span_lint, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
-};
-use clippy_utils::is_from_proc_macro;
-use clippy_utils::macros::{is_panic, macro_backtrace};
-use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments};
-use rustc_ast::token::{Token, TokenKind};
-use rustc_ast::tokenstream::TokenTree;
-use rustc_ast::{
-    AttrArgs, AttrArgsEq, AttrKind, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem,
-};
-use rustc_errors::Applicability;
-use rustc_hir::{
-    Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind,
-};
-use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext};
-use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty;
-use rustc_session::{declare_lint_pass, impl_lint_pass};
-use rustc_span::symbol::Symbol;
-use rustc_span::{sym, Span, DUMMY_SP};
-use semver::Version;
-
-static UNIX_SYSTEMS: &[&str] = &[
-    "android",
-    "dragonfly",
-    "emscripten",
-    "freebsd",
-    "fuchsia",
-    "haiku",
-    "illumos",
-    "ios",
-    "l4re",
-    "linux",
-    "macos",
-    "netbsd",
-    "openbsd",
-    "redox",
-    "solaris",
-    "vxworks",
-];
-
-// NOTE: windows is excluded from the list because it's also a valid target family.
-static NON_UNIX_SYSTEMS: &[&str] = &["hermit", "none", "wasi"];
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for items annotated with `#[inline(always)]`,
-    /// unless the annotated function is empty or simply panics.
-    ///
-    /// ### Why is this bad?
-    /// While there are valid uses of this annotation (and once
-    /// you know when to use it, by all means `allow` this lint), it's a common
-    /// newbie-mistake to pepper one's code with it.
-    ///
-    /// As a rule of thumb, before slapping `#[inline(always)]` on a function,
-    /// measure if that additional function call really affects your runtime profile
-    /// sufficiently to make up for the increase in compile time.
-    ///
-    /// ### Known problems
-    /// False positives, big time. This lint is meant to be
-    /// deactivated by everyone doing serious performance work. This means having
-    /// done the measurement.
-    ///
-    /// ### Example
-    /// ```ignore
-    /// #[inline(always)]
-    /// fn not_quite_hot_code(..) { ... }
-    /// ```
-    #[clippy::version = "pre 1.29.0"]
-    pub INLINE_ALWAYS,
-    pedantic,
-    "use of `#[inline(always)]`"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for `extern crate` and `use` items annotated with
-    /// lint attributes.
-    ///
-    /// This lint permits lint attributes for lints emitted on the items themself.
-    /// For `use` items these lints are:
-    /// * deprecated
-    /// * unreachable_pub
-    /// * unused_imports
-    /// * clippy::enum_glob_use
-    /// * clippy::macro_use_imports
-    /// * clippy::wildcard_imports
-    ///
-    /// For `extern crate` items these lints are:
-    /// * `unused_imports` on items with `#[macro_use]`
-    ///
-    /// ### Why is this bad?
-    /// Lint attributes have no effect on crate imports. Most
-    /// likely a `!` was forgotten.
-    ///
-    /// ### Example
-    /// ```ignore
-    /// #[deny(dead_code)]
-    /// extern crate foo;
-    /// #[forbid(dead_code)]
-    /// use foo::bar;
-    /// ```
-    ///
-    /// Use instead:
-    /// ```rust,ignore
-    /// #[allow(unused_imports)]
-    /// use foo::baz;
-    /// #[allow(unused_imports)]
-    /// #[macro_use]
-    /// extern crate baz;
-    /// ```
-    #[clippy::version = "pre 1.29.0"]
-    pub USELESS_ATTRIBUTE,
-    correctness,
-    "use of lint attributes on `extern crate` items"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for `#[deprecated]` annotations with a `since`
-    /// field that is not a valid semantic version. Also allows "TBD" to signal
-    /// future deprecation.
-    ///
-    /// ### Why is this bad?
-    /// For checking the version of the deprecation, it must be
-    /// a valid semver. Failing that, the contained information is useless.
-    ///
-    /// ### Example
-    /// ```no_run
-    /// #[deprecated(since = "forever")]
-    /// fn something_else() { /* ... */ }
-    /// ```
-    #[clippy::version = "pre 1.29.0"]
-    pub DEPRECATED_SEMVER,
-    correctness,
-    "use of `#[deprecated(since = \"x\")]` where x is not semver"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for empty lines after outer attributes
-    ///
-    /// ### Why is this bad?
-    /// Most likely the attribute was meant to be an inner attribute using a '!'.
-    /// If it was meant to be an outer attribute, then the following item
-    /// should not be separated by empty lines.
-    ///
-    /// ### Known problems
-    /// Can cause false positives.
-    ///
-    /// From the clippy side it's difficult to detect empty lines between an attributes and the
-    /// following item because empty lines and comments are not part of the AST. The parsing
-    /// currently works for basic cases but is not perfect.
-    ///
-    /// ### Example
-    /// ```no_run
-    /// #[allow(dead_code)]
-    ///
-    /// fn not_quite_good_code() { }
-    /// ```
-    ///
-    /// Use instead:
-    /// ```no_run
-    /// // Good (as inner attribute)
-    /// #![allow(dead_code)]
-    ///
-    /// fn this_is_fine() { }
-    ///
-    /// // or
-    ///
-    /// // Good (as outer attribute)
-    /// #[allow(dead_code)]
-    /// fn this_is_fine_too() { }
-    /// ```
-    #[clippy::version = "pre 1.29.0"]
-    pub EMPTY_LINE_AFTER_OUTER_ATTR,
-    nursery,
-    "empty line after outer attribute"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for empty lines after documentation comments.
-    ///
-    /// ### Why is this bad?
-    /// The documentation comment was most likely meant to be an inner attribute or regular comment.
-    /// If it was intended to be a documentation comment, then the empty line should be removed to
-    /// be more idiomatic.
-    ///
-    /// ### Known problems
-    /// Only detects empty lines immediately following the documentation. If the doc comment is followed
-    /// by an attribute and then an empty line, this lint will not trigger. Use `empty_line_after_outer_attr`
-    /// in combination with this lint to detect both cases.
-    ///
-    /// Does not detect empty lines after doc attributes (e.g. `#[doc = ""]`).
-    ///
-    /// ### Example
-    /// ```no_run
-    /// /// Some doc comment with a blank line after it.
-    ///
-    /// fn not_quite_good_code() { }
-    /// ```
-    ///
-    /// Use instead:
-    /// ```no_run
-    /// /// Good (no blank line)
-    /// fn this_is_fine() { }
-    /// ```
-    ///
-    /// ```no_run
-    /// // Good (convert to a regular comment)
-    ///
-    /// fn this_is_fine_too() { }
-    /// ```
-    ///
-    /// ```no_run
-    /// //! Good (convert to a comment on an inner attribute)
-    ///
-    /// fn this_is_fine_as_well() { }
-    /// ```
-    #[clippy::version = "1.70.0"]
-    pub EMPTY_LINE_AFTER_DOC_COMMENTS,
-    nursery,
-    "empty line after documentation comments"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category.
-    ///
-    /// ### Why is this bad?
-    /// Restriction lints sometimes are in contrast with other lints or even go against idiomatic rust.
-    /// These lints should only be enabled on a lint-by-lint basis and with careful consideration.
-    ///
-    /// ### Example
-    /// ```no_run
-    /// #![deny(clippy::restriction)]
-    /// ```
-    ///
-    /// Use instead:
-    /// ```no_run
-    /// #![deny(clippy::as_conversions)]
-    /// ```
-    #[clippy::version = "1.47.0"]
-    pub BLANKET_CLIPPY_RESTRICTION_LINTS,
-    suspicious,
-    "enabling the complete restriction group"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it
-    /// with `#[rustfmt::skip]`.
-    ///
-    /// ### Why is this bad?
-    /// Since tool_attributes ([rust-lang/rust#44690](https://github.com/rust-lang/rust/issues/44690))
-    /// are stable now, they should be used instead of the old `cfg_attr(rustfmt)` attributes.
-    ///
-    /// ### Known problems
-    /// This lint doesn't detect crate level inner attributes, because they get
-    /// processed before the PreExpansionPass lints get executed. See
-    /// [#3123](https://github.com/rust-lang/rust-clippy/pull/3123#issuecomment-422321765)
-    ///
-    /// ### Example
-    /// ```no_run
-    /// #[cfg_attr(rustfmt, rustfmt_skip)]
-    /// fn main() { }
-    /// ```
-    ///
-    /// Use instead:
-    /// ```no_run
-    /// #[rustfmt::skip]
-    /// fn main() { }
-    /// ```
-    #[clippy::version = "1.32.0"]
-    pub DEPRECATED_CFG_ATTR,
-    complexity,
-    "usage of `cfg_attr(rustfmt)` instead of tool attributes"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for cfg attributes having operating systems used in target family position.
-    ///
-    /// ### Why is this bad?
-    /// The configuration option will not be recognised and the related item will not be included
-    /// by the conditional compilation engine.
-    ///
-    /// ### Example
-    /// ```no_run
-    /// #[cfg(linux)]
-    /// fn conditional() { }
-    /// ```
-    ///
-    /// Use instead:
-    /// ```no_run
-    /// # mod hidden {
-    /// #[cfg(target_os = "linux")]
-    /// fn conditional() { }
-    /// # }
-    ///
-    /// // or
-    ///
-    /// #[cfg(unix)]
-    /// fn conditional() { }
-    /// ```
-    /// Check the [Rust Reference](https://doc.rust-lang.org/reference/conditional-compilation.html#target_os) for more details.
-    #[clippy::version = "1.45.0"]
-    pub MISMATCHED_TARGET_OS,
-    correctness,
-    "usage of `cfg(operating_system)` instead of `cfg(target_os = \"operating_system\")`"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for attributes that allow lints without a reason.
-    ///
-    /// (This requires the `lint_reasons` feature)
-    ///
-    /// ### Why is this bad?
-    /// Allowing a lint should always have a reason. This reason should be documented to
-    /// ensure that others understand the reasoning
-    ///
-    /// ### Example
-    /// ```no_run
-    /// #![feature(lint_reasons)]
-    ///
-    /// #![allow(clippy::some_lint)]
-    /// ```
-    ///
-    /// Use instead:
-    /// ```no_run
-    /// #![feature(lint_reasons)]
-    ///
-    /// #![allow(clippy::some_lint, reason = "False positive rust-lang/rust-clippy#1002020")]
-    /// ```
-    #[clippy::version = "1.61.0"]
-    pub ALLOW_ATTRIBUTES_WITHOUT_REASON,
-    restriction,
-    "ensures that all `allow` and `expect` attributes have a reason"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for `#[should_panic]` attributes without specifying the expected panic message.
-    ///
-    /// ### Why is this bad?
-    /// The expected panic message should be specified to ensure that the test is actually
-    /// panicking with the expected message, and not another unrelated panic.
-    ///
-    /// ### Example
-    /// ```no_run
-    /// fn random() -> i32 { 0 }
-    ///
-    /// #[should_panic]
-    /// #[test]
-    /// fn my_test() {
-    ///     let _ = 1 / random();
-    /// }
-    /// ```
-    ///
-    /// Use instead:
-    /// ```no_run
-    /// fn random() -> i32 { 0 }
-    ///
-    /// #[should_panic = "attempt to divide by zero"]
-    /// #[test]
-    /// fn my_test() {
-    ///     let _ = 1 / random();
-    /// }
-    /// ```
-    #[clippy::version = "1.74.0"]
-    pub SHOULD_PANIC_WITHOUT_EXPECT,
-    pedantic,
-    "ensures that all `should_panic` attributes specify its expected panic message"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for `any` and `all` combinators in `cfg` with only one condition.
-    ///
-    /// ### Why is this bad?
-    /// If there is only one condition, no need to wrap it into `any` or `all` combinators.
-    ///
-    /// ### Example
-    /// ```no_run
-    /// #[cfg(any(unix))]
-    /// pub struct Bar;
-    /// ```
-    ///
-    /// Use instead:
-    /// ```no_run
-    /// #[cfg(unix)]
-    /// pub struct Bar;
-    /// ```
-    #[clippy::version = "1.71.0"]
-    pub NON_MINIMAL_CFG,
-    style,
-    "ensure that all `cfg(any())` and `cfg(all())` have more than one condition"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for `#[cfg(features = "...")]` and suggests to replace it with
-    /// `#[cfg(feature = "...")]`.
-    ///
-    /// It also checks if `cfg(test)` was misspelled.
-    ///
-    /// ### Why is this bad?
-    /// Misspelling `feature` as `features` or `test` as `tests` can be sometimes hard to spot. It
-    /// may cause conditional compilation not work quietly.
-    ///
-    /// ### Example
-    /// ```no_run
-    /// #[cfg(features = "some-feature")]
-    /// fn conditional() { }
-    /// #[cfg(tests)]
-    /// mod tests { }
-    /// ```
-    ///
-    /// Use instead:
-    /// ```no_run
-    /// #[cfg(feature = "some-feature")]
-    /// fn conditional() { }
-    /// #[cfg(test)]
-    /// mod tests { }
-    /// ```
-    #[clippy::version = "1.69.0"]
-    pub MAYBE_MISUSED_CFG,
-    suspicious,
-    "prevent from misusing the wrong attr name"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for `#[cfg_attr(feature = "cargo-clippy", ...)]` and for
-    /// `#[cfg(feature = "cargo-clippy")]` and suggests to replace it with
-    /// `#[cfg_attr(clippy, ...)]` or `#[cfg(clippy)]`.
-    ///
-    /// ### Why is this bad?
-    /// This feature has been deprecated for years and shouldn't be used anymore.
-    ///
-    /// ### Example
-    /// ```no_run
-    /// #[cfg(feature = "cargo-clippy")]
-    /// struct Bar;
-    /// ```
-    ///
-    /// Use instead:
-    /// ```no_run
-    /// #[cfg(clippy)]
-    /// struct Bar;
-    /// ```
-    #[clippy::version = "1.78.0"]
-    pub DEPRECATED_CLIPPY_CFG_ATTR,
-    suspicious,
-    "usage of `cfg(feature = \"cargo-clippy\")` instead of `cfg(clippy)`"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for `#[cfg_attr(clippy, allow(clippy::lint))]`
-    /// and suggests to replace it with `#[allow(clippy::lint)]`.
-    ///
-    /// ### Why is this bad?
-    /// There is no reason to put clippy attributes behind a clippy `cfg` as they are not
-    /// run by anything else than clippy.
-    ///
-    /// ### Example
-    /// ```no_run
-    /// #![cfg_attr(clippy, allow(clippy::deprecated_cfg_attr))]
-    /// ```
-    ///
-    /// Use instead:
-    /// ```no_run
-    /// #![allow(clippy::deprecated_cfg_attr)]
-    /// ```
-    #[clippy::version = "1.78.0"]
-    pub UNNECESSARY_CLIPPY_CFG,
-    suspicious,
-    "usage of `cfg_attr(clippy, allow(clippy::lint))` instead of `allow(clippy::lint)`"
-}
-
-declare_lint_pass!(Attributes => [
-    ALLOW_ATTRIBUTES_WITHOUT_REASON,
-    INLINE_ALWAYS,
-    DEPRECATED_SEMVER,
-    USELESS_ATTRIBUTE,
-    BLANKET_CLIPPY_RESTRICTION_LINTS,
-    SHOULD_PANIC_WITHOUT_EXPECT,
-]);
-
-impl<'tcx> LateLintPass<'tcx> for Attributes {
-    fn check_crate(&mut self, cx: &LateContext<'tcx>) {
-        for (name, level) in &cx.sess().opts.lint_opts {
-            if name == "clippy::restriction" && *level > Level::Allow {
-                span_lint_and_then(
-                    cx,
-                    BLANKET_CLIPPY_RESTRICTION_LINTS,
-                    DUMMY_SP,
-                    "`clippy::restriction` is not meant to be enabled as a group",
-                    |diag| {
-                        diag.note(format!(
-                            "because of the command line `--{} clippy::restriction`",
-                            level.as_str()
-                        ));
-                        diag.help("enable the restriction lints you need individually");
-                    },
-                );
-            }
-        }
-    }
-
-    fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) {
-        if let Some(items) = &attr.meta_item_list() {
-            if let Some(ident) = attr.ident() {
-                if is_lint_level(ident.name) {
-                    check_clippy_lint_names(cx, ident.name, items);
-                }
-                if matches!(ident.name, sym::allow | sym::expect) {
-                    check_lint_reason(cx, ident.name, items, attr);
-                }
-                if items.is_empty() || !attr.has_name(sym::deprecated) {
-                    return;
-                }
-                for item in items {
-                    if let NestedMetaItem::MetaItem(mi) = &item
-                        && let MetaItemKind::NameValue(lit) = &mi.kind
-                        && mi.has_name(sym::since)
-                    {
-                        check_deprecated_since(cx, item.span(), lit);
-                    }
-                }
-            }
-        }
-        if attr.has_name(sym::should_panic) {
-            check_should_panic_reason(cx, attr);
-        }
-    }
-
-    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        let attrs = cx.tcx.hir().attrs(item.hir_id());
-        if is_relevant_item(cx, item) {
-            check_attrs(cx, item.span, item.ident.name, attrs);
-        }
-        match item.kind {
-            ItemKind::ExternCrate(..) | ItemKind::Use(..) => {
-                let skip_unused_imports = attrs.iter().any(|attr| attr.has_name(sym::macro_use));
-
-                for attr in attrs {
-                    if in_external_macro(cx.sess(), attr.span) {
-                        return;
-                    }
-                    if let Some(lint_list) = &attr.meta_item_list() {
-                        if attr.ident().map_or(false, |ident| is_lint_level(ident.name)) {
-                            for lint in lint_list {
-                                match item.kind {
-                                    ItemKind::Use(..) => {
-                                        if is_word(lint, sym::unused_imports)
-                                            || is_word(lint, sym::deprecated)
-                                            || is_word(lint, sym!(unreachable_pub))
-                                            || is_word(lint, sym!(unused))
-                                            || is_word(lint, sym!(unused_import_braces))
-                                            || extract_clippy_lint(lint).map_or(false, |s| {
-                                                matches!(
-                                                    s.as_str(),
-                                                    "wildcard_imports"
-                                                        | "enum_glob_use"
-                                                        | "redundant_pub_crate"
-                                                        | "macro_use_imports"
-                                                        | "unsafe_removed_from_name"
-                                                        | "module_name_repetitions"
-                                                        | "single_component_path_imports"
-                                                )
-                                            })
-                                        {
-                                            return;
-                                        }
-                                    },
-                                    ItemKind::ExternCrate(..) => {
-                                        if is_word(lint, sym::unused_imports) && skip_unused_imports {
-                                            return;
-                                        }
-                                        if is_word(lint, sym!(unused_extern_crates)) {
-                                            return;
-                                        }
-                                    },
-                                    _ => {},
-                                }
-                            }
-                            let line_span = first_line_of_span(cx, attr.span);
-
-                            if let Some(mut sugg) = snippet_opt(cx, line_span) {
-                                if sugg.contains("#[") {
-                                    span_lint_and_then(
-                                        cx,
-                                        USELESS_ATTRIBUTE,
-                                        line_span,
-                                        "useless lint attribute",
-                                        |diag| {
-                                            sugg = sugg.replacen("#[", "#![", 1);
-                                            diag.span_suggestion(
-                                                line_span,
-                                                "if you just forgot a `!`, use",
-                                                sugg,
-                                                Applicability::MaybeIncorrect,
-                                            );
-                                        },
-                                    );
-                                }
-                            }
-                        }
-                    }
-                }
-            },
-            _ => {},
-        }
-    }
-
-    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
-        if is_relevant_impl(cx, item) {
-            check_attrs(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()));
-        }
-    }
-
-    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
-        if is_relevant_trait(cx, item) {
-            check_attrs(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()));
-        }
-    }
-}
-
-/// Returns the lint name if it is clippy lint.
-fn extract_clippy_lint(lint: &NestedMetaItem) -> Option<Symbol> {
-    if let Some(meta_item) = lint.meta_item()
-        && meta_item.path.segments.len() > 1
-        && let tool_name = meta_item.path.segments[0].ident
-        && tool_name.name == sym::clippy
-    {
-        let lint_name = meta_item.path.segments.last().unwrap().ident.name;
-        return Some(lint_name);
-    }
-    None
-}
-
-fn check_should_panic_reason(cx: &LateContext<'_>, attr: &Attribute) {
-    if let AttrKind::Normal(normal_attr) = &attr.kind {
-        if let AttrArgs::Eq(_, AttrArgsEq::Hir(_)) = &normal_attr.item.args {
-            // `#[should_panic = ".."]` found, good
-            return;
-        }
-
-        if let AttrArgs::Delimited(args) = &normal_attr.item.args
-            && let mut tt_iter = args.tokens.trees()
-            && let Some(TokenTree::Token(
-                Token {
-                    kind: TokenKind::Ident(sym::expected, _),
-                    ..
-                },
-                _,
-            )) = tt_iter.next()
-            && let Some(TokenTree::Token(
-                Token {
-                    kind: TokenKind::Eq, ..
-                },
-                _,
-            )) = tt_iter.next()
-            && let Some(TokenTree::Token(
-                Token {
-                    kind: TokenKind::Literal(_),
-                    ..
-                },
-                _,
-            )) = tt_iter.next()
-        {
-            // `#[should_panic(expected = "..")]` found, good
-            return;
-        }
-
-        span_lint_and_sugg(
-            cx,
-            SHOULD_PANIC_WITHOUT_EXPECT,
-            attr.span,
-            "#[should_panic] attribute without a reason",
-            "consider specifying the expected panic",
-            "#[should_panic(expected = /* panic message */)]".into(),
-            Applicability::HasPlaceholders,
-        );
-    }
-}
-
-fn check_clippy_lint_names(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem]) {
-    for lint in items {
-        if let Some(lint_name) = extract_clippy_lint(lint) {
-            if lint_name.as_str() == "restriction" && name != sym::allow {
-                span_lint_and_help(
-                    cx,
-                    BLANKET_CLIPPY_RESTRICTION_LINTS,
-                    lint.span(),
-                    "`clippy::restriction` is not meant to be enabled as a group",
-                    None,
-                    "enable the restriction lints you need individually",
-                );
-            }
-        }
-    }
-}
-
-fn check_lint_reason<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMetaItem], attr: &'cx Attribute) {
-    // Check for the feature
-    if !cx.tcx.features().lint_reasons {
-        return;
-    }
-
-    // Check if the reason is present
-    if let Some(item) = items.last().and_then(NestedMetaItem::meta_item)
-        && let MetaItemKind::NameValue(_) = &item.kind
-        && item.path == sym::reason
-    {
-        return;
-    }
-
-    // Check if the attribute is in an external macro and therefore out of the developer's control
-    if in_external_macro(cx.sess(), attr.span) || is_from_proc_macro(cx, &attr) {
-        return;
-    }
-
-    span_lint_and_help(
-        cx,
-        ALLOW_ATTRIBUTES_WITHOUT_REASON,
-        attr.span,
-        &format!("`{}` attribute without specifying a reason", name.as_str()),
-        None,
-        "try adding a reason at the end with `, reason = \"..\"`",
-    );
-}
-
-fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
-    if let ItemKind::Fn(_, _, eid) = item.kind {
-        is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value)
-    } else {
-        true
-    }
-}
-
-fn is_relevant_impl(cx: &LateContext<'_>, item: &ImplItem<'_>) -> bool {
-    match item.kind {
-        ImplItemKind::Fn(_, eid) => is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value),
-        _ => false,
-    }
-}
-
-fn is_relevant_trait(cx: &LateContext<'_>, item: &TraitItem<'_>) -> bool {
-    match item.kind {
-        TraitItemKind::Fn(_, TraitFn::Required(_)) => true,
-        TraitItemKind::Fn(_, TraitFn::Provided(eid)) => {
-            is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value)
-        },
-        _ => false,
-    }
-}
-
-fn is_relevant_block(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_>, block: &Block<'_>) -> bool {
-    block.stmts.first().map_or(
-        block
-            .expr
-            .as_ref()
-            .map_or(false, |e| is_relevant_expr(cx, typeck_results, e)),
-        |stmt| match &stmt.kind {
-            StmtKind::Local(_) => true,
-            StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, typeck_results, expr),
-            StmtKind::Item(_) => false,
-        },
-    )
-}
-
-fn is_relevant_expr(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_>, expr: &Expr<'_>) -> bool {
-    if macro_backtrace(expr.span).last().map_or(false, |macro_call| {
-        is_panic(cx, macro_call.def_id) || cx.tcx.item_name(macro_call.def_id) == sym::unreachable
-    }) {
-        return false;
-    }
-    match &expr.kind {
-        ExprKind::Block(block, _) => is_relevant_block(cx, typeck_results, block),
-        ExprKind::Ret(Some(e)) => is_relevant_expr(cx, typeck_results, e),
-        ExprKind::Ret(None) | ExprKind::Break(_, None) => false,
-        _ => true,
-    }
-}
-
-fn check_attrs(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Attribute]) {
-    if span.from_expansion() {
-        return;
-    }
-
-    for attr in attrs {
-        if let Some(values) = attr.meta_item_list() {
-            if values.len() != 1 || !attr.has_name(sym::inline) {
-                continue;
-            }
-            if is_word(&values[0], sym::always) {
-                span_lint(
-                    cx,
-                    INLINE_ALWAYS,
-                    attr.span,
-                    &format!("you have declared `#[inline(always)]` on `{name}`. This is usually a bad idea"),
-                );
-            }
-        }
-    }
-}
-
-fn check_deprecated_since(cx: &LateContext<'_>, span: Span, lit: &MetaItemLit) {
-    if let LitKind::Str(is, _) = lit.kind {
-        if is.as_str() == "TBD" || Version::parse(is.as_str()).is_ok() {
-            return;
-        }
-    }
-    span_lint(
-        cx,
-        DEPRECATED_SEMVER,
-        span,
-        "the since field must contain a semver-compliant version",
-    );
-}
-
-fn is_word(nmi: &NestedMetaItem, expected: Symbol) -> bool {
-    if let NestedMetaItem::MetaItem(mi) = &nmi {
-        mi.is_word() && mi.has_name(expected)
-    } else {
-        false
-    }
-}
-
-pub struct EarlyAttributes {
-    pub msrv: Msrv,
-}
-
-impl_lint_pass!(EarlyAttributes => [
-    DEPRECATED_CFG_ATTR,
-    MISMATCHED_TARGET_OS,
-    EMPTY_LINE_AFTER_OUTER_ATTR,
-    EMPTY_LINE_AFTER_DOC_COMMENTS,
-    NON_MINIMAL_CFG,
-    MAYBE_MISUSED_CFG,
-    DEPRECATED_CLIPPY_CFG_ATTR,
-    UNNECESSARY_CLIPPY_CFG,
-]);
-
-impl EarlyLintPass for EarlyAttributes {
-    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
-        check_empty_line_after_outer_attr(cx, item);
-    }
-
-    fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
-        check_deprecated_cfg_attr(cx, attr, &self.msrv);
-        check_deprecated_cfg(cx, attr);
-        check_mismatched_target_os(cx, attr);
-        check_minimal_cfg_condition(cx, attr);
-        check_misused_cfg(cx, attr);
-    }
-
-    extract_msrv_attr!(EarlyContext);
-}
-
-/// Check for empty lines after outer attributes.
-///
-/// Attributes and documentation comments are both considered outer attributes
-/// by the AST. However, the average user likely considers them to be different.
-/// Checking for empty lines after each of these attributes is split into two different
-/// lints but can share the same logic.
-fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
-    let mut iter = item.attrs.iter().peekable();
-    while let Some(attr) = iter.next() {
-        if (matches!(attr.kind, AttrKind::Normal(..)) || matches!(attr.kind, AttrKind::DocComment(..)))
-            && attr.style == AttrStyle::Outer
-            && is_present_in_source(cx, attr.span)
-        {
-            let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt(), item.span.parent());
-            let end_of_attr_to_next_attr_or_item = Span::new(
-                attr.span.hi(),
-                iter.peek().map_or(item.span.lo(), |next_attr| next_attr.span.lo()),
-                item.span.ctxt(),
-                item.span.parent(),
-            );
-
-            if let Some(snippet) = snippet_opt(cx, end_of_attr_to_next_attr_or_item) {
-                let lines = snippet.split('\n').collect::<Vec<_>>();
-                let lines = without_block_comments(lines);
-
-                if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 {
-                    let (lint_msg, lint_type) = match attr.kind {
-                        AttrKind::DocComment(..) => (
-                            "found an empty line after a doc comment. \
-                            Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?",
-                            EMPTY_LINE_AFTER_DOC_COMMENTS,
-                        ),
-                        AttrKind::Normal(..) => (
-                            "found an empty line after an outer attribute. \
-                            Perhaps you forgot to add a `!` to make it an inner attribute?",
-                            EMPTY_LINE_AFTER_OUTER_ATTR,
-                        ),
-                    };
-
-                    span_lint(cx, lint_type, begin_of_attr_to_item, lint_msg);
-                }
-            }
-        }
-    }
-}
-
-fn check_cargo_clippy_attr(cx: &EarlyContext<'_>, item: &rustc_ast::MetaItem) {
-    if item.has_name(sym::feature) && item.value_str().is_some_and(|v| v.as_str() == "cargo-clippy") {
-        span_lint_and_sugg(
-            cx,
-            DEPRECATED_CLIPPY_CFG_ATTR,
-            item.span,
-            "`feature = \"cargo-clippy\"` was replaced by `clippy`",
-            "replace with",
-            "clippy".to_string(),
-            Applicability::MachineApplicable,
-        );
-    }
-}
-
-fn check_deprecated_cfg_recursively(cx: &EarlyContext<'_>, attr: &rustc_ast::MetaItem) {
-    if let Some(ident) = attr.ident() {
-        if ["any", "all", "not"].contains(&ident.name.as_str()) {
-            let Some(list) = attr.meta_item_list() else { return };
-            for item in list.iter().filter_map(|item| item.meta_item()) {
-                check_deprecated_cfg_recursively(cx, item);
-            }
-        } else {
-            check_cargo_clippy_attr(cx, attr);
-        }
-    }
-}
-
-fn check_deprecated_cfg(cx: &EarlyContext<'_>, attr: &Attribute) {
-    if attr.has_name(sym::cfg)
-        && let Some(list) = attr.meta_item_list()
-    {
-        for item in list.iter().filter_map(|item| item.meta_item()) {
-            check_deprecated_cfg_recursively(cx, item);
-        }
-    }
-}
-
-fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msrv) {
-    // check cfg_attr
-    if attr.has_name(sym::cfg_attr)
-        && let Some(items) = attr.meta_item_list()
-        && items.len() == 2
-        && let Some(feature_item) = items[0].meta_item()
-    {
-        // check for `rustfmt`
-        if feature_item.has_name(sym::rustfmt)
-            && msrv.meets(msrvs::TOOL_ATTRIBUTES)
-            // check for `rustfmt_skip` and `rustfmt::skip`
-            && let Some(skip_item) = &items[1].meta_item()
-            && (skip_item.has_name(sym!(rustfmt_skip))
-                || skip_item
-                    .path
-                    .segments
-                    .last()
-                    .expect("empty path in attribute")
-                    .ident
-                    .name
-                    == sym::skip)
-            // Only lint outer attributes, because custom inner attributes are unstable
-            // Tracking issue: https://github.com/rust-lang/rust/issues/54726
-            && attr.style == AttrStyle::Outer
-        {
-            span_lint_and_sugg(
-                cx,
-                DEPRECATED_CFG_ATTR,
-                attr.span,
-                "`cfg_attr` is deprecated for rustfmt and got replaced by tool attributes",
-                "use",
-                "#[rustfmt::skip]".to_string(),
-                Applicability::MachineApplicable,
-            );
-        } else {
-            check_deprecated_cfg_recursively(cx, feature_item);
-            if let Some(behind_cfg_attr) = items[1].meta_item() {
-                check_clippy_cfg_attr(cx, feature_item, behind_cfg_attr, attr);
-            }
-        }
-    }
-}
-
-fn check_clippy_cfg_attr(
-    cx: &EarlyContext<'_>,
-    cfg_attr: &rustc_ast::MetaItem,
-    behind_cfg_attr: &rustc_ast::MetaItem,
-    attr: &Attribute,
-) {
-    if cfg_attr.has_name(sym::clippy)
-        && let Some(ident) = behind_cfg_attr.ident()
-        && Level::from_symbol(ident.name, Some(attr.id)).is_some()
-        && let Some(items) = behind_cfg_attr.meta_item_list()
-    {
-        let nb_items = items.len();
-        let mut clippy_lints = Vec::with_capacity(items.len());
-        for item in items {
-            if let Some(meta_item) = item.meta_item()
-                && let [part1, _] = meta_item.path.segments.as_slice()
-                && part1.ident.name == sym::clippy
-            {
-                clippy_lints.push(item.span());
-            }
-        }
-        if clippy_lints.is_empty() {
-            return;
-        }
-        if nb_items == clippy_lints.len() {
-            if let Some(snippet) = snippet_opt(cx, behind_cfg_attr.span) {
-                span_lint_and_sugg(
-                    cx,
-                    UNNECESSARY_CLIPPY_CFG,
-                    attr.span,
-                    "no need to put clippy lints behind a `clippy` cfg",
-                    "replace with",
-                    format!(
-                        "#{}[{}]",
-                        if attr.style == AttrStyle::Inner { "!" } else { "" },
-                        snippet
-                    ),
-                    Applicability::MachineApplicable,
-                );
-            }
-        } else {
-            let snippet = clippy_lints
-                .iter()
-                .filter_map(|sp| snippet_opt(cx, *sp))
-                .collect::<Vec<_>>()
-                .join(",");
-            span_lint_and_note(
-                cx,
-                UNNECESSARY_CLIPPY_CFG,
-                clippy_lints,
-                "no need to put clippy lints behind a `clippy` cfg",
-                None,
-                &format!(
-                    "write instead: `#{}[{}({})]`",
-                    if attr.style == AttrStyle::Inner { "!" } else { "" },
-                    ident.name,
-                    snippet
-                ),
-            );
-        }
-    }
-}
-
-fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
-    for item in items {
-        if let NestedMetaItem::MetaItem(meta) = item {
-            if !meta.has_name(sym::any) && !meta.has_name(sym::all) {
-                continue;
-            }
-            if let MetaItemKind::List(list) = &meta.kind {
-                check_nested_cfg(cx, list);
-                if list.len() == 1 {
-                    span_lint_and_then(
-                        cx,
-                        NON_MINIMAL_CFG,
-                        meta.span,
-                        "unneeded sub `cfg` when there is only one condition",
-                        |diag| {
-                            if let Some(snippet) = snippet_opt(cx, list[0].span()) {
-                                diag.span_suggestion(meta.span, "try", snippet, Applicability::MaybeIncorrect);
-                            }
-                        },
-                    );
-                } else if list.is_empty() && meta.has_name(sym::all) {
-                    span_lint_and_then(
-                        cx,
-                        NON_MINIMAL_CFG,
-                        meta.span,
-                        "unneeded sub `cfg` when there is no condition",
-                        |_| {},
-                    );
-                }
-            }
-        }
-    }
-}
-
-fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
-    for item in items {
-        if let NestedMetaItem::MetaItem(meta) = item {
-            if let Some(ident) = meta.ident()
-                && ident.name.as_str() == "features"
-                && let Some(val) = meta.value_str()
-            {
-                span_lint_and_sugg(
-                    cx,
-                    MAYBE_MISUSED_CFG,
-                    meta.span,
-                    "'feature' may be misspelled as 'features'",
-                    "did you mean",
-                    format!("feature = \"{val}\""),
-                    Applicability::MaybeIncorrect,
-                );
-            }
-            if let MetaItemKind::List(list) = &meta.kind {
-                check_nested_misused_cfg(cx, list);
-            // If this is not a list, then we check for `cfg(test)`.
-            } else if let Some(ident) = meta.ident()
-                && matches!(ident.name.as_str(), "tests" | "Test")
-            {
-                span_lint_and_sugg(
-                    cx,
-                    MAYBE_MISUSED_CFG,
-                    meta.span,
-                    &format!("'test' may be misspelled as '{}'", ident.name.as_str()),
-                    "did you mean",
-                    "test".to_string(),
-                    Applicability::MaybeIncorrect,
-                );
-            }
-        }
-    }
-}
-
-fn check_minimal_cfg_condition(cx: &EarlyContext<'_>, attr: &Attribute) {
-    if attr.has_name(sym::cfg)
-        && let Some(items) = attr.meta_item_list()
-    {
-        check_nested_cfg(cx, &items);
-    }
-}
-
-fn check_misused_cfg(cx: &EarlyContext<'_>, attr: &Attribute) {
-    if attr.has_name(sym::cfg)
-        && let Some(items) = attr.meta_item_list()
-    {
-        check_nested_misused_cfg(cx, &items);
-    }
-}
-
-fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) {
-    fn find_os(name: &str) -> Option<&'static str> {
-        UNIX_SYSTEMS
-            .iter()
-            .chain(NON_UNIX_SYSTEMS.iter())
-            .find(|&&os| os == name)
-            .copied()
-    }
-
-    fn is_unix(name: &str) -> bool {
-        UNIX_SYSTEMS.iter().any(|&os| os == name)
-    }
-
-    fn find_mismatched_target_os(items: &[NestedMetaItem]) -> Vec<(&str, Span)> {
-        let mut mismatched = Vec::new();
-
-        for item in items {
-            if let NestedMetaItem::MetaItem(meta) = item {
-                match &meta.kind {
-                    MetaItemKind::List(list) => {
-                        mismatched.extend(find_mismatched_target_os(list));
-                    },
-                    MetaItemKind::Word => {
-                        if let Some(ident) = meta.ident()
-                            && let Some(os) = find_os(ident.name.as_str())
-                        {
-                            mismatched.push((os, ident.span));
-                        }
-                    },
-                    MetaItemKind::NameValue(..) => {},
-                }
-            }
-        }
-
-        mismatched
-    }
-
-    if attr.has_name(sym::cfg)
-        && let Some(list) = attr.meta_item_list()
-        && let mismatched = find_mismatched_target_os(&list)
-        && !mismatched.is_empty()
-    {
-        let mess = "operating system used in target family position";
-
-        span_lint_and_then(cx, MISMATCHED_TARGET_OS, attr.span, mess, |diag| {
-            // Avoid showing the unix suggestion multiple times in case
-            // we have more than one mismatch for unix-like systems
-            let mut unix_suggested = false;
-
-            for (os, span) in mismatched {
-                let sugg = format!("target_os = \"{os}\"");
-                diag.span_suggestion(span, "try", sugg, Applicability::MaybeIncorrect);
-
-                if !unix_suggested && is_unix(os) {
-                    diag.help("did you mean `unix`?");
-                    unix_suggested = true;
-                }
-            }
-        });
-    }
-}
-
-fn is_lint_level(symbol: Symbol) -> bool {
-    matches!(symbol, sym::allow | sym::expect | sym::warn | sym::deny | sym::forbid)
-}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs
new file mode 100644
index 00000000000..df00f23e37e
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs
@@ -0,0 +1,37 @@
+use super::{Attribute, ALLOW_ATTRIBUTES_WITHOUT_REASON};
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::is_from_proc_macro;
+use rustc_ast::{MetaItemKind, NestedMetaItem};
+use rustc_lint::{LateContext, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_span::sym;
+use rustc_span::symbol::Symbol;
+
+pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMetaItem], attr: &'cx Attribute) {
+    // Check for the feature
+    if !cx.tcx.features().lint_reasons {
+        return;
+    }
+
+    // Check if the reason is present
+    if let Some(item) = items.last().and_then(NestedMetaItem::meta_item)
+        && let MetaItemKind::NameValue(_) = &item.kind
+        && item.path == sym::reason
+    {
+        return;
+    }
+
+    // Check if the attribute is in an external macro and therefore out of the developer's control
+    if in_external_macro(cx.sess(), attr.span) || is_from_proc_macro(cx, &attr) {
+        return;
+    }
+
+    span_lint_and_help(
+        cx,
+        ALLOW_ATTRIBUTES_WITHOUT_REASON,
+        attr.span,
+        &format!("`{}` attribute without specifying a reason", name.as_str()),
+        None,
+        "try adding a reason at the end with `, reason = \"..\"`",
+    );
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs b/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs
new file mode 100644
index 00000000000..9b08fd6d654
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs
@@ -0,0 +1,44 @@
+use super::utils::extract_clippy_lint;
+use super::BLANKET_CLIPPY_RESTRICTION_LINTS;
+use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
+use rustc_ast::NestedMetaItem;
+use rustc_lint::{LateContext, Level, LintContext};
+use rustc_span::symbol::Symbol;
+use rustc_span::{sym, DUMMY_SP};
+
+pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem]) {
+    for lint in items {
+        if let Some(lint_name) = extract_clippy_lint(lint) {
+            if lint_name.as_str() == "restriction" && name != sym::allow {
+                span_lint_and_help(
+                    cx,
+                    BLANKET_CLIPPY_RESTRICTION_LINTS,
+                    lint.span(),
+                    "`clippy::restriction` is not meant to be enabled as a group",
+                    None,
+                    "enable the restriction lints you need individually",
+                );
+            }
+        }
+    }
+}
+
+pub(super) fn check_command_line(cx: &LateContext<'_>) {
+    for (name, level) in &cx.sess().opts.lint_opts {
+        if name == "clippy::restriction" && *level > Level::Allow {
+            span_lint_and_then(
+                cx,
+                BLANKET_CLIPPY_RESTRICTION_LINTS,
+                DUMMY_SP,
+                "`clippy::restriction` is not meant to be enabled as a group",
+                |diag| {
+                    diag.note(format!(
+                        "because of the command line `--{} clippy::restriction`",
+                        level.as_str()
+                    ));
+                    diag.help("enable the restriction lints you need individually");
+                },
+            );
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs
new file mode 100644
index 00000000000..e872ab6b4b5
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs
@@ -0,0 +1,87 @@
+use super::{unnecessary_clippy_cfg, Attribute, DEPRECATED_CFG_ATTR, DEPRECATED_CLIPPY_CFG_ATTR};
+use clippy_config::msrvs::{self, Msrv};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use rustc_ast::AttrStyle;
+use rustc_errors::Applicability;
+use rustc_lint::EarlyContext;
+use rustc_span::sym;
+
+pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msrv) {
+    // check cfg_attr
+    if attr.has_name(sym::cfg_attr)
+        && let Some(items) = attr.meta_item_list()
+        && items.len() == 2
+        && let Some(feature_item) = items[0].meta_item()
+    {
+        // check for `rustfmt`
+        if feature_item.has_name(sym::rustfmt)
+            && msrv.meets(msrvs::TOOL_ATTRIBUTES)
+            // check for `rustfmt_skip` and `rustfmt::skip`
+            && let Some(skip_item) = &items[1].meta_item()
+            && (skip_item.has_name(sym!(rustfmt_skip))
+                || skip_item
+                    .path
+                    .segments
+                    .last()
+                    .expect("empty path in attribute")
+                    .ident
+                    .name
+                    == sym::skip)
+            // Only lint outer attributes, because custom inner attributes are unstable
+            // Tracking issue: https://github.com/rust-lang/rust/issues/54726
+            && attr.style == AttrStyle::Outer
+        {
+            span_lint_and_sugg(
+                cx,
+                DEPRECATED_CFG_ATTR,
+                attr.span,
+                "`cfg_attr` is deprecated for rustfmt and got replaced by tool attributes",
+                "use",
+                "#[rustfmt::skip]".to_string(),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            check_deprecated_cfg_recursively(cx, feature_item);
+            if let Some(behind_cfg_attr) = items[1].meta_item() {
+                unnecessary_clippy_cfg::check(cx, feature_item, behind_cfg_attr, attr);
+            }
+        }
+    }
+}
+
+pub(super) fn check_clippy(cx: &EarlyContext<'_>, attr: &Attribute) {
+    if attr.has_name(sym::cfg)
+        && let Some(list) = attr.meta_item_list()
+    {
+        for item in list.iter().filter_map(|item| item.meta_item()) {
+            check_deprecated_cfg_recursively(cx, item);
+        }
+    }
+}
+
+fn check_deprecated_cfg_recursively(cx: &EarlyContext<'_>, attr: &rustc_ast::MetaItem) {
+    if let Some(ident) = attr.ident() {
+        if ["any", "all", "not"].contains(&ident.name.as_str()) {
+            let Some(list) = attr.meta_item_list() else { return };
+            for item in list.iter().filter_map(|item| item.meta_item()) {
+                check_deprecated_cfg_recursively(cx, item);
+            }
+        } else {
+            check_cargo_clippy_attr(cx, attr);
+        }
+    }
+}
+
+fn check_cargo_clippy_attr(cx: &EarlyContext<'_>, item: &rustc_ast::MetaItem) {
+    if item.has_name(sym::feature) && item.value_str().is_some_and(|v| v.as_str() == "cargo-clippy") {
+        span_lint_and_sugg(
+            cx,
+            DEPRECATED_CLIPPY_CFG_ATTR,
+            item.span,
+            "`feature = \"cargo-clippy\"` was replaced by `clippy`",
+            "replace with",
+            "clippy".to_string(),
+            Applicability::MachineApplicable,
+        );
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs b/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs
new file mode 100644
index 00000000000..1898c145c76
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs
@@ -0,0 +1,20 @@
+use super::DEPRECATED_SEMVER;
+use clippy_utils::diagnostics::span_lint;
+use rustc_ast::{LitKind, MetaItemLit};
+use rustc_lint::LateContext;
+use rustc_span::Span;
+use semver::Version;
+
+pub(super) fn check(cx: &LateContext<'_>, span: Span, lit: &MetaItemLit) {
+    if let LitKind::Str(is, _) = lit.kind {
+        if is.as_str() == "TBD" || Version::parse(is.as_str()).is_ok() {
+            return;
+        }
+    }
+    span_lint(
+        cx,
+        DEPRECATED_SEMVER,
+        span,
+        "the since field must contain a semver-compliant version",
+    );
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs
new file mode 100644
index 00000000000..ca43e76ac57
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/attrs/empty_line_after.rs
@@ -0,0 +1,52 @@
+use super::{EMPTY_LINE_AFTER_DOC_COMMENTS, EMPTY_LINE_AFTER_OUTER_ATTR};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::source::{is_present_in_source, snippet_opt, without_block_comments};
+use rustc_ast::{AttrKind, AttrStyle};
+use rustc_lint::EarlyContext;
+use rustc_span::Span;
+
+/// Check for empty lines after outer attributes.
+///
+/// Attributes and documentation comments are both considered outer attributes
+/// by the AST. However, the average user likely considers them to be different.
+/// Checking for empty lines after each of these attributes is split into two different
+/// lints but can share the same logic.
+pub(super) fn check(cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
+    let mut iter = item.attrs.iter().peekable();
+    while let Some(attr) = iter.next() {
+        if (matches!(attr.kind, AttrKind::Normal(..)) || matches!(attr.kind, AttrKind::DocComment(..)))
+            && attr.style == AttrStyle::Outer
+            && is_present_in_source(cx, attr.span)
+        {
+            let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt(), item.span.parent());
+            let end_of_attr_to_next_attr_or_item = Span::new(
+                attr.span.hi(),
+                iter.peek().map_or(item.span.lo(), |next_attr| next_attr.span.lo()),
+                item.span.ctxt(),
+                item.span.parent(),
+            );
+
+            if let Some(snippet) = snippet_opt(cx, end_of_attr_to_next_attr_or_item) {
+                let lines = snippet.split('\n').collect::<Vec<_>>();
+                let lines = without_block_comments(lines);
+
+                if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 {
+                    let (lint_msg, lint_type) = match attr.kind {
+                        AttrKind::DocComment(..) => (
+                            "found an empty line after a doc comment. \
+                            Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?",
+                            EMPTY_LINE_AFTER_DOC_COMMENTS,
+                        ),
+                        AttrKind::Normal(..) => (
+                            "found an empty line after an outer attribute. \
+                            Perhaps you forgot to add a `!` to make it an inner attribute?",
+                            EMPTY_LINE_AFTER_OUTER_ATTR,
+                        ),
+                    };
+
+                    span_lint(cx, lint_type, begin_of_attr_to_item, lint_msg);
+                }
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs b/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs
new file mode 100644
index 00000000000..cfcd2cc6a00
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs
@@ -0,0 +1,29 @@
+use super::utils::is_word;
+use super::INLINE_ALWAYS;
+use clippy_utils::diagnostics::span_lint;
+use rustc_ast::Attribute;
+use rustc_lint::LateContext;
+use rustc_span::symbol::Symbol;
+use rustc_span::{sym, Span};
+
+pub(super) fn check(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Attribute]) {
+    if span.from_expansion() {
+        return;
+    }
+
+    for attr in attrs {
+        if let Some(values) = attr.meta_item_list() {
+            if values.len() != 1 || !attr.has_name(sym::inline) {
+                continue;
+            }
+            if is_word(&values[0], sym::always) {
+                span_lint(
+                    cx,
+                    INLINE_ALWAYS,
+                    attr.span,
+                    &format!("you have declared `#[inline(always)]` on `{name}`. This is usually a bad idea"),
+                );
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/maybe_misused_cfg.rs b/src/tools/clippy/clippy_lints/src/attrs/maybe_misused_cfg.rs
new file mode 100644
index 00000000000..5a70866eda5
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/attrs/maybe_misused_cfg.rs
@@ -0,0 +1,51 @@
+use super::{Attribute, MAYBE_MISUSED_CFG};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use rustc_ast::{MetaItemKind, NestedMetaItem};
+use rustc_errors::Applicability;
+use rustc_lint::EarlyContext;
+use rustc_span::sym;
+
+pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
+    if attr.has_name(sym::cfg)
+        && let Some(items) = attr.meta_item_list()
+    {
+        check_nested_misused_cfg(cx, &items);
+    }
+}
+
+fn check_nested_misused_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
+    for item in items {
+        if let NestedMetaItem::MetaItem(meta) = item {
+            if let Some(ident) = meta.ident()
+                && ident.name.as_str() == "features"
+                && let Some(val) = meta.value_str()
+            {
+                span_lint_and_sugg(
+                    cx,
+                    MAYBE_MISUSED_CFG,
+                    meta.span,
+                    "'feature' may be misspelled as 'features'",
+                    "did you mean",
+                    format!("feature = \"{val}\""),
+                    Applicability::MaybeIncorrect,
+                );
+            }
+            if let MetaItemKind::List(list) = &meta.kind {
+                check_nested_misused_cfg(cx, list);
+            // If this is not a list, then we check for `cfg(test)`.
+            } else if let Some(ident) = meta.ident()
+                && matches!(ident.name.as_str(), "tests" | "Test")
+            {
+                span_lint_and_sugg(
+                    cx,
+                    MAYBE_MISUSED_CFG,
+                    meta.span,
+                    &format!("'test' may be misspelled as '{}'", ident.name.as_str()),
+                    "did you mean",
+                    "test".to_string(),
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/mismatched_target_os.rs b/src/tools/clippy/clippy_lints/src/attrs/mismatched_target_os.rs
new file mode 100644
index 00000000000..b1cc0a763c5
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/attrs/mismatched_target_os.rs
@@ -0,0 +1,90 @@
+use super::{Attribute, MISMATCHED_TARGET_OS};
+use clippy_utils::diagnostics::span_lint_and_then;
+use rustc_ast::{MetaItemKind, NestedMetaItem};
+use rustc_errors::Applicability;
+use rustc_lint::EarlyContext;
+use rustc_span::{sym, Span};
+
+static UNIX_SYSTEMS: &[&str] = &[
+    "android",
+    "dragonfly",
+    "emscripten",
+    "freebsd",
+    "fuchsia",
+    "haiku",
+    "illumos",
+    "ios",
+    "l4re",
+    "linux",
+    "macos",
+    "netbsd",
+    "openbsd",
+    "redox",
+    "solaris",
+    "vxworks",
+];
+
+// NOTE: windows is excluded from the list because it's also a valid target family.
+static NON_UNIX_SYSTEMS: &[&str] = &["hermit", "none", "wasi"];
+
+pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
+    fn find_os(name: &str) -> Option<&'static str> {
+        UNIX_SYSTEMS
+            .iter()
+            .chain(NON_UNIX_SYSTEMS.iter())
+            .find(|&&os| os == name)
+            .copied()
+    }
+
+    fn is_unix(name: &str) -> bool {
+        UNIX_SYSTEMS.iter().any(|&os| os == name)
+    }
+
+    fn find_mismatched_target_os(items: &[NestedMetaItem]) -> Vec<(&str, Span)> {
+        let mut mismatched = Vec::new();
+
+        for item in items {
+            if let NestedMetaItem::MetaItem(meta) = item {
+                match &meta.kind {
+                    MetaItemKind::List(list) => {
+                        mismatched.extend(find_mismatched_target_os(list));
+                    },
+                    MetaItemKind::Word => {
+                        if let Some(ident) = meta.ident()
+                            && let Some(os) = find_os(ident.name.as_str())
+                        {
+                            mismatched.push((os, ident.span));
+                        }
+                    },
+                    MetaItemKind::NameValue(..) => {},
+                }
+            }
+        }
+
+        mismatched
+    }
+
+    if attr.has_name(sym::cfg)
+        && let Some(list) = attr.meta_item_list()
+        && let mismatched = find_mismatched_target_os(&list)
+        && !mismatched.is_empty()
+    {
+        let mess = "operating system used in target family position";
+
+        span_lint_and_then(cx, MISMATCHED_TARGET_OS, attr.span, mess, |diag| {
+            // Avoid showing the unix suggestion multiple times in case
+            // we have more than one mismatch for unix-like systems
+            let mut unix_suggested = false;
+
+            for (os, span) in mismatched {
+                let sugg = format!("target_os = \"{os}\"");
+                diag.span_suggestion(span, "try", sugg, Applicability::MaybeIncorrect);
+
+                if !unix_suggested && is_unix(os) {
+                    diag.help("did you mean `unix`?");
+                    unix_suggested = true;
+                }
+            }
+        });
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/mixed_attributes_style.rs b/src/tools/clippy/clippy_lints/src/attrs/mixed_attributes_style.rs
new file mode 100644
index 00000000000..c2e21cfd330
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/attrs/mixed_attributes_style.rs
@@ -0,0 +1,30 @@
+use super::MIXED_ATTRIBUTES_STYLE;
+use clippy_utils::diagnostics::span_lint;
+use rustc_ast::AttrStyle;
+use rustc_lint::EarlyContext;
+
+pub(super) fn check(cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
+    let mut has_outer = false;
+    let mut has_inner = false;
+
+    for attr in &item.attrs {
+        if attr.span.from_expansion() {
+            continue;
+        }
+        match attr.style {
+            AttrStyle::Inner => has_inner = true,
+            AttrStyle::Outer => has_outer = true,
+        }
+    }
+    if !has_outer || !has_inner {
+        return;
+    }
+    let mut attrs_iter = item.attrs.iter().filter(|attr| !attr.span.from_expansion());
+    let span = attrs_iter.next().unwrap().span;
+    span_lint(
+        cx,
+        MIXED_ATTRIBUTES_STYLE,
+        span.with_hi(attrs_iter.last().unwrap().span.hi()),
+        "item has both inner and outer attributes",
+    );
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
new file mode 100644
index 00000000000..c4c65d3248a
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
@@ -0,0 +1,588 @@
+//! checks for attributes
+
+mod allow_attributes_without_reason;
+mod blanket_clippy_restriction_lints;
+mod deprecated_cfg_attr;
+mod deprecated_semver;
+mod empty_line_after;
+mod inline_always;
+mod maybe_misused_cfg;
+mod mismatched_target_os;
+mod mixed_attributes_style;
+mod non_minimal_cfg;
+mod should_panic_without_expect;
+mod unnecessary_clippy_cfg;
+mod useless_attribute;
+mod utils;
+
+use clippy_config::msrvs::Msrv;
+use rustc_ast::{Attribute, MetaItemKind, NestedMetaItem};
+use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
+use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, impl_lint_pass};
+use rustc_span::sym;
+use utils::{is_lint_level, is_relevant_impl, is_relevant_item, is_relevant_trait};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for items annotated with `#[inline(always)]`,
+    /// unless the annotated function is empty or simply panics.
+    ///
+    /// ### Why is this bad?
+    /// While there are valid uses of this annotation (and once
+    /// you know when to use it, by all means `allow` this lint), it's a common
+    /// newbie-mistake to pepper one's code with it.
+    ///
+    /// As a rule of thumb, before slapping `#[inline(always)]` on a function,
+    /// measure if that additional function call really affects your runtime profile
+    /// sufficiently to make up for the increase in compile time.
+    ///
+    /// ### Known problems
+    /// False positives, big time. This lint is meant to be
+    /// deactivated by everyone doing serious performance work. This means having
+    /// done the measurement.
+    ///
+    /// ### Example
+    /// ```ignore
+    /// #[inline(always)]
+    /// fn not_quite_hot_code(..) { ... }
+    /// ```
+    #[clippy::version = "pre 1.29.0"]
+    pub INLINE_ALWAYS,
+    pedantic,
+    "use of `#[inline(always)]`"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `extern crate` and `use` items annotated with
+    /// lint attributes.
+    ///
+    /// This lint permits lint attributes for lints emitted on the items themself.
+    /// For `use` items these lints are:
+    /// * deprecated
+    /// * unreachable_pub
+    /// * unused_imports
+    /// * clippy::enum_glob_use
+    /// * clippy::macro_use_imports
+    /// * clippy::wildcard_imports
+    ///
+    /// For `extern crate` items these lints are:
+    /// * `unused_imports` on items with `#[macro_use]`
+    ///
+    /// ### Why is this bad?
+    /// Lint attributes have no effect on crate imports. Most
+    /// likely a `!` was forgotten.
+    ///
+    /// ### Example
+    /// ```ignore
+    /// #[deny(dead_code)]
+    /// extern crate foo;
+    /// #[forbid(dead_code)]
+    /// use foo::bar;
+    /// ```
+    ///
+    /// Use instead:
+    /// ```rust,ignore
+    /// #[allow(unused_imports)]
+    /// use foo::baz;
+    /// #[allow(unused_imports)]
+    /// #[macro_use]
+    /// extern crate baz;
+    /// ```
+    #[clippy::version = "pre 1.29.0"]
+    pub USELESS_ATTRIBUTE,
+    correctness,
+    "use of lint attributes on `extern crate` items"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `#[deprecated]` annotations with a `since`
+    /// field that is not a valid semantic version. Also allows "TBD" to signal
+    /// future deprecation.
+    ///
+    /// ### Why is this bad?
+    /// For checking the version of the deprecation, it must be
+    /// a valid semver. Failing that, the contained information is useless.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// #[deprecated(since = "forever")]
+    /// fn something_else() { /* ... */ }
+    /// ```
+    #[clippy::version = "pre 1.29.0"]
+    pub DEPRECATED_SEMVER,
+    correctness,
+    "use of `#[deprecated(since = \"x\")]` where x is not semver"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for empty lines after outer attributes
+    ///
+    /// ### Why is this bad?
+    /// Most likely the attribute was meant to be an inner attribute using a '!'.
+    /// If it was meant to be an outer attribute, then the following item
+    /// should not be separated by empty lines.
+    ///
+    /// ### Known problems
+    /// Can cause false positives.
+    ///
+    /// From the clippy side it's difficult to detect empty lines between an attributes and the
+    /// following item because empty lines and comments are not part of the AST. The parsing
+    /// currently works for basic cases but is not perfect.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// #[allow(dead_code)]
+    ///
+    /// fn not_quite_good_code() { }
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// // Good (as inner attribute)
+    /// #![allow(dead_code)]
+    ///
+    /// fn this_is_fine() { }
+    ///
+    /// // or
+    ///
+    /// // Good (as outer attribute)
+    /// #[allow(dead_code)]
+    /// fn this_is_fine_too() { }
+    /// ```
+    #[clippy::version = "pre 1.29.0"]
+    pub EMPTY_LINE_AFTER_OUTER_ATTR,
+    nursery,
+    "empty line after outer attribute"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for empty lines after documentation comments.
+    ///
+    /// ### Why is this bad?
+    /// The documentation comment was most likely meant to be an inner attribute or regular comment.
+    /// If it was intended to be a documentation comment, then the empty line should be removed to
+    /// be more idiomatic.
+    ///
+    /// ### Known problems
+    /// Only detects empty lines immediately following the documentation. If the doc comment is followed
+    /// by an attribute and then an empty line, this lint will not trigger. Use `empty_line_after_outer_attr`
+    /// in combination with this lint to detect both cases.
+    ///
+    /// Does not detect empty lines after doc attributes (e.g. `#[doc = ""]`).
+    ///
+    /// ### Example
+    /// ```no_run
+    /// /// Some doc comment with a blank line after it.
+    ///
+    /// fn not_quite_good_code() { }
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// /// Good (no blank line)
+    /// fn this_is_fine() { }
+    /// ```
+    ///
+    /// ```no_run
+    /// // Good (convert to a regular comment)
+    ///
+    /// fn this_is_fine_too() { }
+    /// ```
+    ///
+    /// ```no_run
+    /// //! Good (convert to a comment on an inner attribute)
+    ///
+    /// fn this_is_fine_as_well() { }
+    /// ```
+    #[clippy::version = "1.70.0"]
+    pub EMPTY_LINE_AFTER_DOC_COMMENTS,
+    nursery,
+    "empty line after documentation comments"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category.
+    ///
+    /// ### Why is this bad?
+    /// Restriction lints sometimes are in contrast with other lints or even go against idiomatic rust.
+    /// These lints should only be enabled on a lint-by-lint basis and with careful consideration.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// #![deny(clippy::restriction)]
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// #![deny(clippy::as_conversions)]
+    /// ```
+    #[clippy::version = "1.47.0"]
+    pub BLANKET_CLIPPY_RESTRICTION_LINTS,
+    suspicious,
+    "enabling the complete restriction group"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `#[cfg_attr(rustfmt, rustfmt_skip)]` and suggests to replace it
+    /// with `#[rustfmt::skip]`.
+    ///
+    /// ### Why is this bad?
+    /// Since tool_attributes ([rust-lang/rust#44690](https://github.com/rust-lang/rust/issues/44690))
+    /// are stable now, they should be used instead of the old `cfg_attr(rustfmt)` attributes.
+    ///
+    /// ### Known problems
+    /// This lint doesn't detect crate level inner attributes, because they get
+    /// processed before the PreExpansionPass lints get executed. See
+    /// [#3123](https://github.com/rust-lang/rust-clippy/pull/3123#issuecomment-422321765)
+    ///
+    /// ### Example
+    /// ```no_run
+    /// #[cfg_attr(rustfmt, rustfmt_skip)]
+    /// fn main() { }
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// #[rustfmt::skip]
+    /// fn main() { }
+    /// ```
+    #[clippy::version = "1.32.0"]
+    pub DEPRECATED_CFG_ATTR,
+    complexity,
+    "usage of `cfg_attr(rustfmt)` instead of tool attributes"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for cfg attributes having operating systems used in target family position.
+    ///
+    /// ### Why is this bad?
+    /// The configuration option will not be recognised and the related item will not be included
+    /// by the conditional compilation engine.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// #[cfg(linux)]
+    /// fn conditional() { }
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// # mod hidden {
+    /// #[cfg(target_os = "linux")]
+    /// fn conditional() { }
+    /// # }
+    ///
+    /// // or
+    ///
+    /// #[cfg(unix)]
+    /// fn conditional() { }
+    /// ```
+    /// Check the [Rust Reference](https://doc.rust-lang.org/reference/conditional-compilation.html#target_os) for more details.
+    #[clippy::version = "1.45.0"]
+    pub MISMATCHED_TARGET_OS,
+    correctness,
+    "usage of `cfg(operating_system)` instead of `cfg(target_os = \"operating_system\")`"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for attributes that allow lints without a reason.
+    ///
+    /// (This requires the `lint_reasons` feature)
+    ///
+    /// ### Why is this bad?
+    /// Allowing a lint should always have a reason. This reason should be documented to
+    /// ensure that others understand the reasoning
+    ///
+    /// ### Example
+    /// ```no_run
+    /// #![feature(lint_reasons)]
+    ///
+    /// #![allow(clippy::some_lint)]
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// #![feature(lint_reasons)]
+    ///
+    /// #![allow(clippy::some_lint, reason = "False positive rust-lang/rust-clippy#1002020")]
+    /// ```
+    #[clippy::version = "1.61.0"]
+    pub ALLOW_ATTRIBUTES_WITHOUT_REASON,
+    restriction,
+    "ensures that all `allow` and `expect` attributes have a reason"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `#[should_panic]` attributes without specifying the expected panic message.
+    ///
+    /// ### Why is this bad?
+    /// The expected panic message should be specified to ensure that the test is actually
+    /// panicking with the expected message, and not another unrelated panic.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// fn random() -> i32 { 0 }
+    ///
+    /// #[should_panic]
+    /// #[test]
+    /// fn my_test() {
+    ///     let _ = 1 / random();
+    /// }
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// fn random() -> i32 { 0 }
+    ///
+    /// #[should_panic = "attempt to divide by zero"]
+    /// #[test]
+    /// fn my_test() {
+    ///     let _ = 1 / random();
+    /// }
+    /// ```
+    #[clippy::version = "1.74.0"]
+    pub SHOULD_PANIC_WITHOUT_EXPECT,
+    pedantic,
+    "ensures that all `should_panic` attributes specify its expected panic message"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `any` and `all` combinators in `cfg` with only one condition.
+    ///
+    /// ### Why is this bad?
+    /// If there is only one condition, no need to wrap it into `any` or `all` combinators.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// #[cfg(any(unix))]
+    /// pub struct Bar;
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// #[cfg(unix)]
+    /// pub struct Bar;
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub NON_MINIMAL_CFG,
+    style,
+    "ensure that all `cfg(any())` and `cfg(all())` have more than one condition"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `#[cfg(features = "...")]` and suggests to replace it with
+    /// `#[cfg(feature = "...")]`.
+    ///
+    /// It also checks if `cfg(test)` was misspelled.
+    ///
+    /// ### Why is this bad?
+    /// Misspelling `feature` as `features` or `test` as `tests` can be sometimes hard to spot. It
+    /// may cause conditional compilation not work quietly.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// #[cfg(features = "some-feature")]
+    /// fn conditional() { }
+    /// #[cfg(tests)]
+    /// mod tests { }
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// #[cfg(feature = "some-feature")]
+    /// fn conditional() { }
+    /// #[cfg(test)]
+    /// mod tests { }
+    /// ```
+    #[clippy::version = "1.69.0"]
+    pub MAYBE_MISUSED_CFG,
+    suspicious,
+    "prevent from misusing the wrong attr name"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `#[cfg_attr(feature = "cargo-clippy", ...)]` and for
+    /// `#[cfg(feature = "cargo-clippy")]` and suggests to replace it with
+    /// `#[cfg_attr(clippy, ...)]` or `#[cfg(clippy)]`.
+    ///
+    /// ### Why is this bad?
+    /// This feature has been deprecated for years and shouldn't be used anymore.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// #[cfg(feature = "cargo-clippy")]
+    /// struct Bar;
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// #[cfg(clippy)]
+    /// struct Bar;
+    /// ```
+    #[clippy::version = "1.78.0"]
+    pub DEPRECATED_CLIPPY_CFG_ATTR,
+    suspicious,
+    "usage of `cfg(feature = \"cargo-clippy\")` instead of `cfg(clippy)`"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `#[cfg_attr(clippy, allow(clippy::lint))]`
+    /// and suggests to replace it with `#[allow(clippy::lint)]`.
+    ///
+    /// ### Why is this bad?
+    /// There is no reason to put clippy attributes behind a clippy `cfg` as they are not
+    /// run by anything else than clippy.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// #![cfg_attr(clippy, allow(clippy::deprecated_cfg_attr))]
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// #![allow(clippy::deprecated_cfg_attr)]
+    /// ```
+    #[clippy::version = "1.78.0"]
+    pub UNNECESSARY_CLIPPY_CFG,
+    suspicious,
+    "usage of `cfg_attr(clippy, allow(clippy::lint))` instead of `allow(clippy::lint)`"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks that an item has only one kind of attributes.
+    ///
+    /// ### Why is this bad?
+    /// Having both kinds of attributes makes it more complicated to read code.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// #[cfg(linux)]
+    /// pub fn foo() {
+    ///     #![cfg(windows)]
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// #[cfg(linux)]
+    /// #[cfg(windows)]
+    /// pub fn foo() {
+    /// }
+    /// ```
+    #[clippy::version = "1.78.0"]
+    pub MIXED_ATTRIBUTES_STYLE,
+    suspicious,
+    "item has both inner and outer attributes"
+}
+
+declare_lint_pass!(Attributes => [
+    ALLOW_ATTRIBUTES_WITHOUT_REASON,
+    INLINE_ALWAYS,
+    DEPRECATED_SEMVER,
+    USELESS_ATTRIBUTE,
+    BLANKET_CLIPPY_RESTRICTION_LINTS,
+    SHOULD_PANIC_WITHOUT_EXPECT,
+]);
+
+impl<'tcx> LateLintPass<'tcx> for Attributes {
+    fn check_crate(&mut self, cx: &LateContext<'tcx>) {
+        blanket_clippy_restriction_lints::check_command_line(cx);
+    }
+
+    fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) {
+        if let Some(items) = &attr.meta_item_list() {
+            if let Some(ident) = attr.ident() {
+                if is_lint_level(ident.name, attr.id) {
+                    blanket_clippy_restriction_lints::check(cx, ident.name, items);
+                }
+                if matches!(ident.name, sym::allow | sym::expect) {
+                    allow_attributes_without_reason::check(cx, ident.name, items, attr);
+                }
+                if items.is_empty() || !attr.has_name(sym::deprecated) {
+                    return;
+                }
+                for item in items {
+                    if let NestedMetaItem::MetaItem(mi) = &item
+                        && let MetaItemKind::NameValue(lit) = &mi.kind
+                        && mi.has_name(sym::since)
+                    {
+                        deprecated_semver::check(cx, item.span(), lit);
+                    }
+                }
+            }
+        }
+        if attr.has_name(sym::should_panic) {
+            should_panic_without_expect::check(cx, attr);
+        }
+    }
+
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
+        let attrs = cx.tcx.hir().attrs(item.hir_id());
+        if is_relevant_item(cx, item) {
+            inline_always::check(cx, item.span, item.ident.name, attrs);
+        }
+        match item.kind {
+            ItemKind::ExternCrate(..) | ItemKind::Use(..) => useless_attribute::check(cx, item, attrs),
+            _ => {},
+        }
+    }
+
+    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
+        if is_relevant_impl(cx, item) {
+            inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()));
+        }
+    }
+
+    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
+        if is_relevant_trait(cx, item) {
+            inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()));
+        }
+    }
+}
+
+pub struct EarlyAttributes {
+    pub msrv: Msrv,
+}
+
+impl_lint_pass!(EarlyAttributes => [
+    DEPRECATED_CFG_ATTR,
+    MISMATCHED_TARGET_OS,
+    EMPTY_LINE_AFTER_OUTER_ATTR,
+    EMPTY_LINE_AFTER_DOC_COMMENTS,
+    NON_MINIMAL_CFG,
+    MAYBE_MISUSED_CFG,
+    DEPRECATED_CLIPPY_CFG_ATTR,
+    UNNECESSARY_CLIPPY_CFG,
+    MIXED_ATTRIBUTES_STYLE,
+]);
+
+impl EarlyLintPass for EarlyAttributes {
+    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
+        empty_line_after::check(cx, item);
+        mixed_attributes_style::check(cx, item);
+    }
+
+    fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
+        deprecated_cfg_attr::check(cx, attr, &self.msrv);
+        deprecated_cfg_attr::check_clippy(cx, attr);
+        mismatched_target_os::check(cx, attr);
+        non_minimal_cfg::check(cx, attr);
+        maybe_misused_cfg::check(cx, attr);
+    }
+
+    extract_msrv_attr!(EarlyContext);
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs b/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs
new file mode 100644
index 00000000000..3fde7061585
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs
@@ -0,0 +1,49 @@
+use super::{Attribute, NON_MINIMAL_CFG};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet_opt;
+use rustc_ast::{MetaItemKind, NestedMetaItem};
+use rustc_errors::Applicability;
+use rustc_lint::EarlyContext;
+use rustc_span::sym;
+
+pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
+    if attr.has_name(sym::cfg)
+        && let Some(items) = attr.meta_item_list()
+    {
+        check_nested_cfg(cx, &items);
+    }
+}
+
+fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
+    for item in items {
+        if let NestedMetaItem::MetaItem(meta) = item {
+            if !meta.has_name(sym::any) && !meta.has_name(sym::all) {
+                continue;
+            }
+            if let MetaItemKind::List(list) = &meta.kind {
+                check_nested_cfg(cx, list);
+                if list.len() == 1 {
+                    span_lint_and_then(
+                        cx,
+                        NON_MINIMAL_CFG,
+                        meta.span,
+                        "unneeded sub `cfg` when there is only one condition",
+                        |diag| {
+                            if let Some(snippet) = snippet_opt(cx, list[0].span()) {
+                                diag.span_suggestion(meta.span, "try", snippet, Applicability::MaybeIncorrect);
+                            }
+                        },
+                    );
+                } else if list.is_empty() && meta.has_name(sym::all) {
+                    span_lint_and_then(
+                        cx,
+                        NON_MINIMAL_CFG,
+                        meta.span,
+                        "unneeded sub `cfg` when there is no condition",
+                        |_| {},
+                    );
+                }
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs
new file mode 100644
index 00000000000..2d45cbbf621
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs
@@ -0,0 +1,54 @@
+use super::{Attribute, SHOULD_PANIC_WITHOUT_EXPECT};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use rustc_ast::token::{Token, TokenKind};
+use rustc_ast::tokenstream::TokenTree;
+use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind};
+use rustc_errors::Applicability;
+use rustc_lint::LateContext;
+use rustc_span::sym;
+
+pub(super) fn check(cx: &LateContext<'_>, attr: &Attribute) {
+    if let AttrKind::Normal(normal_attr) = &attr.kind {
+        if let AttrArgs::Eq(_, AttrArgsEq::Hir(_)) = &normal_attr.item.args {
+            // `#[should_panic = ".."]` found, good
+            return;
+        }
+
+        if let AttrArgs::Delimited(args) = &normal_attr.item.args
+            && let mut tt_iter = args.tokens.trees()
+            && let Some(TokenTree::Token(
+                Token {
+                    kind: TokenKind::Ident(sym::expected, _),
+                    ..
+                },
+                _,
+            )) = tt_iter.next()
+            && let Some(TokenTree::Token(
+                Token {
+                    kind: TokenKind::Eq, ..
+                },
+                _,
+            )) = tt_iter.next()
+            && let Some(TokenTree::Token(
+                Token {
+                    kind: TokenKind::Literal(_),
+                    ..
+                },
+                _,
+            )) = tt_iter.next()
+        {
+            // `#[should_panic(expected = "..")]` found, good
+            return;
+        }
+
+        span_lint_and_sugg(
+            cx,
+            SHOULD_PANIC_WITHOUT_EXPECT,
+            attr.span,
+            "#[should_panic] attribute without a reason",
+            "consider specifying the expected panic",
+            "#[should_panic(expected = /* panic message */)]".into(),
+            Applicability::HasPlaceholders,
+        );
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs b/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs
new file mode 100644
index 00000000000..05da69636c6
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/attrs/unnecessary_clippy_cfg.rs
@@ -0,0 +1,70 @@
+use super::{Attribute, UNNECESSARY_CLIPPY_CFG};
+use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
+use clippy_utils::source::snippet_opt;
+use rustc_ast::AttrStyle;
+use rustc_errors::Applicability;
+use rustc_lint::{EarlyContext, Level};
+use rustc_span::sym;
+
+pub(super) fn check(
+    cx: &EarlyContext<'_>,
+    cfg_attr: &rustc_ast::MetaItem,
+    behind_cfg_attr: &rustc_ast::MetaItem,
+    attr: &Attribute,
+) {
+    if cfg_attr.has_name(sym::clippy)
+        && let Some(ident) = behind_cfg_attr.ident()
+        && Level::from_symbol(ident.name, Some(attr.id)).is_some()
+        && let Some(items) = behind_cfg_attr.meta_item_list()
+    {
+        let nb_items = items.len();
+        let mut clippy_lints = Vec::with_capacity(items.len());
+        for item in items {
+            if let Some(meta_item) = item.meta_item()
+                && let [part1, _] = meta_item.path.segments.as_slice()
+                && part1.ident.name == sym::clippy
+            {
+                clippy_lints.push(item.span());
+            }
+        }
+        if clippy_lints.is_empty() {
+            return;
+        }
+        if nb_items == clippy_lints.len() {
+            if let Some(snippet) = snippet_opt(cx, behind_cfg_attr.span) {
+                span_lint_and_sugg(
+                    cx,
+                    UNNECESSARY_CLIPPY_CFG,
+                    attr.span,
+                    "no need to put clippy lints behind a `clippy` cfg",
+                    "replace with",
+                    format!(
+                        "#{}[{}]",
+                        if attr.style == AttrStyle::Inner { "!" } else { "" },
+                        snippet
+                    ),
+                    Applicability::MachineApplicable,
+                );
+            }
+        } else {
+            let snippet = clippy_lints
+                .iter()
+                .filter_map(|sp| snippet_opt(cx, *sp))
+                .collect::<Vec<_>>()
+                .join(",");
+            span_lint_and_note(
+                cx,
+                UNNECESSARY_CLIPPY_CFG,
+                clippy_lints,
+                "no need to put clippy lints behind a `clippy` cfg",
+                None,
+                &format!(
+                    "write instead: `#{}[{}({})]`",
+                    if attr.style == AttrStyle::Inner { "!" } else { "" },
+                    ident.name,
+                    snippet
+                ),
+            );
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
new file mode 100644
index 00000000000..7575f502a7c
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
@@ -0,0 +1,73 @@
+use super::utils::{extract_clippy_lint, is_lint_level, is_word};
+use super::{Attribute, USELESS_ATTRIBUTE};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::{first_line_of_span, snippet_opt};
+use rustc_errors::Applicability;
+use rustc_hir::{Item, ItemKind};
+use rustc_lint::{LateContext, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_span::sym;
+
+pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute]) {
+    let skip_unused_imports = attrs.iter().any(|attr| attr.has_name(sym::macro_use));
+
+    for attr in attrs {
+        if in_external_macro(cx.sess(), attr.span) {
+            return;
+        }
+        if let Some(lint_list) = &attr.meta_item_list() {
+            if attr.ident().map_or(false, |ident| is_lint_level(ident.name, attr.id)) {
+                for lint in lint_list {
+                    match item.kind {
+                        ItemKind::Use(..) => {
+                            if is_word(lint, sym::unused_imports)
+                                || is_word(lint, sym::deprecated)
+                                || is_word(lint, sym!(unreachable_pub))
+                                || is_word(lint, sym!(unused))
+                                || is_word(lint, sym!(unused_import_braces))
+                                || extract_clippy_lint(lint).map_or(false, |s| {
+                                    matches!(
+                                        s.as_str(),
+                                        "wildcard_imports"
+                                            | "enum_glob_use"
+                                            | "redundant_pub_crate"
+                                            | "macro_use_imports"
+                                            | "unsafe_removed_from_name"
+                                            | "module_name_repetitions"
+                                            | "single_component_path_imports"
+                                    )
+                                })
+                            {
+                                return;
+                            }
+                        },
+                        ItemKind::ExternCrate(..) => {
+                            if is_word(lint, sym::unused_imports) && skip_unused_imports {
+                                return;
+                            }
+                            if is_word(lint, sym!(unused_extern_crates)) {
+                                return;
+                            }
+                        },
+                        _ => {},
+                    }
+                }
+                let line_span = first_line_of_span(cx, attr.span);
+
+                if let Some(mut sugg) = snippet_opt(cx, line_span) {
+                    if sugg.contains("#[") {
+                        span_lint_and_then(cx, USELESS_ATTRIBUTE, line_span, "useless lint attribute", |diag| {
+                            sugg = sugg.replacen("#[", "#![", 1);
+                            diag.span_suggestion(
+                                line_span,
+                                "if you just forgot a `!`, use",
+                                sugg,
+                                Applicability::MaybeIncorrect,
+                            );
+                        });
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/utils.rs b/src/tools/clippy/clippy_lints/src/attrs/utils.rs
new file mode 100644
index 00000000000..9b36cc00444
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/attrs/utils.rs
@@ -0,0 +1,87 @@
+use clippy_utils::macros::{is_panic, macro_backtrace};
+use rustc_ast::{AttrId, NestedMetaItem};
+use rustc_hir::{
+    Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind,
+};
+use rustc_lint::{LateContext, Level};
+use rustc_middle::ty;
+use rustc_span::sym;
+use rustc_span::symbol::Symbol;
+
+pub(super) fn is_word(nmi: &NestedMetaItem, expected: Symbol) -> bool {
+    if let NestedMetaItem::MetaItem(mi) = &nmi {
+        mi.is_word() && mi.has_name(expected)
+    } else {
+        false
+    }
+}
+
+pub(super) fn is_lint_level(symbol: Symbol, attr_id: AttrId) -> bool {
+    Level::from_symbol(symbol, Some(attr_id)).is_some()
+}
+
+pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
+    if let ItemKind::Fn(_, _, eid) = item.kind {
+        is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value)
+    } else {
+        true
+    }
+}
+
+pub(super) fn is_relevant_impl(cx: &LateContext<'_>, item: &ImplItem<'_>) -> bool {
+    match item.kind {
+        ImplItemKind::Fn(_, eid) => is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value),
+        _ => false,
+    }
+}
+
+pub(super) fn is_relevant_trait(cx: &LateContext<'_>, item: &TraitItem<'_>) -> bool {
+    match item.kind {
+        TraitItemKind::Fn(_, TraitFn::Required(_)) => true,
+        TraitItemKind::Fn(_, TraitFn::Provided(eid)) => {
+            is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir().body(eid).value)
+        },
+        _ => false,
+    }
+}
+
+fn is_relevant_block(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_>, block: &Block<'_>) -> bool {
+    block.stmts.first().map_or(
+        block
+            .expr
+            .as_ref()
+            .map_or(false, |e| is_relevant_expr(cx, typeck_results, e)),
+        |stmt| match &stmt.kind {
+            StmtKind::Local(_) => true,
+            StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, typeck_results, expr),
+            StmtKind::Item(_) => false,
+        },
+    )
+}
+
+fn is_relevant_expr(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_>, expr: &Expr<'_>) -> bool {
+    if macro_backtrace(expr.span).last().map_or(false, |macro_call| {
+        is_panic(cx, macro_call.def_id) || cx.tcx.item_name(macro_call.def_id) == sym::unreachable
+    }) {
+        return false;
+    }
+    match &expr.kind {
+        ExprKind::Block(block, _) => is_relevant_block(cx, typeck_results, block),
+        ExprKind::Ret(Some(e)) => is_relevant_expr(cx, typeck_results, e),
+        ExprKind::Ret(None) | ExprKind::Break(_, None) => false,
+        _ => true,
+    }
+}
+
+/// Returns the lint name if it is clippy lint.
+pub(super) fn extract_clippy_lint(lint: &NestedMetaItem) -> Option<Symbol> {
+    if let Some(meta_item) = lint.meta_item()
+        && meta_item.path.segments.len() > 1
+        && let tool_name = meta_item.path.segments[0].ident
+        && tool_name.name == sym::clippy
+    {
+        let lint_name = meta_item.path.segments.last().unwrap().ident.name;
+        return Some(lint_name);
+    }
+    None
+}
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index 0d66f2d644d..a474356608f 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -88,7 +88,6 @@ impl<'tcx> LateLintPass<'tcx> for NonminimalBool {
 
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
         match expr.kind {
-            ExprKind::Unary(UnOp::Not, sub) => check_inverted_condition(cx, expr.span, sub),
             // This check the case where an element in a boolean comparison is inverted, like:
             //
             // ```
@@ -119,27 +118,6 @@ fn bin_op_eq_str(op: BinOpKind) -> Option<&'static str> {
     }
 }
 
-fn check_inverted_condition(cx: &LateContext<'_>, expr_span: Span, sub_expr: &Expr<'_>) {
-    if !expr_span.from_expansion()
-        && let ExprKind::Binary(op, left, right) = sub_expr.kind
-        && let Some(left) = snippet_opt(cx, left.span)
-        && let Some(right) = snippet_opt(cx, right.span)
-    {
-        let Some(op) = inverted_bin_op_eq_str(op.node) else {
-            return;
-        };
-        span_lint_and_sugg(
-            cx,
-            NONMINIMAL_BOOL,
-            expr_span,
-            "this boolean expression can be simplified",
-            "try",
-            format!("{left} {op} {right}",),
-            Applicability::MachineApplicable,
-        );
-    }
-}
-
 fn check_inverted_bool_in_condition(
     cx: &LateContext<'_>,
     expr_span: Span,
@@ -148,8 +126,8 @@ fn check_inverted_bool_in_condition(
     right: &Expr<'_>,
 ) {
     if expr_span.from_expansion()
-        && (!cx.typeck_results().node_types()[left.hir_id].is_bool()
-            || !cx.typeck_results().node_types()[right.hir_id].is_bool())
+        || !cx.typeck_results().node_types()[left.hir_id].is_bool()
+        || !cx.typeck_results().node_types()[right.hir_id].is_bool()
     {
         return;
     }
diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
index cc513d46bf4..08341ff32f3 100644
--- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
@@ -151,13 +151,24 @@ pub(super) fn check<'tcx>(
             return false;
         }
 
+        // If the whole cast expression is a unary expression (`(*x as T)`) or an addressof
+        // expression (`(&x as T)`), then not surrounding the suggestion into a block risks us
+        // changing the precedence of operators if the cast expression is followed by an operation
+        // with higher precedence than the unary operator (`(*x as T).foo()` would become
+        // `*x.foo()`, which changes what the `*` applies on).
+        // The same is true if the expression encompassing the cast expression is a unary
+        // expression or an addressof expression.
+        let needs_block = matches!(cast_expr.kind, ExprKind::Unary(..) | ExprKind::AddrOf(..))
+            || get_parent_expr(cx, expr)
+                .map_or(false, |e| matches!(e.kind, ExprKind::Unary(..) | ExprKind::AddrOf(..)));
+
         span_lint_and_sugg(
             cx,
             UNNECESSARY_CAST,
             expr.span,
             &format!("casting to the same type is unnecessary (`{cast_from}` -> `{cast_to}`)"),
             "try",
-            if get_parent_expr(cx, expr).map_or(false, |e| matches!(e.kind, ExprKind::AddrOf(..))) {
+            if needs_block {
                 format!("{{ {cast_str} }}")
             } else {
                 cast_str
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index fb3ae2457e3..2b324f5f96e 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -47,6 +47,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX_INFO,
     crate::assertions_on_constants::ASSERTIONS_ON_CONSTANTS_INFO,
     crate::assertions_on_result_states::ASSERTIONS_ON_RESULT_STATES_INFO,
+    crate::assigning_clones::ASSIGNING_CLONES_INFO,
     crate::async_yields_async::ASYNC_YIELDS_ASYNC_INFO,
     crate::attrs::ALLOW_ATTRIBUTES_WITHOUT_REASON_INFO,
     crate::attrs::BLANKET_CLIPPY_RESTRICTION_LINTS_INFO,
@@ -58,6 +59,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::attrs::INLINE_ALWAYS_INFO,
     crate::attrs::MAYBE_MISUSED_CFG_INFO,
     crate::attrs::MISMATCHED_TARGET_OS_INFO,
+    crate::attrs::MIXED_ATTRIBUTES_STYLE_INFO,
     crate::attrs::NON_MINIMAL_CFG_INFO,
     crate::attrs::SHOULD_PANIC_WITHOUT_EXPECT_INFO,
     crate::attrs::UNNECESSARY_CLIPPY_CFG_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 6144ec7b3ca..f0f2c7d6658 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -451,8 +451,8 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r
         && let Some(def_id) = trait_ref.trait_def_id()
         && cx.tcx.is_diagnostic_item(sym::PartialEq, def_id)
         && !has_non_exhaustive_attr(cx.tcx, *adt)
+        && !ty_implements_eq_trait(cx.tcx, ty, eq_trait_def_id)
         && let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id)
-        && !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[])
         // If all of our fields implement `Eq`, we can implement `Eq` too
         && adt
             .all_fields()
@@ -471,6 +471,10 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r
     }
 }
 
+fn ty_implements_eq_trait<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, eq_trait_id: DefId) -> bool {
+    tcx.non_blanket_impls_for_ty(eq_trait_id, ty).next().is_some()
+}
+
 /// Creates the `ParamEnv` used for the give type's derived `Eq` impl.
 fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> ParamEnv<'_> {
     // Initial map from generic index to param def.
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs
index d5205e65cef..0c1bb2da7e8 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs
@@ -72,7 +72,7 @@ impl EarlyLintPass for DisallowedScriptIdents {
             return;
         }
 
-        let symbols = cx.sess().parse_sess.symbol_gallery.symbols.lock();
+        let symbols = cx.sess().psess.symbol_gallery.symbols.lock();
         // Sort by `Span` so that error messages make sense with respect to the
         // order of identifier locations in the code.
         let mut symbols: Vec<_> = symbols.iter().collect();
diff --git a/src/tools/clippy/clippy_lints/src/doc/markdown.rs b/src/tools/clippy/clippy_lints/src/doc/markdown.rs
index a58219c2946..d2f14756591 100644
--- a/src/tools/clippy/clippy_lints/src/doc/markdown.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/markdown.rs
@@ -8,7 +8,7 @@ use url::Url;
 
 use crate::doc::DOC_MARKDOWN;
 
-pub fn check(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str, span: Span) {
+pub fn check(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str, span: Span, code_level: isize) {
     for orig_word in text.split(|c: char| c.is_whitespace() || c == '\'') {
         // Trim punctuation as in `some comment (see foo::bar).`
         //                                                   ^^
@@ -46,11 +46,11 @@ pub fn check(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str,
             span.parent(),
         );
 
-        check_word(cx, word, span);
+        check_word(cx, word, span, code_level);
     }
 }
 
-fn check_word(cx: &LateContext<'_>, word: &str, span: Span) {
+fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize) {
     /// Checks if a string is upper-camel-case, i.e., starts with an uppercase and
     /// contains at least two uppercase letters (`Clippy` is ok) and one lower-case
     /// letter (`NASA` is ok).
@@ -60,7 +60,14 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span) {
             return false;
         }
 
-        let s = s.strip_suffix('s').unwrap_or(s);
+        let s = if let Some(prefix) = s.strip_suffix("es")
+            && prefix.chars().all(|c| c.is_ascii_uppercase())
+            && matches!(prefix.chars().last(), Some('S' | 'X'))
+        {
+            prefix
+        } else {
+            s.strip_suffix('s').unwrap_or(s)
+        };
 
         s.chars().all(char::is_alphanumeric)
             && s.chars().filter(|&c| c.is_uppercase()).take(2).count() > 1
@@ -90,7 +97,7 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span) {
     }
 
     // We assume that mixed-case words are not meant to be put inside backticks. (Issue #2343)
-    if has_underscore(word) && has_hyphen(word) {
+    if code_level > 0 || (has_underscore(word) && has_hyphen(word)) {
         return;
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs
index 9af34c3a7bf..003d26b7b89 100644
--- a/src/tools/clippy/clippy_lints/src/doc/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs
@@ -599,10 +599,19 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
     let mut ignore = false;
     let mut edition = None;
     let mut ticks_unbalanced = false;
-    let mut text_to_check: Vec<(CowStr<'_>, Range<usize>)> = Vec::new();
+    let mut text_to_check: Vec<(CowStr<'_>, Range<usize>, isize)> = Vec::new();
     let mut paragraph_range = 0..0;
+    let mut code_level = 0;
+
     for (event, range) in events {
         match event {
+            Html(tag) => {
+                if tag.starts_with("<code") {
+                    code_level += 1;
+                } else if tag.starts_with("</code") {
+                    code_level -= 1;
+                }
+            },
             Start(CodeBlock(ref kind)) => {
                 in_code = true;
                 if let CodeBlockKind::Fenced(lang) = kind {
@@ -652,16 +661,15 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                         "a backtick may be missing a pair",
                     );
                 } else {
-                    for (text, range) in text_to_check {
+                    for (text, range, assoc_code_level) in text_to_check {
                         if let Some(span) = fragments.span(cx, range) {
-                            markdown::check(cx, valid_idents, &text, span);
+                            markdown::check(cx, valid_idents, &text, span, assoc_code_level);
                         }
                     }
                 }
                 text_to_check = Vec::new();
             },
             Start(_tag) | End(_tag) => (), // We don't care about other tags
-            Html(_html) => (),             // HTML is weird, just ignore it
             SoftBreak | HardBreak | TaskListMarker(_) | Code(_) | Rule => (),
             FootnoteReference(text) | Text(text) => {
                 paragraph_range.end = range.end;
@@ -694,7 +702,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                         // Don't check the text associated with external URLs
                         continue;
                     }
-                    text_to_check.push((text, range));
+                    text_to_check.push((text, range, code_level));
                 }
             },
         }
diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
index fdb9ceb7179..e55a988321b 100644
--- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
@@ -48,9 +48,9 @@ pub fn check(
                 let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings();
                 #[expect(clippy::arc_with_non_send_sync)] // `Lrc` is expected by with_dcx
                 let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
-                let sess = ParseSess::with_dcx(dcx, sm);
+                let psess = ParseSess::with_dcx(dcx, sm);
 
-                let mut parser = match maybe_new_parser_from_source_str(&sess, filename, code) {
+                let mut parser = match maybe_new_parser_from_source_str(&psess, filename, code) {
                     Ok(p) => p,
                     Err(errs) => {
                         errs.into_iter().for_each(Diag::cancel);
diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index 0b4bc375df0..de6073c2723 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -214,12 +214,31 @@ impl MapType {
     }
 }
 
+/// Details on an expression checking whether a map contains a key.
+///
+/// For instance, with the following:
+/// ```ignore
+/// !!!self.the_map.contains_key("the_key")
+/// ```
+///
+/// - `negated` will be set to `true` (the 3 `!` negate the condition)
+/// - `map` will be the `self.the_map` expression
+/// - `key` will be the `"the_key"` expression
 struct ContainsExpr<'tcx> {
+    /// Whether the check for `contains_key` was negated.
     negated: bool,
+    /// The map on which the check is performed.
     map: &'tcx Expr<'tcx>,
+    /// The key that is checked to be contained.
     key: &'tcx Expr<'tcx>,
+    /// The context of the whole condition expression.
     call_ctxt: SyntaxContext,
 }
+
+/// Inspect the given expression and return details about the `contains_key` check.
+///
+/// If the given expression is not a `contains_key` check against a `BTreeMap` or a `HashMap`,
+/// return `None`.
 fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Option<(MapType, ContainsExpr<'tcx>)> {
     let mut negated = false;
     let expr = peel_hir_expr_while(expr, |e| match e.kind {
@@ -229,6 +248,7 @@ fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Optio
         },
         _ => None,
     });
+
     match expr.kind {
         ExprKind::MethodCall(
             _,
@@ -261,11 +281,28 @@ fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Optio
     }
 }
 
+/// Details on an expression inserting a key into a map.
+///
+/// For instance, on the following:
+/// ```ignore
+/// self.the_map.insert("the_key", 3 + 4);
+/// ```
+///
+/// - `map` will be the `self.the_map` expression
+/// - `key` will be the `"the_key"` expression
+/// - `value` will be the `3 + 4` expression
 struct InsertExpr<'tcx> {
+    /// The map into which the insertion is performed.
     map: &'tcx Expr<'tcx>,
+    /// The key at which to insert.
     key: &'tcx Expr<'tcx>,
+    /// The value to insert.
     value: &'tcx Expr<'tcx>,
 }
+
+/// Inspect the given expression and return details about the `insert` call.
+///
+/// If the given expression is not an `insert` call into a `BTreeMap` or a `HashMap`, return `None`.
 fn try_parse_insert<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<InsertExpr<'tcx>> {
     if let ExprKind::MethodCall(_, map, [key, value], _) = expr.kind {
         let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?;
@@ -298,7 +335,7 @@ struct Insertion<'tcx> {
     value: &'tcx Expr<'tcx>,
 }
 
-/// This visitor needs to do a multiple things:
+/// This visitor needs to do multiple things:
 /// * Find all usages of the map. An insertion can only be made before any other usages of the map.
 /// * Determine if there's an insertion using the same key. There's no need for the entry api
 ///   otherwise.
@@ -346,7 +383,7 @@ impl<'tcx> InsertSearcher<'_, 'tcx> {
         res
     }
 
-    /// Visits an expression which is not itself in a tail position, but other sibling expressions
+    /// Visit an expression which is not itself in a tail position, but other sibling expressions
     /// may be. e.g. if conditions
     fn visit_non_tail_expr(&mut self, e: &'tcx Expr<'_>) {
         let in_tail_pos = self.in_tail_pos;
@@ -354,6 +391,19 @@ impl<'tcx> InsertSearcher<'_, 'tcx> {
         self.visit_expr(e);
         self.in_tail_pos = in_tail_pos;
     }
+
+    /// Visit the key and value expression of an insert expression.
+    /// There may not be uses of the map in either of those two either.
+    fn visit_insert_expr_arguments(&mut self, e: &InsertExpr<'tcx>) {
+        let in_tail_pos = self.in_tail_pos;
+        let allow_insert_closure = self.allow_insert_closure;
+        let is_single_insert = self.is_single_insert;
+        walk_expr(self, e.key);
+        walk_expr(self, e.value);
+        self.in_tail_pos = in_tail_pos;
+        self.allow_insert_closure = allow_insert_closure;
+        self.is_single_insert = is_single_insert;
+    }
 }
 impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
     fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
@@ -425,6 +475,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
 
         match try_parse_insert(self.cx, expr) {
             Some(insert_expr) if SpanlessEq::new(self.cx).eq_expr(self.map, insert_expr.map) => {
+                self.visit_insert_expr_arguments(&insert_expr);
                 // Multiple inserts, inserts with a different key, and inserts from a macro can't use the entry api.
                 if self.is_map_used
                     || !SpanlessEq::new(self.cx).eq_expr(self.key, insert_expr.key)
diff --git a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
index bc236c5c71f..83ecaeef982 100644
--- a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
+++ b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
@@ -1,7 +1,7 @@
 //! checks for `#[inline]` on trait methods without bodies
 
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::sugg::DiagnosticExt;
+use clippy_utils::sugg::DiagExt;
 use rustc_ast::ast::Attribute;
 use rustc_errors::Applicability;
 use rustc_hir::{TraitFn, TraitItem, TraitItemKind};
diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs
index 606c2ed72be..0ea53c39280 100644
--- a/src/tools/clippy/clippy_lints/src/let_underscore.rs
+++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type};
 use clippy_utils::{is_from_proc_macro, is_must_use_func_call, paths};
-use rustc_hir::{Local, PatKind};
+use rustc_hir::{Local, LocalSource, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{GenericArgKind, IsSuggestable};
@@ -139,7 +139,8 @@ const SYNC_GUARD_PATHS: [&[&str]; 3] = [
 
 impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
     fn check_local(&mut self, cx: &LateContext<'tcx>, local: &Local<'tcx>) {
-        if !in_external_macro(cx.tcx.sess, local.span)
+        if matches!(local.source, LocalSource::Normal)
+            && !in_external_macro(cx.tcx.sess, local.span)
             && let PatKind::Wild = local.pat.kind
             && let Some(init) = local.init
         {
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 76e75968314..b930175c4d8 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -80,6 +80,7 @@ mod as_conversions;
 mod asm_syntax;
 mod assertions_on_constants;
 mod assertions_on_result_states;
+mod assigning_clones;
 mod async_yields_async;
 mod attrs;
 mod await_holding_invalid;
@@ -1118,6 +1119,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(move |_| Box::new(incompatible_msrv::IncompatibleMsrv::new(msrv())));
     store.register_late_pass(|_| Box::new(to_string_trait_impl::ToStringTraitImpl));
     store.register_early_pass(|| Box::new(multiple_bound_locations::MultipleBoundLocations));
+    store.register_late_pass(|_| Box::new(assigning_clones::AssigningClones));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
index 58f713d8187..18f799e875a 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
@@ -3,6 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_copy;
+use clippy_utils::usage::local_used_in;
 use clippy_utils::{get_enclosing_block, higher, path_to_local, sugg};
 use rustc_ast::ast;
 use rustc_errors::Applicability;
@@ -63,8 +64,9 @@ pub(super) fn check<'tcx>(
                             && get_slice_like_element_ty(cx, cx.typeck_results().expr_ty(base_right)).is_some()
                             && let Some((start_left, offset_left)) = get_details_from_idx(cx, idx_left, &starts)
                             && let Some((start_right, offset_right)) = get_details_from_idx(cx, idx_right, &starts)
-
-                            // Source and destination must be different
+                            && !local_used_in(cx, canonical_id, base_left)
+                            && !local_used_in(cx, canonical_id, base_right)
+							// Source and destination must be different
                             && path_to_local(base_left) != path_to_local(base_right)
                         {
                             Some((
diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
index 245a903f998..65d922f03df 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -255,6 +255,9 @@ fn never_loop_expr<'tcx>(
             InlineAsmOperand::Const { .. } | InlineAsmOperand::SymFn { .. } | InlineAsmOperand::SymStatic { .. } => {
                 NeverLoopResult::Normal
             },
+            InlineAsmOperand::Label { block } => {
+                never_loop_block(cx, block, local_labels, main_loop_id)
+            }
         })),
         ExprKind::OffsetOf(_, _)
         | ExprKind::Yield(_, _)
diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
index 69f86836775..b770ad0ddb5 100644
--- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
@@ -37,12 +37,7 @@ pub(super) fn check<'tcx>(
     }
 }
 
-fn set_diagnostic<'tcx>(
-    diag: &mut Diag<'_, ()>,
-    cx: &LateContext<'tcx>,
-    expr: &'tcx Expr<'tcx>,
-    found: FoundSigDrop,
-) {
+fn set_diagnostic<'tcx>(diag: &mut Diag<'_, ()>, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, found: FoundSigDrop) {
     if found.lint_suggestion == LintSuggestion::MoveAndClone {
         // If our suggestion is to move and clone, then we want to leave it to the user to
         // decide how to address this lint, since it may be that cloning is inappropriate.
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index adb696ad509..8a24ccea3a1 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -3875,6 +3875,7 @@ declare_clippy_lint! {
 }
 
 declare_clippy_lint! {
+    /// ### What it does
     /// Checks for usage of `option.map(f).unwrap_or_default()` and `result.map(f).unwrap_or_default()` where f is a function or closure that returns the `bool` type.
     ///
     /// ### Why is this bad?
@@ -3981,6 +3982,7 @@ declare_clippy_lint! {
 }
 
 declare_clippy_lint! {
+    /// ### What it does
     /// Checks for the manual creation of C strings (a string with a `NUL` byte at the end), either
     /// through one of the `CStr` constructor functions, or more plainly by calling `.as_ptr()`
     /// on a (byte) string literal with a hardcoded `\0` byte at the end.
diff --git a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
index 514015af045..b8baad18cc8 100644
--- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
@@ -22,9 +22,9 @@ fn get_enum_ty(enum_ty: Ty<'_>) -> Option<Ty<'_>> {
     }
 
     impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTyVisitor {
-        type BreakTy = Ty<'tcx>;
+        type Result = ControlFlow<Ty<'tcx>>;
 
-        fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
             self.level += 1;
             if self.level == 1 {
                 t.super_visit_with(self)
diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs
index b3b8a5e9963..627b4968d9f 100644
--- a/src/tools/clippy/clippy_lints/src/new_without_default.rs
+++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::return_ty;
 use clippy_utils::source::snippet;
-use clippy_utils::sugg::DiagnosticExt;
+use clippy_utils::sugg::DiagExt;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::HirIdSet;
diff --git a/src/tools/clippy/clippy_lints/src/operators/identity_op.rs b/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
index f671517c134..0879dcd9bcd 100644
--- a/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
@@ -42,7 +42,7 @@ pub(crate) fn check<'tcx>(
 
     match op {
         BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => {
-            check_op(
+            let _ = check_op(
                 cx,
                 left,
                 0,
@@ -50,8 +50,7 @@ pub(crate) fn check<'tcx>(
                 peeled_right_span,
                 needs_parenthesis(cx, expr, right),
                 right_is_coerced_to_value,
-            );
-            check_op(
+            ) || check_op(
                 cx,
                 right,
                 0,
@@ -62,7 +61,7 @@ pub(crate) fn check<'tcx>(
             );
         },
         BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => {
-            check_op(
+            let _ = check_op(
                 cx,
                 right,
                 0,
@@ -73,7 +72,7 @@ pub(crate) fn check<'tcx>(
             );
         },
         BinOpKind::Mul => {
-            check_op(
+            let _ = check_op(
                 cx,
                 left,
                 1,
@@ -81,8 +80,18 @@ pub(crate) fn check<'tcx>(
                 peeled_right_span,
                 needs_parenthesis(cx, expr, right),
                 right_is_coerced_to_value,
-            );
-            check_op(
+            ) || check_op(
+                cx,
+                right,
+                1,
+                expr.span,
+                peeled_left_span,
+                Parens::Unneeded,
+                left_is_coerced_to_value,
+            );
+        },
+        BinOpKind::Div => {
+            let _ = check_op(
                 cx,
                 right,
                 1,
@@ -92,17 +101,8 @@ pub(crate) fn check<'tcx>(
                 left_is_coerced_to_value,
             );
         },
-        BinOpKind::Div => check_op(
-            cx,
-            right,
-            1,
-            expr.span,
-            peeled_left_span,
-            Parens::Unneeded,
-            left_is_coerced_to_value,
-        ),
         BinOpKind::BitAnd => {
-            check_op(
+            let _ = check_op(
                 cx,
                 left,
                 -1,
@@ -110,8 +110,7 @@ pub(crate) fn check<'tcx>(
                 peeled_right_span,
                 needs_parenthesis(cx, expr, right),
                 right_is_coerced_to_value,
-            );
-            check_op(
+            ) || check_op(
                 cx,
                 right,
                 -1,
@@ -201,12 +200,12 @@ fn check_remainder(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>, span
     }
 }
 
-fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, parens: Parens, is_erased: bool) {
+fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, parens: Parens, is_erased: bool) -> bool {
     if let Some(Constant::Int(v)) = constant_simple(cx, cx.typeck_results(), e).map(Constant::peel_refs) {
         let check = match *cx.typeck_results().expr_ty(e).peel_refs().kind() {
             ty::Int(ity) => unsext(cx.tcx, -1_i128, ity),
             ty::Uint(uty) => clip(cx.tcx, !0, uty),
-            _ => return,
+            _ => return false,
         };
         if match m {
             0 => v == 0,
@@ -215,8 +214,10 @@ fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, pa
             _ => unreachable!(),
         } {
             span_ineffective_operation(cx, span, arg, parens, is_erased);
+            return true;
         }
     }
+    false
 }
 
 fn span_ineffective_operation(
diff --git a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs
index fecc5a8578e..311cbd050a1 100644
--- a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs
@@ -21,9 +21,8 @@ pub(super) fn check<'tcx>(
         // lhs op= l op r
         if eq_expr_value(cx, lhs, l) {
             lint_misrefactored_assign_op(cx, expr, op, rhs, lhs, r);
-        }
-        // lhs op= l commutative_op r
-        if is_commutative(op) && eq_expr_value(cx, lhs, r) {
+        } else if is_commutative(op) && eq_expr_value(cx, lhs, r) {
+            // lhs op= l commutative_op r
             lint_misrefactored_assign_op(cx, expr, op, rhs, lhs, l);
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index 1df2d5e4602..cf7f730140c 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -203,109 +203,107 @@ fn expr_return_none_or_err(
     }
 }
 
+/// Checks if the given expression on the given context matches the following structure:
+///
+/// ```ignore
+/// if option.is_none() {
+///    return None;
+/// }
+/// ```
+///
+/// ```ignore
+/// if result.is_err() {
+///     return result;
+/// }
+/// ```
+///
+/// If it matches, it will suggest to use the question mark operator instead
+fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
+    if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr)
+        && !is_else_clause(cx.tcx, expr)
+        && let ExprKind::MethodCall(segment, caller, ..) = &cond.kind
+        && let caller_ty = cx.typeck_results().expr_ty(caller)
+        && let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then)
+        && (is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block))
+    {
+        let mut applicability = Applicability::MachineApplicable;
+        let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability);
+        let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env)
+            && !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..));
+        let sugg = if let Some(else_inner) = r#else {
+            if eq_expr_value(cx, caller, peel_blocks(else_inner)) {
+                format!("Some({receiver_str}?)")
+            } else {
+                return;
+            }
+        } else {
+            format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" })
+        };
+
+        span_lint_and_sugg(
+            cx,
+            QUESTION_MARK,
+            expr.span,
+            "this block may be rewritten with the `?` operator",
+            "replace it with",
+            sugg,
+            applicability,
+        );
+    }
+}
+
+fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
+    if let Some(higher::IfLet {
+        let_pat,
+        let_expr,
+        if_then,
+        if_else,
+        ..
+    }) = higher::IfLet::hir(cx, expr)
+        && !is_else_clause(cx.tcx, expr)
+        && let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind
+        && ddpos.as_opt_usize().is_none()
+        && let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind
+        && let caller_ty = cx.typeck_results().expr_ty(let_expr)
+        && let if_block = IfBlockType::IfLet(
+            cx.qpath_res(path1, let_pat.hir_id),
+            caller_ty,
+            ident.name,
+            let_expr,
+            if_then,
+            if_else,
+        )
+        && ((is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
+            || is_early_return(sym::Result, cx, &if_block))
+        && if_else
+            .map(|e| eq_expr_value(cx, let_expr, peel_blocks(e)))
+            .filter(|e| *e)
+            .is_none()
+    {
+        let mut applicability = Applicability::MachineApplicable;
+        let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
+        let requires_semi = matches!(cx.tcx.parent_hir_node(expr.hir_id), Node::Stmt(_));
+        let sugg = format!(
+            "{receiver_str}{}?{}",
+            if by_ref == ByRef::Yes { ".as_ref()" } else { "" },
+            if requires_semi { ";" } else { "" }
+        );
+        span_lint_and_sugg(
+            cx,
+            QUESTION_MARK,
+            expr.span,
+            "this block may be rewritten with the `?` operator",
+            "replace it with",
+            sugg,
+            applicability,
+        );
+    }
+}
+
 impl QuestionMark {
     fn inside_try_block(&self) -> bool {
         self.try_block_depth_stack.last() > Some(&0)
     }
-
-    /// Checks if the given expression on the given context matches the following structure:
-    ///
-    /// ```ignore
-    /// if option.is_none() {
-    ///    return None;
-    /// }
-    /// ```
-    ///
-    /// ```ignore
-    /// if result.is_err() {
-    ///     return result;
-    /// }
-    /// ```
-    ///
-    /// If it matches, it will suggest to use the question mark operator instead
-    fn check_is_none_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
-        if !self.inside_try_block()
-            && let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr)
-            && !is_else_clause(cx.tcx, expr)
-            && let ExprKind::MethodCall(segment, caller, ..) = &cond.kind
-            && let caller_ty = cx.typeck_results().expr_ty(caller)
-            && let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then)
-            && (is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block))
-        {
-            let mut applicability = Applicability::MachineApplicable;
-            let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability);
-            let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env)
-                && !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..));
-            let sugg = if let Some(else_inner) = r#else {
-                if eq_expr_value(cx, caller, peel_blocks(else_inner)) {
-                    format!("Some({receiver_str}?)")
-                } else {
-                    return;
-                }
-            } else {
-                format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" })
-            };
-
-            span_lint_and_sugg(
-                cx,
-                QUESTION_MARK,
-                expr.span,
-                "this block may be rewritten with the `?` operator",
-                "replace it with",
-                sugg,
-                applicability,
-            );
-        }
-    }
-
-    fn check_if_let_some_or_err_and_early_return<'tcx>(&self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
-        if !self.inside_try_block()
-            && let Some(higher::IfLet {
-                let_pat,
-                let_expr,
-                if_then,
-                if_else,
-                ..
-            }) = higher::IfLet::hir(cx, expr)
-            && !is_else_clause(cx.tcx, expr)
-            && let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind
-            && ddpos.as_opt_usize().is_none()
-            && let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind
-            && let caller_ty = cx.typeck_results().expr_ty(let_expr)
-            && let if_block = IfBlockType::IfLet(
-                cx.qpath_res(path1, let_pat.hir_id),
-                caller_ty,
-                ident.name,
-                let_expr,
-                if_then,
-                if_else,
-            )
-            && ((is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
-                || is_early_return(sym::Result, cx, &if_block))
-            && if_else
-                .map(|e| eq_expr_value(cx, let_expr, peel_blocks(e)))
-                .filter(|e| *e)
-                .is_none()
-        {
-            let mut applicability = Applicability::MachineApplicable;
-            let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
-            let requires_semi = matches!(cx.tcx.parent_hir_node(expr.hir_id), Node::Stmt(_));
-            let sugg = format!(
-                "{receiver_str}{}?{}",
-                if by_ref == ByRef::Yes { ".as_ref()" } else { "" },
-                if requires_semi { ";" } else { "" }
-            );
-            span_lint_and_sugg(
-                cx,
-                QUESTION_MARK,
-                expr.span,
-                "this block may be rewritten with the `?` operator",
-                "replace it with",
-                sugg,
-                applicability,
-            );
-        }
-    }
 }
 
 fn is_try_block(cx: &LateContext<'_>, bl: &rustc_hir::Block<'_>) -> bool {
@@ -324,15 +322,18 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark {
             return;
         }
 
-        if !in_constant(cx, stmt.hir_id) {
+        if !self.inside_try_block() && !in_constant(cx, stmt.hir_id) {
             check_let_some_else_return_none(cx, stmt);
         }
         self.check_manual_let_else(cx, stmt);
     }
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if !in_constant(cx, expr.hir_id) && is_lint_allowed(cx, QUESTION_MARK_USED, expr.hir_id) {
-            self.check_is_none_or_err_and_early_return(cx, expr);
-            self.check_if_let_some_or_err_and_early_return(cx, expr);
+        if !self.inside_try_block()
+            && !in_constant(cx, expr.hir_id)
+            && is_lint_allowed(cx, QUESTION_MARK_USED, expr.hir_id)
+        {
+            check_is_none_or_err_and_early_return(cx, expr);
+            check_if_let_some_or_err_and_early_return(cx, expr);
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
index e3f0ce2a922..f61527cc0a9 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
@@ -159,6 +159,15 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
             //           ^^  we only want to lint for this call (but we walk up the calls to consider both calls).
             // without this check, we'd end up linting twice.
             && !matches!(recv.kind, hir::ExprKind::Call(..))
+            // Check if `recv` comes from a macro expansion. If it does, make sure that it's an expansion that is
+            // the same as the one the call is in.
+            // For instance, let's assume `x!()` returns a closure:
+            //    B ---v
+            //      x!()()
+            //          ^- A
+            // The call happens in the expansion `A`, while the closure originates from the expansion `B`.
+            // We don't want to suggest replacing `x!()()` with `x!()`.
+            && recv.span.ctxt().outer_expn() == expr.span.ctxt().outer_expn()
             && let (full_expr, call_depth) = get_parent_call_exprs(cx, expr)
             && let Some((body, fn_decl, coroutine_kind, params)) = find_innermost_closure(cx, recv, call_depth)
             // outside macros we lint properly. Inside macros, we lint only ||() style closures.
diff --git a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs
index fb000cd7184..17b031d5f01 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs
@@ -59,24 +59,22 @@ impl EarlyLintPass for RedundantFieldNames {
         }
         if let ExprKind::Struct(ref se) = expr.kind {
             for field in &se.fields {
-                if field.is_shorthand {
-                    continue;
-                }
-                if let ExprKind::Path(None, path) = &field.expr.kind {
-                    if path.segments.len() == 1
-                        && path.segments[0].ident == field.ident
-                        && path.segments[0].args.is_none()
-                    {
-                        span_lint_and_sugg(
-                            cx,
-                            REDUNDANT_FIELD_NAMES,
-                            field.span,
-                            "redundant field names in struct initialization",
-                            "replace it with",
-                            field.ident.to_string(),
-                            Applicability::MachineApplicable,
-                        );
-                    }
+                if !field.is_shorthand
+                    && let ExprKind::Path(None, path) = &field.expr.kind
+                    && let [segment] = path.segments.as_slice()
+                    && segment.args.is_none()
+                    && segment.ident == field.ident
+                    && field.span.eq_ctxt(field.ident.span)
+                {
+                    span_lint_and_sugg(
+                        cx,
+                        REDUNDANT_FIELD_NAMES,
+                        field.span,
+                        "redundant field names in struct initialization",
+                        "replace it with",
+                        field.ident.to_string(),
+                        Applicability::MachineApplicable,
+                    );
                 }
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
index 38fd54a0f1e..c0e4f3c368a 100644
--- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
+++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
@@ -109,7 +109,6 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports {
                     sym::core => (STD_INSTEAD_OF_CORE, "std", "core"),
                     sym::alloc => (STD_INSTEAD_OF_ALLOC, "std", "alloc"),
                     _ => {
-                        self.prev_span = path.span;
                         return;
                     },
                 },
@@ -117,13 +116,12 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports {
                     if cx.tcx.crate_name(def_id.krate) == sym::core {
                         (ALLOC_INSTEAD_OF_CORE, "alloc", "core")
                     } else {
-                        self.prev_span = path.span;
                         return;
                     }
                 },
                 _ => return,
             };
-            if path.span != self.prev_span {
+            if first_segment.ident.span != self.prev_span {
                 span_lint_and_sugg(
                     cx,
                     lint,
@@ -133,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports {
                     replace_with.to_string(),
                     Applicability::MachineApplicable,
                 );
-                self.prev_span = path.span;
+                self.prev_span = first_segment.ident.span;
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs b/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs
index 9fee4c06200..1af3733ebfa 100644
--- a/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs
+++ b/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs
@@ -1,12 +1,11 @@
-use clippy_config::msrvs::Msrv;
+use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::fn_has_unsatisfiable_preds;
 use clippy_utils::qualify_min_const_fn::is_min_const_fn;
 use clippy_utils::source::snippet;
+use clippy_utils::{fn_has_unsatisfiable_preds, peel_blocks};
 use rustc_errors::Applicability;
 use rustc_hir::{intravisit, ExprKind};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::lint::in_external_macro;
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
 use rustc_span::sym::thread_local_macro;
 
@@ -57,6 +56,31 @@ impl ThreadLocalInitializerCanBeMadeConst {
 
 impl_lint_pass!(ThreadLocalInitializerCanBeMadeConst => [THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST]);
 
+#[inline]
+fn is_thread_local_initializer(
+    cx: &LateContext<'_>,
+    fn_kind: rustc_hir::intravisit::FnKind<'_>,
+    span: rustc_span::Span,
+) -> Option<bool> {
+    let macro_def_id = span.source_callee()?.macro_def_id?;
+    Some(
+        cx.tcx.is_diagnostic_item(thread_local_macro, macro_def_id)
+            && matches!(fn_kind, intravisit::FnKind::ItemFn(..)),
+    )
+}
+
+#[inline]
+fn initializer_can_be_made_const(cx: &LateContext<'_>, defid: rustc_span::def_id::DefId, msrv: &Msrv) -> bool {
+    // Building MIR for `fn`s with unsatisfiable preds results in ICE.
+    if !fn_has_unsatisfiable_preds(cx, defid)
+        && let mir = cx.tcx.optimized_mir(defid)
+        && let Ok(()) = is_min_const_fn(cx.tcx, mir, msrv)
+    {
+        return true;
+    }
+    false
+}
+
 impl<'tcx> LateLintPass<'tcx> for ThreadLocalInitializerCanBeMadeConst {
     fn check_fn(
         &mut self,
@@ -65,31 +89,32 @@ impl<'tcx> LateLintPass<'tcx> for ThreadLocalInitializerCanBeMadeConst {
         _: &'tcx rustc_hir::FnDecl<'tcx>,
         body: &'tcx rustc_hir::Body<'tcx>,
         span: rustc_span::Span,
-        defid: rustc_span::def_id::LocalDefId,
+        local_defid: rustc_span::def_id::LocalDefId,
     ) {
-        if in_external_macro(cx.sess(), span)
-            && let Some(callee) = span.source_callee()
-            && let Some(macro_def_id) = callee.macro_def_id
-            && cx.tcx.is_diagnostic_item(thread_local_macro, macro_def_id)
-            && let intravisit::FnKind::ItemFn(..) = fn_kind
-            // Building MIR for `fn`s with unsatisfiable preds results in ICE.
-            && !fn_has_unsatisfiable_preds(cx, defid.to_def_id())
-            && let mir = cx.tcx.optimized_mir(defid.to_def_id())
-            && let Ok(()) = is_min_const_fn(cx.tcx, mir, &self.msrv)
-            // this is the `__init` function emitted by the `thread_local!` macro
-            // when the `const` keyword is not used. We avoid checking the `__init` directly
-            // as that is not a public API.
-            // we know that the function is const-qualifiable, so now we need only to get the
-            // initializer expression to span-lint it.
+        let defid = local_defid.to_def_id();
+        if self.msrv.meets(msrvs::THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST)
+            && is_thread_local_initializer(cx, fn_kind, span).unwrap_or(false)
+            // Some implementations of `thread_local!` include an initializer fn.
+            // In the case of a const initializer, the init fn is also const,
+            // so we can skip the lint in that case. This occurs only on some
+            // backends due to conditional compilation:
+            // https://doc.rust-lang.org/src/std/sys/common/thread_local/mod.rs.html
+            // for details on this issue, see:
+            // https://github.com/rust-lang/rust-clippy/pull/12276
+            && !cx.tcx.is_const_fn(defid)
+            && initializer_can_be_made_const(cx, defid, &self.msrv)
+            // we know that the function is const-qualifiable, so now
+            // we need only to get the initializer expression to span-lint it.
             && let ExprKind::Block(block, _) = body.value.kind
-            && let Some(ret_expr) = block.expr
+            && let Some(unpeeled) = block.expr
+            && let ret_expr = peel_blocks(unpeeled)
             && let initializer_snippet = snippet(cx, ret_expr.span, "thread_local! { ... }")
             && initializer_snippet != "thread_local! { ... }"
         {
             span_lint_and_sugg(
                 cx,
                 THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST,
-                ret_expr.span,
+                unpeeled.span,
                 "initializer for `thread_local` value can be made `const`",
                 "replace with",
                 format!("const {{ {initializer_snippet} }}"),
diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
index 06de7a11031..e47b14bf63b 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
@@ -592,7 +592,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
                 | (eager_transmute::check(cx, e, arg, from_ty, to_ty));
 
             if !linted {
-                transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, from_ty_adjusted, to_ty, arg);
+                transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, from_ty_adjusted, to_ty, arg, const_context);
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
index bbecc39a813..043c9c88601 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
@@ -18,10 +18,12 @@ pub(super) fn check<'tcx>(
     from_ty_adjusted: bool,
     to_ty: Ty<'tcx>,
     arg: &'tcx Expr<'_>,
+    const_context: bool,
 ) -> bool {
     use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast};
     let mut app = Applicability::MachineApplicable;
     let mut sugg = match check_cast(cx, e, from_ty, to_ty) {
+        Some(FnPtrAddrCast | PtrAddrCast) if const_context => return false,
         Some(PtrPtrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) => {
             Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app)
                 .as_ty(to_ty.to_string())
diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs
index a285f771f1b..7926738d68f 100644
--- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs
@@ -1,10 +1,9 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::paths::ALLOCATOR_GLOBAL;
+use clippy_utils::last_path_segment;
 use clippy_utils::source::snippet;
-use clippy_utils::{last_path_segment, match_def_path};
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
-use rustc_hir::{self as hir, GenericArg, QPath, TyKind};
+use rustc_hir::{self as hir, GenericArg, LangItem, QPath, TyKind};
 use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::LateContext;
 use rustc_middle::ty::layout::LayoutOf;
@@ -50,7 +49,7 @@ pub(super) fn check<'tcx>(
                 (None, Some(GenericArg::Type(inner))) | (Some(GenericArg::Type(inner)), None) => {
                     if let TyKind::Path(path) = inner.kind
                         && let Some(did) = cx.qpath_res(&path, inner.hir_id).opt_def_id() {
-                        match_def_path(cx, did, &ALLOCATOR_GLOBAL)
+                        cx.tcx.lang_items().get(LangItem::GlobalAlloc) == Some(did)
                     } else {
                         false
                     }
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index ef61b303f9c..f7f5f7ca35f 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -833,6 +833,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                             self.hash_body(anon_const.body);
                         },
                         InlineAsmOperand::SymStatic { path, def_id: _ } => self.hash_qpath(path),
+                        InlineAsmOperand::Label { block } => self.hash_block(block),
                     }
                 }
             },
diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
index f9cc5f19125..06229ac938f 100644
--- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
+++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
@@ -141,9 +141,9 @@ impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b,
 struct ContainsRegion;
 
 impl TypeVisitor<TyCtxt<'_>> for ContainsRegion {
-    type BreakTy = ();
+    type Result = ControlFlow<()>;
 
-    fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow<Self::BreakTy> {
+    fn visit_region(&mut self, _: ty::Region<'_>) -> Self::Result {
         ControlFlow::Break(())
     }
 }
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index 2f728b62754..987f28192a8 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -115,4 +115,3 @@ pub const OPTION_UNWRAP: [&str; 4] = ["core", "option", "Option", "unwrap"];
 pub const OPTION_EXPECT: [&str; 4] = ["core", "option", "Option", "expect"];
 #[expect(clippy::invalid_paths)] // not sure why it thinks this, it works so
 pub const BOOL_THEN: [&str; 4] = ["core", "bool", "<impl bool>", "then"];
-pub const ALLOCATOR_GLOBAL: [&str; 3] = ["alloc", "alloc", "Global"];
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 183dbe3aecc..e369cb9d0a4 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -334,7 +334,7 @@ fn check_terminator<'tcx>(
                 // within const fns. `transmute` is allowed in all other const contexts.
                 // This won't really scale to more intrinsics or functions. Let's allow const
                 // transmutes in const fn before we add more hacks to this.
-                if matches!(tcx.intrinsic(fn_def_id), Some(sym::transmute)) {
+                if tcx.is_intrinsic(fn_def_id, sym::transmute) {
                     return Err((
                         span,
                         "can only call `transmute` from const items, not `const fn`".into(),
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index d2ec327534a..5090d0bd98b 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -685,7 +685,7 @@ fn indentation<T: LintContext>(cx: &T, span: Span) -> Option<String> {
 }
 
 /// Convenience extension trait for `Diag`.
-pub trait DiagnosticExt<T: LintContext> {
+pub trait DiagExt<T: LintContext> {
     /// Suggests to add an attribute to an item.
     ///
     /// Correctly handles indentation of the attribute and item.
@@ -732,7 +732,7 @@ pub trait DiagnosticExt<T: LintContext> {
     fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str, applicability: Applicability);
 }
 
-impl<T: LintContext> DiagnosticExt<T> for rustc_errors::Diag<'_, ()> {
+impl<T: LintContext> DiagExt<T> for rustc_errors::Diag<'_, ()> {
     fn suggest_item_with_attr<D: Display + ?Sized>(
         &mut self,
         cx: &T,
@@ -995,7 +995,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
                         // no adjustment needed here, as field projections are handled by the compiler
                         ProjectionKind::Field(..) => match cmt.place.ty_before_projection(i).kind() {
                             ty::Adt(..) | ty::Tuple(_) => {
-                                replacement_str = ident_str_with_proj.clone();
+                                replacement_str.clone_from(&ident_str_with_proj);
                                 projections_handled = true;
                             },
                             _ => (),
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 6762c883005..6e011a28bb7 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -916,8 +916,8 @@ pub fn for_each_top_level_late_bound_region<B>(
         f: F,
     }
     impl<'tcx, B, F: FnMut(BoundRegion) -> ControlFlow<B>> TypeVisitor<TyCtxt<'tcx>> for V<F> {
-        type BreakTy = B;
-        fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+        type Result = ControlFlow<B>;
+        fn visit_region(&mut self, r: Region<'tcx>) -> Self::Result {
             if let RegionKind::ReBound(idx, bound) = r.kind()
                 && idx.as_u32() == self.index
             {
@@ -926,7 +926,7 @@ pub fn for_each_top_level_late_bound_region<B>(
                 ControlFlow::Continue(())
             }
         }
-        fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &Binder<'tcx, T>) -> ControlFlow<Self::BreakTy> {
+        fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &Binder<'tcx, T>) -> Self::Result {
             self.index += 1;
             let res = t.super_visit_with(self);
             self.index -= 1;
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index fb038b617df..070b62887d5 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2024-02-22"
+channel = "nightly-2024-03-07"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index b966fcf9b80..9e42abbc9aa 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -68,8 +68,8 @@ fn test_arg_value() {
     assert_eq!(arg_value(args, "--foo", |_| true), None);
 }
 
-fn track_clippy_args(parse_sess: &mut ParseSess, args_env_var: &Option<String>) {
-    parse_sess.env_depinfo.get_mut().insert((
+fn track_clippy_args(psess: &mut ParseSess, args_env_var: &Option<String>) {
+    psess.env_depinfo.get_mut().insert((
         Symbol::intern("CLIPPY_ARGS"),
         args_env_var.as_deref().map(Symbol::intern),
     ));
@@ -77,8 +77,8 @@ fn track_clippy_args(parse_sess: &mut ParseSess, args_env_var: &Option<String>)
 
 /// Track files that may be accessed at runtime in `file_depinfo` so that cargo will re-run clippy
 /// when any of them are modified
-fn track_files(parse_sess: &mut ParseSess) {
-    let file_depinfo = parse_sess.file_depinfo.get_mut();
+fn track_files(psess: &mut ParseSess) {
+    let file_depinfo = psess.file_depinfo.get_mut();
 
     // Used by `clippy::cargo` lints and to determine the MSRV. `cargo clippy` executes `clippy-driver`
     // with the current directory set to `CARGO_MANIFEST_DIR` so a relative path is fine
@@ -115,8 +115,8 @@ struct RustcCallbacks {
 impl rustc_driver::Callbacks for RustcCallbacks {
     fn config(&mut self, config: &mut interface::Config) {
         let clippy_args_var = self.clippy_args_var.take();
-        config.parse_sess_created = Some(Box::new(move |parse_sess| {
-            track_clippy_args(parse_sess, &clippy_args_var);
+        config.psess_created = Some(Box::new(move |psess| {
+            track_clippy_args(psess, &clippy_args_var);
         }));
     }
 }
@@ -132,13 +132,13 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
         let conf_path = clippy_config::lookup_conf_file();
         let previous = config.register_lints.take();
         let clippy_args_var = self.clippy_args_var.take();
-        config.parse_sess_created = Some(Box::new(move |parse_sess| {
-            track_clippy_args(parse_sess, &clippy_args_var);
-            track_files(parse_sess);
+        config.psess_created = Some(Box::new(move |psess| {
+            track_clippy_args(psess, &clippy_args_var);
+            track_files(psess);
 
             // Trigger a rebuild if CLIPPY_CONF_DIR changes. The value must be a valid string so
             // changes between dirs that are invalid UTF-8 will not trigger rebuilds
-            parse_sess.env_depinfo.get_mut().insert((
+            psess.env_depinfo.get_mut().insert((
                 Symbol::intern("CLIPPY_CONF_DIR"),
                 env::var("CLIPPY_CONF_DIR").ok().map(|dir| Symbol::intern(&dir)),
             ));
@@ -190,7 +190,7 @@ pub fn main() {
     });
 
     exit(rustc_driver::catch_with_exit_code(move || {
-        let mut orig_args: Vec<String> = env::args().collect();
+        let mut orig_args = rustc_driver::args::raw_args(&early_dcx)?;
 
         let has_sysroot_arg = |args: &mut [String]| -> bool {
             if arg_value(args, "--sysroot", |_| true).is_some() {
diff --git a/src/tools/clippy/src/main.rs b/src/tools/clippy/src/main.rs
index dffa854177b..30beaae34d2 100644
--- a/src/tools/clippy/src/main.rs
+++ b/src/tools/clippy/src/main.rs
@@ -174,8 +174,13 @@ To allow or deny a lint from the command line you can use <cyan,bold>cargo clipp
 You can use tool lints to allow or deny lints from your code, e.g.:
 
     <yellow,bold>#[allow(clippy::needless_lifetimes)]</>
-"
-    )
+
+<green,bold>Manifest Options:</>
+    <cyan,bold>--manifest-path</> <cyan><<PATH>></>  Path to Cargo.toml
+    <cyan,bold>--frozen</>                Require Cargo.lock and cache are up to date
+    <cyan,bold>--locked</>                Require Cargo.lock is up to date
+    <cyan,bold>--offline</>               Run without accessing the network
+")
 }
 #[cfg(test)]
 mod tests {
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index a088896b6b0..a0c8bf9334c 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -138,6 +138,7 @@ fn base_config(test_dir: &str) -> (Config, Args) {
             "-Aunused",
             "-Ainternal_features",
             "-Zui-testing",
+            "-Zdeduplicate-diagnostics=no",
             "-Dwarnings",
             &format!("-Ldependency={}", deps_path.display()),
         ]
diff --git a/src/tools/clippy/tests/missing-test-files.rs b/src/tools/clippy/tests/missing-test-files.rs
index 0d35a22cd9a..141c11ddb47 100644
--- a/src/tools/clippy/tests/missing-test-files.rs
+++ b/src/tools/clippy/tests/missing-test-files.rs
@@ -54,7 +54,7 @@ fn explore_directory(dir: &Path) -> Vec<String> {
             let file_prefix = path.file_prefix().unwrap().to_str().unwrap().to_string();
             if let Some(ext) = path.extension() {
                 match ext.to_str().unwrap() {
-                    "rs" | "toml" => current_file = file_prefix.clone(),
+                    "rs" | "toml" => current_file.clone_from(&file_prefix),
                     "stderr" | "stdout" => {
                         if file_prefix != current_file {
                             missing_files.push(path.to_str().unwrap().to_string());
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
index 9b0db660c99..400bfd5d975 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
@@ -5,6 +5,7 @@
 //@normalize-stderr-test: "'rustc'" -> "'<unnamed>'"
 //@normalize-stderr-test: "rustc 1\.\d+.* running on .*" -> "rustc <version> running on <target>"
 //@normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> ""
+//@normalize-stderr-test: "this compiler `.*` is outdated" -> "this compiler <version> is outdated"
 
 #![deny(clippy::internal)]
 #![allow(clippy::missing_clippy_version_attribute)]
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
index d8b158816c9..b84f4e87e07 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
@@ -4,11 +4,14 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 
 error: the compiler unexpectedly panicked. this is a bug.
 
-note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml
+note: it seems that this compiler <version> is outdated, a newer nightly should have been released in the mean time
+  |
+  = note: please consider running `rustup update nightly` to update the nightly channel and check if this problem still persists
+  = note: if the problem still persists, we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml
 
 note: rustc <version> running on <target>
 
-note: compiler flags: -Z ui-testing
+note: compiler flags: -Z ui-testing -Z deduplicate-diagnostics=no
 
 note: Clippy version: foo
 
diff --git a/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs b/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs
index b9b4a07d29d..5a2a868ed3e 100644
--- a/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs
+++ b/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs
@@ -5,22 +5,16 @@ extern crate rustc_hir;
 extern crate rustc_lint;
 extern crate rustc_middle;
 
-use rustc_errors::{DiagnosticMessage, MultiSpan};
+use rustc_errors::{DiagMessage, MultiSpan};
 use rustc_hir::hir_id::HirId;
 use rustc_lint::{Lint, LintContext};
 use rustc_middle::ty::TyCtxt;
 
-pub fn a(cx: impl LintContext, lint: &'static Lint, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) {
+pub fn a(cx: impl LintContext, lint: &'static Lint, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
     cx.span_lint(lint, span, msg, |_| {});
 }
 
-pub fn b(
-    tcx: TyCtxt<'_>,
-    lint: &'static Lint,
-    hir_id: HirId,
-    span: impl Into<MultiSpan>,
-    msg: impl Into<DiagnosticMessage>,
-) {
+pub fn b(tcx: TyCtxt<'_>, lint: &'static Lint, hir_id: HirId, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
     tcx.node_span_lint(lint, hir_id, span, msg, |_| {});
 }
 
diff --git a/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
index 1a1ad26290c..ae5d6843406 100644
--- a/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
+++ b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
@@ -8,7 +8,7 @@ LL |     cx.span_lint(lint, span, msg, |_| {});
    = help: to override `-D warnings` add `#[allow(clippy::disallowed_methods)]`
 
 error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::node_span_lint`
-  --> tests/ui-internal/disallow_span_lint.rs:24:5
+  --> tests/ui-internal/disallow_span_lint.rs:18:5
    |
 LL |     tcx.node_span_lint(lint, hir_id, span, msg, |_| {});
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr
index 87f84d8f7dd..37d69055737 100644
--- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr
+++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr
@@ -1,5 +1,5 @@
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:266:19
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:271:19
    |
 LL |     /* Safety: */ unsafe {}
    |                   ^^^^^^^^^
@@ -9,7 +9,7 @@ LL |     /* Safety: */ unsafe {}
    = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]`
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:270:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:275:5
    |
 LL |     unsafe {}
    |     ^^^^^^^^^
@@ -17,7 +17,7 @@ LL |     unsafe {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:274:14
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:14
    |
 LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    |              ^^^^^^^^^^^^^
@@ -25,7 +25,7 @@ LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:274:29
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:29
    |
 LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    |                             ^^^^^^^^^^^^^
@@ -33,7 +33,7 @@ LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:274:48
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:48
    |
 LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    |                                                ^^^^^^^^^^^^^
@@ -41,7 +41,7 @@ LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:18
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:283:18
    |
 LL |     let _ = (42, unsafe {}, "test", unsafe {});
    |                  ^^^^^^^^^
@@ -49,7 +49,7 @@ LL |     let _ = (42, unsafe {}, "test", unsafe {});
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:37
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:283:37
    |
 LL |     let _ = (42, unsafe {}, "test", unsafe {});
    |                                     ^^^^^^^^^
@@ -57,7 +57,7 @@ LL |     let _ = (42, unsafe {}, "test", unsafe {});
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:282:14
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:14
    |
 LL |     let _ = *unsafe { &42 };
    |              ^^^^^^^^^^^^^^
@@ -65,7 +65,7 @@ LL |     let _ = *unsafe { &42 };
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:19
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:292:19
    |
 LL |     let _ = match unsafe {} {
    |                   ^^^^^^^^^
@@ -73,7 +73,7 @@ LL |     let _ = match unsafe {} {
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:293:14
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:298:14
    |
 LL |     let _ = &unsafe {};
    |              ^^^^^^^^^
@@ -81,7 +81,7 @@ LL |     let _ = &unsafe {};
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:297:14
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:302:14
    |
 LL |     let _ = [unsafe {}; 5];
    |              ^^^^^^^^^
@@ -89,7 +89,7 @@ LL |     let _ = [unsafe {}; 5];
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:301:13
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:306:13
    |
 LL |     let _ = unsafe {};
    |             ^^^^^^^^^
@@ -97,7 +97,7 @@ LL |     let _ = unsafe {};
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:311:8
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:316:8
    |
 LL |     t!(unsafe {});
    |        ^^^^^^^^^
@@ -105,7 +105,7 @@ LL |     t!(unsafe {});
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:317:13
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:322:13
    |
 LL |             unsafe {}
    |             ^^^^^^^^^
@@ -117,7 +117,7 @@ LL |     t!();
    = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:325:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:330:5
    |
 LL |     unsafe {} // SAFETY:
    |     ^^^^^^^^^
@@ -125,7 +125,7 @@ LL |     unsafe {} // SAFETY:
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:329:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:334:5
    |
 LL |     unsafe {
    |     ^^^^^^^^
@@ -133,7 +133,7 @@ LL |     unsafe {
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:339:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:344:5
    |
 LL |     unsafe {};
    |     ^^^^^^^^^
@@ -141,7 +141,7 @@ LL |     unsafe {};
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:343:20
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:348:20
    |
 LL |     println!("{}", unsafe { String::from_utf8_unchecked(vec![]) });
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -149,7 +149,7 @@ LL |     println!("{}", unsafe { String::from_utf8_unchecked(vec![]) });
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:350:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:355:5
    |
 LL |     unsafe impl A for () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -157,7 +157,7 @@ LL |     unsafe impl A for () {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:357:9
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:362:9
    |
 LL |         unsafe impl B for (u32) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -165,7 +165,7 @@ LL |         unsafe impl B for (u32) {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:378:13
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:383:13
    |
 LL |             unsafe impl T for $t {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^
@@ -177,7 +177,7 @@ LL |     no_safety_comment!(());
    = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:403:13
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:408:13
    |
 LL |             unsafe impl T for $t {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^
@@ -189,7 +189,7 @@ LL |     no_safety_comment!(());
    = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:411:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:416:5
    |
 LL |     unsafe impl T for (i32) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -197,7 +197,7 @@ LL |     unsafe impl T for (i32) {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:403:13
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:408:13
    |
 LL |             unsafe impl T for $t {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^
@@ -209,7 +209,7 @@ LL |     no_safety_comment!(u32);
    = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:417:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:422:5
    |
 LL |     unsafe impl T for (bool) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -217,7 +217,7 @@ LL |     unsafe impl T for (bool) {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:463:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:468:5
    |
 LL |     unsafe impl NoComment for () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -225,7 +225,7 @@ LL |     unsafe impl NoComment for () {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:467:19
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:472:19
    |
 LL |     /* SAFETY: */ unsafe impl InlineComment for () {}
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -233,7 +233,7 @@ LL |     /* SAFETY: */ unsafe impl InlineComment for () {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:471:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:476:5
    |
 LL |     unsafe impl TrailingComment for () {} // SAFETY:
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -241,13 +241,13 @@ LL |     unsafe impl TrailingComment for () {} // SAFETY:
    = help: consider adding a safety comment on the preceding line
 
 error: constant item has unnecessary safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:475:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:480:5
    |
 LL |     const BIG_NUMBER: i32 = 1000000;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: consider removing the safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:474:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:479:5
    |
 LL |     // SAFETY:
    |     ^^^^^^^^^^
@@ -255,7 +255,7 @@ LL |     // SAFETY:
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]`
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:476:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:481:5
    |
 LL |     unsafe impl Interference for () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -263,7 +263,7 @@ LL |     unsafe impl Interference for () {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:483:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:488:5
    |
 LL |     unsafe impl ImplInFn for () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -271,7 +271,7 @@ LL |     unsafe impl ImplInFn for () {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:492:1
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:497:1
    |
 LL | unsafe impl CrateRoot for () {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -279,7 +279,7 @@ LL | unsafe impl CrateRoot for () {}
    = help: consider adding a safety comment on the preceding line
 
 error: statement has unnecessary safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:505:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:5
    |
 LL | /     let _ = {
 LL | |         if unsafe { true } {
@@ -291,13 +291,13 @@ LL | |     };
    | |______^
    |
 help: consider removing the safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:504:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:509:5
    |
 LL |     // SAFETY: this is more than one level away, so it should warn
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:506:12
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:511:12
    |
 LL |         if unsafe { true } {
    |            ^^^^^^^^^^^^^^^
@@ -305,7 +305,7 @@ LL |         if unsafe { true } {
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:509:23
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:514:23
    |
 LL |             let bar = unsafe {};
    |                       ^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr
index 5ffe73f5a2f..400fde997e9 100644
--- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr
+++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr
@@ -1,5 +1,5 @@
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:266:19
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:271:19
    |
 LL |     /* Safety: */ unsafe {}
    |                   ^^^^^^^^^
@@ -9,7 +9,7 @@ LL |     /* Safety: */ unsafe {}
    = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]`
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:270:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:275:5
    |
 LL |     unsafe {}
    |     ^^^^^^^^^
@@ -17,7 +17,7 @@ LL |     unsafe {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:274:14
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:14
    |
 LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    |              ^^^^^^^^^^^^^
@@ -25,7 +25,7 @@ LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:274:29
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:29
    |
 LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    |                             ^^^^^^^^^^^^^
@@ -33,7 +33,7 @@ LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:274:48
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:279:48
    |
 LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    |                                                ^^^^^^^^^^^^^
@@ -41,7 +41,7 @@ LL |     let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }];
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:18
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:283:18
    |
 LL |     let _ = (42, unsafe {}, "test", unsafe {});
    |                  ^^^^^^^^^
@@ -49,7 +49,7 @@ LL |     let _ = (42, unsafe {}, "test", unsafe {});
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:278:37
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:283:37
    |
 LL |     let _ = (42, unsafe {}, "test", unsafe {});
    |                                     ^^^^^^^^^
@@ -57,7 +57,7 @@ LL |     let _ = (42, unsafe {}, "test", unsafe {});
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:282:14
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:14
    |
 LL |     let _ = *unsafe { &42 };
    |              ^^^^^^^^^^^^^^
@@ -65,7 +65,7 @@ LL |     let _ = *unsafe { &42 };
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:19
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:292:19
    |
 LL |     let _ = match unsafe {} {
    |                   ^^^^^^^^^
@@ -73,7 +73,7 @@ LL |     let _ = match unsafe {} {
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:293:14
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:298:14
    |
 LL |     let _ = &unsafe {};
    |              ^^^^^^^^^
@@ -81,7 +81,7 @@ LL |     let _ = &unsafe {};
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:297:14
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:302:14
    |
 LL |     let _ = [unsafe {}; 5];
    |              ^^^^^^^^^
@@ -89,7 +89,7 @@ LL |     let _ = [unsafe {}; 5];
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:301:13
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:306:13
    |
 LL |     let _ = unsafe {};
    |             ^^^^^^^^^
@@ -97,7 +97,7 @@ LL |     let _ = unsafe {};
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:311:8
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:316:8
    |
 LL |     t!(unsafe {});
    |        ^^^^^^^^^
@@ -105,7 +105,7 @@ LL |     t!(unsafe {});
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:317:13
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:322:13
    |
 LL |             unsafe {}
    |             ^^^^^^^^^
@@ -117,7 +117,7 @@ LL |     t!();
    = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:325:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:330:5
    |
 LL |     unsafe {} // SAFETY:
    |     ^^^^^^^^^
@@ -125,7 +125,7 @@ LL |     unsafe {} // SAFETY:
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:329:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:334:5
    |
 LL |     unsafe {
    |     ^^^^^^^^
@@ -133,7 +133,7 @@ LL |     unsafe {
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:339:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:344:5
    |
 LL |     unsafe {};
    |     ^^^^^^^^^
@@ -141,7 +141,7 @@ LL |     unsafe {};
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:343:20
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:348:20
    |
 LL |     println!("{}", unsafe { String::from_utf8_unchecked(vec![]) });
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -149,7 +149,7 @@ LL |     println!("{}", unsafe { String::from_utf8_unchecked(vec![]) });
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:350:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:355:5
    |
 LL |     unsafe impl A for () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -157,7 +157,7 @@ LL |     unsafe impl A for () {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:357:9
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:362:9
    |
 LL |         unsafe impl B for (u32) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -165,7 +165,7 @@ LL |         unsafe impl B for (u32) {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:378:13
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:383:13
    |
 LL |             unsafe impl T for $t {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^
@@ -177,7 +177,7 @@ LL |     no_safety_comment!(());
    = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:403:13
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:408:13
    |
 LL |             unsafe impl T for $t {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^
@@ -189,7 +189,7 @@ LL |     no_safety_comment!(());
    = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:411:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:416:5
    |
 LL |     unsafe impl T for (i32) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -197,7 +197,7 @@ LL |     unsafe impl T for (i32) {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:403:13
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:408:13
    |
 LL |             unsafe impl T for $t {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^
@@ -209,7 +209,7 @@ LL |     no_safety_comment!(u32);
    = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:417:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:422:5
    |
 LL |     unsafe impl T for (bool) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -217,7 +217,7 @@ LL |     unsafe impl T for (bool) {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:463:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:468:5
    |
 LL |     unsafe impl NoComment for () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -225,7 +225,7 @@ LL |     unsafe impl NoComment for () {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:467:19
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:472:19
    |
 LL |     /* SAFETY: */ unsafe impl InlineComment for () {}
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -233,7 +233,7 @@ LL |     /* SAFETY: */ unsafe impl InlineComment for () {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:471:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:476:5
    |
 LL |     unsafe impl TrailingComment for () {} // SAFETY:
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -241,13 +241,13 @@ LL |     unsafe impl TrailingComment for () {} // SAFETY:
    = help: consider adding a safety comment on the preceding line
 
 error: constant item has unnecessary safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:475:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:480:5
    |
 LL |     const BIG_NUMBER: i32 = 1000000;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: consider removing the safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:474:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:479:5
    |
 LL |     // SAFETY:
    |     ^^^^^^^^^^
@@ -255,7 +255,7 @@ LL |     // SAFETY:
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]`
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:476:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:481:5
    |
 LL |     unsafe impl Interference for () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -263,7 +263,7 @@ LL |     unsafe impl Interference for () {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:483:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:488:5
    |
 LL |     unsafe impl ImplInFn for () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -271,7 +271,7 @@ LL |     unsafe impl ImplInFn for () {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe impl missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:492:1
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:497:1
    |
 LL | unsafe impl CrateRoot for () {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -279,7 +279,7 @@ LL | unsafe impl CrateRoot for () {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:502:9
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:507:9
    |
 LL |         unsafe {};
    |         ^^^^^^^^^
@@ -287,7 +287,7 @@ LL |         unsafe {};
    = help: consider adding a safety comment on the preceding line
 
 error: statement has unnecessary safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:505:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:5
    |
 LL | /     let _ = {
 LL | |         if unsafe { true } {
@@ -299,13 +299,13 @@ LL | |     };
    | |______^
    |
 help: consider removing the safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:504:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:509:5
    |
 LL |     // SAFETY: this is more than one level away, so it should warn
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:506:12
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:511:12
    |
 LL |         if unsafe { true } {
    |            ^^^^^^^^^^^^^^^
@@ -313,7 +313,7 @@ LL |         if unsafe { true } {
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:509:23
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:514:23
    |
 LL |             let bar = unsafe {};
    |                       ^^^^^^^^^
@@ -321,7 +321,7 @@ LL |             let bar = unsafe {};
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:527:9
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:532:9
    |
 LL |         unsafe { a_function_with_a_very_long_name_to_break_the_line() };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -329,7 +329,7 @@ LL |         unsafe { a_function_with_a_very_long_name_to_break_the_line() };
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:531:9
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:536:9
    |
 LL |         unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -337,7 +337,7 @@ LL |         unsafe { a_const_function_with_a_very_long_name_to_break_the_line()
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:535:9
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:540:9
    |
 LL |         unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -345,7 +345,7 @@ LL |         unsafe { a_const_function_with_a_very_long_name_to_break_the_line()
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:541:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:546:5
    |
 LL |     unsafe {}
    |     ^^^^^^^^^
@@ -353,7 +353,7 @@ LL |     unsafe {}
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:545:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:550:5
    |
 LL |     unsafe {
    |     ^^^^^^^^
@@ -361,7 +361,7 @@ LL |     unsafe {
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:552:9
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:557:9
    |
 LL |         unsafe { a_function_with_a_very_long_name_to_break_the_line() };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -369,7 +369,7 @@ LL |         unsafe { a_function_with_a_very_long_name_to_break_the_line() };
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:557:9
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:562:9
    |
 LL |         unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -377,7 +377,7 @@ LL |         unsafe { a_const_function_with_a_very_long_name_to_break_the_line()
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:563:9
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:568:9
    |
 LL |         unsafe { a_const_function_with_a_very_long_name_to_break_the_line() };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -385,7 +385,7 @@ LL |         unsafe { a_const_function_with_a_very_long_name_to_break_the_line()
    = help: consider adding a safety comment on the preceding line
 
 error: unsafe block missing a safety comment
-  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:568:5
+  --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:573:5
    |
 LL |     unsafe {}
    |     ^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs
index 8997073c8a5..e5ef9d35fb6 100644
--- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs
@@ -4,7 +4,12 @@
 //@[disabled] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/undocumented_unsafe_blocks/disabled
 
 #![warn(clippy::undocumented_unsafe_blocks, clippy::unnecessary_safety_comment)]
-#![allow(deref_nullptr, non_local_definitions, clippy::let_unit_value, clippy::missing_safety_doc)]
+#![allow(
+    deref_nullptr,
+    non_local_definitions,
+    clippy::let_unit_value,
+    clippy::missing_safety_doc
+)]
 #![feature(lint_reasons)]
 
 extern crate proc_macro_unsafe;
diff --git a/src/tools/clippy/tests/ui/assigning_clones.fixed b/src/tools/clippy/tests/ui/assigning_clones.fixed
new file mode 100644
index 00000000000..c66e0c1f602
--- /dev/null
+++ b/src/tools/clippy/tests/ui/assigning_clones.fixed
@@ -0,0 +1,222 @@
+#![allow(unused)]
+#![allow(clippy::redundant_clone)]
+#![allow(clippy::ptr_arg)] // https://github.com/rust-lang/rust-clippy/issues/10612
+#![allow(clippy::needless_late_init)]
+#![allow(clippy::box_collection)]
+#![warn(clippy::assigning_clones)]
+
+use std::borrow::ToOwned;
+use std::ops::{Add, Deref, DerefMut};
+
+// Clone
+pub struct HasCloneFrom;
+
+impl Clone for HasCloneFrom {
+    fn clone(&self) -> Self {
+        Self
+    }
+    fn clone_from(&mut self, source: &Self) {
+        *self = HasCloneFrom;
+    }
+}
+
+fn clone_method_rhs_val(mut_thing: &mut HasCloneFrom, value_thing: HasCloneFrom) {
+    mut_thing.clone_from(&value_thing);
+}
+
+fn clone_method_rhs_ref(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
+    mut_thing.clone_from(ref_thing);
+}
+
+fn clone_method_lhs_val(mut mut_thing: HasCloneFrom, ref_thing: &HasCloneFrom) {
+    mut_thing.clone_from(ref_thing);
+}
+
+fn clone_function_lhs_mut_ref(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
+    Clone::clone_from(mut_thing, ref_thing);
+}
+
+fn clone_function_lhs_val(mut mut_thing: HasCloneFrom, ref_thing: &HasCloneFrom) {
+    Clone::clone_from(&mut mut_thing, ref_thing);
+}
+
+fn clone_function_through_trait(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
+    Clone::clone_from(mut_thing, ref_thing);
+}
+
+fn clone_function_through_type(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
+    Clone::clone_from(mut_thing, ref_thing);
+}
+
+fn clone_function_fully_qualified(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
+    Clone::clone_from(mut_thing, ref_thing);
+}
+
+fn clone_method_lhs_complex(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
+    // These parens should be kept as necessary for a receiver
+    (mut_thing + &mut HasCloneFrom).clone_from(ref_thing);
+}
+
+fn clone_method_rhs_complex(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
+    // These parens should be removed since they are not needed in a function argument
+    mut_thing.clone_from(ref_thing + ref_thing);
+}
+
+fn assign_to_init_mut_var(b: HasCloneFrom) -> HasCloneFrom {
+    let mut a = HasCloneFrom;
+    for _ in 1..10 {
+        a.clone_from(&b);
+    }
+    a
+}
+
+fn assign_to_late_init_mut_var(b: HasCloneFrom) {
+    let mut a;
+    a = HasCloneFrom;
+    a = b.clone();
+}
+
+fn assign_to_uninit_var(b: HasCloneFrom) {
+    let a;
+    a = b.clone();
+}
+
+fn assign_to_uninit_mut_var(b: HasCloneFrom) {
+    let mut a;
+    a = b.clone();
+}
+
+#[derive(Clone)]
+pub struct HasDeriveClone;
+
+fn ignore_derive_clone(a: &mut HasDeriveClone, b: &HasDeriveClone) {
+    // Should not be linted, since the Clone impl is derived
+    *a = b.clone();
+}
+
+pub struct HasCloneImpl;
+
+impl Clone for HasCloneImpl {
+    fn clone(&self) -> Self {
+        Self
+    }
+}
+
+fn ignore_missing_clone_from(a: &mut HasCloneImpl, b: &HasCloneImpl) {
+    // Should not be linted, since the Clone impl doesn't override clone_from
+    *a = b.clone();
+}
+
+struct FakeClone;
+
+impl FakeClone {
+    /// This looks just like `Clone::clone`
+    fn clone(&self) -> Self {
+        FakeClone
+    }
+}
+
+fn ignore_fake_clone() {
+    let mut a = FakeClone;
+    let b = FakeClone;
+    // Should not be linted, since the Clone impl doesn't come from std
+    a = b.clone();
+}
+
+fn ignore_generic_clone<T: Clone>(a: &mut T, b: &T) {
+    // Should not be linted, since we don't know the actual clone impl
+    *a = b.clone();
+}
+
+macro_rules! clone_inside {
+    ($a:expr, $b: expr) => {
+        $a = $b.clone();
+    };
+}
+
+fn clone_inside_macro() {
+    let mut a = String::new();
+    let b = String::new();
+    clone_inside!(a, b);
+}
+
+// ToOwned
+fn owned_method_mut_ref(mut_string: &mut String, ref_str: &str) {
+    ref_str.clone_into(mut_string);
+}
+
+fn owned_method_val(mut mut_string: String, ref_str: &str) {
+    ref_str.clone_into(&mut mut_string);
+}
+
+struct HasDeref {
+    a: String,
+}
+
+impl Deref for HasDeref {
+    type Target = String;
+    fn deref(&self) -> &Self::Target {
+        &self.a
+    }
+}
+
+impl DerefMut for HasDeref {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.a
+    }
+}
+
+fn owned_method_box(mut_box_string: &mut Box<String>, ref_str: &str) {
+    ref_str.clone_into(&mut (*mut_box_string));
+}
+
+fn owned_method_deref(mut_box_string: &mut HasDeref, ref_str: &str) {
+    ref_str.clone_into(&mut (*mut_box_string));
+}
+
+fn owned_function_mut_ref(mut_thing: &mut String, ref_str: &str) {
+    ToOwned::clone_into(ref_str, mut_thing);
+}
+
+fn owned_function_val(mut mut_thing: String, ref_str: &str) {
+    ToOwned::clone_into(ref_str, &mut mut_thing);
+}
+
+struct FakeToOwned;
+impl FakeToOwned {
+    /// This looks just like `ToOwned::to_owned`
+    fn to_owned(&self) -> Self {
+        FakeToOwned
+    }
+}
+
+fn fake_to_owned() {
+    let mut a = FakeToOwned;
+    let b = FakeToOwned;
+    // Should not be linted, since the ToOwned impl doesn't come from std
+    a = b.to_owned();
+}
+
+fn main() {}
+
+/// Trait implementation to allow producing a `Thing` with a low-precedence expression.
+impl Add for HasCloneFrom {
+    type Output = Self;
+    fn add(self, _: HasCloneFrom) -> Self {
+        self
+    }
+}
+/// Trait implementation to allow producing a `&Thing` with a low-precedence expression.
+impl<'a> Add for &'a HasCloneFrom {
+    type Output = Self;
+    fn add(self, _: &'a HasCloneFrom) -> Self {
+        self
+    }
+}
+/// Trait implementation to allow producing a `&mut Thing` with a low-precedence expression.
+impl<'a> Add for &'a mut HasCloneFrom {
+    type Output = Self;
+    fn add(self, _: &'a mut HasCloneFrom) -> Self {
+        self
+    }
+}
diff --git a/src/tools/clippy/tests/ui/assigning_clones.rs b/src/tools/clippy/tests/ui/assigning_clones.rs
new file mode 100644
index 00000000000..b9f994d3e03
--- /dev/null
+++ b/src/tools/clippy/tests/ui/assigning_clones.rs
@@ -0,0 +1,222 @@
+#![allow(unused)]
+#![allow(clippy::redundant_clone)]
+#![allow(clippy::ptr_arg)] // https://github.com/rust-lang/rust-clippy/issues/10612
+#![allow(clippy::needless_late_init)]
+#![allow(clippy::box_collection)]
+#![warn(clippy::assigning_clones)]
+
+use std::borrow::ToOwned;
+use std::ops::{Add, Deref, DerefMut};
+
+// Clone
+pub struct HasCloneFrom;
+
+impl Clone for HasCloneFrom {
+    fn clone(&self) -> Self {
+        Self
+    }
+    fn clone_from(&mut self, source: &Self) {
+        *self = HasCloneFrom;
+    }
+}
+
+fn clone_method_rhs_val(mut_thing: &mut HasCloneFrom, value_thing: HasCloneFrom) {
+    *mut_thing = value_thing.clone();
+}
+
+fn clone_method_rhs_ref(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
+    *mut_thing = ref_thing.clone();
+}
+
+fn clone_method_lhs_val(mut mut_thing: HasCloneFrom, ref_thing: &HasCloneFrom) {
+    mut_thing = ref_thing.clone();
+}
+
+fn clone_function_lhs_mut_ref(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
+    *mut_thing = Clone::clone(ref_thing);
+}
+
+fn clone_function_lhs_val(mut mut_thing: HasCloneFrom, ref_thing: &HasCloneFrom) {
+    mut_thing = Clone::clone(ref_thing);
+}
+
+fn clone_function_through_trait(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
+    *mut_thing = Clone::clone(ref_thing);
+}
+
+fn clone_function_through_type(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
+    *mut_thing = HasCloneFrom::clone(ref_thing);
+}
+
+fn clone_function_fully_qualified(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
+    *mut_thing = <HasCloneFrom as Clone>::clone(ref_thing);
+}
+
+fn clone_method_lhs_complex(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
+    // These parens should be kept as necessary for a receiver
+    *(mut_thing + &mut HasCloneFrom) = ref_thing.clone();
+}
+
+fn clone_method_rhs_complex(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
+    // These parens should be removed since they are not needed in a function argument
+    *mut_thing = (ref_thing + ref_thing).clone();
+}
+
+fn assign_to_init_mut_var(b: HasCloneFrom) -> HasCloneFrom {
+    let mut a = HasCloneFrom;
+    for _ in 1..10 {
+        a = b.clone();
+    }
+    a
+}
+
+fn assign_to_late_init_mut_var(b: HasCloneFrom) {
+    let mut a;
+    a = HasCloneFrom;
+    a = b.clone();
+}
+
+fn assign_to_uninit_var(b: HasCloneFrom) {
+    let a;
+    a = b.clone();
+}
+
+fn assign_to_uninit_mut_var(b: HasCloneFrom) {
+    let mut a;
+    a = b.clone();
+}
+
+#[derive(Clone)]
+pub struct HasDeriveClone;
+
+fn ignore_derive_clone(a: &mut HasDeriveClone, b: &HasDeriveClone) {
+    // Should not be linted, since the Clone impl is derived
+    *a = b.clone();
+}
+
+pub struct HasCloneImpl;
+
+impl Clone for HasCloneImpl {
+    fn clone(&self) -> Self {
+        Self
+    }
+}
+
+fn ignore_missing_clone_from(a: &mut HasCloneImpl, b: &HasCloneImpl) {
+    // Should not be linted, since the Clone impl doesn't override clone_from
+    *a = b.clone();
+}
+
+struct FakeClone;
+
+impl FakeClone {
+    /// This looks just like `Clone::clone`
+    fn clone(&self) -> Self {
+        FakeClone
+    }
+}
+
+fn ignore_fake_clone() {
+    let mut a = FakeClone;
+    let b = FakeClone;
+    // Should not be linted, since the Clone impl doesn't come from std
+    a = b.clone();
+}
+
+fn ignore_generic_clone<T: Clone>(a: &mut T, b: &T) {
+    // Should not be linted, since we don't know the actual clone impl
+    *a = b.clone();
+}
+
+macro_rules! clone_inside {
+    ($a:expr, $b: expr) => {
+        $a = $b.clone();
+    };
+}
+
+fn clone_inside_macro() {
+    let mut a = String::new();
+    let b = String::new();
+    clone_inside!(a, b);
+}
+
+// ToOwned
+fn owned_method_mut_ref(mut_string: &mut String, ref_str: &str) {
+    *mut_string = ref_str.to_owned();
+}
+
+fn owned_method_val(mut mut_string: String, ref_str: &str) {
+    mut_string = ref_str.to_owned();
+}
+
+struct HasDeref {
+    a: String,
+}
+
+impl Deref for HasDeref {
+    type Target = String;
+    fn deref(&self) -> &Self::Target {
+        &self.a
+    }
+}
+
+impl DerefMut for HasDeref {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.a
+    }
+}
+
+fn owned_method_box(mut_box_string: &mut Box<String>, ref_str: &str) {
+    **mut_box_string = ref_str.to_owned();
+}
+
+fn owned_method_deref(mut_box_string: &mut HasDeref, ref_str: &str) {
+    **mut_box_string = ref_str.to_owned();
+}
+
+fn owned_function_mut_ref(mut_thing: &mut String, ref_str: &str) {
+    *mut_thing = ToOwned::to_owned(ref_str);
+}
+
+fn owned_function_val(mut mut_thing: String, ref_str: &str) {
+    mut_thing = ToOwned::to_owned(ref_str);
+}
+
+struct FakeToOwned;
+impl FakeToOwned {
+    /// This looks just like `ToOwned::to_owned`
+    fn to_owned(&self) -> Self {
+        FakeToOwned
+    }
+}
+
+fn fake_to_owned() {
+    let mut a = FakeToOwned;
+    let b = FakeToOwned;
+    // Should not be linted, since the ToOwned impl doesn't come from std
+    a = b.to_owned();
+}
+
+fn main() {}
+
+/// Trait implementation to allow producing a `Thing` with a low-precedence expression.
+impl Add for HasCloneFrom {
+    type Output = Self;
+    fn add(self, _: HasCloneFrom) -> Self {
+        self
+    }
+}
+/// Trait implementation to allow producing a `&Thing` with a low-precedence expression.
+impl<'a> Add for &'a HasCloneFrom {
+    type Output = Self;
+    fn add(self, _: &'a HasCloneFrom) -> Self {
+        self
+    }
+}
+/// Trait implementation to allow producing a `&mut Thing` with a low-precedence expression.
+impl<'a> Add for &'a mut HasCloneFrom {
+    type Output = Self;
+    fn add(self, _: &'a mut HasCloneFrom) -> Self {
+        self
+    }
+}
diff --git a/src/tools/clippy/tests/ui/assigning_clones.stderr b/src/tools/clippy/tests/ui/assigning_clones.stderr
new file mode 100644
index 00000000000..b76323f3606
--- /dev/null
+++ b/src/tools/clippy/tests/ui/assigning_clones.stderr
@@ -0,0 +1,107 @@
+error: assigning the result of `Clone::clone()` may be inefficient
+  --> tests/ui/assigning_clones.rs:24:5
+   |
+LL |     *mut_thing = value_thing.clone();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `mut_thing.clone_from(&value_thing)`
+   |
+   = note: `-D clippy::assigning-clones` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::assigning_clones)]`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+  --> tests/ui/assigning_clones.rs:28:5
+   |
+LL |     *mut_thing = ref_thing.clone();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `mut_thing.clone_from(ref_thing)`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+  --> tests/ui/assigning_clones.rs:32:5
+   |
+LL |     mut_thing = ref_thing.clone();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `mut_thing.clone_from(ref_thing)`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+  --> tests/ui/assigning_clones.rs:36:5
+   |
+LL |     *mut_thing = Clone::clone(ref_thing);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+  --> tests/ui/assigning_clones.rs:40:5
+   |
+LL |     mut_thing = Clone::clone(ref_thing);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(&mut mut_thing, ref_thing)`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+  --> tests/ui/assigning_clones.rs:44:5
+   |
+LL |     *mut_thing = Clone::clone(ref_thing);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+  --> tests/ui/assigning_clones.rs:48:5
+   |
+LL |     *mut_thing = HasCloneFrom::clone(ref_thing);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+  --> tests/ui/assigning_clones.rs:52:5
+   |
+LL |     *mut_thing = <HasCloneFrom as Clone>::clone(ref_thing);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+  --> tests/ui/assigning_clones.rs:57:5
+   |
+LL |     *(mut_thing + &mut HasCloneFrom) = ref_thing.clone();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `(mut_thing + &mut HasCloneFrom).clone_from(ref_thing)`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+  --> tests/ui/assigning_clones.rs:62:5
+   |
+LL |     *mut_thing = (ref_thing + ref_thing).clone();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `mut_thing.clone_from(ref_thing + ref_thing)`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+  --> tests/ui/assigning_clones.rs:68:9
+   |
+LL |         a = b.clone();
+   |         ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)`
+
+error: assigning the result of `ToOwned::to_owned()` may be inefficient
+  --> tests/ui/assigning_clones.rs:145:5
+   |
+LL |     *mut_string = ref_str.to_owned();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(mut_string)`
+
+error: assigning the result of `ToOwned::to_owned()` may be inefficient
+  --> tests/ui/assigning_clones.rs:149:5
+   |
+LL |     mut_string = ref_str.to_owned();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut mut_string)`
+
+error: assigning the result of `ToOwned::to_owned()` may be inefficient
+  --> tests/ui/assigning_clones.rs:170:5
+   |
+LL |     **mut_box_string = ref_str.to_owned();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))`
+
+error: assigning the result of `ToOwned::to_owned()` may be inefficient
+  --> tests/ui/assigning_clones.rs:174:5
+   |
+LL |     **mut_box_string = ref_str.to_owned();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))`
+
+error: assigning the result of `ToOwned::to_owned()` may be inefficient
+  --> tests/ui/assigning_clones.rs:178:5
+   |
+LL |     *mut_thing = ToOwned::to_owned(ref_str);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, mut_thing)`
+
+error: assigning the result of `ToOwned::to_owned()` may be inefficient
+  --> tests/ui/assigning_clones.rs:182:5
+   |
+LL |     mut_thing = ToOwned::to_owned(ref_str);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, &mut mut_thing)`
+
+error: aborting due to 17 previous errors
+
diff --git a/src/tools/clippy/tests/ui/crashes/unreachable-array-or-slice.rs b/src/tools/clippy/tests/ui/crashes/unreachable-array-or-slice.rs
index b56abccbd41..e920e58d6ec 100644
--- a/src/tools/clippy/tests/ui/crashes/unreachable-array-or-slice.rs
+++ b/src/tools/clippy/tests/ui/crashes/unreachable-array-or-slice.rs
@@ -3,6 +3,6 @@ struct Foo(isize, isize, isize, isize);
 pub fn main() {
     let Self::anything_here_kills_it(a, b, ..) = Foo(5, 5, 5, 5);
     match [5, 5, 5, 5] {
-        [..] => { }
+        [..] => {},
     }
 }
diff --git a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed
index aa7a95405e0..6f42487bbf4 100644
--- a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed
+++ b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed
@@ -153,4 +153,30 @@ pub enum MissingEqNonExhaustive3 {
     Bar,
 }
 
+mod struct_gen {
+    // issue 9413
+    pub trait Group {
+        type Element: Eq + PartialEq;
+    }
+
+    pub trait Suite {
+        type Group: Group;
+    }
+
+    #[derive(PartialEq, Eq)]
+    //~^ ERROR: you are deriving `PartialEq` and can implement `Eq`
+    pub struct Foo<C: Suite>(<C::Group as Group>::Element);
+
+    #[derive(PartialEq, Eq)]
+    pub struct Bar<C: Suite>(i32, <C::Group as Group>::Element);
+
+    // issue 9319
+    #[derive(PartialEq, Eq)]
+    //~^ ERROR: you are deriving `PartialEq` and can implement `Eq`
+    pub struct Oof<T: Fn()>(T);
+
+    #[derive(PartialEq, Eq)]
+    pub struct Rab<T: Fn()>(T);
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs
index 90ac7a7989e..24f687c6c9d 100644
--- a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs
+++ b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs
@@ -153,4 +153,30 @@ pub enum MissingEqNonExhaustive3 {
     Bar,
 }
 
+mod struct_gen {
+    // issue 9413
+    pub trait Group {
+        type Element: Eq + PartialEq;
+    }
+
+    pub trait Suite {
+        type Group: Group;
+    }
+
+    #[derive(PartialEq)]
+    //~^ ERROR: you are deriving `PartialEq` and can implement `Eq`
+    pub struct Foo<C: Suite>(<C::Group as Group>::Element);
+
+    #[derive(PartialEq, Eq)]
+    pub struct Bar<C: Suite>(i32, <C::Group as Group>::Element);
+
+    // issue 9319
+    #[derive(PartialEq)]
+    //~^ ERROR: you are deriving `PartialEq` and can implement `Eq`
+    pub struct Oof<T: Fn()>(T);
+
+    #[derive(PartialEq, Eq)]
+    pub struct Rab<T: Fn()>(T);
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.stderr b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.stderr
index 42b9895121f..3d92112dc36 100644
--- a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.stderr
+++ b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.stderr
@@ -67,5 +67,17 @@ error: you are deriving `PartialEq` and can implement `Eq`
 LL |     #[derive(PartialEq)]
    |              ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
 
-error: aborting due to 11 previous errors
+error: you are deriving `PartialEq` and can implement `Eq`
+  --> tests/ui/derive_partial_eq_without_eq.rs:166:14
+   |
+LL |     #[derive(PartialEq)]
+   |              ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
+
+error: you are deriving `PartialEq` and can implement `Eq`
+  --> tests/ui/derive_partial_eq_without_eq.rs:174:14
+   |
+LL |     #[derive(PartialEq)]
+   |              ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq`
+
+error: aborting due to 13 previous errors
 
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
index 16f7bafd44b..178d4a1aa2b 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
@@ -230,3 +230,8 @@ fn issue_11568() {}
 
 /// There is no try (`do()` or `do_not()`).
 fn parenthesized_word() {}
+
+/// `ABes`
+/// OSes
+/// UXes
+fn plural_acronym_test() {}
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
index 4058b2bad74..01edb44c64c 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.rs
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
@@ -230,3 +230,8 @@ fn issue_11568() {}
 
 /// There is no try (do() or do_not()).
 fn parenthesized_word() {}
+
+/// ABes
+/// OSes
+/// UXes
+fn plural_acronym_test() {}
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
index 7db9ff2b83b..ac876306b39 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
@@ -341,5 +341,16 @@ help: try
 LL | /// There is no try (do() or `do_not()`).
    |                              ~~~~~~~~~~
 
-error: aborting due to 31 previous errors
+error: item in documentation is missing backticks
+  --> tests/ui/doc/doc-fixable.rs:234:5
+   |
+LL | /// ABes
+   |     ^^^^
+   |
+help: try
+   |
+LL | /// `ABes`
+   |     ~~~~~~
+
+error: aborting due to 32 previous errors
 
diff --git a/src/tools/clippy/tests/ui/doc/issue_9473.fixed b/src/tools/clippy/tests/ui/doc/issue_9473.fixed
new file mode 100644
index 00000000000..276ce7620ca
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/issue_9473.fixed
@@ -0,0 +1,9 @@
+#![warn(clippy::doc_markdown)]
+
+// Should not warn!
+/// Blah blah blah <code>[FooBar]&lt;[FooBar]&gt;</code>.
+pub struct Foo(u32);
+
+// Should warn.
+/// Blah blah blah <code>[FooBar]&lt;[FooBar]&gt;</code>[`FooBar`].
+pub struct FooBar(u32);
diff --git a/src/tools/clippy/tests/ui/doc/issue_9473.rs b/src/tools/clippy/tests/ui/doc/issue_9473.rs
new file mode 100644
index 00000000000..52527f7106d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/issue_9473.rs
@@ -0,0 +1,9 @@
+#![warn(clippy::doc_markdown)]
+
+// Should not warn!
+/// Blah blah blah <code>[FooBar]&lt;[FooBar]&gt;</code>.
+pub struct Foo(u32);
+
+// Should warn.
+/// Blah blah blah <code>[FooBar]&lt;[FooBar]&gt;</code>[FooBar].
+pub struct FooBar(u32);
diff --git a/src/tools/clippy/tests/ui/doc/issue_9473.stderr b/src/tools/clippy/tests/ui/doc/issue_9473.stderr
new file mode 100644
index 00000000000..35aa2884cc1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/issue_9473.stderr
@@ -0,0 +1,15 @@
+error: item in documentation is missing backticks
+  --> tests/ui/doc/issue_9473.rs:8:58
+   |
+LL | /// Blah blah blah <code>[FooBar]&lt;[FooBar]&gt;</code>[FooBar].
+   |                                                          ^^^^^^
+   |
+   = note: `-D clippy::doc-markdown` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::doc_markdown)]`
+help: try
+   |
+LL | /// Blah blah blah <code>[FooBar]&lt;[FooBar]&gt;</code>[`FooBar`].
+   |                                                          ~~~~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/clippy/tests/ui/else_if_without_else.rs b/src/tools/clippy/tests/ui/else_if_without_else.rs
index eb5e2266540..e7786f7dd27 100644
--- a/src/tools/clippy/tests/ui/else_if_without_else.rs
+++ b/src/tools/clippy/tests/ui/else_if_without_else.rs
@@ -1,3 +1,5 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![warn(clippy::all)]
 #![warn(clippy::else_if_without_else)]
 
diff --git a/src/tools/clippy/tests/ui/else_if_without_else.stderr b/src/tools/clippy/tests/ui/else_if_without_else.stderr
index 80355cb2dba..3bb840f39e7 100644
--- a/src/tools/clippy/tests/ui/else_if_without_else.stderr
+++ b/src/tools/clippy/tests/ui/else_if_without_else.stderr
@@ -1,5 +1,5 @@
 error: `if` expression with an `else if`, but without a final `else`
-  --> tests/ui/else_if_without_else.rs:45:12
+  --> tests/ui/else_if_without_else.rs:47:12
    |
 LL |       } else if bla2() {
    |  ____________^
@@ -13,7 +13,7 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::else_if_without_else)]`
 
 error: `if` expression with an `else if`, but without a final `else`
-  --> tests/ui/else_if_without_else.rs:54:12
+  --> tests/ui/else_if_without_else.rs:56:12
    |
 LL |       } else if bla3() {
    |  ____________^
diff --git a/src/tools/clippy/tests/ui/empty_docs.rs b/src/tools/clippy/tests/ui/empty_docs.rs
index c47a603e71b..272fab7d5ca 100644
--- a/src/tools/clippy/tests/ui/empty_docs.rs
+++ b/src/tools/clippy/tests/ui/empty_docs.rs
@@ -1,5 +1,7 @@
 #![allow(unused)]
 #![warn(clippy::empty_docs)]
+#![allow(clippy::mixed_attributes_style)]
+
 mod outer {
     //!
 
diff --git a/src/tools/clippy/tests/ui/empty_docs.stderr b/src/tools/clippy/tests/ui/empty_docs.stderr
index 3f1d071fb13..f12aead6aa7 100644
--- a/src/tools/clippy/tests/ui/empty_docs.stderr
+++ b/src/tools/clippy/tests/ui/empty_docs.stderr
@@ -1,5 +1,5 @@
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:4:5
+  --> tests/ui/empty_docs.rs:6:5
    |
 LL |     //!
    |     ^^^
@@ -9,7 +9,7 @@ LL |     //!
    = help: to override `-D warnings` add `#[allow(clippy::empty_docs)]`
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:12:5
+  --> tests/ui/empty_docs.rs:14:5
    |
 LL |     ///
    |     ^^^
@@ -17,7 +17,7 @@ LL |     ///
    = help: consider removing or filling it
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:14:9
+  --> tests/ui/empty_docs.rs:16:9
    |
 LL |         ///
    |         ^^^
@@ -25,7 +25,7 @@ LL |         ///
    = help: consider removing or filling it
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:25:5
+  --> tests/ui/empty_docs.rs:27:5
    |
 LL |     #[doc = ""]
    |     ^^^^^^^^^^^
@@ -33,7 +33,7 @@ LL |     #[doc = ""]
    = help: consider removing or filling it
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:28:5
+  --> tests/ui/empty_docs.rs:30:5
    |
 LL | /     #[doc = ""]
 LL | |     #[doc = ""]
@@ -42,7 +42,7 @@ LL | |     #[doc = ""]
    = help: consider removing or filling it
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:35:5
+  --> tests/ui/empty_docs.rs:37:5
    |
 LL |     ///
    |     ^^^
@@ -50,7 +50,7 @@ LL |     ///
    = help: consider removing or filling it
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:48:13
+  --> tests/ui/empty_docs.rs:50:13
    |
 LL |             /*! */
    |             ^^^^^^
@@ -58,7 +58,7 @@ LL |             /*! */
    = help: consider removing or filling it
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:56:13
+  --> tests/ui/empty_docs.rs:58:13
    |
 LL |             ///
    |             ^^^
@@ -66,7 +66,7 @@ LL |             ///
    = help: consider removing or filling it
 
 error: empty doc comment
-  --> tests/ui/empty_docs.rs:64:9
+  --> tests/ui/empty_docs.rs:66:9
    |
 LL |         ///
    |         ^^^
diff --git a/src/tools/clippy/tests/ui/entry.fixed b/src/tools/clippy/tests/ui/entry.fixed
index 4099fe7e139..71ec13f4610 100644
--- a/src/tools/clippy/tests/ui/entry.fixed
+++ b/src/tools/clippy/tests/ui/entry.fixed
@@ -165,4 +165,15 @@ pub fn issue_10331() {
     }
 }
 
+/// Issue 11935
+/// Do not suggest using entries if the map is used inside the `insert` expression.
+pub fn issue_11935() {
+    let mut counts: HashMap<u64, u64> = HashMap::new();
+    if !counts.contains_key(&1) {
+        counts.insert(1, 1);
+    } else {
+        counts.insert(1, counts.get(&1).unwrap() + 1);
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/entry.rs b/src/tools/clippy/tests/ui/entry.rs
index 409be0aa060..86092b7c055 100644
--- a/src/tools/clippy/tests/ui/entry.rs
+++ b/src/tools/clippy/tests/ui/entry.rs
@@ -169,4 +169,15 @@ pub fn issue_10331() {
     }
 }
 
+/// Issue 11935
+/// Do not suggest using entries if the map is used inside the `insert` expression.
+pub fn issue_11935() {
+    let mut counts: HashMap<u64, u64> = HashMap::new();
+    if !counts.contains_key(&1) {
+        counts.insert(1, 1);
+    } else {
+        counts.insert(1, counts.get(&1).unwrap() + 1);
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/explicit_iter_loop.fixed b/src/tools/clippy/tests/ui/explicit_iter_loop.fixed
index 06229a52a18..f38b34c5a7c 100644
--- a/src/tools/clippy/tests/ui/explicit_iter_loop.fixed
+++ b/src/tools/clippy/tests/ui/explicit_iter_loop.fixed
@@ -6,7 +6,7 @@
     clippy::deref_addrof,
     clippy::unnecessary_mut_passed,
     dead_code,
-    non_local_definitions,
+    non_local_definitions
 )]
 
 use core::slice;
diff --git a/src/tools/clippy/tests/ui/explicit_iter_loop.rs b/src/tools/clippy/tests/ui/explicit_iter_loop.rs
index c2bf45ab2e9..2e701ada5ac 100644
--- a/src/tools/clippy/tests/ui/explicit_iter_loop.rs
+++ b/src/tools/clippy/tests/ui/explicit_iter_loop.rs
@@ -6,7 +6,7 @@
     clippy::deref_addrof,
     clippy::unnecessary_mut_passed,
     dead_code,
-    non_local_definitions,
+    non_local_definitions
 )]
 
 use core::slice;
diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.rs b/src/tools/clippy/tests/ui/field_reassign_with_default.rs
index 2045b1eebcd..620cffb4f04 100644
--- a/src/tools/clippy/tests/ui/field_reassign_with_default.rs
+++ b/src/tools/clippy/tests/ui/field_reassign_with_default.rs
@@ -2,6 +2,7 @@
 //@aux-build:proc_macros.rs
 
 #![warn(clippy::field_reassign_with_default)]
+#![allow(clippy::assigning_clones)]
 
 #[macro_use]
 extern crate proc_macro_derive;
diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.stderr b/src/tools/clippy/tests/ui/field_reassign_with_default.stderr
index bc032834920..ae909475c6f 100644
--- a/src/tools/clippy/tests/ui/field_reassign_with_default.stderr
+++ b/src/tools/clippy/tests/ui/field_reassign_with_default.stderr
@@ -1,11 +1,11 @@
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> tests/ui/field_reassign_with_default.rs:56:5
+  --> tests/ui/field_reassign_with_default.rs:57:5
    |
 LL |     a.i = 42;
    |     ^^^^^^^^^
    |
 note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments
-  --> tests/ui/field_reassign_with_default.rs:55:5
+  --> tests/ui/field_reassign_with_default.rs:56:5
    |
 LL |     let mut a: A = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -13,121 +13,121 @@ LL |     let mut a: A = Default::default();
    = help: to override `-D warnings` add `#[allow(clippy::field_reassign_with_default)]`
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> tests/ui/field_reassign_with_default.rs:96:5
+  --> tests/ui/field_reassign_with_default.rs:97:5
    |
 LL |     a.j = 43;
    |     ^^^^^^^^^
    |
 note: consider initializing the variable with `main::A { j: 43, i: 42 }` and removing relevant reassignments
-  --> tests/ui/field_reassign_with_default.rs:95:5
+  --> tests/ui/field_reassign_with_default.rs:96:5
    |
 LL |     let mut a: A = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> tests/ui/field_reassign_with_default.rs:101:5
+  --> tests/ui/field_reassign_with_default.rs:102:5
    |
 LL |     a.i = 42;
    |     ^^^^^^^^^
    |
 note: consider initializing the variable with `main::A { i: 42, j: 44 }` and removing relevant reassignments
-  --> tests/ui/field_reassign_with_default.rs:100:5
+  --> tests/ui/field_reassign_with_default.rs:101:5
    |
 LL |     let mut a: A = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> tests/ui/field_reassign_with_default.rs:107:5
+  --> tests/ui/field_reassign_with_default.rs:108:5
    |
 LL |     a.i = 42;
    |     ^^^^^^^^^
    |
 note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments
-  --> tests/ui/field_reassign_with_default.rs:106:5
+  --> tests/ui/field_reassign_with_default.rs:107:5
    |
 LL |     let mut a = A::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> tests/ui/field_reassign_with_default.rs:117:5
+  --> tests/ui/field_reassign_with_default.rs:118:5
    |
 LL |     a.i = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: consider initializing the variable with `main::A { i: Default::default(), ..Default::default() }` and removing relevant reassignments
-  --> tests/ui/field_reassign_with_default.rs:116:5
+  --> tests/ui/field_reassign_with_default.rs:117:5
    |
 LL |     let mut a: A = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> tests/ui/field_reassign_with_default.rs:121:5
+  --> tests/ui/field_reassign_with_default.rs:122:5
    |
 LL |     a.i = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: consider initializing the variable with `main::A { i: Default::default(), j: 45 }` and removing relevant reassignments
-  --> tests/ui/field_reassign_with_default.rs:120:5
+  --> tests/ui/field_reassign_with_default.rs:121:5
    |
 LL |     let mut a: A = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> tests/ui/field_reassign_with_default.rs:143:5
+  --> tests/ui/field_reassign_with_default.rs:144:5
    |
 LL |     a.i = vec![1];
    |     ^^^^^^^^^^^^^^
    |
 note: consider initializing the variable with `C { i: vec![1], ..Default::default() }` and removing relevant reassignments
-  --> tests/ui/field_reassign_with_default.rs:142:5
+  --> tests/ui/field_reassign_with_default.rs:143:5
    |
 LL |     let mut a: C = C::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> tests/ui/field_reassign_with_default.rs:161:5
+  --> tests/ui/field_reassign_with_default.rs:162:5
    |
 LL |     a.i = true;
    |     ^^^^^^^^^^^
    |
 note: consider initializing the variable with `Wrapper::<bool> { i: true }` and removing relevant reassignments
-  --> tests/ui/field_reassign_with_default.rs:160:5
+  --> tests/ui/field_reassign_with_default.rs:161:5
    |
 LL |     let mut a: Wrapper<bool> = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> tests/ui/field_reassign_with_default.rs:164:5
+  --> tests/ui/field_reassign_with_default.rs:165:5
    |
 LL |     a.i = 42;
    |     ^^^^^^^^^
    |
 note: consider initializing the variable with `WrapperMulti::<i32, i64> { i: 42, ..Default::default() }` and removing relevant reassignments
-  --> tests/ui/field_reassign_with_default.rs:163:5
+  --> tests/ui/field_reassign_with_default.rs:164:5
    |
 LL |     let mut a: WrapperMulti<i32, i64> = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> tests/ui/field_reassign_with_default.rs:235:13
+  --> tests/ui/field_reassign_with_default.rs:236:13
    |
 LL |             f.name = name.len();
    |             ^^^^^^^^^^^^^^^^^^^^
    |
 note: consider initializing the variable with `issue6312::ImplDropAllCopy { name: name.len(), ..Default::default() }` and removing relevant reassignments
-  --> tests/ui/field_reassign_with_default.rs:234:13
+  --> tests/ui/field_reassign_with_default.rs:235:13
    |
 LL |             let mut f = ImplDropAllCopy::default();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> tests/ui/field_reassign_with_default.rs:251:13
+  --> tests/ui/field_reassign_with_default.rs:252:13
    |
 LL |             f.name = name.len();
    |             ^^^^^^^^^^^^^^^^^^^^
    |
 note: consider initializing the variable with `issue6312::NoDropAllCopy { name: name.len(), ..Default::default() }` and removing relevant reassignments
-  --> tests/ui/field_reassign_with_default.rs:250:13
+  --> tests/ui/field_reassign_with_default.rs:251:13
    |
 LL |             let mut f = NoDropAllCopy::default();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/identity_op.fixed b/src/tools/clippy/tests/ui/identity_op.fixed
index 660e9a21b18..b18d8560f6f 100644
--- a/src/tools/clippy/tests/ui/identity_op.fixed
+++ b/src/tools/clippy/tests/ui/identity_op.fixed
@@ -134,7 +134,7 @@ fn main() {
     //~^ ERROR: this operation has no effect
     f(if b { 1 } else { 2 } + 3);
     //~^ ERROR: this operation has no effect
-    
+
     const _: i32 = { 2 * 4 } + 3;
     //~^ ERROR: this operation has no effect
     const _: i32 = { 1 + 2 * 3 } + 3;
diff --git a/src/tools/clippy/tests/ui/identity_op.rs b/src/tools/clippy/tests/ui/identity_op.rs
index bbef531e9dc..f1f01b42447 100644
--- a/src/tools/clippy/tests/ui/identity_op.rs
+++ b/src/tools/clippy/tests/ui/identity_op.rs
@@ -134,7 +134,7 @@ fn main() {
     //~^ ERROR: this operation has no effect
     f(0 + if b { 1 } else { 2 } + 3);
     //~^ ERROR: this operation has no effect
-    
+
     const _: i32 = { 2 * 4 } + 0 + 3;
     //~^ ERROR: this operation has no effect
     const _: i32 = 0 + { 1 + 2 * 3 } + 3;
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.rs b/src/tools/clippy/tests/ui/indexing_slicing_index.rs
index 2ababad7fc7..27ee2f91594 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_index.rs
+++ b/src/tools/clippy/tests/ui/indexing_slicing_index.rs
@@ -1,3 +1,5 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![feature(inline_const)]
 #![warn(clippy::indexing_slicing)]
 // We also check the out_of_bounds_indexing lint here, because it lints similar things and
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
index 06a4defcb93..5f62ec9b556 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
+++ b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
@@ -1,5 +1,5 @@
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:14:20
+  --> tests/ui/indexing_slicing_index.rs:16:20
    |
 LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false.
    |                    ^^^^^^^^^^
@@ -10,19 +10,19 @@ LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-re
    = help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]`
 
 error[E0080]: evaluation of `main::{constant#3}` failed
-  --> tests/ui/indexing_slicing_index.rs:46:14
+  --> tests/ui/indexing_slicing_index.rs:48:14
    |
 LL |     const { &ARR[idx4()] };
    |              ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
 
 note: erroneous constant encountered
-  --> tests/ui/indexing_slicing_index.rs:46:5
+  --> tests/ui/indexing_slicing_index.rs:48:5
    |
 LL |     const { &ARR[idx4()] };
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:27:5
+  --> tests/ui/indexing_slicing_index.rs:29:5
    |
 LL |     x[index];
    |     ^^^^^^^^
@@ -30,7 +30,7 @@ LL |     x[index];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: index is out of bounds
-  --> tests/ui/indexing_slicing_index.rs:30:5
+  --> tests/ui/indexing_slicing_index.rs:32:5
    |
 LL |     x[4];
    |     ^^^^
@@ -39,13 +39,13 @@ LL |     x[4];
    = help: to override `-D warnings` add `#[allow(clippy::out_of_bounds_indexing)]`
 
 error: index is out of bounds
-  --> tests/ui/indexing_slicing_index.rs:32:5
+  --> tests/ui/indexing_slicing_index.rs:34:5
    |
 LL |     x[1 << 3];
    |     ^^^^^^^^^
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:43:14
+  --> tests/ui/indexing_slicing_index.rs:45:14
    |
 LL |     const { &ARR[idx()] };
    |              ^^^^^^^^^^
@@ -54,7 +54,7 @@ LL |     const { &ARR[idx()] };
    = note: the suggestion might not be applicable in constant blocks
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:46:14
+  --> tests/ui/indexing_slicing_index.rs:48:14
    |
 LL |     const { &ARR[idx4()] };
    |              ^^^^^^^^^^^
@@ -63,13 +63,13 @@ LL |     const { &ARR[idx4()] };
    = note: the suggestion might not be applicable in constant blocks
 
 error: index is out of bounds
-  --> tests/ui/indexing_slicing_index.rs:53:5
+  --> tests/ui/indexing_slicing_index.rs:55:5
    |
 LL |     y[4];
    |     ^^^^
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:56:5
+  --> tests/ui/indexing_slicing_index.rs:58:5
    |
 LL |     v[0];
    |     ^^^^
@@ -77,7 +77,7 @@ LL |     v[0];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:58:5
+  --> tests/ui/indexing_slicing_index.rs:60:5
    |
 LL |     v[10];
    |     ^^^^^
@@ -85,7 +85,7 @@ LL |     v[10];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:60:5
+  --> tests/ui/indexing_slicing_index.rs:62:5
    |
 LL |     v[1 << 3];
    |     ^^^^^^^^^
@@ -93,13 +93,13 @@ LL |     v[1 << 3];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: index is out of bounds
-  --> tests/ui/indexing_slicing_index.rs:68:5
+  --> tests/ui/indexing_slicing_index.rs:70:5
    |
 LL |     x[N];
    |     ^^^^
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:71:5
+  --> tests/ui/indexing_slicing_index.rs:73:5
    |
 LL |     v[N];
    |     ^^^^
@@ -107,7 +107,7 @@ LL |     v[N];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: indexing may panic
-  --> tests/ui/indexing_slicing_index.rs:73:5
+  --> tests/ui/indexing_slicing_index.rs:75:5
    |
 LL |     v[M];
    |     ^^^^
@@ -115,7 +115,7 @@ LL |     v[M];
    = help: consider using `.get(n)` or `.get_mut(n)` instead
 
 error: index is out of bounds
-  --> tests/ui/indexing_slicing_index.rs:77:13
+  --> tests/ui/indexing_slicing_index.rs:79:13
    |
 LL |     let _ = x[4];
    |             ^^^^
diff --git a/src/tools/clippy/tests/ui/let_underscore_untyped.rs b/src/tools/clippy/tests/ui/let_underscore_untyped.rs
index bd94a3ada18..6275b6f970a 100644
--- a/src/tools/clippy/tests/ui/let_underscore_untyped.rs
+++ b/src/tools/clippy/tests/ui/let_underscore_untyped.rs
@@ -73,3 +73,5 @@ fn main() {
     #[allow(clippy::let_underscore_untyped)]
     let _ = a();
 }
+
+async fn dont_lint_async_prototype(_: u8) {}
diff --git a/src/tools/clippy/tests/ui/manual_let_else.rs b/src/tools/clippy/tests/ui/manual_let_else.rs
index 5d94660ec89..1fb252e3f97 100644
--- a/src/tools/clippy/tests/ui/manual_let_else.rs
+++ b/src/tools/clippy/tests/ui/manual_let_else.rs
@@ -1,3 +1,4 @@
+#![feature(try_blocks)]
 #![allow(unused_braces, unused_variables, dead_code)]
 #![allow(
     clippy::collapsible_else_if,
@@ -446,3 +447,12 @@ struct U<T> {
     w: T,
     x: T,
 }
+
+fn issue12337() {
+    // We want to generally silence question_mark lints within try blocks, since `?` has different
+    // behavior to `return`, and question_mark calls into manual_let_else logic, so make sure that
+    // we still emit a lint for manual_let_else
+    let _: Option<()> = try {
+        let v = if let Some(v_some) = g() { v_some } else { return };
+    };
+}
diff --git a/src/tools/clippy/tests/ui/manual_let_else.stderr b/src/tools/clippy/tests/ui/manual_let_else.stderr
index b6433fc460c..7012c6b8891 100644
--- a/src/tools/clippy/tests/ui/manual_let_else.stderr
+++ b/src/tools/clippy/tests/ui/manual_let_else.stderr
@@ -1,5 +1,5 @@
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:27:5
+  --> tests/ui/manual_let_else.rs:28:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
@@ -8,7 +8,7 @@ LL |     let v = if let Some(v_some) = g() { v_some } else { return };
    = help: to override `-D warnings` add `#[allow(clippy::manual_let_else)]`
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:30:5
+  --> tests/ui/manual_let_else.rs:31:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -26,7 +26,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:37:5
+  --> tests/ui/manual_let_else.rs:38:5
    |
 LL | /     let v = if let Some(v) = g() {
 LL | |
@@ -47,25 +47,25 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:49:9
+  --> tests/ui/manual_let_else.rs:50:9
    |
 LL |         let v = if let Some(v_some) = g() { v_some } else { continue };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { continue };`
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:51:9
+  --> tests/ui/manual_let_else.rs:52:9
    |
 LL |         let v = if let Some(v_some) = g() { v_some } else { break };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { break };`
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:56:5
+  --> tests/ui/manual_let_else.rs:57:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { panic!() };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { panic!() };`
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:60:5
+  --> tests/ui/manual_let_else.rs:61:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -83,7 +83,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:68:5
+  --> tests/ui/manual_let_else.rs:69:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -101,7 +101,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:76:5
+  --> tests/ui/manual_let_else.rs:77:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -121,7 +121,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:85:5
+  --> tests/ui/manual_let_else.rs:86:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -141,7 +141,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:94:5
+  --> tests/ui/manual_let_else.rs:95:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -168,7 +168,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:110:5
+  --> tests/ui/manual_let_else.rs:111:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -190,7 +190,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:121:5
+  --> tests/ui/manual_let_else.rs:122:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -217,7 +217,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:137:5
+  --> tests/ui/manual_let_else.rs:138:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -239,7 +239,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:148:5
+  --> tests/ui/manual_let_else.rs:149:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -257,7 +257,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:156:5
+  --> tests/ui/manual_let_else.rs:157:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -278,7 +278,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:166:5
+  --> tests/ui/manual_let_else.rs:167:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -299,7 +299,7 @@ LL +     } };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:176:5
+  --> tests/ui/manual_let_else.rs:177:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |
@@ -328,7 +328,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:194:5
+  --> tests/ui/manual_let_else.rs:195:5
    |
 LL | /     let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
 LL | |
@@ -346,7 +346,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:202:5
+  --> tests/ui/manual_let_else.rs:203:5
    |
 LL | /     let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) {
 LL | |
@@ -364,7 +364,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:212:13
+  --> tests/ui/manual_let_else.rs:213:13
    |
 LL |             let $n = if let Some(v) = $e { v } else { return };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };`
@@ -375,19 +375,19 @@ LL |     create_binding_if_some!(w, g());
    = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:221:5
+  --> tests/ui/manual_let_else.rs:222:5
    |
 LL |     let v = if let Variant::A(a, 0) = e() { a } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(v, 0) = e() else { return };`
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:225:5
+  --> tests/ui/manual_let_else.rs:226:5
    |
 LL |     let mut v = if let Variant::B(b) = e() { b } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(mut v) = e() else { return };`
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:230:5
+  --> tests/ui/manual_let_else.rs:231:5
    |
 LL | /     let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested {
 LL | |
@@ -405,19 +405,19 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:237:5
+  --> tests/ui/manual_let_else.rs:238:5
    |
 LL |     let v = if let Variant::A(.., a) = e() { a } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(.., v) = e() else { return };`
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:241:5
+  --> tests/ui/manual_let_else.rs:242:5
    |
 LL |     let w = if let (Some(v), ()) = (g(), ()) { v } else { return };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let (Some(w), ()) = (g(), ()) else { return };`
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:245:5
+  --> tests/ui/manual_let_else.rs:246:5
    |
 LL | /     let w = if let Some(S { v: x }) = Some(S { v: 0 }) {
 LL | |
@@ -435,7 +435,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:253:5
+  --> tests/ui/manual_let_else.rs:254:5
    |
 LL | /     let v = if let Some(S { v: x }) = Some(S { v: 0 }) {
 LL | |
@@ -453,7 +453,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:261:5
+  --> tests/ui/manual_let_else.rs:262:5
    |
 LL | /     let (x, S { v }, w) = if let Some(U { v, w, x }) = None::<U<S<()>>> {
 LL | |
@@ -471,7 +471,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> tests/ui/manual_let_else.rs:378:5
+  --> tests/ui/manual_let_else.rs:379:5
    |
 LL | /     let _ = match ff {
 LL | |
@@ -480,5 +480,11 @@ LL | |         _ => macro_call!(),
 LL | |     };
    | |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };`
 
-error: aborting due to 30 previous errors
+error: this could be rewritten as `let...else`
+  --> tests/ui/manual_let_else.rs:456:9
+   |
+LL |         let v = if let Some(v_some) = g() { v_some } else { return };
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
+
+error: aborting due to 31 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs
index 8146091a2bb..c917fa7f2d0 100644
--- a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs
+++ b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.rs
@@ -1,5 +1,6 @@
-#![warn(clippy::needless_range_loop, clippy::manual_memcpy)]
-#![allow(clippy::useless_vec)]
+#![warn(clippy::manual_memcpy)]
+#![allow(clippy::assigning_clones, clippy::useless_vec, clippy::needless_range_loop)]
+
 //@no-rustfix
 const LOOP_OFFSET: usize = 5000;
 
@@ -158,6 +159,59 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) {
         //~^ ERROR: it looks like you're manually copying between slices
         dst[i] = src[i];
     }
+
+    // Don't trigger lint for following multi-dimensional arrays
+    let src = [[0; 5]; 5];
+    for i in 0..4 {
+        dst[i] = src[i + 1][i];
+    }
+    for i in 0..5 {
+        dst[i] = src[i][i];
+    }
+    for i in 0..5 {
+        dst[i] = src[i][3];
+    }
+
+    let src = [0; 5];
+    let mut dst = [[0; 5]; 5];
+    for i in 0..5 {
+        dst[i][i] = src[i];
+    }
+
+    let src = [[[0; 5]; 5]; 5];
+    let mut dst = [0; 5];
+    for i in 0..5 {
+        dst[i] = src[i][i][i];
+    }
+    for i in 0..5 {
+        dst[i] = src[i][i][0];
+    }
+    for i in 0..5 {
+        dst[i] = src[i][0][i];
+    }
+    for i in 0..5 {
+        dst[i] = src[0][i][i];
+    }
+    for i in 0..5 {
+        dst[i] = src[0][i][1];
+    }
+    for i in 0..5 {
+        dst[i] = src[i][0][1];
+    }
+
+    // Trigger lint
+    let src = [[0; 5]; 5];
+    let mut dst = [0; 5];
+    for i in 0..5 {
+        //~^ ERROR: it looks like you're manually copying between slices
+        dst[i] = src[0][i];
+    }
+
+    let src = [[[0; 5]; 5]; 5];
+    for i in 0..5 {
+        //~^ ERROR: it looks like you're manually copying between slices
+        dst[i] = src[0][1][i];
+    }
 }
 
 #[warn(clippy::needless_range_loop, clippy::manual_memcpy)]
diff --git a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr
index 55cca1fb584..803053b2db2 100644
--- a/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr
+++ b/src/tools/clippy/tests/ui/manual_memcpy/without_loop_counters.stderr
@@ -1,5 +1,5 @@
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:8:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:9:5
    |
 LL | /     for i in 0..src.len() {
 LL | |
@@ -12,7 +12,7 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::manual_memcpy)]`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:15:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:16:5
    |
 LL | /     for i in 0..src.len() {
 LL | |
@@ -21,7 +21,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[10..(src.len() + 10)].copy_from_slice(&src[..]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:21:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:22:5
    |
 LL | /     for i in 0..src.len() {
 LL | |
@@ -30,7 +30,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[..src.len()].copy_from_slice(&src[10..(src.len() + 10)]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:27:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:28:5
    |
 LL | /     for i in 11..src.len() {
 LL | |
@@ -39,7 +39,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[11..src.len()].copy_from_slice(&src[(11 - 10)..(src.len() - 10)]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:33:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:34:5
    |
 LL | /     for i in 0..dst.len() {
 LL | |
@@ -48,7 +48,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[..dst.len()]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:47:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:48:5
    |
 LL | /     for i in 10..256 {
 LL | |
@@ -64,7 +64,7 @@ LL +     dst2[(10 + 500)..(256 + 500)].copy_from_slice(&src[10..256]);
    |
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:60:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:61:5
    |
 LL | /     for i in 10..LOOP_OFFSET {
 LL | |
@@ -73,7 +73,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].copy_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:74:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:75:5
    |
 LL | /     for i in 0..src_vec.len() {
 LL | |
@@ -82,7 +82,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst_vec[..src_vec.len()].copy_from_slice(&src_vec[..]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:104:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:105:5
    |
 LL | /     for i in from..from + src.len() {
 LL | |
@@ -91,7 +91,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[from..(from + src.len())].copy_from_slice(&src[..(from + src.len() - from)]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:109:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:110:5
    |
 LL | /     for i in from..from + 3 {
 LL | |
@@ -100,7 +100,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[from..(from + 3)].copy_from_slice(&src[..(from + 3 - from)]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:115:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:116:5
    |
 LL | /     for i in 0..5 {
 LL | |
@@ -109,7 +109,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[..5].copy_from_slice(&src);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:121:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:122:5
    |
 LL | /     for i in 0..0 {
 LL | |
@@ -118,7 +118,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[..0].copy_from_slice(&src[..0]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:145:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:146:5
    |
 LL | /     for i in 0..4 {
 LL | |
@@ -127,7 +127,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[..4]);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:151:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:152:5
    |
 LL | /     for i in 0..5 {
 LL | |
@@ -136,7 +136,7 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst[..5].copy_from_slice(&src);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:157:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:158:5
    |
 LL | /     for i in 0..5 {
 LL | |
@@ -145,7 +145,25 @@ LL | |     }
    | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src);`
 
 error: it looks like you're manually copying between slices
-  --> tests/ui/manual_memcpy/without_loop_counters.rs:165:5
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:205:5
+   |
+LL | /     for i in 0..5 {
+LL | |
+LL | |         dst[i] = src[0][i];
+LL | |     }
+   | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[0]);`
+
+error: it looks like you're manually copying between slices
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:211:5
+   |
+LL | /     for i in 0..5 {
+LL | |
+LL | |         dst[i] = src[0][1][i];
+LL | |     }
+   | |_____^ help: try replacing the loop by: `dst.copy_from_slice(&src[0][1]);`
+
+error: it looks like you're manually copying between slices
+  --> tests/ui/manual_memcpy/without_loop_counters.rs:219:5
    |
 LL | /     for i in 0..src.len() {
 LL | |
@@ -153,5 +171,5 @@ LL | |         dst[i] = src[i].clone();
 LL | |     }
    | |_____^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..]);`
 
-error: aborting due to 16 previous errors
+error: aborting due to 18 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_range_patterns.fixed b/src/tools/clippy/tests/ui/manual_range_patterns.fixed
index b348d7071f6..e9f6fbcc3fc 100644
--- a/src/tools/clippy/tests/ui/manual_range_patterns.fixed
+++ b/src/tools/clippy/tests/ui/manual_range_patterns.fixed
@@ -1,4 +1,5 @@
 #![allow(unused)]
+#![allow(non_contiguous_range_endpoints)]
 #![warn(clippy::manual_range_patterns)]
 #![feature(exclusive_range_pattern)]
 
diff --git a/src/tools/clippy/tests/ui/manual_range_patterns.rs b/src/tools/clippy/tests/ui/manual_range_patterns.rs
index a0750f54b73..d525aaa24ad 100644
--- a/src/tools/clippy/tests/ui/manual_range_patterns.rs
+++ b/src/tools/clippy/tests/ui/manual_range_patterns.rs
@@ -1,4 +1,5 @@
 #![allow(unused)]
+#![allow(non_contiguous_range_endpoints)]
 #![warn(clippy::manual_range_patterns)]
 #![feature(exclusive_range_pattern)]
 
diff --git a/src/tools/clippy/tests/ui/manual_range_patterns.stderr b/src/tools/clippy/tests/ui/manual_range_patterns.stderr
index 7c19fdd475f..af9256aeea3 100644
--- a/src/tools/clippy/tests/ui/manual_range_patterns.stderr
+++ b/src/tools/clippy/tests/ui/manual_range_patterns.stderr
@@ -1,5 +1,5 @@
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:8:25
+  --> tests/ui/manual_range_patterns.rs:9:25
    |
 LL |     let _ = matches!(f, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
@@ -8,109 +8,109 @@ LL |     let _ = matches!(f, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10);
    = help: to override `-D warnings` add `#[allow(clippy::manual_range_patterns)]`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:9:25
+  --> tests/ui/manual_range_patterns.rs:10:25
    |
 LL |     let _ = matches!(f, 4 | 2 | 3 | 1 | 5 | 6 | 9 | 7 | 8 | 10);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:16:25
+  --> tests/ui/manual_range_patterns.rs:17:25
    |
 LL |     let _ = matches!(f, 1 | (2..=4));
    |                         ^^^^^^^^^^^ help: try: `1..=4`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:17:25
+  --> tests/ui/manual_range_patterns.rs:18:25
    |
 LL |     let _ = matches!(f, 1 | (2..4));
    |                         ^^^^^^^^^^ help: try: `1..4`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:18:25
+  --> tests/ui/manual_range_patterns.rs:19:25
    |
 LL |     let _ = matches!(f, (1..=10) | (2..=13) | (14..=48324728) | 48324729);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=48324729`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:19:25
+  --> tests/ui/manual_range_patterns.rs:20:25
    |
 LL |     let _ = matches!(f, 0 | (1..=10) | 48324730 | (2..=13) | (14..=48324728) | 48324729);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0..=48324730`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:20:25
+  --> tests/ui/manual_range_patterns.rs:21:25
    |
 LL |     let _ = matches!(f, 0..=1 | 0..=2 | 0..=3);
    |                         ^^^^^^^^^^^^^^^^^^^^^ help: try: `0..=3`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:23:9
+  --> tests/ui/manual_range_patterns.rs:24:9
    |
 LL |         1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 => true,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:26:25
+  --> tests/ui/manual_range_patterns.rs:27:25
    |
 LL |     let _ = matches!(f, -1 | -5 | 3 | -2 | -4 | -3 | 0 | 1 | 2);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-5..=3`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:28:25
+  --> tests/ui/manual_range_patterns.rs:29:25
    |
 LL |     let _ = matches!(f, -1_000_000..=1_000_000 | -1_000_001 | 1_000_001);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-1_000_001..=1_000_001`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:31:17
+  --> tests/ui/manual_range_patterns.rs:32:17
    |
 LL |     matches!(f, 0x00 | 0x01 | 0x02 | 0x03);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0x00..=0x03`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:32:17
+  --> tests/ui/manual_range_patterns.rs:33:17
    |
 LL |     matches!(f, 0x00..=0x05 | 0x06 | 0x07);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `0x00..=0x07`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:33:17
+  --> tests/ui/manual_range_patterns.rs:34:17
    |
 LL |     matches!(f, -0x09 | -0x08 | -0x07..=0x00);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-0x09..=0x00`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:35:17
+  --> tests/ui/manual_range_patterns.rs:36:17
    |
 LL |     matches!(f, 0..5 | 5);
    |                 ^^^^^^^^ help: try: `0..=5`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:36:17
+  --> tests/ui/manual_range_patterns.rs:37:17
    |
 LL |     matches!(f, 0 | 1..5);
    |                 ^^^^^^^^ help: try: `0..5`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:38:17
+  --> tests/ui/manual_range_patterns.rs:39:17
    |
 LL |     matches!(f, 0..=5 | 6..10);
    |                 ^^^^^^^^^^^^^ help: try: `0..10`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:39:17
+  --> tests/ui/manual_range_patterns.rs:40:17
    |
 LL |     matches!(f, 0..5 | 5..=10);
    |                 ^^^^^^^^^^^^^ help: try: `0..=10`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:40:17
+  --> tests/ui/manual_range_patterns.rs:41:17
    |
 LL |     matches!(f, 5..=10 | 0..5);
    |                 ^^^^^^^^^^^^^ help: try: `0..=10`
 
 error: this OR pattern can be rewritten using a range
-  --> tests/ui/manual_range_patterns.rs:44:26
+  --> tests/ui/manual_range_patterns.rs:45:26
    |
 LL |             matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10)
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10`
diff --git a/src/tools/clippy/tests/ui/manual_retain.fixed b/src/tools/clippy/tests/ui/manual_retain.fixed
index 5540029bf6b..e359dfbb98c 100644
--- a/src/tools/clippy/tests/ui/manual_retain.fixed
+++ b/src/tools/clippy/tests/ui/manual_retain.fixed
@@ -1,3 +1,5 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![warn(clippy::manual_retain)]
 #![allow(unused, clippy::redundant_clone)]
 use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
diff --git a/src/tools/clippy/tests/ui/manual_retain.rs b/src/tools/clippy/tests/ui/manual_retain.rs
index cee641d9d65..931814f08b7 100644
--- a/src/tools/clippy/tests/ui/manual_retain.rs
+++ b/src/tools/clippy/tests/ui/manual_retain.rs
@@ -1,3 +1,5 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![warn(clippy::manual_retain)]
 #![allow(unused, clippy::redundant_clone)]
 use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
diff --git a/src/tools/clippy/tests/ui/manual_retain.stderr b/src/tools/clippy/tests/ui/manual_retain.stderr
index c25c804df75..fdbbc53e4df 100644
--- a/src/tools/clippy/tests/ui/manual_retain.stderr
+++ b/src/tools/clippy/tests/ui/manual_retain.stderr
@@ -1,5 +1,5 @@
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:25:5
+  --> tests/ui/manual_retain.rs:27:5
    |
 LL |     binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)`
@@ -8,43 +8,43 @@ LL |     binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect();
    = help: to override `-D warnings` add `#[allow(clippy::manual_retain)]`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:26:5
+  --> tests/ui/manual_retain.rs:28:5
    |
 LL |     binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:27:5
+  --> tests/ui/manual_retain.rs:29:5
    |
 LL |     binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:31:5
+  --> tests/ui/manual_retain.rs:33:5
    |
 LL |     tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:32:5
+  --> tests/ui/manual_retain.rs:34:5
    |
 LL |     tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:62:5
+  --> tests/ui/manual_retain.rs:64:5
    |
 LL |     btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|k, _| k % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:63:5
+  --> tests/ui/manual_retain.rs:65:5
    |
 LL |     btree_map = btree_map.into_iter().filter(|(_, v)| v % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|_, &mut v| v % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:64:5
+  --> tests/ui/manual_retain.rs:66:5
    |
 LL | /     btree_map = btree_map
 LL | |         .into_iter()
@@ -53,49 +53,49 @@ LL | |         .collect();
    | |__________________^ help: consider calling `.retain()` instead: `btree_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:89:5
+  --> tests/ui/manual_retain.rs:91:5
    |
 LL |     btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:90:5
+  --> tests/ui/manual_retain.rs:92:5
    |
 LL |     btree_set = btree_set.iter().filter(|&x| x % 2 == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:91:5
+  --> tests/ui/manual_retain.rs:93:5
    |
 LL |     btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:95:5
+  --> tests/ui/manual_retain.rs:97:5
    |
 LL |     tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:96:5
+  --> tests/ui/manual_retain.rs:98:5
    |
 LL |     tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:126:5
+  --> tests/ui/manual_retain.rs:128:5
    |
 LL |     hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|k, _| k % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:127:5
+  --> tests/ui/manual_retain.rs:129:5
    |
 LL |     hash_map = hash_map.into_iter().filter(|(_, v)| v % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|_, &mut v| v % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:128:5
+  --> tests/ui/manual_retain.rs:130:5
    |
 LL | /     hash_map = hash_map
 LL | |         .into_iter()
@@ -104,133 +104,133 @@ LL | |         .collect();
    | |__________________^ help: consider calling `.retain()` instead: `hash_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:152:5
+  --> tests/ui/manual_retain.rs:154:5
    |
 LL |     hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:153:5
+  --> tests/ui/manual_retain.rs:155:5
    |
 LL |     hash_set = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:154:5
+  --> tests/ui/manual_retain.rs:156:5
    |
 LL |     hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:158:5
+  --> tests/ui/manual_retain.rs:160:5
    |
 LL |     tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:159:5
+  --> tests/ui/manual_retain.rs:161:5
    |
 LL |     tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:188:5
+  --> tests/ui/manual_retain.rs:190:5
    |
 LL |     s = s.chars().filter(|&c| c != 'o').to_owned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `s.retain(|c| c != 'o')`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:200:5
+  --> tests/ui/manual_retain.rs:202:5
    |
 LL |     vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:201:5
+  --> tests/ui/manual_retain.rs:203:5
    |
 LL |     vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:202:5
+  --> tests/ui/manual_retain.rs:204:5
    |
 LL |     vec = vec.into_iter().filter(|x| x % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:206:5
+  --> tests/ui/manual_retain.rs:208:5
    |
 LL |     tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:207:5
+  --> tests/ui/manual_retain.rs:209:5
    |
 LL |     tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:229:5
+  --> tests/ui/manual_retain.rs:231:5
    |
 LL |     vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:230:5
+  --> tests/ui/manual_retain.rs:232:5
    |
 LL |     vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:231:5
+  --> tests/ui/manual_retain.rs:233:5
    |
 LL |     vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:288:5
+  --> tests/ui/manual_retain.rs:290:5
    |
 LL |     vec = vec.into_iter().filter(|(x, y)| *x == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|(x, y)| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:292:5
+  --> tests/ui/manual_retain.rs:294:5
    |
 LL |     tuples = tuples.into_iter().filter(|(_, n)| *n > 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(_, n)| *n > 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:309:5
+  --> tests/ui/manual_retain.rs:311:5
    |
 LL |     vec = vec.iter().filter(|&&x| x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:310:5
+  --> tests/ui/manual_retain.rs:312:5
    |
 LL |     vec = vec.iter().filter(|&&x| x == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:311:5
+  --> tests/ui/manual_retain.rs:313:5
    |
 LL |     vec = vec.into_iter().filter(|&x| x == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:314:5
+  --> tests/ui/manual_retain.rs:316:5
    |
 LL |     vec = vec.iter().filter(|&x| *x == 0).copied().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:315:5
+  --> tests/ui/manual_retain.rs:317:5
    |
 LL |     vec = vec.iter().filter(|&x| *x == 0).cloned().collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)`
 
 error: this expression can be written more simply using `.retain()`
-  --> tests/ui/manual_retain.rs:316:5
+  --> tests/ui/manual_retain.rs:318:5
    |
 LL |     vec = vec.into_iter().filter(|x| *x == 0).collect();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)`
diff --git a/src/tools/clippy/tests/ui/many_single_char_names.rs b/src/tools/clippy/tests/ui/many_single_char_names.rs
index 68578340d90..2af45eaab8a 100644
--- a/src/tools/clippy/tests/ui/many_single_char_names.rs
+++ b/src/tools/clippy/tests/ui/many_single_char_names.rs
@@ -1,3 +1,5 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![allow(clippy::too_many_arguments, clippy::diverging_sub_expression)]
 #![warn(clippy::many_single_char_names)]
 
diff --git a/src/tools/clippy/tests/ui/many_single_char_names.stderr b/src/tools/clippy/tests/ui/many_single_char_names.stderr
index 131836ef7c8..3b2460b5c07 100644
--- a/src/tools/clippy/tests/ui/many_single_char_names.stderr
+++ b/src/tools/clippy/tests/ui/many_single_char_names.stderr
@@ -1,5 +1,5 @@
 error: 5 bindings with single-character names in scope
-  --> tests/ui/many_single_char_names.rs:5:9
+  --> tests/ui/many_single_char_names.rs:7:9
    |
 LL |     let a: i32;
    |         ^
@@ -14,7 +14,7 @@ LL |             let e: i32;
    = help: to override `-D warnings` add `#[allow(clippy::many_single_char_names)]`
 
 error: 6 bindings with single-character names in scope
-  --> tests/ui/many_single_char_names.rs:5:9
+  --> tests/ui/many_single_char_names.rs:7:9
    |
 LL |     let a: i32;
    |         ^
@@ -28,7 +28,7 @@ LL |             let f: i32;
    |                 ^
 
 error: 5 bindings with single-character names in scope
-  --> tests/ui/many_single_char_names.rs:5:9
+  --> tests/ui/many_single_char_names.rs:7:9
    |
 LL |     let a: i32;
    |         ^
@@ -40,13 +40,13 @@ LL |             e => panic!(),
    |             ^
 
 error: 8 bindings with single-character names in scope
-  --> tests/ui/many_single_char_names.rs:34:13
+  --> tests/ui/many_single_char_names.rs:36:13
    |
 LL | fn bindings(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32, h: i32) {}
    |             ^       ^       ^       ^       ^       ^       ^       ^
 
 error: 8 bindings with single-character names in scope
-  --> tests/ui/many_single_char_names.rs:38:10
+  --> tests/ui/many_single_char_names.rs:40:10
    |
 LL |     let (a, b, c, d, e, f, g, h): (bool, bool, bool, bool, bool, bool, bool, bool) = unimplemented!();
    |          ^  ^  ^  ^  ^  ^  ^  ^
diff --git a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs
index 3917bb9e03d..2dccadd9fce 100644
--- a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs
+++ b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs
@@ -1,3 +1,5 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![feature(custom_inner_attributes)]
 #![clippy::msrv = "invalid.version"]
 //~^ ERROR: `invalid.version` is not a valid Rust version
diff --git a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr
index cf0d08a5d21..b4cb1b5713f 100644
--- a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr
+++ b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr
@@ -1,35 +1,35 @@
 error: `invalid.version` is not a valid Rust version
-  --> tests/ui/min_rust_version_invalid_attr.rs:2:1
+  --> tests/ui/min_rust_version_invalid_attr.rs:4:1
    |
 LL | #![clippy::msrv = "invalid.version"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `invalid.version` is not a valid Rust version
-  --> tests/ui/min_rust_version_invalid_attr.rs:7:1
+  --> tests/ui/min_rust_version_invalid_attr.rs:9:1
    |
 LL | #[clippy::msrv = "invalid.version"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `clippy::msrv` is defined multiple times
-  --> tests/ui/min_rust_version_invalid_attr.rs:14:5
+  --> tests/ui/min_rust_version_invalid_attr.rs:16:5
    |
 LL |     #![clippy::msrv = "1.10.1"]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first definition found here
-  --> tests/ui/min_rust_version_invalid_attr.rs:12:5
+  --> tests/ui/min_rust_version_invalid_attr.rs:14:5
    |
 LL |     #![clippy::msrv = "1.40"]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `clippy::msrv` is defined multiple times
-  --> tests/ui/min_rust_version_invalid_attr.rs:19:9
+  --> tests/ui/min_rust_version_invalid_attr.rs:21:9
    |
 LL |         #![clippy::msrv = "1.0.0"]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first definition found here
-  --> tests/ui/min_rust_version_invalid_attr.rs:18:9
+  --> tests/ui/min_rust_version_invalid_attr.rs:20:9
    |
 LL |         #![clippy::msrv = "1"]
    |         ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/mixed_attributes_style.rs b/src/tools/clippy/tests/ui/mixed_attributes_style.rs
new file mode 100644
index 00000000000..ad93e3019fa
--- /dev/null
+++ b/src/tools/clippy/tests/ui/mixed_attributes_style.rs
@@ -0,0 +1,39 @@
+#![warn(clippy::mixed_attributes_style)]
+
+#[allow(unused)] //~ ERROR: item has both inner and outer attributes
+fn foo1() {
+    #![allow(unused)]
+}
+
+#[allow(unused)]
+#[allow(unused)]
+fn foo2() {}
+
+fn foo3() {
+    #![allow(unused)]
+    #![allow(unused)]
+}
+
+/// linux
+//~^ ERROR: item has both inner and outer attributes
+fn foo4() {
+    //! windows
+}
+
+/// linux
+/// windows
+fn foo5() {}
+
+fn foo6() {
+    //! linux
+    //! windows
+}
+
+#[allow(unused)] //~ ERROR: item has both inner and outer attributes
+mod bar {
+    #![allow(unused)]
+}
+
+fn main() {
+    // test code goes here
+}
diff --git a/src/tools/clippy/tests/ui/mixed_attributes_style.stderr b/src/tools/clippy/tests/ui/mixed_attributes_style.stderr
new file mode 100644
index 00000000000..d1d5cd3f47f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/mixed_attributes_style.stderr
@@ -0,0 +1,30 @@
+error: item has both inner and outer attributes
+  --> tests/ui/mixed_attributes_style.rs:3:1
+   |
+LL | / #[allow(unused)]
+LL | | fn foo1() {
+LL | |     #![allow(unused)]
+   | |_____________________^
+   |
+   = note: `-D clippy::mixed-attributes-style` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::mixed_attributes_style)]`
+
+error: item has both inner and outer attributes
+  --> tests/ui/mixed_attributes_style.rs:17:1
+   |
+LL | / /// linux
+LL | |
+LL | | fn foo4() {
+LL | |     //! windows
+   | |_______________^
+
+error: item has both inner and outer attributes
+  --> tests/ui/mixed_attributes_style.rs:32:1
+   |
+LL | / #[allow(unused)]
+LL | | mod bar {
+LL | |     #![allow(unused)]
+   | |_____________________^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/mut_mut.rs b/src/tools/clippy/tests/ui/mut_mut.rs
index 72a171119f3..288b003405d 100644
--- a/src/tools/clippy/tests/ui/mut_mut.rs
+++ b/src/tools/clippy/tests/ui/mut_mut.rs
@@ -1,4 +1,6 @@
 //@aux-build:proc_macros.rs
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![warn(clippy::mut_mut)]
 #![allow(unused)]
 #![allow(
diff --git a/src/tools/clippy/tests/ui/mut_mut.stderr b/src/tools/clippy/tests/ui/mut_mut.stderr
index 810c0c96743..73f2410a252 100644
--- a/src/tools/clippy/tests/ui/mut_mut.stderr
+++ b/src/tools/clippy/tests/ui/mut_mut.stderr
@@ -1,5 +1,5 @@
 error: generally you want to avoid `&mut &mut _` if possible
-  --> tests/ui/mut_mut.rs:14:11
+  --> tests/ui/mut_mut.rs:16:11
    |
 LL | fn fun(x: &mut &mut u32) -> bool {
    |           ^^^^^^^^^^^^^
@@ -8,13 +8,13 @@ LL | fn fun(x: &mut &mut u32) -> bool {
    = help: to override `-D warnings` add `#[allow(clippy::mut_mut)]`
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> tests/ui/mut_mut.rs:31:17
+  --> tests/ui/mut_mut.rs:33:17
    |
 LL |     let mut x = &mut &mut 1u32;
    |                 ^^^^^^^^^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> tests/ui/mut_mut.rs:46:25
+  --> tests/ui/mut_mut.rs:48:25
    |
 LL |     let mut z = inline!(&mut $(&mut 3u32));
    |                         ^
@@ -22,37 +22,37 @@ LL |     let mut z = inline!(&mut $(&mut 3u32));
    = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this expression mutably borrows a mutable reference. Consider reborrowing
-  --> tests/ui/mut_mut.rs:33:21
+  --> tests/ui/mut_mut.rs:35:21
    |
 LL |         let mut y = &mut x;
    |                     ^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> tests/ui/mut_mut.rs:37:32
+  --> tests/ui/mut_mut.rs:39:32
    |
 LL |         let y: &mut &mut u32 = &mut &mut 2;
    |                                ^^^^^^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> tests/ui/mut_mut.rs:37:16
+  --> tests/ui/mut_mut.rs:39:16
    |
 LL |         let y: &mut &mut u32 = &mut &mut 2;
    |                ^^^^^^^^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> tests/ui/mut_mut.rs:42:37
+  --> tests/ui/mut_mut.rs:44:37
    |
 LL |         let y: &mut &mut &mut u32 = &mut &mut &mut 2;
    |                                     ^^^^^^^^^^^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> tests/ui/mut_mut.rs:42:16
+  --> tests/ui/mut_mut.rs:44:16
    |
 LL |         let y: &mut &mut &mut u32 = &mut &mut &mut 2;
    |                ^^^^^^^^^^^^^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> tests/ui/mut_mut.rs:42:21
+  --> tests/ui/mut_mut.rs:44:21
    |
 LL |         let y: &mut &mut &mut u32 = &mut &mut &mut 2;
    |                     ^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/no_effect_replace.rs b/src/tools/clippy/tests/ui/no_effect_replace.rs
index e4fd5caae2a..2a940d87fb9 100644
--- a/src/tools/clippy/tests/ui/no_effect_replace.rs
+++ b/src/tools/clippy/tests/ui/no_effect_replace.rs
@@ -1,3 +1,5 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![warn(clippy::no_effect_replace)]
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/no_effect_replace.stderr b/src/tools/clippy/tests/ui/no_effect_replace.stderr
index ded86c5c5b8..ad2dcd2cc9b 100644
--- a/src/tools/clippy/tests/ui/no_effect_replace.stderr
+++ b/src/tools/clippy/tests/ui/no_effect_replace.stderr
@@ -1,5 +1,5 @@
 error: replacing text with itself
-  --> tests/ui/no_effect_replace.rs:4:13
+  --> tests/ui/no_effect_replace.rs:6:13
    |
 LL |     let _ = "12345".replace('1', "1");
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,43 +8,43 @@ LL |     let _ = "12345".replace('1', "1");
    = help: to override `-D warnings` add `#[allow(clippy::no_effect_replace)]`
 
 error: replacing text with itself
-  --> tests/ui/no_effect_replace.rs:7:13
+  --> tests/ui/no_effect_replace.rs:9:13
    |
 LL |     let _ = "12345".replace("12", "12");
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: replacing text with itself
-  --> tests/ui/no_effect_replace.rs:9:13
+  --> tests/ui/no_effect_replace.rs:11:13
    |
 LL |     let _ = String::new().replace("12", "12");
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: replacing text with itself
-  --> tests/ui/no_effect_replace.rs:12:13
+  --> tests/ui/no_effect_replace.rs:14:13
    |
 LL |     let _ = "12345".replacen('1', "1", 1);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: replacing text with itself
-  --> tests/ui/no_effect_replace.rs:14:13
+  --> tests/ui/no_effect_replace.rs:16:13
    |
 LL |     let _ = "12345".replacen("12", "12", 1);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: replacing text with itself
-  --> tests/ui/no_effect_replace.rs:16:13
+  --> tests/ui/no_effect_replace.rs:18:13
    |
 LL |     let _ = String::new().replacen("12", "12", 1);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: replacing text with itself
-  --> tests/ui/no_effect_replace.rs:23:13
+  --> tests/ui/no_effect_replace.rs:25:13
    |
 LL |     let _ = "hello".replace(&x.f(), &x.f());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: replacing text with itself
-  --> tests/ui/no_effect_replace.rs:27:13
+  --> tests/ui/no_effect_replace.rs:29:13
    |
 LL |     let _ = "hello".replace(&y(), &y());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/non_canonical_clone_impl.fixed b/src/tools/clippy/tests/ui/non_canonical_clone_impl.fixed
index 165702b3041..7d1be412e54 100644
--- a/src/tools/clippy/tests/ui/non_canonical_clone_impl.fixed
+++ b/src/tools/clippy/tests/ui/non_canonical_clone_impl.fixed
@@ -1,4 +1,5 @@
 #![allow(clippy::clone_on_copy, unused)]
+#![allow(clippy::assigning_clones)]
 #![no_main]
 
 // lint
diff --git a/src/tools/clippy/tests/ui/non_canonical_clone_impl.rs b/src/tools/clippy/tests/ui/non_canonical_clone_impl.rs
index 3b07dd5ce62..beae05efb2f 100644
--- a/src/tools/clippy/tests/ui/non_canonical_clone_impl.rs
+++ b/src/tools/clippy/tests/ui/non_canonical_clone_impl.rs
@@ -1,4 +1,5 @@
 #![allow(clippy::clone_on_copy, unused)]
+#![allow(clippy::assigning_clones)]
 #![no_main]
 
 // lint
diff --git a/src/tools/clippy/tests/ui/non_canonical_clone_impl.stderr b/src/tools/clippy/tests/ui/non_canonical_clone_impl.stderr
index 8eff322fa2d..6bfc99d988b 100644
--- a/src/tools/clippy/tests/ui/non_canonical_clone_impl.stderr
+++ b/src/tools/clippy/tests/ui/non_canonical_clone_impl.stderr
@@ -1,5 +1,5 @@
 error: non-canonical implementation of `clone` on a `Copy` type
-  --> tests/ui/non_canonical_clone_impl.rs:9:29
+  --> tests/ui/non_canonical_clone_impl.rs:10:29
    |
 LL |       fn clone(&self) -> Self {
    |  _____________________________^
@@ -11,7 +11,7 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::non_canonical_clone_impl)]`
 
 error: unnecessary implementation of `clone_from` on a `Copy` type
-  --> tests/ui/non_canonical_clone_impl.rs:13:5
+  --> tests/ui/non_canonical_clone_impl.rs:14:5
    |
 LL | /     fn clone_from(&mut self, source: &Self) {
 LL | |         source.clone();
@@ -20,7 +20,7 @@ LL | |     }
    | |_____^ help: remove it
 
 error: non-canonical implementation of `clone` on a `Copy` type
-  --> tests/ui/non_canonical_clone_impl.rs:80:29
+  --> tests/ui/non_canonical_clone_impl.rs:81:29
    |
 LL |       fn clone(&self) -> Self {
    |  _____________________________^
@@ -29,7 +29,7 @@ LL | |     }
    | |_____^ help: change this to: `{ *self }`
 
 error: unnecessary implementation of `clone_from` on a `Copy` type
-  --> tests/ui/non_canonical_clone_impl.rs:84:5
+  --> tests/ui/non_canonical_clone_impl.rs:85:5
    |
 LL | /     fn clone_from(&mut self, source: &Self) {
 LL | |         source.clone();
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.rs b/src/tools/clippy/tests/ui/nonminimal_bool.rs
index 908ef6cb2a0..38157116e91 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool.rs
+++ b/src/tools/clippy/tests/ui/nonminimal_bool.rs
@@ -1,4 +1,5 @@
 //@no-rustfix: overlapping suggestions
+
 #![feature(lint_reasons)]
 #![allow(
     unused,
@@ -173,3 +174,8 @@ fn issue_5794() {
     if !b == !c {} //~ ERROR: this boolean expression can be simplified
     if !b != !c {} //~ ERROR: this boolean expression can be simplified
 }
+
+fn issue_12371(x: usize) -> bool {
+    // Should not warn!
+    !x != 0
+}
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.stderr b/src/tools/clippy/tests/ui/nonminimal_bool.stderr
index 954e2345266..b6af06d845a 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool.stderr
+++ b/src/tools/clippy/tests/ui/nonminimal_bool.stderr
@@ -1,5 +1,5 @@
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:18:13
+  --> tests/ui/nonminimal_bool.rs:19:13
    |
 LL |     let _ = !true;
    |             ^^^^^ help: try: `false`
@@ -8,43 +8,43 @@ LL |     let _ = !true;
    = help: to override `-D warnings` add `#[allow(clippy::nonminimal_bool)]`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:21:13
+  --> tests/ui/nonminimal_bool.rs:22:13
    |
 LL |     let _ = !false;
    |             ^^^^^^ help: try: `true`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:23:13
+  --> tests/ui/nonminimal_bool.rs:24:13
    |
 LL |     let _ = !!a;
    |             ^^^ help: try: `a`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:25:13
+  --> tests/ui/nonminimal_bool.rs:26:13
    |
 LL |     let _ = false || a;
    |             ^^^^^^^^^^ help: try: `a`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:30:13
+  --> tests/ui/nonminimal_bool.rs:31:13
    |
 LL |     let _ = !(!a && b);
    |             ^^^^^^^^^^ help: try: `a || !b`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:32:13
+  --> tests/ui/nonminimal_bool.rs:33:13
    |
 LL |     let _ = !(!a || b);
    |             ^^^^^^^^^^ help: try: `a && !b`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:34:13
+  --> tests/ui/nonminimal_bool.rs:35:13
    |
 LL |     let _ = !a && !(b && c);
    |             ^^^^^^^^^^^^^^^ help: try: `!(a || b && c)`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:43:13
+  --> tests/ui/nonminimal_bool.rs:44:13
    |
 LL |     let _ = a == b && c == 5 && a == b;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -57,7 +57,7 @@ LL |     let _ = a == b && c == 5;
    |             ~~~~~~~~~~~~~~~~
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:45:13
+  --> tests/ui/nonminimal_bool.rs:46:13
    |
 LL |     let _ = a == b || c == 5 || a == b;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -70,7 +70,7 @@ LL |     let _ = a == b || c == 5;
    |             ~~~~~~~~~~~~~~~~
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:47:13
+  --> tests/ui/nonminimal_bool.rs:48:13
    |
 LL |     let _ = a == b && c == 5 && b == a;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -83,7 +83,7 @@ LL |     let _ = a == b && c == 5;
    |             ~~~~~~~~~~~~~~~~
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:49:13
+  --> tests/ui/nonminimal_bool.rs:50:13
    |
 LL |     let _ = a != b || !(a != b || c == d);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -96,7 +96,7 @@ LL |     let _ = a != b || c != d;
    |             ~~~~~~~~~~~~~~~~
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:51:13
+  --> tests/ui/nonminimal_bool.rs:52:13
    |
 LL |     let _ = a != b && !(a != b && c == d);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -109,43 +109,43 @@ LL |     let _ = a != b && c != d;
    |             ~~~~~~~~~~~~~~~~
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:82:8
+  --> tests/ui/nonminimal_bool.rs:83:8
    |
 LL |     if matches!(true, true) && true {
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(true, true)`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:162:8
+  --> tests/ui/nonminimal_bool.rs:163:8
    |
 LL |     if !(12 == a) {}
    |        ^^^^^^^^^^ help: try: `12 != a`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:163:8
+  --> tests/ui/nonminimal_bool.rs:164:8
    |
 LL |     if !(a == 12) {}
    |        ^^^^^^^^^^ help: try: `a != 12`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:164:8
+  --> tests/ui/nonminimal_bool.rs:165:8
    |
 LL |     if !(12 != a) {}
    |        ^^^^^^^^^^ help: try: `12 == a`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:165:8
+  --> tests/ui/nonminimal_bool.rs:166:8
    |
 LL |     if !(a != 12) {}
    |        ^^^^^^^^^^ help: try: `a == 12`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:169:8
+  --> tests/ui/nonminimal_bool.rs:170:8
    |
 LL |     if !b == true {}
    |        ^^^^^^^^^^ help: try: `b != true`
 
 error: this comparison might be written more concisely
-  --> tests/ui/nonminimal_bool.rs:169:8
+  --> tests/ui/nonminimal_bool.rs:170:8
    |
 LL |     if !b == true {}
    |        ^^^^^^^^^^ help: try simplifying it as shown: `b != true`
@@ -154,61 +154,61 @@ LL |     if !b == true {}
    = help: to override `-D warnings` add `#[allow(clippy::bool_comparison)]`
 
 error: equality checks against true are unnecessary
-  --> tests/ui/nonminimal_bool.rs:169:8
+  --> tests/ui/nonminimal_bool.rs:170:8
    |
 LL |     if !b == true {}
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!b`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:170:8
+  --> tests/ui/nonminimal_bool.rs:171:8
    |
 LL |     if !b != true {}
    |        ^^^^^^^^^^ help: try: `b == true`
 
 error: inequality checks against true can be replaced by a negation
-  --> tests/ui/nonminimal_bool.rs:170:8
+  --> tests/ui/nonminimal_bool.rs:171:8
    |
 LL |     if !b != true {}
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!(!b)`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:171:8
+  --> tests/ui/nonminimal_bool.rs:172:8
    |
 LL |     if true == !b {}
    |        ^^^^^^^^^^ help: try: `true != b`
 
 error: this comparison might be written more concisely
-  --> tests/ui/nonminimal_bool.rs:171:8
+  --> tests/ui/nonminimal_bool.rs:172:8
    |
 LL |     if true == !b {}
    |        ^^^^^^^^^^ help: try simplifying it as shown: `true != b`
 
 error: equality checks against true are unnecessary
-  --> tests/ui/nonminimal_bool.rs:171:8
+  --> tests/ui/nonminimal_bool.rs:172:8
    |
 LL |     if true == !b {}
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!b`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:172:8
+  --> tests/ui/nonminimal_bool.rs:173:8
    |
 LL |     if true != !b {}
    |        ^^^^^^^^^^ help: try: `true == b`
 
 error: inequality checks against true can be replaced by a negation
-  --> tests/ui/nonminimal_bool.rs:172:8
+  --> tests/ui/nonminimal_bool.rs:173:8
    |
 LL |     if true != !b {}
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!(!b)`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:173:8
+  --> tests/ui/nonminimal_bool.rs:174:8
    |
 LL |     if !b == !c {}
    |        ^^^^^^^^ help: try: `b == c`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool.rs:174:8
+  --> tests/ui/nonminimal_bool.rs:175:8
    |
 LL |     if !b != !c {}
    |        ^^^^^^^^ help: try: `b != c`
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed b/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed
index e27c0350d49..bd4be3e5a44 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed
+++ b/src/tools/clippy/tests/ui/nonminimal_bool_methods.fixed
@@ -1,3 +1,5 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![allow(unused, clippy::diverging_sub_expression, clippy::needless_if)]
 #![warn(clippy::nonminimal_bool)]
 
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs b/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs
index 040a6e920a1..4523c7385df 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs
+++ b/src/tools/clippy/tests/ui/nonminimal_bool_methods.rs
@@ -1,3 +1,5 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![allow(unused, clippy::diverging_sub_expression, clippy::needless_if)]
 #![warn(clippy::nonminimal_bool)]
 
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool_methods.stderr b/src/tools/clippy/tests/ui/nonminimal_bool_methods.stderr
index ede88ba529c..e32c8dacd2f 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool_methods.stderr
+++ b/src/tools/clippy/tests/ui/nonminimal_bool_methods.stderr
@@ -1,5 +1,5 @@
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:8:13
+  --> tests/ui/nonminimal_bool_methods.rs:10:13
    |
 LL |     let _ = !a.is_some();
    |             ^^^^^^^^^^^^ help: try: `a.is_none()`
@@ -8,73 +8,73 @@ LL |     let _ = !a.is_some();
    = help: to override `-D warnings` add `#[allow(clippy::nonminimal_bool)]`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:10:13
+  --> tests/ui/nonminimal_bool_methods.rs:12:13
    |
 LL |     let _ = !a.is_none();
    |             ^^^^^^^^^^^^ help: try: `a.is_some()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:12:13
+  --> tests/ui/nonminimal_bool_methods.rs:14:13
    |
 LL |     let _ = !b.is_err();
    |             ^^^^^^^^^^^ help: try: `b.is_ok()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:14:13
+  --> tests/ui/nonminimal_bool_methods.rs:16:13
    |
 LL |     let _ = !b.is_ok();
    |             ^^^^^^^^^^ help: try: `b.is_err()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:16:13
+  --> tests/ui/nonminimal_bool_methods.rs:18:13
    |
 LL |     let _ = !(a.is_some() && !c);
    |             ^^^^^^^^^^^^^^^^^^^^ help: try: `a.is_none() || c`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:17:13
+  --> tests/ui/nonminimal_bool_methods.rs:19:13
    |
 LL |     let _ = !(a.is_some() || !c);
    |             ^^^^^^^^^^^^^^^^^^^^ help: try: `a.is_none() && c`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:18:26
+  --> tests/ui/nonminimal_bool_methods.rs:20:26
    |
 LL |     let _ = !(!c ^ c) || !a.is_some();
    |                          ^^^^^^^^^^^^ help: try: `a.is_none()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:19:25
+  --> tests/ui/nonminimal_bool_methods.rs:21:25
    |
 LL |     let _ = (!c ^ c) || !a.is_some();
    |                         ^^^^^^^^^^^^ help: try: `a.is_none()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:20:23
+  --> tests/ui/nonminimal_bool_methods.rs:22:23
    |
 LL |     let _ = !c ^ c || !a.is_some();
    |                       ^^^^^^^^^^^^ help: try: `a.is_none()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:92:8
+  --> tests/ui/nonminimal_bool_methods.rs:94:8
    |
 LL |     if !res.is_ok() {}
    |        ^^^^^^^^^^^^ help: try: `res.is_err()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:93:8
+  --> tests/ui/nonminimal_bool_methods.rs:95:8
    |
 LL |     if !res.is_err() {}
    |        ^^^^^^^^^^^^^ help: try: `res.is_ok()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:96:8
+  --> tests/ui/nonminimal_bool_methods.rs:98:8
    |
 LL |     if !res.is_some() {}
    |        ^^^^^^^^^^^^^^ help: try: `res.is_none()`
 
 error: this boolean expression can be simplified
-  --> tests/ui/nonminimal_bool_methods.rs:97:8
+  --> tests/ui/nonminimal_bool_methods.rs:99:8
    |
 LL |     if !res.is_none() {}
    |        ^^^^^^^^^^^^^^ help: try: `res.is_some()`
diff --git a/src/tools/clippy/tests/ui/option_option.rs b/src/tools/clippy/tests/ui/option_option.rs
index 9bbdd3aaacc..2f6e4d76145 100644
--- a/src/tools/clippy/tests/ui/option_option.rs
+++ b/src/tools/clippy/tests/ui/option_option.rs
@@ -1,3 +1,5 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![deny(clippy::option_option)]
 #![allow(clippy::unnecessary_wraps)]
 
diff --git a/src/tools/clippy/tests/ui/option_option.stderr b/src/tools/clippy/tests/ui/option_option.stderr
index 0cd048e400e..76cb9ae944c 100644
--- a/src/tools/clippy/tests/ui/option_option.stderr
+++ b/src/tools/clippy/tests/ui/option_option.stderr
@@ -1,77 +1,77 @@
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:4:10
+  --> tests/ui/option_option.rs:6:10
    |
 LL | const C: Option<Option<i32>> = None;
    |          ^^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> tests/ui/option_option.rs:1:9
+  --> tests/ui/option_option.rs:3:9
    |
 LL | #![deny(clippy::option_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:6:11
+  --> tests/ui/option_option.rs:8:11
    |
 LL | static S: Option<Option<i32>> = None;
    |           ^^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:9:13
+  --> tests/ui/option_option.rs:11:13
    |
 LL | fn input(_: Option<Option<u8>>) {}
    |             ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:12:16
+  --> tests/ui/option_option.rs:14:16
    |
 LL | fn output() -> Option<Option<u8>> {
    |                ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:17:27
+  --> tests/ui/option_option.rs:19:27
    |
 LL | fn output_nested() -> Vec<Option<Option<u8>>> {
    |                           ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:23:30
+  --> tests/ui/option_option.rs:25:30
    |
 LL | fn output_nested_nested() -> Option<Option<Option<u8>>> {
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:29:8
+  --> tests/ui/option_option.rs:31:8
    |
 LL |     x: Option<Option<u8>>,
    |        ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:34:23
+  --> tests/ui/option_option.rs:36:23
    |
 LL |     fn struct_fn() -> Option<Option<u8>> {
    |                       ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:41:22
+  --> tests/ui/option_option.rs:43:22
    |
 LL |     fn trait_fn() -> Option<Option<u8>>;
    |                      ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:46:11
+  --> tests/ui/option_option.rs:48:11
    |
 LL |     Tuple(Option<Option<u8>>),
    |           ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:48:17
+  --> tests/ui/option_option.rs:50:17
    |
 LL |     Struct { x: Option<Option<u8>> },
    |                 ^^^^^^^^^^^^^^^^^^
 
 error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases
-  --> tests/ui/option_option.rs:90:14
+  --> tests/ui/option_option.rs:92:14
    |
 LL |         foo: Option<Option<Cow<'a, str>>>,
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/ptr_as_ptr.fixed b/src/tools/clippy/tests/ui/ptr_as_ptr.fixed
index fa15c323540..61d37b8ba3a 100644
--- a/src/tools/clippy/tests/ui/ptr_as_ptr.fixed
+++ b/src/tools/clippy/tests/ui/ptr_as_ptr.fixed
@@ -1,4 +1,5 @@
 //@aux-build:proc_macros.rs
+//@compile-flags: -Zdeduplicate-diagnostics=yes
 
 #![warn(clippy::ptr_as_ptr)]
 
diff --git a/src/tools/clippy/tests/ui/ptr_as_ptr.rs b/src/tools/clippy/tests/ui/ptr_as_ptr.rs
index 7ab52e63da5..8f2068cd268 100644
--- a/src/tools/clippy/tests/ui/ptr_as_ptr.rs
+++ b/src/tools/clippy/tests/ui/ptr_as_ptr.rs
@@ -1,4 +1,5 @@
 //@aux-build:proc_macros.rs
+//@compile-flags: -Zdeduplicate-diagnostics=yes
 
 #![warn(clippy::ptr_as_ptr)]
 
diff --git a/src/tools/clippy/tests/ui/ptr_as_ptr.stderr b/src/tools/clippy/tests/ui/ptr_as_ptr.stderr
index e162f35baf5..e6cd697c7ba 100644
--- a/src/tools/clippy/tests/ui/ptr_as_ptr.stderr
+++ b/src/tools/clippy/tests/ui/ptr_as_ptr.stderr
@@ -1,5 +1,5 @@
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:18:33
+  --> tests/ui/ptr_as_ptr.rs:19:33
    |
 LL |         *unsafe { Box::from_raw(Box::into_raw(Box::new(o)) as *mut super::issue_11278_a::T<String>) }
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `Box::into_raw(Box::new(o)).cast::<super::issue_11278_a::T<String>>()`
@@ -8,37 +8,37 @@ LL |         *unsafe { Box::from_raw(Box::into_raw(Box::new(o)) as *mut super::i
    = help: to override `-D warnings` add `#[allow(clippy::ptr_as_ptr)]`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:27:13
+  --> tests/ui/ptr_as_ptr.rs:28:13
    |
 LL |     let _ = ptr as *const i32;
    |             ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:28:13
+  --> tests/ui/ptr_as_ptr.rs:29:13
    |
 LL |     let _ = mut_ptr as *mut i32;
    |             ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:33:17
+  --> tests/ui/ptr_as_ptr.rs:34:17
    |
 LL |         let _ = *ptr_ptr as *const i32;
    |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `(*ptr_ptr).cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:46:25
+  --> tests/ui/ptr_as_ptr.rs:47:25
    |
 LL |     let _: *const i32 = ptr as *const _;
    |                         ^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:47:23
+  --> tests/ui/ptr_as_ptr.rs:48:23
    |
 LL |     let _: *mut i32 = mut_ptr as _;
    |                       ^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:50:21
+  --> tests/ui/ptr_as_ptr.rs:51:21
    |
 LL |     let _ = inline!($ptr as *const i32);
    |                     ^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `$ptr.cast::<i32>()`
@@ -46,157 +46,157 @@ LL |     let _ = inline!($ptr as *const i32);
    = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:71:13
+  --> tests/ui/ptr_as_ptr.rs:72:13
    |
 LL |     let _ = ptr as *const i32;
    |             ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:72:13
+  --> tests/ui/ptr_as_ptr.rs:73:13
    |
 LL |     let _ = mut_ptr as *mut i32;
    |             ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:79:9
+  --> tests/ui/ptr_as_ptr.rs:80:9
    |
 LL |         ptr::null_mut() as *mut u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:83:9
+  --> tests/ui/ptr_as_ptr.rs:84:9
    |
 LL |         std::ptr::null_mut() as *mut u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut::<u32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:88:9
+  --> tests/ui/ptr_as_ptr.rs:89:9
    |
 LL |         ptr::null_mut() as *mut u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:92:9
+  --> tests/ui/ptr_as_ptr.rs:93:9
    |
 LL |         core::ptr::null_mut() as *mut u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut::<u32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:97:9
+  --> tests/ui/ptr_as_ptr.rs:98:9
    |
 LL |         ptr::null() as *const u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:101:9
+  --> tests/ui/ptr_as_ptr.rs:102:9
    |
 LL |         std::ptr::null() as *const u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null::<u32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:106:9
+  --> tests/ui/ptr_as_ptr.rs:107:9
    |
 LL |         ptr::null() as *const u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:110:9
+  --> tests/ui/ptr_as_ptr.rs:111:9
    |
 LL |         core::ptr::null() as *const u32
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null::<u32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:117:9
+  --> tests/ui/ptr_as_ptr.rs:118:9
    |
 LL |         ptr::null_mut() as *mut _
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:121:9
+  --> tests/ui/ptr_as_ptr.rs:122:9
    |
 LL |         std::ptr::null_mut() as *mut _
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:126:9
+  --> tests/ui/ptr_as_ptr.rs:127:9
    |
 LL |         ptr::null_mut() as *mut _
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:130:9
+  --> tests/ui/ptr_as_ptr.rs:131:9
    |
 LL |         core::ptr::null_mut() as *mut _
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:135:9
+  --> tests/ui/ptr_as_ptr.rs:136:9
    |
 LL |         ptr::null() as *const _
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:139:9
+  --> tests/ui/ptr_as_ptr.rs:140:9
    |
 LL |         std::ptr::null() as *const _
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:144:9
+  --> tests/ui/ptr_as_ptr.rs:145:9
    |
 LL |         ptr::null() as *const _
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:148:9
+  --> tests/ui/ptr_as_ptr.rs:149:9
    |
 LL |         core::ptr::null() as *const _
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:155:9
+  --> tests/ui/ptr_as_ptr.rs:156:9
    |
 LL |         ptr::null_mut() as _
    |         ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:159:9
+  --> tests/ui/ptr_as_ptr.rs:160:9
    |
 LL |         std::ptr::null_mut() as _
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:164:9
+  --> tests/ui/ptr_as_ptr.rs:165:9
    |
 LL |         ptr::null_mut() as _
    |         ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:168:9
+  --> tests/ui/ptr_as_ptr.rs:169:9
    |
 LL |         core::ptr::null_mut() as _
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:173:9
+  --> tests/ui/ptr_as_ptr.rs:174:9
    |
 LL |         ptr::null() as _
    |         ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:177:9
+  --> tests/ui/ptr_as_ptr.rs:178:9
    |
 LL |         std::ptr::null() as _
    |         ^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:182:9
+  --> tests/ui/ptr_as_ptr.rs:183:9
    |
 LL |         ptr::null() as _
    |         ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> tests/ui/ptr_as_ptr.rs:186:9
+  --> tests/ui/ptr_as_ptr.rs:187:9
    |
 LL |         core::ptr::null() as _
    |         ^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()`
diff --git a/src/tools/clippy/tests/ui/question_mark.fixed b/src/tools/clippy/tests/ui/question_mark.fixed
index 2ef006c1419..567472a8af2 100644
--- a/src/tools/clippy/tests/ui/question_mark.fixed
+++ b/src/tools/clippy/tests/ui/question_mark.fixed
@@ -273,3 +273,13 @@ const fn issue9175(option: Option<()>) -> Option<()> {
     //stuff
     Some(())
 }
+
+fn issue12337() -> Option<i32> {
+    let _: Option<i32> = try {
+        let Some(_) = Some(42) else {
+            return None;
+        };
+        123
+    };
+    Some(42)
+}
diff --git a/src/tools/clippy/tests/ui/question_mark.rs b/src/tools/clippy/tests/ui/question_mark.rs
index c170669823f..abf8c270de8 100644
--- a/src/tools/clippy/tests/ui/question_mark.rs
+++ b/src/tools/clippy/tests/ui/question_mark.rs
@@ -313,3 +313,13 @@ const fn issue9175(option: Option<()>) -> Option<()> {
     //stuff
     Some(())
 }
+
+fn issue12337() -> Option<i32> {
+    let _: Option<i32> = try {
+        let Some(_) = Some(42) else {
+            return None;
+        };
+        123
+    };
+    Some(42)
+}
diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed
index ce5c7f2600b..191f7719904 100644
--- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed
+++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed
@@ -111,3 +111,20 @@ fn fp_11274() {
     }
     m!(|x| println!("{x}"));
 }
+
+// Issue #12358: When a macro expands into a closure, immediately calling the expanded closure
+// triggers the lint.
+fn issue_12358() {
+    macro_rules! make_closure {
+        () => {
+            (|| || {})
+        };
+        (x) => {
+            make_closure!()()
+        };
+    }
+
+    // The lint would suggest to alter the line below to `make_closure!(x)`, which is semantically
+    // different.
+    make_closure!(x)();
+}
diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs
index ac09390e6ea..33a3b90f9cf 100644
--- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs
+++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs
@@ -111,3 +111,20 @@ fn fp_11274() {
     }
     m!(|x| println!("{x}"));
 }
+
+// Issue #12358: When a macro expands into a closure, immediately calling the expanded closure
+// triggers the lint.
+fn issue_12358() {
+    macro_rules! make_closure {
+        () => {
+            (|| || {})
+        };
+        (x) => {
+            make_closure!()()
+        };
+    }
+
+    // The lint would suggest to alter the line below to `make_closure!(x)`, which is semantically
+    // different.
+    make_closure!(x)();
+}
diff --git a/src/tools/clippy/tests/ui/redundant_field_names.fixed b/src/tools/clippy/tests/ui/redundant_field_names.fixed
index c578e786426..72fc4cb7333 100644
--- a/src/tools/clippy/tests/ui/redundant_field_names.fixed
+++ b/src/tools/clippy/tests/ui/redundant_field_names.fixed
@@ -20,7 +20,7 @@ struct Person {
 }
 
 pub struct S {
-    v: String,
+    v: usize,
 }
 
 fn main() {
@@ -59,11 +59,22 @@ fn main() {
     let _ = RangeToInclusive { end };
 
     external! {
-        let v = String::new();
+        let v = 1;
         let _ = S {
             v: v
         };
     }
+
+    let v = 2;
+    macro_rules! internal {
+        ($i:ident) => {
+            let _ = S { v };
+            let _ = S { $i: v };
+            let _ = S { v: $i };
+            let _ = S { $i: $i };
+        };
+    }
+    internal!(v);
 }
 
 fn issue_3476() {
diff --git a/src/tools/clippy/tests/ui/redundant_field_names.rs b/src/tools/clippy/tests/ui/redundant_field_names.rs
index d8c2286d5ad..2617d7e7283 100644
--- a/src/tools/clippy/tests/ui/redundant_field_names.rs
+++ b/src/tools/clippy/tests/ui/redundant_field_names.rs
@@ -20,7 +20,7 @@ struct Person {
 }
 
 pub struct S {
-    v: String,
+    v: usize,
 }
 
 fn main() {
@@ -59,11 +59,22 @@ fn main() {
     let _ = RangeToInclusive { end: end };
 
     external! {
-        let v = String::new();
+        let v = 1;
         let _ = S {
             v: v
         };
     }
+
+    let v = 2;
+    macro_rules! internal {
+        ($i:ident) => {
+            let _ = S { v: v };
+            let _ = S { $i: v };
+            let _ = S { v: $i };
+            let _ = S { $i: $i };
+        };
+    }
+    internal!(v);
 }
 
 fn issue_3476() {
diff --git a/src/tools/clippy/tests/ui/redundant_field_names.stderr b/src/tools/clippy/tests/ui/redundant_field_names.stderr
index 53234736207..38c021fdba3 100644
--- a/src/tools/clippy/tests/ui/redundant_field_names.stderr
+++ b/src/tools/clippy/tests/ui/redundant_field_names.stderr
@@ -44,10 +44,21 @@ LL |     let _ = RangeToInclusive { end: end };
    |                                ^^^^^^^^ help: replace it with: `end`
 
 error: redundant field names in struct initialization
-  --> tests/ui/redundant_field_names.rs:88:25
+  --> tests/ui/redundant_field_names.rs:71:25
+   |
+LL |             let _ = S { v: v };
+   |                         ^^^^ help: replace it with: `v`
+...
+LL |     internal!(v);
+   |     ------------ in this macro invocation
+   |
+   = note: this error originates in the macro `internal` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: redundant field names in struct initialization
+  --> tests/ui/redundant_field_names.rs:99:25
    |
 LL |     let _ = RangeFrom { start: start };
    |                         ^^^^^^^^^^^^ help: replace it with: `start`
 
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/renamed_builtin_attr.fixed b/src/tools/clippy/tests/ui/renamed_builtin_attr.fixed
index bc055215708..aebf8712dd9 100644
--- a/src/tools/clippy/tests/ui/renamed_builtin_attr.fixed
+++ b/src/tools/clippy/tests/ui/renamed_builtin_attr.fixed
@@ -1,2 +1,4 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #[clippy::cognitive_complexity = "1"]
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/renamed_builtin_attr.rs b/src/tools/clippy/tests/ui/renamed_builtin_attr.rs
index fdb425363e8..6c18151195f 100644
--- a/src/tools/clippy/tests/ui/renamed_builtin_attr.rs
+++ b/src/tools/clippy/tests/ui/renamed_builtin_attr.rs
@@ -1,2 +1,4 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #[clippy::cyclomatic_complexity = "1"]
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/renamed_builtin_attr.stderr b/src/tools/clippy/tests/ui/renamed_builtin_attr.stderr
index f9108d169c7..fb51313dab6 100644
--- a/src/tools/clippy/tests/ui/renamed_builtin_attr.stderr
+++ b/src/tools/clippy/tests/ui/renamed_builtin_attr.stderr
@@ -1,5 +1,5 @@
 error: usage of deprecated attribute
-  --> tests/ui/renamed_builtin_attr.rs:1:11
+  --> tests/ui/renamed_builtin_attr.rs:3:11
    |
 LL | #[clippy::cyclomatic_complexity = "1"]
    |           ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `cognitive_complexity`
diff --git a/src/tools/clippy/tests/ui/single_match.fixed b/src/tools/clippy/tests/ui/single_match.fixed
index 0a49be2dc4f..6df64eb4053 100644
--- a/src/tools/clippy/tests/ui/single_match.fixed
+++ b/src/tools/clippy/tests/ui/single_match.fixed
@@ -1,3 +1,5 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![warn(clippy::single_match)]
 #![allow(
     unused,
diff --git a/src/tools/clippy/tests/ui/single_match.rs b/src/tools/clippy/tests/ui/single_match.rs
index 4e35d265acb..4f005f4e04f 100644
--- a/src/tools/clippy/tests/ui/single_match.rs
+++ b/src/tools/clippy/tests/ui/single_match.rs
@@ -1,3 +1,5 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![warn(clippy::single_match)]
 #![allow(
     unused,
diff --git a/src/tools/clippy/tests/ui/single_match.stderr b/src/tools/clippy/tests/ui/single_match.stderr
index 40af38879ae..651d0b4911d 100644
--- a/src/tools/clippy/tests/ui/single_match.stderr
+++ b/src/tools/clippy/tests/ui/single_match.stderr
@@ -1,5 +1,5 @@
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:14:5
+  --> tests/ui/single_match.rs:16:5
    |
 LL | /     match x {
 LL | |         Some(y) => {
@@ -19,7 +19,7 @@ LL ~     };
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:22:5
+  --> tests/ui/single_match.rs:24:5
    |
 LL | /     match x {
 LL | |         // Note the missing block braces.
@@ -31,7 +31,7 @@ LL | |     }
    | |_____^ help: try: `if let Some(y) = x { println!("{:?}", y) }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:31:5
+  --> tests/ui/single_match.rs:33:5
    |
 LL | /     match z {
 LL | |         (2..=3, 7..=9) => dummy(),
@@ -40,7 +40,7 @@ LL | |     };
    | |_____^ help: try: `if let (2..=3, 7..=9) = z { dummy() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:60:5
+  --> tests/ui/single_match.rs:62:5
    |
 LL | /     match x {
 LL | |         Some(y) => dummy(),
@@ -49,7 +49,7 @@ LL | |     };
    | |_____^ help: try: `if let Some(y) = x { dummy() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:65:5
+  --> tests/ui/single_match.rs:67:5
    |
 LL | /     match y {
 LL | |         Ok(y) => dummy(),
@@ -58,7 +58,7 @@ LL | |     };
    | |_____^ help: try: `if let Ok(y) = y { dummy() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:72:5
+  --> tests/ui/single_match.rs:74:5
    |
 LL | /     match c {
 LL | |         Cow::Borrowed(..) => dummy(),
@@ -67,7 +67,7 @@ LL | |     };
    | |_____^ help: try: `if let Cow::Borrowed(..) = c { dummy() }`
 
 error: you seem to be trying to use `match` for an equality check. Consider using `if`
-  --> tests/ui/single_match.rs:93:5
+  --> tests/ui/single_match.rs:95:5
    |
 LL | /     match x {
 LL | |         "test" => println!(),
@@ -76,7 +76,7 @@ LL | |     }
    | |_____^ help: try: `if x == "test" { println!() }`
 
 error: you seem to be trying to use `match` for an equality check. Consider using `if`
-  --> tests/ui/single_match.rs:106:5
+  --> tests/ui/single_match.rs:108:5
    |
 LL | /     match x {
 LL | |         Foo::A => println!(),
@@ -85,7 +85,7 @@ LL | |     }
    | |_____^ help: try: `if x == Foo::A { println!() }`
 
 error: you seem to be trying to use `match` for an equality check. Consider using `if`
-  --> tests/ui/single_match.rs:112:5
+  --> tests/ui/single_match.rs:114:5
    |
 LL | /     match x {
 LL | |         FOO_C => println!(),
@@ -94,7 +94,7 @@ LL | |     }
    | |_____^ help: try: `if x == FOO_C { println!() }`
 
 error: you seem to be trying to use `match` for an equality check. Consider using `if`
-  --> tests/ui/single_match.rs:117:5
+  --> tests/ui/single_match.rs:119:5
    |
 LL | /     match &&x {
 LL | |         Foo::A => println!(),
@@ -103,7 +103,7 @@ LL | |     }
    | |_____^ help: try: `if x == Foo::A { println!() }`
 
 error: you seem to be trying to use `match` for an equality check. Consider using `if`
-  --> tests/ui/single_match.rs:123:5
+  --> tests/ui/single_match.rs:125:5
    |
 LL | /     match &x {
 LL | |         Foo::A => println!(),
@@ -112,7 +112,7 @@ LL | |     }
    | |_____^ help: try: `if x == &Foo::A { println!() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:140:5
+  --> tests/ui/single_match.rs:142:5
    |
 LL | /     match x {
 LL | |         Bar::A => println!(),
@@ -121,7 +121,7 @@ LL | |     }
    | |_____^ help: try: `if let Bar::A = x { println!() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:148:5
+  --> tests/ui/single_match.rs:150:5
    |
 LL | /     match x {
 LL | |         None => println!(),
@@ -130,7 +130,7 @@ LL | |     };
    | |_____^ help: try: `if let None = x { println!() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:170:5
+  --> tests/ui/single_match.rs:172:5
    |
 LL | /     match x {
 LL | |         (Some(_), _) => {},
@@ -139,7 +139,7 @@ LL | |     }
    | |_____^ help: try: `if let (Some(_), _) = x {}`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:176:5
+  --> tests/ui/single_match.rs:178:5
    |
 LL | /     match x {
 LL | |         (Some(E::V), _) => todo!(),
@@ -148,7 +148,7 @@ LL | |     }
    | |_____^ help: try: `if let (Some(E::V), _) = x { todo!() }`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:182:5
+  --> tests/ui/single_match.rs:184:5
    |
 LL | /     match (Some(42), Some(E::V), Some(42)) {
 LL | |         (.., Some(E::V), _) => {},
@@ -157,7 +157,7 @@ LL | |     }
    | |_____^ help: try: `if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {}`
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:254:5
+  --> tests/ui/single_match.rs:256:5
    |
 LL | /     match bar {
 LL | |         Some(v) => unsafe {
@@ -177,7 +177,7 @@ LL +     } }
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match.rs:262:5
+  --> tests/ui/single_match.rs:264:5
    |
 LL | /     match bar {
 LL | |         #[rustfmt::skip]
diff --git a/src/tools/clippy/tests/ui/single_match_else.fixed b/src/tools/clippy/tests/ui/single_match_else.fixed
index f3b1de3b44f..2970f5485fa 100644
--- a/src/tools/clippy/tests/ui/single_match_else.fixed
+++ b/src/tools/clippy/tests/ui/single_match_else.fixed
@@ -1,4 +1,6 @@
 //@aux-build: proc_macros.rs
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![warn(clippy::single_match_else)]
 #![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)]
 extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/single_match_else.rs b/src/tools/clippy/tests/ui/single_match_else.rs
index ddee2e42ec2..26974b2a48a 100644
--- a/src/tools/clippy/tests/ui/single_match_else.rs
+++ b/src/tools/clippy/tests/ui/single_match_else.rs
@@ -1,4 +1,6 @@
 //@aux-build: proc_macros.rs
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![warn(clippy::single_match_else)]
 #![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)]
 extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/single_match_else.stderr b/src/tools/clippy/tests/ui/single_match_else.stderr
index 63c733e9a7a..48c74c0caea 100644
--- a/src/tools/clippy/tests/ui/single_match_else.stderr
+++ b/src/tools/clippy/tests/ui/single_match_else.stderr
@@ -1,5 +1,5 @@
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:16:13
+  --> tests/ui/single_match_else.rs:18:13
    |
 LL |       let _ = match ExprNode::Butterflies {
    |  _____________^
@@ -22,7 +22,7 @@ LL ~     };
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:81:5
+  --> tests/ui/single_match_else.rs:83:5
    |
 LL | /     match Some(1) {
 LL | |         Some(a) => println!("${:?}", a),
@@ -42,7 +42,7 @@ LL +     }
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:90:5
+  --> tests/ui/single_match_else.rs:92:5
    |
 LL | /     match Some(1) {
 LL | |         Some(a) => println!("${:?}", a),
@@ -62,7 +62,7 @@ LL +     }
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:100:5
+  --> tests/ui/single_match_else.rs:102:5
    |
 LL | /     match Result::<i32, Infallible>::Ok(1) {
 LL | |         Ok(a) => println!("${:?}", a),
@@ -82,7 +82,7 @@ LL +     }
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:109:5
+  --> tests/ui/single_match_else.rs:111:5
    |
 LL | /     match Cow::from("moo") {
 LL | |         Cow::Owned(a) => println!("${:?}", a),
@@ -102,7 +102,7 @@ LL +     }
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:119:5
+  --> tests/ui/single_match_else.rs:121:5
    |
 LL | /     match bar {
 LL | |         Some(v) => unsafe {
@@ -125,7 +125,7 @@ LL +     }
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:130:5
+  --> tests/ui/single_match_else.rs:132:5
    |
 LL | /     match bar {
 LL | |         Some(v) => {
@@ -149,7 +149,7 @@ LL +     } }
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:142:5
+  --> tests/ui/single_match_else.rs:144:5
    |
 LL | /     match bar {
 LL | |         Some(v) => unsafe {
@@ -173,7 +173,7 @@ LL +     } }
    |
 
 error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
-  --> tests/ui/single_match_else.rs:154:5
+  --> tests/ui/single_match_else.rs:156:5
    |
 LL | /     match bar {
 LL | |         #[rustfmt::skip]
diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.fixed b/src/tools/clippy/tests/ui/std_instead_of_core.fixed
index a7555704fbe..0a734a65d29 100644
--- a/src/tools/clippy/tests/ui/std_instead_of_core.fixed
+++ b/src/tools/clippy/tests/ui/std_instead_of_core.fixed
@@ -1,4 +1,5 @@
 //@aux-build:proc_macro_derive.rs
+
 #![warn(clippy::std_instead_of_core)]
 #![allow(unused_imports)]
 
@@ -16,12 +17,20 @@ fn std_instead_of_core() {
     use ::core::hash::Hash;
     //~^ ERROR: used import from `std` instead of `core`
     // Don't lint on `env` macro
-    use std::env;
+    use core::env;
 
     // Multiple imports
     use core::fmt::{Debug, Result};
     //~^ ERROR: used import from `std` instead of `core`
 
+    // Multiple imports multiline
+    #[rustfmt::skip]
+    use core::{
+        //~^ ERROR: used import from `std` instead of `core`
+        fmt::Write as _,
+        ptr::read_unaligned,
+    };
+
     // Function calls
     let ptr = core::ptr::null::<u32>();
     //~^ ERROR: used import from `std` instead of `core`
diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.rs b/src/tools/clippy/tests/ui/std_instead_of_core.rs
index af7f3399f49..c12c459c7eb 100644
--- a/src/tools/clippy/tests/ui/std_instead_of_core.rs
+++ b/src/tools/clippy/tests/ui/std_instead_of_core.rs
@@ -1,4 +1,5 @@
 //@aux-build:proc_macro_derive.rs
+
 #![warn(clippy::std_instead_of_core)]
 #![allow(unused_imports)]
 
@@ -22,6 +23,14 @@ fn std_instead_of_core() {
     use std::fmt::{Debug, Result};
     //~^ ERROR: used import from `std` instead of `core`
 
+    // Multiple imports multiline
+    #[rustfmt::skip]
+    use std::{
+        //~^ ERROR: used import from `std` instead of `core`
+        fmt::Write as _,
+        ptr::read_unaligned,
+    };
+
     // Function calls
     let ptr = std::ptr::null::<u32>();
     //~^ ERROR: used import from `std` instead of `core`
diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.stderr b/src/tools/clippy/tests/ui/std_instead_of_core.stderr
index 30dd49dc268..ee42b474a32 100644
--- a/src/tools/clippy/tests/ui/std_instead_of_core.stderr
+++ b/src/tools/clippy/tests/ui/std_instead_of_core.stderr
@@ -1,5 +1,5 @@
 error: used import from `std` instead of `core`
-  --> tests/ui/std_instead_of_core.rs:13:9
+  --> tests/ui/std_instead_of_core.rs:14:9
    |
 LL |     use std::hash::Hasher;
    |         ^^^ help: consider importing the item from `core`: `core`
@@ -8,49 +8,61 @@ LL |     use std::hash::Hasher;
    = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_core)]`
 
 error: used import from `std` instead of `core`
-  --> tests/ui/std_instead_of_core.rs:16:11
+  --> tests/ui/std_instead_of_core.rs:17:11
    |
 LL |     use ::std::hash::Hash;
    |           ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> tests/ui/std_instead_of_core.rs:22:9
+  --> tests/ui/std_instead_of_core.rs:20:9
+   |
+LL |     use std::env;
+   |         ^^^ help: consider importing the item from `core`: `core`
+
+error: used import from `std` instead of `core`
+  --> tests/ui/std_instead_of_core.rs:23:9
    |
 LL |     use std::fmt::{Debug, Result};
    |         ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> tests/ui/std_instead_of_core.rs:26:15
+  --> tests/ui/std_instead_of_core.rs:28:9
+   |
+LL |     use std::{
+   |         ^^^ help: consider importing the item from `core`: `core`
+
+error: used import from `std` instead of `core`
+  --> tests/ui/std_instead_of_core.rs:35:15
    |
 LL |     let ptr = std::ptr::null::<u32>();
    |               ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> tests/ui/std_instead_of_core.rs:28:21
+  --> tests/ui/std_instead_of_core.rs:37:21
    |
 LL |     let ptr_mut = ::std::ptr::null_mut::<usize>();
    |                     ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> tests/ui/std_instead_of_core.rs:32:16
+  --> tests/ui/std_instead_of_core.rs:41:16
    |
 LL |     let cell = std::cell::Cell::new(8u32);
    |                ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> tests/ui/std_instead_of_core.rs:34:27
+  --> tests/ui/std_instead_of_core.rs:43:27
    |
 LL |     let cell_absolute = ::std::cell::Cell::new(8u32);
    |                           ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `core`
-  --> tests/ui/std_instead_of_core.rs:43:9
+  --> tests/ui/std_instead_of_core.rs:52:9
    |
 LL |     use std::iter::Iterator;
    |         ^^^ help: consider importing the item from `core`: `core`
 
 error: used import from `std` instead of `alloc`
-  --> tests/ui/std_instead_of_core.rs:50:9
+  --> tests/ui/std_instead_of_core.rs:59:9
    |
 LL |     use std::vec;
    |         ^^^ help: consider importing the item from `alloc`: `alloc`
@@ -59,13 +71,13 @@ LL |     use std::vec;
    = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_alloc)]`
 
 error: used import from `std` instead of `alloc`
-  --> tests/ui/std_instead_of_core.rs:52:9
+  --> tests/ui/std_instead_of_core.rs:61:9
    |
 LL |     use std::vec::Vec;
    |         ^^^ help: consider importing the item from `alloc`: `alloc`
 
 error: used import from `alloc` instead of `core`
-  --> tests/ui/std_instead_of_core.rs:58:9
+  --> tests/ui/std_instead_of_core.rs:67:9
    |
 LL |     use alloc::slice::from_ref;
    |         ^^^^^ help: consider importing the item from `core`: `core`
@@ -73,5 +85,5 @@ LL |     use alloc::slice::from_ref;
    = note: `-D clippy::alloc-instead-of-core` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::alloc_instead_of_core)]`
 
-error: aborting due to 11 previous errors
+error: aborting due to 13 previous errors
 
diff --git a/src/tools/clippy/tests/ui/suspicious_operation_groupings.fixed b/src/tools/clippy/tests/ui/suspicious_operation_groupings.fixed
index 9d9732307c8..60fde6e22cb 100644
--- a/src/tools/clippy/tests/ui/suspicious_operation_groupings.fixed
+++ b/src/tools/clippy/tests/ui/suspicious_operation_groupings.fixed
@@ -1,3 +1,5 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![warn(clippy::suspicious_operation_groupings)]
 #![allow(dead_code, unused_parens, clippy::eq_op)]
 
diff --git a/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs b/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs
index 201b8e657f4..ce37148a853 100644
--- a/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs
+++ b/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs
@@ -1,3 +1,5 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![warn(clippy::suspicious_operation_groupings)]
 #![allow(dead_code, unused_parens, clippy::eq_op)]
 
diff --git a/src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr b/src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr
index 9d1d8a1f34f..7cb066d57e7 100644
--- a/src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr
+++ b/src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr
@@ -1,5 +1,5 @@
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:15:9
+  --> tests/ui/suspicious_operation_groupings.rs:17:9
    |
 LL |         self.x == other.y && self.y == other.y && self.z == other.z
    |         ^^^^^^^^^^^^^^^^^ help: did you mean: `self.x == other.x`
@@ -8,151 +8,151 @@ LL |         self.x == other.y && self.y == other.y && self.z == other.z
    = help: to override `-D warnings` add `#[allow(clippy::suspicious_operation_groupings)]`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:28:20
+  --> tests/ui/suspicious_operation_groupings.rs:30:20
    |
 LL |     s1.a < s2.a && s1.a < s2.b
    |                    ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:76:33
+  --> tests/ui/suspicious_operation_groupings.rs:78:33
    |
 LL |     s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d
    |                                 ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:81:19
+  --> tests/ui/suspicious_operation_groupings.rs:83:19
    |
 LL |     s1.a * s2.a + s1.b * s2.c + s1.c * s2.c
    |                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:81:19
+  --> tests/ui/suspicious_operation_groupings.rs:83:19
    |
 LL |     s1.a * s2.a + s1.b * s2.c + s1.c * s2.c
    |                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:86:19
+  --> tests/ui/suspicious_operation_groupings.rs:88:19
    |
 LL |     s1.a * s2.a + s2.b * s2.b + s1.c * s2.c
    |                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:91:19
+  --> tests/ui/suspicious_operation_groupings.rs:93:19
    |
 LL |     s1.a * s2.a + s1.b * s1.b + s1.c * s2.c
    |                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:96:5
+  --> tests/ui/suspicious_operation_groupings.rs:98:5
    |
 LL |     s1.a * s1.a + s1.b * s2.b + s1.c * s2.c
    |     ^^^^^^^^^^^ help: did you mean: `s1.a * s2.a`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:101:33
+  --> tests/ui/suspicious_operation_groupings.rs:103:33
    |
 LL |     s1.a * s2.a + s1.b * s2.b + s1.c * s1.c
    |                                 ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:114:20
+  --> tests/ui/suspicious_operation_groupings.rs:116:20
    |
 LL |     (s1.a * s2.a + s1.b * s1.b)
    |                    ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:119:34
+  --> tests/ui/suspicious_operation_groupings.rs:121:34
    |
 LL |     (s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d)
    |                                  ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:124:38
+  --> tests/ui/suspicious_operation_groupings.rs:126:38
    |
 LL |     (s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)
    |                                      ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:129:39
+  --> tests/ui/suspicious_operation_groupings.rs:131:39
    |
 LL |     ((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d))
    |                                       ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:134:42
+  --> tests/ui/suspicious_operation_groupings.rs:136:42
    |
 LL |     (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d)))
    |                                          ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:134:42
+  --> tests/ui/suspicious_operation_groupings.rs:136:42
    |
 LL |     (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d)))
    |                                          ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:139:40
+  --> tests/ui/suspicious_operation_groupings.rs:141:40
    |
 LL |     (((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b)) + (s1.d * s2.d))
    |                                        ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:144:40
+  --> tests/ui/suspicious_operation_groupings.rs:146:40
    |
 LL |     ((s1.a * s2.a) + ((s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)))
    |                                        ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:149:20
+  --> tests/ui/suspicious_operation_groupings.rs:151:20
    |
 LL |     (s1.a * s2.a + s2.b * s2.b) / 2
    |                    ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:154:35
+  --> tests/ui/suspicious_operation_groupings.rs:156:35
    |
 LL |     i32::swap_bytes(s1.a * s2.a + s2.b * s2.b)
    |                                   ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:159:29
+  --> tests/ui/suspicious_operation_groupings.rs:161:29
    |
 LL |     s1.a > 0 && s1.b > 0 && s1.d == s2.c && s1.d == s2.d
    |                             ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:164:17
+  --> tests/ui/suspicious_operation_groupings.rs:166:17
    |
 LL |     s1.a > 0 && s1.d == s2.c && s1.b > 0 && s1.d == s2.d
    |                 ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:173:77
+  --> tests/ui/suspicious_operation_groupings.rs:175:77
    |
 LL |     (n1.inner.0).0 == (n2.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.1).0
    |                                                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `(n1.inner.2).0 == (n2.inner.2).0`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:187:25
+  --> tests/ui/suspicious_operation_groupings.rs:189:25
    |
 LL |         s1.a <= s2.a && s1.a <= s2.b
    |                         ^^^^^^^^^^^^ help: did you mean: `s1.b <= s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:193:23
+  --> tests/ui/suspicious_operation_groupings.rs:195:23
    |
 LL |     if s1.a < s2.a && s1.a < s2.b {
    |                       ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:200:48
+  --> tests/ui/suspicious_operation_groupings.rs:202:48
    |
 LL |     -(-(-s1.a * -s2.a) + (-(-s1.b * -s2.b) + -(-s1.c * -s2.b) + -(-s1.d * -s2.d)))
    |                                                ^^^^^^^^^^^^^ help: did you mean: `-s1.c * -s2.c`
 
 error: this sequence of operators looks suspiciously like a bug
-  --> tests/ui/suspicious_operation_groupings.rs:205:27
+  --> tests/ui/suspicious_operation_groupings.rs:207:27
    |
 LL |     -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a })
    |                           ^^^^^^^^^^^^^ help: did you mean: `-s1.b < -s2.b`
diff --git a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.fixed b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.fixed
index bbde25b0a88..a6ed59d49c5 100644
--- a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.fixed
+++ b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.fixed
@@ -27,4 +27,18 @@ fn main() {
     }
     //~^^^^ ERROR: initializer for `thread_local` value can be made `const`
     //~^^^ ERROR: initializer for `thread_local` value can be made `const`
+
+    thread_local! {
+        static PEEL_ME: i32 = const { 1 };
+        //~^ ERROR: initializer for `thread_local` value can be made `const`
+        static PEEL_ME_MANY: i32 = const { { let x = 1; x * x } };
+        //~^ ERROR: initializer for `thread_local` value can be made `const`
+    }
+}
+
+#[clippy::msrv = "1.58"]
+fn f() {
+    thread_local! {
+        static TLS: i32 = 1;
+    }
 }
diff --git a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.rs b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.rs
index 3d7aacf2f09..3f0159c5806 100644
--- a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.rs
+++ b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.rs
@@ -27,4 +27,18 @@ fn main() {
     }
     //~^^^^ ERROR: initializer for `thread_local` value can be made `const`
     //~^^^ ERROR: initializer for `thread_local` value can be made `const`
+
+    thread_local! {
+        static PEEL_ME: i32 = { 1 };
+        //~^ ERROR: initializer for `thread_local` value can be made `const`
+        static PEEL_ME_MANY: i32 = { let x = 1; x * x };
+        //~^ ERROR: initializer for `thread_local` value can be made `const`
+    }
+}
+
+#[clippy::msrv = "1.58"]
+fn f() {
+    thread_local! {
+        static TLS: i32 = 1;
+    }
 }
diff --git a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.stderr b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.stderr
index 9ee52fbbb31..b4f8bd822b0 100644
--- a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.stderr
+++ b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.stderr
@@ -25,5 +25,17 @@ error: initializer for `thread_local` value can be made `const`
 LL |         static BUF_4_CAN_BE_MADE_CONST: RefCell<String> = RefCell::new(String::new());
    |                                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `const { RefCell::new(String::new()) }`
 
-error: aborting due to 4 previous errors
+error: initializer for `thread_local` value can be made `const`
+  --> tests/ui/thread_local_initializer_can_be_made_const.rs:32:31
+   |
+LL |         static PEEL_ME: i32 = { 1 };
+   |                               ^^^^^ help: replace with: `const { 1 }`
+
+error: initializer for `thread_local` value can be made `const`
+  --> tests/ui/thread_local_initializer_can_be_made_const.rs:34:36
+   |
+LL |         static PEEL_ME_MANY: i32 = { let x = 1; x * x };
+   |                                    ^^^^^^^^^^^^^^^^^^^^ help: replace with: `const { { let x = 1; x * x } }`
+
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
index 08b8e786611..2365695d691 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
@@ -82,3 +82,10 @@ fn issue_10449() {
 
     let _x: u8 = unsafe { *(f as *const u8) };
 }
+
+// Pointers cannot be cast to integers in const contexts
+const fn issue_12402<P>(ptr: *const P) {
+    unsafe { transmute::<*const i32, usize>(&42i32) };
+    unsafe { transmute::<fn(*const P), usize>(issue_12402) };
+    let _ = unsafe { transmute::<_, usize>(ptr) };
+}
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
index 92eb765e5f9..cd1607b4c19 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
@@ -82,3 +82,10 @@ fn issue_10449() {
 
     let _x: u8 = unsafe { *std::mem::transmute::<fn(), *const u8>(f) };
 }
+
+// Pointers cannot be cast to integers in const contexts
+const fn issue_12402<P>(ptr: *const P) {
+    unsafe { transmute::<*const i32, usize>(&42i32) };
+    unsafe { transmute::<fn(*const P), usize>(issue_12402) };
+    let _ = unsafe { transmute::<_, usize>(ptr) };
+}
diff --git a/src/tools/clippy/tests/ui/type_complexity.rs b/src/tools/clippy/tests/ui/type_complexity.rs
index be28ee2da0c..b057dc4e89f 100644
--- a/src/tools/clippy/tests/ui/type_complexity.rs
+++ b/src/tools/clippy/tests/ui/type_complexity.rs
@@ -1,3 +1,5 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![warn(clippy::all)]
 #![allow(unused, clippy::needless_pass_by_value, clippy::vec_box, clippy::useless_vec)]
 #![feature(associated_type_defaults)]
diff --git a/src/tools/clippy/tests/ui/type_complexity.stderr b/src/tools/clippy/tests/ui/type_complexity.stderr
index 9e27899e4f9..bfbab8647e8 100644
--- a/src/tools/clippy/tests/ui/type_complexity.stderr
+++ b/src/tools/clippy/tests/ui/type_complexity.stderr
@@ -1,5 +1,5 @@
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:7:12
+  --> tests/ui/type_complexity.rs:9:12
    |
 LL | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0))));
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,85 +8,85 @@ LL | const CST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0))));
    = help: to override `-D warnings` add `#[allow(clippy::type_complexity)]`
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:10:12
+  --> tests/ui/type_complexity.rs:12:12
    |
 LL | static ST: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0))));
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:14:8
+  --> tests/ui/type_complexity.rs:16:8
    |
 LL |     f: Vec<Vec<Box<(u32, u32, u32, u32)>>>,
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:18:11
+  --> tests/ui/type_complexity.rs:20:11
    |
 LL | struct Ts(Vec<Vec<Box<(u32, u32, u32, u32)>>>);
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:22:11
+  --> tests/ui/type_complexity.rs:24:11
    |
 LL |     Tuple(Vec<Vec<Box<(u32, u32, u32, u32)>>>),
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:24:17
+  --> tests/ui/type_complexity.rs:26:17
    |
 LL |     Struct { f: Vec<Vec<Box<(u32, u32, u32, u32)>>> },
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:29:14
+  --> tests/ui/type_complexity.rs:31:14
    |
 LL |     const A: (u32, (u32, (u32, (u32, u32)))) = (0, (0, (0, (0, 0))));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:31:30
+  --> tests/ui/type_complexity.rs:33:30
    |
 LL |     fn impl_method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {}
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:36:14
+  --> tests/ui/type_complexity.rs:38:14
    |
 LL |     const A: Vec<Vec<Box<(u32, u32, u32, u32)>>>;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:38:14
+  --> tests/ui/type_complexity.rs:40:14
    |
 LL |     type B = Vec<Vec<Box<(u32, u32, u32, u32)>>>;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:40:25
+  --> tests/ui/type_complexity.rs:42:25
    |
 LL |     fn method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:42:29
+  --> tests/ui/type_complexity.rs:44:29
    |
 LL |     fn def_method(&self, p: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {}
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:55:15
+  --> tests/ui/type_complexity.rs:57:15
    |
 LL | fn test1() -> Vec<Vec<Box<(u32, u32, u32, u32)>>> {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:60:14
+  --> tests/ui/type_complexity.rs:62:14
    |
 LL | fn test2(_x: Vec<Vec<Box<(u32, u32, u32, u32)>>>) {}
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: very complex type used. Consider factoring parts into `type` definitions
-  --> tests/ui/type_complexity.rs:64:13
+  --> tests/ui/type_complexity.rs:66:13
    |
 LL |     let _y: Vec<Vec<Box<(u32, u32, u32, u32)>>> = vec![];
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/unknown_attribute.rs b/src/tools/clippy/tests/ui/unknown_attribute.rs
index 932f284d5b7..3241742b5d4 100644
--- a/src/tools/clippy/tests/ui/unknown_attribute.rs
+++ b/src/tools/clippy/tests/ui/unknown_attribute.rs
@@ -1,3 +1,5 @@
+//@compile-flags: -Zdeduplicate-diagnostics=yes
+
 #[clippy::unknown]
 //~^ ERROR: usage of unknown attribute
 #[clippy::cognitive_complexity = "1"]
diff --git a/src/tools/clippy/tests/ui/unknown_attribute.stderr b/src/tools/clippy/tests/ui/unknown_attribute.stderr
index d1f8eeb51ae..b306abe0a9d 100644
--- a/src/tools/clippy/tests/ui/unknown_attribute.stderr
+++ b/src/tools/clippy/tests/ui/unknown_attribute.stderr
@@ -1,5 +1,5 @@
 error: usage of unknown attribute
-  --> tests/ui/unknown_attribute.rs:1:11
+  --> tests/ui/unknown_attribute.rs:3:11
    |
 LL | #[clippy::unknown]
    |           ^^^^^^^
diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.fixed b/src/tools/clippy/tests/ui/unnecessary_cast.fixed
index f52d3250339..288541362cd 100644
--- a/src/tools/clippy/tests/ui/unnecessary_cast.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_cast.fixed
@@ -221,4 +221,10 @@ mod fixable {
     fn issue_9603() {
         let _: f32 = -0x400 as f32;
     }
+
+    // Issue #11968: The suggestion for this lint removes the parentheses and leave the code as
+    // `*x.pow(2)` which tries to dereference the return value rather than `x`.
+    fn issue_11968(x: &usize) -> usize {
+        { *x }.pow(2)
+    }
 }
diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.rs b/src/tools/clippy/tests/ui/unnecessary_cast.rs
index dfd8b454e6c..eef3a42e351 100644
--- a/src/tools/clippy/tests/ui/unnecessary_cast.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_cast.rs
@@ -221,4 +221,10 @@ mod fixable {
     fn issue_9603() {
         let _: f32 = -0x400 as f32;
     }
+
+    // Issue #11968: The suggestion for this lint removes the parentheses and leave the code as
+    // `*x.pow(2)` which tries to dereference the return value rather than `x`.
+    fn issue_11968(x: &usize) -> usize {
+        (*x as usize).pow(2)
+    }
 }
diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.stderr b/src/tools/clippy/tests/ui/unnecessary_cast.stderr
index 935bb71da32..80fd5c13d81 100644
--- a/src/tools/clippy/tests/ui/unnecessary_cast.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_cast.stderr
@@ -241,5 +241,11 @@ error: casting to the same type is unnecessary (`f32` -> `f32`)
 LL |         let _num = foo() as f32;
    |                    ^^^^^^^^^^^^ help: try: `foo()`
 
-error: aborting due to 40 previous errors
+error: casting to the same type is unnecessary (`usize` -> `usize`)
+  --> tests/ui/unnecessary_cast.rs:228:9
+   |
+LL |         (*x as usize).pow(2)
+   |         ^^^^^^^^^^^^^ help: try: `{ *x }`
+
+error: aborting due to 41 previous errors
 
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 8c50bcd5b61..06d8f099c33 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -451,6 +451,15 @@ impl Config {
         self.target_cfg().panic == PanicStrategy::Unwind
     }
 
+    pub fn has_threads(&self) -> bool {
+        // Wasm targets don't have threads unless `-threads` is in the target
+        // name, such as `wasm32-wasip1-threads`.
+        if self.target.starts_with("wasm") {
+            return self.target.contains("threads");
+        }
+        true
+    }
+
     pub fn has_asm_support(&self) -> bool {
         static ASM_SUPPORTED_ARCHS: &[&str] = &[
             "x86", "x86_64", "arm", "aarch64", "riscv32",
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 6de445a5783..f15761354f7 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -787,6 +787,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "needs-sanitizer-shadow-call-stack",
     "needs-sanitizer-support",
     "needs-sanitizer-thread",
+    "needs-threads",
     "needs-unwind",
     "needs-xray",
     "no-prefer-dynamic",
diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs
index 39786588150..d7c74038aea 100644
--- a/src/tools/compiletest/src/header/needs.rs
+++ b/src/tools/compiletest/src/header/needs.rs
@@ -84,6 +84,11 @@ pub(super) fn handle_needs(
             condition: config.run_enabled(),
             ignore_reason: "ignored when running the resulting test binaries is disabled",
         },
+        Need {
+            name: "needs-threads",
+            condition: config.has_threads(),
+            ignore_reason: "ignored on targets without threading support",
+        },
         Need {
             name: "needs-unwind",
             condition: config.can_unwind(),
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index a01f71a6876..815ac3839df 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -533,6 +533,16 @@ fn wasm_special() {
         ("wasm32-wasi", "wasm32", true),
         ("wasm32-wasi", "wasm32-bare", false),
         ("wasm32-wasi", "wasi", true),
+        // NB: the wasm32-wasip1 target is new so this isn't tested for
+        // the bootstrap compiler.
+        #[cfg(not(bootstrap))]
+        ("wasm32-wasip1", "emscripten", false),
+        #[cfg(not(bootstrap))]
+        ("wasm32-wasip1", "wasm32", true),
+        #[cfg(not(bootstrap))]
+        ("wasm32-wasip1", "wasm32-bare", false),
+        #[cfg(not(bootstrap))]
+        ("wasm32-wasip1", "wasi", true),
         ("wasm64-unknown-unknown", "emscripten", false),
         ("wasm64-unknown-unknown", "wasm32", false),
         ("wasm64-unknown-unknown", "wasm32-bare", false),
@@ -582,3 +592,23 @@ fn ignore_mode() {
         assert!(!check_ignore(&config, &format!("//@ ignore-mode-{other}")));
     }
 }
+
+#[test]
+fn threads_support() {
+    let threads = [
+        ("x86_64-unknown-linux-gnu", true),
+        ("aarch64-apple-darwin", true),
+        ("wasm32-unknown-unknown", false),
+        ("wasm64-unknown-unknown", false),
+        #[cfg(not(bootstrap))]
+        ("wasm32-wasip1", false),
+        #[cfg(not(bootstrap))]
+        ("wasm32-wasip1-threads", true),
+        ("wasm32-wasi-preview1-threads", true),
+    ];
+    for (target, has_threads) in threads {
+        let config = cfg().target(target).build();
+        assert_eq!(config.has_threads(), has_threads);
+        assert_eq!(check_ignore(&config, "//@ needs-threads"), !has_threads)
+    }
+}
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index 2f37a64576e..a9b5aa5f1ef 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -342,6 +342,8 @@ fn main() {
     // (`install_ice_hook` might change `RUST_BACKTRACE`.)
     let env_snapshot = env::vars_os().collect::<Vec<_>>();
 
+    let args = rustc_driver::args::raw_args(&early_dcx).unwrap_or_else(|_| std::process::exit(rustc_driver::EXIT_FAILURE));
+
     // If the environment asks us to actually be rustc, then do that.
     if let Some(crate_kind) = env::var_os("MIRI_BE_RUSTC") {
         // Earliest rustc setup.
@@ -359,7 +361,7 @@ fn main() {
 
         // We cannot use `rustc_driver::main` as we need to adjust the CLI arguments.
         run_compiler(
-            env::args().collect(),
+            args,
             target_crate,
             &mut MiriBeRustCompilerCalls { target_crate },
             using_internal_features,
@@ -382,7 +384,7 @@ fn main() {
 
     // If user has explicitly enabled/disabled isolation
     let mut isolation_enabled: Option<bool> = None;
-    for arg in env::args() {
+    for arg in args {
         if rustc_args.is_empty() {
             // Very first arg: binary name.
             rustc_args.push(arg);
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index de0ed879b36..4683965159d 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -1,7 +1,7 @@
 use std::fmt::{self, Write};
 use std::num::NonZero;
 
-use rustc_errors::{Diag, DiagnosticMessage, Level};
+use rustc_errors::{Diag, DiagMessage, Level};
 use rustc_span::{SpanData, Symbol, DUMMY_SP};
 use rustc_target::abi::{Align, Size};
 
@@ -95,7 +95,7 @@ impl fmt::Debug for TerminationInfo {
 }
 
 impl MachineStopType for TerminationInfo {
-    fn diagnostic_message(&self) -> DiagnosticMessage {
+    fn diagnostic_message(&self) -> DiagMessage {
         self.to_string().into()
     }
     fn add_args(
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 65260254ae2..9e4b5fe8ad7 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -381,7 +381,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         f: ty::Instance<'tcx>,
         caller_abi: Abi,
         args: &[Immediate<Provenance>],
-        dest: Option<&PlaceTy<'tcx, Provenance>>,
+        dest: Option<&MPlaceTy<'tcx, Provenance>>,
         stack_pop: StackPopCleanup,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index d40f1c4525f..19d02c6f746 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -8,7 +8,6 @@ use std::fmt;
 use std::path::Path;
 use std::process;
 
-use either::Either;
 use rand::rngs::StdRng;
 use rand::Rng;
 use rand::SeedableRng;
@@ -950,7 +949,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         instance: ty::Instance<'tcx>,
         abi: Abi,
         args: &[FnArg<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
@@ -962,7 +961,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
             // to run extra MIR), and Ok(Some(body)) if we found MIR to run for the
             // foreign function
             // Any needed call to `goto_block` will be performed by `emulate_foreign_item`.
-            let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit?
+            let args = ecx.copy_fn_args(args); // FIXME: Should `InPlace` arguments be reset to uninit?
             let link_name = ecx.item_link_name(instance.def_id());
             return ecx.emulate_foreign_item(link_name, abi, &args, dest, ret, unwind);
         }
@@ -977,11 +976,11 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         fn_val: DynSym,
         abi: Abi,
         args: &[FnArg<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
-        let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit?
+        let args = ecx.copy_fn_args(args); // FIXME: Should `InPlace` arguments be reset to uninit?
         ecx.emulate_dyn_sym(fn_val, abi, &args, dest, ret, unwind)
     }
 
@@ -990,7 +989,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ecx: &mut MiriInterpCx<'mir, 'tcx>,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
@@ -1334,18 +1333,12 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
 
     fn protect_in_place_function_argument(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        place: &PlaceTy<'tcx, Provenance>,
+        place: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
         // If we have a borrow tracker, we also have it set up protection so that all reads *and
         // writes* during this call are insta-UB.
         let protected_place = if ecx.machine.borrow_tracker.is_some() {
-            // Have to do `to_op` first because a `Place::Local` doesn't imply the local doesn't have an address.
-            if let Either::Left(place) = ecx.place_to_op(place)?.as_mplace_or_imm() {
-                ecx.protect_place(&place)?.into()
-            } else {
-                // Locals that don't have their address taken are as protected as they can ever be.
-                place.clone()
-            }
+            ecx.protect_place(&place)?.into()
         } else {
             // No borrow tracker.
             place.clone()
diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs
index 48dafc40c62..abfa7143a73 100644
--- a/src/tools/miri/src/shims/backtrace.rs
+++ b/src/tools/miri/src/shims/backtrace.rs
@@ -12,7 +12,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         abi: Abi,
         link_name: Symbol,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let [flags] = this.check_shim(abi, Abi::Rust, link_name, args)?;
@@ -32,7 +32,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         abi: Abi,
         link_name: Symbol,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let tcx = this.tcx;
@@ -145,7 +145,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         abi: Abi,
         link_name: Symbol,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let [ptr, flags] = this.check_shim(abi, Abi::Rust, link_name, args)?;
@@ -174,7 +174,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // `lo.col` is 0-based - add 1 to make it 1-based for the caller.
         let colno: u32 = u32::try_from(lo.col.0.saturating_add(1)).unwrap_or(0);
 
-        let dest = this.force_allocation(dest)?;
         if let ty::Adt(adt, _) = dest.layout.ty.kind() {
             if !adt.repr().c() {
                 throw_ub_format!(
@@ -191,29 +190,29 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let filename_alloc =
                     this.allocate_str(&filename, MiriMemoryKind::Rust.into(), Mutability::Mut)?;
 
-                this.write_immediate(name_alloc.to_ref(this), &this.project_field(&dest, 0)?)?;
-                this.write_immediate(filename_alloc.to_ref(this), &this.project_field(&dest, 1)?)?;
+                this.write_immediate(name_alloc.to_ref(this), &this.project_field(dest, 0)?)?;
+                this.write_immediate(filename_alloc.to_ref(this), &this.project_field(dest, 1)?)?;
             }
             1 => {
                 this.write_scalar(
                     Scalar::from_target_usize(name.len().try_into().unwrap(), this),
-                    &this.project_field(&dest, 0)?,
+                    &this.project_field(dest, 0)?,
                 )?;
                 this.write_scalar(
                     Scalar::from_target_usize(filename.len().try_into().unwrap(), this),
-                    &this.project_field(&dest, 1)?,
+                    &this.project_field(dest, 1)?,
                 )?;
             }
             _ => throw_unsup_format!("unknown `miri_resolve_frame` flags {}", flags),
         }
 
-        this.write_scalar(Scalar::from_u32(lineno), &this.project_field(&dest, 2)?)?;
-        this.write_scalar(Scalar::from_u32(colno), &this.project_field(&dest, 3)?)?;
+        this.write_scalar(Scalar::from_u32(lineno), &this.project_field(dest, 2)?)?;
+        this.write_scalar(Scalar::from_u32(colno), &this.project_field(dest, 3)?)?;
 
         // Support a 4-field struct for now - this is deprecated
         // and slated for removal.
         if num_fields == 5 {
-            this.write_pointer(fn_ptr, &this.project_field(&dest, 4)?)?;
+            this.write_pointer(fn_ptr, &this.project_field(dest, 4)?)?;
         }
 
         Ok(())
diff --git a/src/tools/miri/src/shims/ffi_support.rs b/src/tools/miri/src/shims/ffi_support.rs
index e628c44a867..6da119e5fa8 100644
--- a/src/tools/miri/src/shims/ffi_support.rs
+++ b/src/tools/miri/src/shims/ffi_support.rs
@@ -70,7 +70,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn call_external_c_and_store_return<'a>(
         &mut self,
         link_name: Symbol,
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
         ptr: CodePtr,
         libffi_args: Vec<libffi::high::Arg<'a>>,
     ) -> InterpResult<'tcx, ()> {
@@ -205,7 +205,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn call_external_c_fct(
         &mut self,
         link_name: Symbol,
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
         args: &[OpTy<'tcx, Provenance>],
     ) -> InterpResult<'tcx, bool> {
         // Get the pointer to the function in the shared object file if it exists.
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 4ae607e98da..a25d377f3a7 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -57,7 +57,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         link_name: Symbol,
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
@@ -123,7 +123,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // Second: functions that return immediately.
         match this.emulate_foreign_item_inner(link_name, abi, args, dest)? {
             EmulateForeignItemResult::NeedsJumping => {
-                trace!("{:?}", this.dump_place(dest));
+                trace!("{:?}", this.dump_place(&dest.clone().into()));
                 this.go_to_block(ret);
             }
             EmulateForeignItemResult::AlreadyJumped => (),
@@ -149,7 +149,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         sym: DynSym,
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
@@ -401,7 +401,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         link_name: Symbol,
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, EmulateForeignItemResult> {
         let this = self.eval_context_mut();
 
@@ -1085,7 +1085,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
 
                 let (op, op_len) = this.operand_to_simd(op)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, op_len);
 
diff --git a/src/tools/miri/src/shims/intrinsics/atomic.rs b/src/tools/miri/src/shims/intrinsics/atomic.rs
index 4d7f6a6b4e0..865886a7fc1 100644
--- a/src/tools/miri/src/shims/intrinsics/atomic.rs
+++ b/src/tools/miri/src/shims/intrinsics/atomic.rs
@@ -18,7 +18,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         &mut self,
         intrinsic_name: &str,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
@@ -124,7 +124,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
     fn atomic_load(
         &mut self,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
         atomic: AtomicReadOrd,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
@@ -181,7 +181,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
     fn atomic_rmw_op(
         &mut self,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
         atomic_op: AtomicOp,
         atomic: AtomicRwOrd,
     ) -> InterpResult<'tcx> {
@@ -223,7 +223,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
     fn atomic_exchange(
         &mut self,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
         atomic: AtomicRwOrd,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
@@ -240,7 +240,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
     fn atomic_compare_exchange_impl(
         &mut self,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
         success: AtomicRwOrd,
         fail: AtomicReadOrd,
         can_fail_spuriously: bool,
@@ -269,7 +269,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
     fn atomic_compare_exchange(
         &mut self,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
         success: AtomicRwOrd,
         fail: AtomicReadOrd,
     ) -> InterpResult<'tcx> {
@@ -279,7 +279,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
     fn atomic_compare_exchange_weak(
         &mut self,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
         success: AtomicRwOrd,
         fail: AtomicReadOrd,
     ) -> InterpResult<'tcx> {
diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs
index b67d588dbc9..46f0c771cb5 100644
--- a/src/tools/miri/src/shims/intrinsics/mod.rs
+++ b/src/tools/miri/src/shims/intrinsics/mod.rs
@@ -23,7 +23,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         &mut self,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
         _unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
@@ -61,7 +61,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // The rest jumps to `ret` immediately.
         this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, dest)?;
 
-        trace!("{:?}", this.dump_place(dest));
+        trace!("{:?}", this.dump_place(&dest.clone().into()));
         this.go_to_block(ret);
         Ok(())
     }
@@ -72,7 +72,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         intrinsic_name: &str,
         generic_args: ty::GenericArgsRef<'tcx>,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs
index bb18fba5c98..ddddcdcebd2 100644
--- a/src/tools/miri/src/shims/intrinsics/simd.rs
+++ b/src/tools/miri/src/shims/intrinsics/simd.rs
@@ -21,7 +21,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         intrinsic_name: &str,
         generic_args: ty::GenericArgsRef<'tcx>,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         match intrinsic_name {
@@ -40,7 +40,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             => {
                 let [op] = check_arg_count(args)?;
                 let (op, op_len) = this.operand_to_simd(op)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, op_len);
 
@@ -167,7 +167,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [left, right] = check_arg_count(args)?;
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, left_len);
                 assert_eq!(dest_len, right_len);
@@ -255,7 +255,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let (a, a_len) = this.operand_to_simd(a)?;
                 let (b, b_len) = this.operand_to_simd(b)?;
                 let (c, c_len) = this.operand_to_simd(c)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, a_len);
                 assert_eq!(dest_len, b_len);
@@ -390,7 +390,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let (mask, mask_len) = this.operand_to_simd(mask)?;
                 let (yes, yes_len) = this.operand_to_simd(yes)?;
                 let (no, no_len) = this.operand_to_simd(no)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, mask_len);
                 assert_eq!(dest_len, yes_len);
@@ -411,7 +411,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [mask, yes, no] = check_arg_count(args)?;
                 let (yes, yes_len) = this.operand_to_simd(yes)?;
                 let (no, no_len) = this.operand_to_simd(no)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
                 let bitmask_len = dest_len.next_multiple_of(8);
 
                 // The mask must be an integer or an array.
@@ -487,7 +487,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "cast" | "as" | "cast_ptr" | "expose_addr" | "from_exposed_addr" => {
                 let [op] = check_arg_count(args)?;
                 let (op, op_len) = this.operand_to_simd(op)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, op_len);
 
@@ -545,7 +545,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [left, right] = check_arg_count(args)?;
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 let index = generic_args[2]
                     .expect_const()
@@ -582,7 +582,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [left, right, index] = check_arg_count(args)?;
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 // `index` is an array, not a SIMD type
                 let ty::Array(_, index_len) = index.layout.ty.kind() else {
@@ -623,7 +623,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let (passthru, passthru_len) = this.operand_to_simd(passthru)?;
                 let (ptrs, ptrs_len) = this.operand_to_simd(ptrs)?;
                 let (mask, mask_len) = this.operand_to_simd(mask)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, passthru_len);
                 assert_eq!(dest_len, ptrs_len);
@@ -669,7 +669,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let (mask, mask_len) = this.operand_to_simd(mask)?;
                 let ptr = this.read_pointer(ptr)?;
                 let (default, default_len) = this.operand_to_simd(default)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, mask_len);
                 assert_eq!(dest_len, default_len);
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index 65b5838cd14..34b6481dd38 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -28,7 +28,7 @@ pub struct CatchUnwindData<'tcx> {
     /// The `data` argument for that callback.
     data: Scalar<Provenance>,
     /// The return place from the original call to `try`.
-    dest: PlaceTy<'tcx, Provenance>,
+    dest: MPlaceTy<'tcx, Provenance>,
     /// The return block from the original call to `try`.
     ret: mir::BasicBlock,
 }
@@ -72,7 +72,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn handle_catch_unwind(
         &mut self,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
         ret: mir::BasicBlock,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index b5cd18396a2..4ceda809350 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -44,7 +44,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         link_name: Symbol,
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, EmulateForeignItemResult> {
         let this = self.eval_context_mut();
 
diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
index 64094ac307d..6814e0d4283 100644
--- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
@@ -17,7 +17,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         link_name: Symbol,
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, EmulateForeignItemResult> {
         let this = self.eval_context_mut();
         match link_name.as_str() {
diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
index b9215129674..d13ada0f4cf 100644
--- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
@@ -24,7 +24,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         link_name: Symbol,
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, EmulateForeignItemResult> {
         let this = self.eval_context_mut();
 
@@ -228,7 +228,7 @@ fn getrandom<'tcx>(
     ptr: &OpTy<'tcx, Provenance>,
     len: &OpTy<'tcx, Provenance>,
     flags: &OpTy<'tcx, Provenance>,
-    dest: &PlaceTy<'tcx, Provenance>,
+    dest: &MPlaceTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx> {
     let ptr = this.read_pointer(ptr)?;
     let len = this.read_target_usize(len)?;
diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs
index 66105391c47..ed27066aa6a 100644
--- a/src/tools/miri/src/shims/unix/linux/sync.rs
+++ b/src/tools/miri/src/shims/unix/linux/sync.rs
@@ -8,7 +8,7 @@ use crate::*;
 pub fn futex<'tcx>(
     this: &mut MiriInterpCx<'_, 'tcx>,
     args: &[OpTy<'tcx, Provenance>],
-    dest: &PlaceTy<'tcx, Provenance>,
+    dest: &MPlaceTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx> {
     // The amount of arguments used depends on the type of futex operation.
     // The full futex syscall takes six arguments (excluding the syscall
@@ -179,7 +179,7 @@ pub fn futex<'tcx>(
                     struct Callback<'tcx> {
                         thread: ThreadId,
                         addr_usize: u64,
-                        dest: PlaceTy<'tcx, Provenance>,
+                        dest: MPlaceTy<'tcx, Provenance>,
                     }
 
                     impl<'tcx> VisitProvenance for Callback<'tcx> {
diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
index ecc07e28a29..3af01eb44d8 100644
--- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
@@ -17,7 +17,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         link_name: Symbol,
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, EmulateForeignItemResult> {
         let this = self.eval_context_mut();
 
diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs
index 054e9719b34..dd301f9ee6d 100644
--- a/src/tools/miri/src/shims/unix/sync.rs
+++ b/src/tools/miri/src/shims/unix/sync.rs
@@ -843,7 +843,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         cond_op: &OpTy<'tcx, Provenance>,
         mutex_op: &OpTy<'tcx, Provenance>,
         abstime_op: &OpTy<'tcx, Provenance>,
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
@@ -883,7 +883,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             active_thread: ThreadId,
             mutex_id: MutexId,
             id: CondvarId,
-            dest: PlaceTy<'tcx, Provenance>,
+            dest: MPlaceTy<'tcx, Provenance>,
         }
 
         impl<'tcx> VisitProvenance for Callback<'tcx> {
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index 734737a86dd..9e0baf86cbc 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -27,7 +27,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         link_name: Symbol,
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, EmulateForeignItemResult> {
         let this = self.eval_context_mut();
 
@@ -366,6 +366,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
                 this.WakeByAddressSingle(ptr_op)?;
             }
+            "WakeByAddressAll" => {
+                let [ptr_op] =
+                    this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+
+                this.WakeByAddressAll(ptr_op)?;
+            }
 
             // Dynamic symbol loading
             "GetProcAddress" => {
diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs
index 2b9801fea68..c0a79e959a6 100644
--- a/src/tools/miri/src/shims/windows/sync.rs
+++ b/src/tools/miri/src/shims/windows/sync.rs
@@ -201,7 +201,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // When we are woken up, set the `pending` flag accordingly.
                 struct Callback<'tcx> {
                     init_once_id: InitOnceId,
-                    pending_place: PlaceTy<'tcx, Provenance>,
+                    pending_place: MPlaceTy<'tcx, Provenance>,
                 }
 
                 impl<'tcx> VisitProvenance for Callback<'tcx> {
@@ -290,7 +290,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         compare_op: &OpTy<'tcx, Provenance>,
         size_op: &OpTy<'tcx, Provenance>,
         timeout_op: &OpTy<'tcx, Provenance>,
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
@@ -334,7 +334,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 struct Callback<'tcx> {
                     thread: ThreadId,
                     addr: u64,
-                    dest: PlaceTy<'tcx, Provenance>,
+                    dest: MPlaceTy<'tcx, Provenance>,
                 }
 
                 impl<'tcx> VisitProvenance for Callback<'tcx> {
@@ -384,6 +384,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         Ok(())
     }
+    fn WakeByAddressAll(&mut self, ptr_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+
+        let ptr = this.read_pointer(ptr_op)?;
+
+        // See the Linux futex implementation for why this fence exists.
+        this.atomic_fence(AtomicFenceOrd::SeqCst)?;
+
+        while let Some(thread) = this.futex_wake(ptr.addr().bytes(), u32::MAX) {
+            this.unblock_thread(thread);
+            this.unregister_timeout_callback_if_exists(thread);
+        }
+
+        Ok(())
+    }
 
     fn SleepConditionVariableSRW(
         &mut self,
@@ -391,7 +406,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         lock_op: &OpTy<'tcx, Provenance>,
         timeout_op: &OpTy<'tcx, Provenance>,
         flags_op: &OpTy<'tcx, Provenance>,
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
@@ -438,7 +453,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 condvar_id: CondvarId,
                 lock_id: RwLockId,
                 mode: RwLockMode,
-                dest: PlaceTy<'tcx, Provenance>,
+                dest: MPlaceTy<'tcx, Provenance>,
             }
 
             impl<'tcx> VisitProvenance for Callback<'tcx> {
diff --git a/src/tools/miri/src/shims/x86/aesni.rs b/src/tools/miri/src/shims/x86/aesni.rs
index fb0b7015127..6c090d877ea 100644
--- a/src/tools/miri/src/shims/x86/aesni.rs
+++ b/src/tools/miri/src/shims/x86/aesni.rs
@@ -15,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         link_name: Symbol,
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, EmulateForeignItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "aes")?;
@@ -138,7 +138,7 @@ fn aes_round<'tcx>(
     this: &mut crate::MiriInterpCx<'_, 'tcx>,
     state: &OpTy<'tcx, Provenance>,
     key: &OpTy<'tcx, Provenance>,
-    dest: &PlaceTy<'tcx, Provenance>,
+    dest: &MPlaceTy<'tcx, Provenance>,
     f: impl Fn(u128, u128) -> u128,
 ) -> InterpResult<'tcx, ()> {
     assert_eq!(dest.layout.size, state.layout.size);
diff --git a/src/tools/miri/src/shims/x86/avx.rs b/src/tools/miri/src/shims/x86/avx.rs
index 65de1607595..23c78647b9c 100644
--- a/src/tools/miri/src/shims/x86/avx.rs
+++ b/src/tools/miri/src/shims/x86/avx.rs
@@ -21,7 +21,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         link_name: Symbol,
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, EmulateForeignItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "avx")?;
@@ -164,7 +164,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (data, data_len) = this.operand_to_simd(data)?;
                 let (control, control_len) = this.operand_to_simd(control)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, data_len);
                 assert_eq!(dest_len, control_len);
@@ -199,7 +199,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (data, data_len) = this.operand_to_simd(data)?;
                 let (control, control_len) = this.operand_to_simd(control)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, data_len);
                 assert_eq!(dest_len, control_len);
@@ -354,10 +354,10 @@ fn mask_load<'tcx>(
     this: &mut crate::MiriInterpCx<'_, 'tcx>,
     ptr: &OpTy<'tcx, Provenance>,
     mask: &OpTy<'tcx, Provenance>,
-    dest: &PlaceTy<'tcx, Provenance>,
+    dest: &MPlaceTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, ()> {
     let (mask, mask_len) = this.operand_to_simd(mask)?;
-    let (dest, dest_len) = this.place_to_simd(dest)?;
+    let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
     assert_eq!(dest_len, mask_len);
 
diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs
index 9cfee20014f..7cd397625dc 100644
--- a/src/tools/miri/src/shims/x86/mod.rs
+++ b/src/tools/miri/src/shims/x86/mod.rs
@@ -29,7 +29,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         link_name: Symbol,
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, EmulateForeignItemResult> {
         let this = self.eval_context_mut();
         // Prefix should have already been checked.
@@ -286,11 +286,11 @@ fn bin_op_simd_float_first<'tcx, F: rustc_apfloat::Float>(
     which: FloatBinOp,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
-    dest: &PlaceTy<'tcx, Provenance>,
+    dest: &MPlaceTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, ()> {
     let (left, left_len) = this.operand_to_simd(left)?;
     let (right, right_len) = this.operand_to_simd(right)?;
-    let (dest, dest_len) = this.place_to_simd(dest)?;
+    let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
     assert_eq!(dest_len, left_len);
     assert_eq!(dest_len, right_len);
@@ -317,11 +317,11 @@ fn bin_op_simd_float_all<'tcx, F: rustc_apfloat::Float>(
     which: FloatBinOp,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
-    dest: &PlaceTy<'tcx, Provenance>,
+    dest: &MPlaceTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, ()> {
     let (left, left_len) = this.operand_to_simd(left)?;
     let (right, right_len) = this.operand_to_simd(right)?;
-    let (dest, dest_len) = this.place_to_simd(dest)?;
+    let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
     assert_eq!(dest_len, left_len);
     assert_eq!(dest_len, right_len);
@@ -414,10 +414,10 @@ fn unary_op_ss<'tcx>(
     this: &mut crate::MiriInterpCx<'_, 'tcx>,
     which: FloatUnaryOp,
     op: &OpTy<'tcx, Provenance>,
-    dest: &PlaceTy<'tcx, Provenance>,
+    dest: &MPlaceTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, ()> {
     let (op, op_len) = this.operand_to_simd(op)?;
-    let (dest, dest_len) = this.place_to_simd(dest)?;
+    let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
     assert_eq!(dest_len, op_len);
 
@@ -437,10 +437,10 @@ fn unary_op_ps<'tcx>(
     this: &mut crate::MiriInterpCx<'_, 'tcx>,
     which: FloatUnaryOp,
     op: &OpTy<'tcx, Provenance>,
-    dest: &PlaceTy<'tcx, Provenance>,
+    dest: &MPlaceTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, ()> {
     let (op, op_len) = this.operand_to_simd(op)?;
-    let (dest, dest_len) = this.place_to_simd(dest)?;
+    let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
     assert_eq!(dest_len, op_len);
 
@@ -462,11 +462,11 @@ fn round_first<'tcx, F: rustc_apfloat::Float>(
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
     rounding: &OpTy<'tcx, Provenance>,
-    dest: &PlaceTy<'tcx, Provenance>,
+    dest: &MPlaceTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, ()> {
     let (left, left_len) = this.operand_to_simd(left)?;
     let (right, right_len) = this.operand_to_simd(right)?;
-    let (dest, dest_len) = this.place_to_simd(dest)?;
+    let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
     assert_eq!(dest_len, left_len);
     assert_eq!(dest_len, right_len);
@@ -492,10 +492,10 @@ fn round_all<'tcx, F: rustc_apfloat::Float>(
     this: &mut crate::MiriInterpCx<'_, 'tcx>,
     op: &OpTy<'tcx, Provenance>,
     rounding: &OpTy<'tcx, Provenance>,
-    dest: &PlaceTy<'tcx, Provenance>,
+    dest: &MPlaceTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, ()> {
     let (op, op_len) = this.operand_to_simd(op)?;
-    let (dest, dest_len) = this.place_to_simd(dest)?;
+    let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
     assert_eq!(dest_len, op_len);
 
@@ -544,10 +544,10 @@ fn convert_float_to_int<'tcx>(
     this: &mut crate::MiriInterpCx<'_, 'tcx>,
     op: &OpTy<'tcx, Provenance>,
     rnd: rustc_apfloat::Round,
-    dest: &PlaceTy<'tcx, Provenance>,
+    dest: &MPlaceTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, ()> {
     let (op, op_len) = this.operand_to_simd(op)?;
-    let (dest, dest_len) = this.place_to_simd(dest)?;
+    let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
     // Output must be *signed* integers.
     assert!(matches!(dest.layout.field(this, 0).ty.kind(), ty::Int(_)));
@@ -587,7 +587,7 @@ fn split_simd_to_128bit_chunks<'tcx>(
     this: &mut crate::MiriInterpCx<'_, 'tcx>,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
-    dest: &PlaceTy<'tcx, Provenance>,
+    dest: &MPlaceTy<'tcx, Provenance>,
 ) -> InterpResult<
     'tcx,
     (u64, u64, MPlaceTy<'tcx, Provenance>, MPlaceTy<'tcx, Provenance>, MPlaceTy<'tcx, Provenance>),
@@ -597,7 +597,7 @@ fn split_simd_to_128bit_chunks<'tcx>(
 
     let (left, left_len) = this.operand_to_simd(left)?;
     let (right, right_len) = this.operand_to_simd(right)?;
-    let (dest, dest_len) = this.place_to_simd(dest)?;
+    let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
     assert_eq!(dest_len, left_len);
     assert_eq!(dest_len, right_len);
@@ -636,7 +636,7 @@ fn horizontal_bin_op<'tcx>(
     saturating: bool,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
-    dest: &PlaceTy<'tcx, Provenance>,
+    dest: &MPlaceTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, ()> {
     let (num_chunks, items_per_chunk, left, right, dest) =
         split_simd_to_128bit_chunks(this, left, right, dest)?;
@@ -684,7 +684,7 @@ fn conditional_dot_product<'tcx>(
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
     imm: &OpTy<'tcx, Provenance>,
-    dest: &PlaceTy<'tcx, Provenance>,
+    dest: &MPlaceTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, ()> {
     let (num_chunks, items_per_chunk, left, right, dest) =
         split_simd_to_128bit_chunks(this, left, right, dest)?;
diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs
index da0db92738f..b8c0dfb1c7f 100644
--- a/src/tools/miri/src/shims/x86/sse.rs
+++ b/src/tools/miri/src/shims/x86/sse.rs
@@ -19,7 +19,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         link_name: Symbol,
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, EmulateForeignItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "sse")?;
@@ -198,7 +198,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
 
                 let (left, left_len) = this.operand_to_simd(left)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, left_len);
 
diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs
index b34b93e3739..18ff5d809e3 100644
--- a/src/tools/miri/src/shims/x86/sse2.rs
+++ b/src/tools/miri/src/shims/x86/sse2.rs
@@ -17,7 +17,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         link_name: Symbol,
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, EmulateForeignItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "sse2")?;
@@ -46,7 +46,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(left_len, right_len);
                 assert_eq!(dest_len.checked_mul(2).unwrap(), left_len);
@@ -85,7 +85,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 // left and right are u8x16, dest is u64x2
                 assert_eq!(left_len, right_len);
@@ -122,7 +122,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, left_len);
                 assert_eq!(dest_len, right_len);
@@ -172,7 +172,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, left_len);
                 assert_eq!(dest_len, right_len);
@@ -223,7 +223,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, left_len);
                 assert_eq!(dest_len, right_len);
@@ -306,7 +306,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 // left and right are i16x8, dest is i8x16
                 assert_eq!(left_len, 8);
@@ -337,7 +337,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 // left and right are i16x8, dest is u8x16
                 assert_eq!(left_len, 8);
@@ -367,7 +367,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 // left and right are i32x4, dest is i16x8
                 assert_eq!(left_len, 4);
@@ -430,7 +430,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
                 let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
 
                 let (op, op_len) = this.operand_to_simd(op)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, op_len);
 
@@ -449,7 +449,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
                 let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
 
                 let (op, op_len) = this.operand_to_simd(op)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, op_len);
 
@@ -563,7 +563,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, _) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, left_len);
 
diff --git a/src/tools/miri/src/shims/x86/sse3.rs b/src/tools/miri/src/shims/x86/sse3.rs
index 99a7a4f2f88..5ac30dca79a 100644
--- a/src/tools/miri/src/shims/x86/sse3.rs
+++ b/src/tools/miri/src/shims/x86/sse3.rs
@@ -15,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         link_name: Symbol,
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, EmulateForeignItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "sse3")?;
diff --git a/src/tools/miri/src/shims/x86/sse41.rs b/src/tools/miri/src/shims/x86/sse41.rs
index 32b1fe43c58..16a82eed99b 100644
--- a/src/tools/miri/src/shims/x86/sse41.rs
+++ b/src/tools/miri/src/shims/x86/sse41.rs
@@ -14,7 +14,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         link_name: Symbol,
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, EmulateForeignItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "sse4.1")?;
@@ -34,7 +34,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, left_len);
                 assert_eq!(dest_len, right_len);
@@ -70,7 +70,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(left_len, right_len);
                 assert_eq!(dest_len, left_len.checked_mul(2).unwrap());
@@ -142,7 +142,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
                 let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
 
                 let (op, op_len) = this.operand_to_simd(op)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 // Find minimum
                 let mut min_value = u16::MAX;
@@ -178,7 +178,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(left_len, right_len);
                 assert_eq!(left_len, dest_len.checked_mul(2).unwrap());
diff --git a/src/tools/miri/src/shims/x86/ssse3.rs b/src/tools/miri/src/shims/x86/ssse3.rs
index 724150fd2fe..dd5d064b20f 100644
--- a/src/tools/miri/src/shims/x86/ssse3.rs
+++ b/src/tools/miri/src/shims/x86/ssse3.rs
@@ -15,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
         link_name: Symbol,
         abi: Abi,
         args: &[OpTy<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
+        dest: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, EmulateForeignItemResult> {
         let this = self.eval_context_mut();
         this.expect_target_feature_for_intrinsic(link_name, "ssse3")?;
@@ -29,7 +29,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
                 let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
 
                 let (op, op_len) = this.operand_to_simd(op)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(op_len, dest_len);
 
@@ -52,7 +52,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, left_len);
                 assert_eq!(dest_len, right_len);
@@ -102,7 +102,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(left_len, right_len);
                 assert_eq!(dest_len.checked_mul(2).unwrap(), left_len);
@@ -138,7 +138,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, left_len);
                 assert_eq!(dest_len, right_len);
@@ -172,7 +172,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 
                 let (left, left_len) = this.operand_to_simd(left)?;
                 let (right, right_len) = this.operand_to_simd(right)?;
-                let (dest, dest_len) = this.place_to_simd(dest)?;
+                let (dest, dest_len) = this.mplace_to_simd(dest)?;
 
                 assert_eq!(dest_len, left_len);
                 assert_eq!(dest_len, right_len);
diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs
index 9f467724565..db0768848fd 100644
--- a/src/tools/miri/tests/compiletest.rs
+++ b/src/tools/miri/tests/compiletest.rs
@@ -81,8 +81,10 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) ->
 
     // Add a test env var to do environment communication tests.
     program.envs.push(("MIRI_ENV_VAR_TEST".into(), Some("0".into())));
+
     // Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
-    program.envs.push(("MIRI_TEMP".into(), Some(env::temp_dir().into())));
+    let miri_temp = env::var_os("MIRI_TEMP").unwrap_or_else(|| env::temp_dir().into());
+    program.envs.push(("MIRI_TEMP".into(), Some(miri_temp)));
 
     let mut config = Config {
         target: Some(target.to_owned()),
diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs
index 6ba39c1f563..304a178dc34 100644
--- a/src/tools/miri/tests/pass/shims/fs.rs
+++ b/src/tools/miri/tests/pass/shims/fs.rs
@@ -1,6 +1,10 @@
 //@ignore-target-windows: File handling is not implemented yet
 //@compile-flags: -Zmiri-disable-isolation
 
+// If this test is failing for you locally, you can try
+// 1. Deleting the files `/tmp/miri_*`
+// 2. Setting `MIRI_TEMP` or `TMPDIR` to a different directory, without the `miri_*` files
+
 #![feature(io_error_more)]
 #![feature(io_error_uncategorized)]
 
diff --git a/src/tools/opt-dist/src/utils/artifact_size.rs b/src/tools/opt-dist/src/utils/artifact_size.rs
index eb1f6bcf21d..b6c453fb40b 100644
--- a/src/tools/opt-dist/src/utils/artifact_size.rs
+++ b/src/tools/opt-dist/src/utils/artifact_size.rs
@@ -16,7 +16,7 @@ pub fn print_binary_sizes(env: &Environment) -> anyhow::Result<()> {
     let root = env.build_artifacts().join("stage2");
 
     let mut files = get_files_from_dir(&root.join("bin"), None)?;
-    files.extend(get_files_from_dir(&root.join("lib"), Some(".so"))?);
+    files.extend(get_files_from_dir(&root.join("lib"), None)?);
     files.sort_unstable();
 
     let items: Vec<_> = files
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
index be1c8d9094b..a1be6018083 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
@@ -1,5 +1,6 @@
 //! Compute the binary representation of a type
 
+use std::borrow::Cow;
 use std::fmt;
 
 use base_db::salsa::Cycle;
@@ -114,8 +115,8 @@ struct LayoutCx<'a> {
 impl<'a> LayoutCalculator for LayoutCx<'a> {
     type TargetDataLayoutRef = &'a TargetDataLayout;
 
-    fn delayed_bug(&self, txt: String) {
-        never!("{}", txt);
+    fn delayed_bug(&self, txt: impl Into<Cow<'static, str>>) {
+        never!("{}", txt.into());
     }
 
     fn current_data_layout(&self) -> &'a TargetDataLayout {
diff --git a/src/tools/rustfmt/src/comment.rs b/src/tools/rustfmt/src/comment.rs
index f7cd7cefb3d..7d1b0384431 100644
--- a/src/tools/rustfmt/src/comment.rs
+++ b/src/tools/rustfmt/src/comment.rs
@@ -1721,10 +1721,10 @@ pub(crate) fn recover_comment_removed(
         // We missed some comments. Warn and keep the original text.
         if context.config.error_on_unformatted() {
             context.report.append(
-                context.parse_sess.span_to_filename(span),
+                context.psess.span_to_filename(span),
                 vec![FormattingError::from_span(
                     span,
-                    context.parse_sess,
+                    context.psess,
                     ErrorKind::LostComment,
                 )],
             );
diff --git a/src/tools/rustfmt/src/formatting.rs b/src/tools/rustfmt/src/formatting.rs
index 1c64921b1a6..3bcb4d15184 100644
--- a/src/tools/rustfmt/src/formatting.rs
+++ b/src/tools/rustfmt/src/formatting.rs
@@ -79,7 +79,7 @@ fn should_skip_module<T: FormatHandler>(
     // FIXME(calebcartwright) - we need to determine how we'll handle the
     // `format_generated_files` option with stdin based input.
     if !input_is_stdin && !config.format_generated_files() {
-        let source_file = context.parse_session.span_to_file_contents(module.span);
+        let source_file = context.psess.span_to_file_contents(module.span);
         let src = source_file.src.as_ref().expect("SourceFile without src");
 
         if is_generated_file(src) {
@@ -109,8 +109,8 @@ fn format_project<T: FormatHandler>(
     let main_file = input.file_name();
     let input_is_stdin = main_file == FileName::Stdin;
 
-    let parse_session = ParseSess::new(config)?;
-    if config.skip_children() && parse_session.ignore_file(&main_file) {
+    let psess = ParseSess::new(config)?;
+    if config.skip_children() && psess.ignore_file(&main_file) {
         return Ok(FormatReport::new());
     }
 
@@ -118,7 +118,7 @@ fn format_project<T: FormatHandler>(
     let mut report = FormatReport::new();
     let directory_ownership = input.to_directory_ownership();
 
-    let krate = match Parser::parse_crate(input, &parse_session) {
+    let krate = match Parser::parse_crate(input, &psess) {
         Ok(krate) => krate,
         // Surface parse error via Session (errors are merged there from report)
         Err(e) => {
@@ -131,9 +131,9 @@ fn format_project<T: FormatHandler>(
         }
     };
 
-    let mut context = FormatContext::new(&krate, report, parse_session, config, handler);
+    let mut context = FormatContext::new(&krate, report, psess, config, handler);
     let files = modules::ModResolver::new(
-        &context.parse_session,
+        &context.psess,
         directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaBlock),
         !input_is_stdin && !config.skip_children(),
     )
@@ -148,16 +148,11 @@ fn format_project<T: FormatHandler>(
     timer = timer.done_parsing();
 
     // Suppress error output if we have to do any further parsing.
-    context.parse_session.set_silent_emitter();
+    context.psess.set_silent_emitter();
 
     for (path, module) in files {
         if input_is_stdin && contains_skip(module.attrs()) {
-            return echo_back_stdin(
-                context
-                    .parse_session
-                    .snippet_provider(module.span)
-                    .entire_snippet(),
-            );
+            return echo_back_stdin(context.psess.snippet_provider(module.span).entire_snippet());
         }
         should_emit_verbose(input_is_stdin, config, || println!("Formatting {}", path));
         context.format_file(path, &module, is_macro_def)?;
@@ -179,7 +174,7 @@ fn format_project<T: FormatHandler>(
 struct FormatContext<'a, T: FormatHandler> {
     krate: &'a ast::Crate,
     report: FormatReport,
-    parse_session: ParseSess,
+    psess: ParseSess,
     config: &'a Config,
     handler: &'a mut T,
 }
@@ -188,21 +183,21 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
     fn new(
         krate: &'a ast::Crate,
         report: FormatReport,
-        parse_session: ParseSess,
+        psess: ParseSess,
         config: &'a Config,
         handler: &'a mut T,
     ) -> Self {
         FormatContext {
             krate,
             report,
-            parse_session,
+            psess,
             config,
             handler,
         }
     }
 
     fn ignore_file(&self, path: &FileName) -> bool {
-        self.parse_session.ignore_file(path)
+        self.psess.ignore_file(path)
     }
 
     // Formats a single file/module.
@@ -212,9 +207,9 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
         module: &Module<'_>,
         is_macro_def: bool,
     ) -> Result<(), ErrorKind> {
-        let snippet_provider = self.parse_session.snippet_provider(module.span);
-        let mut visitor = FmtVisitor::from_parse_sess(
-            &self.parse_session,
+        let snippet_provider = self.psess.snippet_provider(module.span);
+        let mut visitor = FmtVisitor::from_psess(
+            &self.psess,
             self.config,
             &snippet_provider,
             self.report.clone(),
@@ -257,7 +252,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
             .add_non_formatted_ranges(visitor.skipped_range.borrow().clone());
 
         self.handler.handle_formatted_file(
-            &self.parse_session,
+            &self.psess,
             path,
             visitor.buffer.to_owned(),
             &mut self.report,
@@ -269,7 +264,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
 trait FormatHandler {
     fn handle_formatted_file(
         &mut self,
-        parse_session: &ParseSess,
+        psess: &ParseSess,
         path: FileName,
         result: String,
         report: &mut FormatReport,
@@ -280,14 +275,14 @@ impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> {
     // Called for each formatted file.
     fn handle_formatted_file(
         &mut self,
-        parse_session: &ParseSess,
+        psess: &ParseSess,
         path: FileName,
         result: String,
         report: &mut FormatReport,
     ) -> Result<(), ErrorKind> {
         if let Some(ref mut out) = self.out {
             match source_file::write_file(
-                Some(parse_session),
+                Some(psess),
                 &path,
                 &result,
                 out,
@@ -318,17 +313,13 @@ pub(crate) struct FormattingError {
 }
 
 impl FormattingError {
-    pub(crate) fn from_span(
-        span: Span,
-        parse_sess: &ParseSess,
-        kind: ErrorKind,
-    ) -> FormattingError {
+    pub(crate) fn from_span(span: Span, psess: &ParseSess, kind: ErrorKind) -> FormattingError {
         FormattingError {
-            line: parse_sess.line_of_byte_pos(span.lo()),
+            line: psess.line_of_byte_pos(span.lo()),
             is_comment: kind.is_comment(),
             kind,
             is_string: false,
-            line_buffer: parse_sess.span_to_first_line_string(span),
+            line_buffer: psess.span_to_first_line_string(span),
         }
     }
 
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index b4c58d2fefb..8d77d2b3254 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -136,8 +136,8 @@ fn return_macro_parse_failure_fallback(
     }
 
     context.skipped_range.borrow_mut().push((
-        context.parse_sess.line_of_byte_pos(span.lo()),
-        context.parse_sess.line_of_byte_pos(span.hi()),
+        context.psess.line_of_byte_pos(span.lo()),
+        context.psess.line_of_byte_pos(span.hi()),
     ));
 
     // Return the snippet unmodified if the macro is not block-like
diff --git a/src/tools/rustfmt/src/missed_spans.rs b/src/tools/rustfmt/src/missed_spans.rs
index 28edcb784b4..b1a7769c21b 100644
--- a/src/tools/rustfmt/src/missed_spans.rs
+++ b/src/tools/rustfmt/src/missed_spans.rs
@@ -91,7 +91,7 @@ impl<'a> FmtVisitor<'a> {
         assert!(
             start < end,
             "Request to format inverted span: {}",
-            self.parse_sess.span_to_debug_info(mk_sp(start, end)),
+            self.psess.span_to_debug_info(mk_sp(start, end)),
         );
 
         self.last_pos = end;
@@ -166,8 +166,8 @@ impl<'a> FmtVisitor<'a> {
         // Trim whitespace from the right hand side of each line.
         // Annoyingly, the library functions for splitting by lines etc. are not
         // quite right, so we must do it ourselves.
-        let line = self.parse_sess.line_of_byte_pos(span.lo());
-        let file_name = &self.parse_sess.span_to_filename(span);
+        let line = self.psess.line_of_byte_pos(span.lo());
+        let file_name = &self.psess.span_to_filename(span);
         let mut status = SnippetStatus::new(line);
 
         let snippet = &*transform_missing_snippet(self.config, old_snippet);
diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs
index af9a154a6ae..0590f28ee05 100644
--- a/src/tools/rustfmt/src/modules.rs
+++ b/src/tools/rustfmt/src/modules.rs
@@ -57,8 +57,8 @@ impl<'a> Module<'a> {
 }
 
 /// Maps each module to the corresponding file.
-pub(crate) struct ModResolver<'ast, 'sess> {
-    parse_sess: &'sess ParseSess,
+pub(crate) struct ModResolver<'ast, 'psess> {
+    psess: &'psess ParseSess,
     directory: Directory,
     file_map: FileModMap<'ast>,
     recursive: bool,
@@ -99,10 +99,10 @@ enum SubModKind<'a, 'ast> {
     Internal(&'a ast::Item),
 }
 
-impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
+impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
     /// Creates a new `ModResolver`.
     pub(crate) fn new(
-        parse_sess: &'sess ParseSess,
+        psess: &'psess ParseSess,
         directory_ownership: DirectoryOwnership,
         recursive: bool,
     ) -> Self {
@@ -112,7 +112,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                 ownership: directory_ownership,
             },
             file_map: BTreeMap::new(),
-            parse_sess,
+            psess,
             recursive,
         }
     }
@@ -122,7 +122,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
         mut self,
         krate: &'ast ast::Crate,
     ) -> Result<FileModMap<'ast>, ModuleResolutionError> {
-        let root_filename = self.parse_sess.span_to_filename(krate.spans.inner_span);
+        let root_filename = self.psess.span_to_filename(krate.spans.inner_span);
         self.directory.path = match root_filename {
             FileName::Real(ref p) => p.parent().unwrap_or(Path::new("")).to_path_buf(),
             _ => PathBuf::new(),
@@ -133,7 +133,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
             self.visit_mod_from_ast(&krate.items)?;
         }
 
-        let snippet_provider = self.parse_sess.snippet_provider(krate.spans.inner_span);
+        let snippet_provider = self.psess.snippet_provider(krate.spans.inner_span);
 
         self.file_map.insert(
             root_filename,
@@ -149,7 +149,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
 
     /// Visit `cfg_if` macro and look for module declarations.
     fn visit_cfg_if(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), ModuleResolutionError> {
-        let mut visitor = visitor::CfgIfVisitor::new(self.parse_sess);
+        let mut visitor = visitor::CfgIfVisitor::new(self.psess);
         visitor.visit_item(&item);
         for module_item in visitor.mods() {
             if let ast::ItemKind::Mod(_, ref sub_mod_kind) = module_item.item.kind {
@@ -338,10 +338,10 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
             DirectoryOwnership::UnownedViaBlock => None,
         };
         if let Some(path) = Parser::submod_path_from_attr(attrs, &self.directory.path) {
-            if self.parse_sess.is_file_parsed(&path) {
+            if self.psess.is_file_parsed(&path) {
                 return Ok(None);
             }
-            return match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.span) {
+            return match Parser::parse_file_as_module(self.psess, &path, sub_mod.span) {
                 Ok((ref attrs, _, _)) if contains_skip(attrs) => Ok(None),
                 Ok((attrs, items, span)) => Ok(Some(SubModKind::External(
                     path,
@@ -368,7 +368,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
         let mut mods_outside_ast = self.find_mods_outside_of_ast(attrs, sub_mod);
 
         match self
-            .parse_sess
+            .psess
             .default_submod_path(mod_name, relative, &self.directory.path)
         {
             Ok(ModulePathSuccess {
@@ -380,7 +380,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                 let should_insert = !mods_outside_ast
                     .iter()
                     .any(|(outside_path, _, _)| outside_path == &file_path);
-                if self.parse_sess.is_file_parsed(&file_path) {
+                if self.psess.is_file_parsed(&file_path) {
                     if outside_mods_empty {
                         return Ok(None);
                     } else {
@@ -390,7 +390,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                         return Ok(Some(SubModKind::MultiExternal(mods_outside_ast)));
                     }
                 }
-                match Parser::parse_file_as_module(self.parse_sess, &file_path, sub_mod.span) {
+                match Parser::parse_file_as_module(self.psess, &file_path, sub_mod.span) {
                     Ok((ref attrs, _, _)) if contains_skip(attrs) => Ok(None),
                     Ok((attrs, items, span)) if outside_mods_empty => {
                         Ok(Some(SubModKind::External(
@@ -517,7 +517,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
             if !actual_path.exists() {
                 continue;
             }
-            if self.parse_sess.is_file_parsed(&actual_path) {
+            if self.psess.is_file_parsed(&actual_path) {
                 // If the specified file is already parsed, then we just use that.
                 result.push((
                     actual_path,
@@ -527,7 +527,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                 continue;
             }
             let (attrs, items, span) =
-                match Parser::parse_file_as_module(self.parse_sess, &actual_path, sub_mod.span) {
+                match Parser::parse_file_as_module(self.psess, &actual_path, sub_mod.span) {
                     Ok((ref attrs, _, _)) if contains_skip(attrs) => continue,
                     Ok(m) => m,
                     Err(..) => continue,
diff --git a/src/tools/rustfmt/src/modules/visitor.rs b/src/tools/rustfmt/src/modules/visitor.rs
index 48431693332..3e05b6d0c5d 100644
--- a/src/tools/rustfmt/src/modules/visitor.rs
+++ b/src/tools/rustfmt/src/modules/visitor.rs
@@ -12,15 +12,15 @@ pub(crate) struct ModItem {
 
 /// Traverse `cfg_if!` macro and fetch modules.
 pub(crate) struct CfgIfVisitor<'a> {
-    parse_sess: &'a ParseSess,
+    psess: &'a ParseSess,
     mods: Vec<ModItem>,
 }
 
 impl<'a> CfgIfVisitor<'a> {
-    pub(crate) fn new(parse_sess: &'a ParseSess) -> CfgIfVisitor<'a> {
+    pub(crate) fn new(psess: &'a ParseSess) -> CfgIfVisitor<'a> {
         CfgIfVisitor {
             mods: vec![],
-            parse_sess,
+            psess,
         }
     }
 
@@ -62,7 +62,7 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> {
             }
         };
 
-        let items = parse_cfg_if(self.parse_sess, mac)?;
+        let items = parse_cfg_if(self.psess, mac)?;
         self.mods
             .append(&mut items.into_iter().map(|item| ModItem { item }).collect());
 
diff --git a/src/tools/rustfmt/src/parse/macros/asm.rs b/src/tools/rustfmt/src/parse/macros/asm.rs
index 01edfab3654..6373d0251f8 100644
--- a/src/tools/rustfmt/src/parse/macros/asm.rs
+++ b/src/tools/rustfmt/src/parse/macros/asm.rs
@@ -7,5 +7,5 @@ use crate::rewrite::RewriteContext;
 pub(crate) fn parse_asm(context: &RewriteContext<'_>, mac: &ast::MacCall) -> Option<AsmArgs> {
     let ts = mac.args.tokens.clone();
     let mut parser = super::build_parser(context, ts);
-    parse_asm_args(&mut parser, context.parse_sess.inner(), mac.span(), false).ok()
+    parse_asm_args(&mut parser, mac.span(), false).ok()
 }
diff --git a/src/tools/rustfmt/src/parse/macros/cfg_if.rs b/src/tools/rustfmt/src/parse/macros/cfg_if.rs
index bafef7b0f46..5fc988e4319 100644
--- a/src/tools/rustfmt/src/parse/macros/cfg_if.rs
+++ b/src/tools/rustfmt/src/parse/macros/cfg_if.rs
@@ -9,10 +9,10 @@ use crate::parse::macros::build_stream_parser;
 use crate::parse::session::ParseSess;
 
 pub(crate) fn parse_cfg_if<'a>(
-    sess: &'a ParseSess,
+    psess: &'a ParseSess,
     mac: &'a ast::MacCall,
 ) -> Result<Vec<ast::Item>, &'static str> {
-    match catch_unwind(AssertUnwindSafe(|| parse_cfg_if_inner(sess, mac))) {
+    match catch_unwind(AssertUnwindSafe(|| parse_cfg_if_inner(psess, mac))) {
         Ok(Ok(items)) => Ok(items),
         Ok(err @ Err(_)) => err,
         Err(..) => Err("failed to parse cfg_if!"),
@@ -20,11 +20,11 @@ pub(crate) fn parse_cfg_if<'a>(
 }
 
 fn parse_cfg_if_inner<'a>(
-    sess: &'a ParseSess,
+    psess: &'a ParseSess,
     mac: &'a ast::MacCall,
 ) -> Result<Vec<ast::Item>, &'static str> {
     let ts = mac.args.tokens.clone();
-    let mut parser = build_stream_parser(sess.inner(), ts);
+    let mut parser = build_stream_parser(psess.inner(), ts);
 
     let mut items = vec![];
     let mut process_if_cfg = true;
@@ -67,7 +67,7 @@ fn parse_cfg_if_inner<'a>(
                 Ok(None) => continue,
                 Err(err) => {
                     err.cancel();
-                    parser.sess.dcx.reset_err_count();
+                    parser.psess.dcx.reset_err_count();
                     return Err(
                         "Expected item inside cfg_if block, but failed to parse it as an item",
                     );
diff --git a/src/tools/rustfmt/src/parse/macros/lazy_static.rs b/src/tools/rustfmt/src/parse/macros/lazy_static.rs
index 8b1dc6694d6..badd9569950 100644
--- a/src/tools/rustfmt/src/parse/macros/lazy_static.rs
+++ b/src/tools/rustfmt/src/parse/macros/lazy_static.rs
@@ -16,8 +16,8 @@ pub(crate) fn parse_lazy_static(
         ($method:ident $(,)* $($arg:expr),* $(,)*) => {
             match parser.$method($($arg,)*) {
                 Ok(val) => {
-                    if parser.sess.dcx.has_errors().is_some() {
-                        parser.sess.dcx.reset_err_count();
+                    if parser.psess.dcx.has_errors().is_some() {
+                        parser.psess.dcx.reset_err_count();
                         return None;
                     } else {
                         val
@@ -25,7 +25,7 @@ pub(crate) fn parse_lazy_static(
                 }
                 Err(err) => {
                     err.cancel();
-                    parser.sess.dcx.reset_err_count();
+                    parser.psess.dcx.reset_err_count();
                     return None;
                 }
             }
diff --git a/src/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs
index a9f9ea1826a..3cf133c647c 100644
--- a/src/tools/rustfmt/src/parse/macros/mod.rs
+++ b/src/tools/rustfmt/src/parse/macros/mod.rs
@@ -14,12 +14,12 @@ pub(crate) mod asm;
 pub(crate) mod cfg_if;
 pub(crate) mod lazy_static;
 
-fn build_stream_parser<'a>(sess: &'a ParseSess, tokens: TokenStream) -> Parser<'a> {
-    stream_to_parser(sess, tokens, MACRO_ARGUMENTS).recovery(Recovery::Forbidden)
+fn build_stream_parser<'a>(psess: &'a ParseSess, tokens: TokenStream) -> Parser<'a> {
+    stream_to_parser(psess, tokens, MACRO_ARGUMENTS).recovery(Recovery::Forbidden)
 }
 
 fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser<'a> {
-    build_stream_parser(context.parse_sess.inner(), tokens)
+    build_stream_parser(context.psess.inner(), tokens)
 }
 
 fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
@@ -29,8 +29,8 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
             if Parser::nonterminal_may_begin_with($nt_kind, &cloned_parser.token) {
                 match $try_parse(&mut cloned_parser) {
                     Ok(x) => {
-                        if parser.sess.dcx.has_errors().is_some() {
-                            parser.sess.dcx.reset_err_count();
+                        if parser.psess.dcx.has_errors().is_some() {
+                            parser.psess.dcx.reset_err_count();
                         } else {
                             // Parsing succeeded.
                             *parser = cloned_parser;
@@ -39,7 +39,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
                     }
                     Err(e) => {
                         e.cancel();
-                        parser.sess.dcx.reset_err_count();
+                        parser.psess.dcx.reset_err_count();
                     }
                 }
             }
diff --git a/src/tools/rustfmt/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs
index 19b0dada08f..5dcdca1d953 100644
--- a/src/tools/rustfmt/src/parse/parser.rs
+++ b/src/tools/rustfmt/src/parse/parser.rs
@@ -29,7 +29,7 @@ pub(crate) struct Parser<'a> {
 /// A builder for the `Parser`.
 #[derive(Default)]
 pub(crate) struct ParserBuilder<'a> {
-    sess: Option<&'a ParseSess>,
+    psess: Option<&'a ParseSess>,
     input: Option<Input>,
 }
 
@@ -39,20 +39,20 @@ impl<'a> ParserBuilder<'a> {
         self
     }
 
-    pub(crate) fn sess(mut self, sess: &'a ParseSess) -> ParserBuilder<'a> {
-        self.sess = Some(sess);
+    pub(crate) fn psess(mut self, psess: &'a ParseSess) -> ParserBuilder<'a> {
+        self.psess = Some(psess);
         self
     }
 
     pub(crate) fn build(self) -> Result<Parser<'a>, ParserError> {
-        let sess = self.sess.ok_or(ParserError::NoParseSess)?;
+        let psess = self.psess.ok_or(ParserError::NoParseSess)?;
         let input = self.input.ok_or(ParserError::NoInput)?;
 
-        let parser = match Self::parser(sess.inner(), input) {
+        let parser = match Self::parser(psess.inner(), input) {
             Ok(p) => p,
             Err(db) => {
                 if let Some(diagnostics) = db {
-                    sess.emit_diagnostics(diagnostics);
+                    psess.emit_diagnostics(diagnostics);
                     return Err(ParserError::ParserCreationError);
                 }
                 return Err(ParserError::ParsePanicError);
@@ -63,16 +63,16 @@ impl<'a> ParserBuilder<'a> {
     }
 
     fn parser(
-        sess: &'a rustc_session::parse::ParseSess,
+        psess: &'a rustc_session::parse::ParseSess,
         input: Input,
     ) -> Result<rustc_parse::parser::Parser<'a>, Option<Vec<Diag<'a>>>> {
         match input {
             Input::File(ref file) => catch_unwind(AssertUnwindSafe(move || {
-                new_parser_from_file(sess, file, None)
+                new_parser_from_file(psess, file, None)
             }))
             .map_err(|_| None),
             Input::Text(text) => rustc_parse::maybe_new_parser_from_source_str(
-                sess,
+                psess,
                 rustc_span::FileName::Custom("stdin".to_owned()),
                 text,
             )
@@ -106,27 +106,27 @@ impl<'a> Parser<'a> {
     }
 
     pub(crate) fn parse_file_as_module(
-        sess: &'a ParseSess,
+        psess: &'a ParseSess,
         path: &Path,
         span: Span,
     ) -> Result<(ast::AttrVec, ThinVec<ptr::P<ast::Item>>, Span), ParserError> {
         let result = catch_unwind(AssertUnwindSafe(|| {
-            let mut parser = new_parser_from_file(sess.inner(), path, Some(span));
+            let mut parser = new_parser_from_file(psess.inner(), path, Some(span));
             match parser.parse_mod(&TokenKind::Eof) {
                 Ok((a, i, spans)) => Some((a, i, spans.inner_span)),
                 Err(e) => {
                     e.emit();
-                    if sess.can_reset_errors() {
-                        sess.reset_errors();
+                    if psess.can_reset_errors() {
+                        psess.reset_errors();
                     }
                     None
                 }
             }
         }));
         match result {
-            Ok(Some(m)) if !sess.has_errors() => Ok(m),
-            Ok(Some(m)) if sess.can_reset_errors() => {
-                sess.reset_errors();
+            Ok(Some(m)) if !psess.has_errors() => Ok(m),
+            Ok(Some(m)) if psess.can_reset_errors() => {
+                psess.reset_errors();
                 Ok(m)
             }
             Ok(_) => Err(ParserError::ParseError),
@@ -137,25 +137,25 @@ impl<'a> Parser<'a> {
 
     pub(crate) fn parse_crate(
         input: Input,
-        sess: &'a ParseSess,
+        psess: &'a ParseSess,
     ) -> Result<ast::Crate, ParserError> {
-        let krate = Parser::parse_crate_inner(input, sess)?;
-        if !sess.has_errors() {
+        let krate = Parser::parse_crate_inner(input, psess)?;
+        if !psess.has_errors() {
             return Ok(krate);
         }
 
-        if sess.can_reset_errors() {
-            sess.reset_errors();
+        if psess.can_reset_errors() {
+            psess.reset_errors();
             return Ok(krate);
         }
 
         Err(ParserError::ParseError)
     }
 
-    fn parse_crate_inner(input: Input, sess: &'a ParseSess) -> Result<ast::Crate, ParserError> {
+    fn parse_crate_inner(input: Input, psess: &'a ParseSess) -> Result<ast::Crate, ParserError> {
         ParserBuilder::default()
             .input(input)
-            .sess(sess)
+            .psess(psess)
             .build()?
             .parse_crate_mod()
     }
diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs
index d6386a9504d..cb46e65999d 100644
--- a/src/tools/rustfmt/src/parse/session.rs
+++ b/src/tools/rustfmt/src/parse/session.rs
@@ -1,9 +1,8 @@
-use std::borrow::Cow;
 use std::path::Path;
 use std::sync::atomic::{AtomicBool, Ordering};
 
 use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
-use rustc_errors::emitter::{stderr_destination, DynEmitter, Emitter, HumanEmitter};
+use rustc_errors::emitter::{stderr_destination, DynEmitter, Emitter, HumanEmitter, SilentEmitter};
 use rustc_errors::translation::Translate;
 use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel};
 use rustc_session::parse::ParseSess as RawParseSess;
@@ -23,46 +22,11 @@ use crate::{Config, ErrorKind, FileName};
 
 /// ParseSess holds structs necessary for constructing a parser.
 pub(crate) struct ParseSess {
-    parse_sess: RawParseSess,
+    raw_psess: RawParseSess,
     ignore_path_set: Lrc<IgnorePathSet>,
     can_reset_errors: Lrc<AtomicBool>,
 }
 
-/// Emitter which discards every error.
-struct SilentEmitter;
-
-impl Translate for SilentEmitter {
-    fn fluent_bundle(&self) -> Option<&Lrc<rustc_errors::FluentBundle>> {
-        None
-    }
-
-    fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
-        panic!("silent emitter attempted to translate a diagnostic");
-    }
-
-    // Override `translate_message` for the silent emitter because eager translation of
-    // subdiagnostics result in a call to this.
-    fn translate_message<'a>(
-        &'a self,
-        message: &'a rustc_errors::DiagnosticMessage,
-        _: &'a rustc_errors::translation::FluentArgs<'_>,
-    ) -> Result<Cow<'_, str>, rustc_errors::error::TranslateError<'_>> {
-        rustc_errors::emitter::silent_translate(message)
-    }
-}
-
-impl Emitter for SilentEmitter {
-    fn source_map(&self) -> Option<&Lrc<SourceMap>> {
-        None
-    }
-
-    fn emit_diagnostic(&mut self, _diag: DiagInner) {}
-}
-
-fn silent_emitter() -> Box<DynEmitter> {
-    Box::new(SilentEmitter {})
-}
-
 /// Emit errors against every files expect ones specified in the `ignore_path_set`.
 struct SilentOnIgnoredFilesEmitter {
     ignore_path_set: IntoDynSyncSend<Lrc<IgnorePathSet>>,
@@ -143,17 +107,23 @@ fn default_dcx(
         ColorConfig::Never
     };
 
-    let emitter = if hide_parse_errors {
-        silent_emitter()
+    let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+        rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+        false,
+    );
+    let emitter = Box::new(
+        HumanEmitter::new(stderr_destination(emit_color), fallback_bundle.clone())
+            .sm(Some(source_map.clone())),
+    );
+
+    let emitter: Box<DynEmitter> = if hide_parse_errors {
+        Box::new(SilentEmitter {
+            fallback_bundle,
+            fatal_dcx: DiagCtxt::new(emitter),
+            fatal_note: None,
+        })
     } else {
-        let fallback_bundle = rustc_errors::fallback_fluent_bundle(
-            rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
-            false,
-        );
-        Box::new(
-            HumanEmitter::new(stderr_destination(emit_color), fallback_bundle)
-                .sm(Some(source_map.clone())),
-        )
+        emitter
     };
     DiagCtxt::new(Box::new(SilentOnIgnoredFilesEmitter {
         has_non_ignorable_parser_errors: false,
@@ -180,10 +150,10 @@ impl ParseSess {
             config.hide_parse_errors(),
             config.color(),
         );
-        let parse_sess = RawParseSess::with_dcx(dcx, source_map);
+        let raw_psess = RawParseSess::with_dcx(dcx, source_map);
 
         Ok(ParseSess {
-            parse_sess,
+            raw_psess,
             ignore_path_set,
             can_reset_errors,
         })
@@ -202,14 +172,14 @@ impl ParseSess {
         relative: Option<symbol::Ident>,
         dir_path: &Path,
     ) -> Result<ModulePathSuccess, ModError<'_>> {
-        rustc_expand::module::default_submod_path(&self.parse_sess, id, relative, dir_path).or_else(
+        rustc_expand::module::default_submod_path(&self.raw_psess, id, relative, dir_path).or_else(
             |e| {
                 // If resloving a module relative to {dir_path}/{symbol} fails because a file
                 // could not be found, then try to resolve the module relative to {dir_path}.
                 // If we still can't find the module after searching for it in {dir_path},
                 // surface the original error.
                 if matches!(e, ModError::FileNotFound(..)) && relative.is_some() {
-                    rustc_expand::module::default_submod_path(&self.parse_sess, id, None, dir_path)
+                    rustc_expand::module::default_submod_path(&self.raw_psess, id, None, dir_path)
                         .map_err(|_| e)
                 } else {
                     Err(e)
@@ -219,7 +189,7 @@ impl ParseSess {
     }
 
     pub(crate) fn is_file_parsed(&self, path: &Path) -> bool {
-        self.parse_sess
+        self.raw_psess
             .source_map()
             .get_source_file(&rustc_span::FileName::Real(
                 rustc_span::RealFileName::LocalPath(path.to_path_buf()),
@@ -232,21 +202,28 @@ impl ParseSess {
     }
 
     pub(crate) fn set_silent_emitter(&mut self) {
-        self.parse_sess.dcx = DiagCtxt::new(silent_emitter());
+        // Ideally this invocation wouldn't be necessary and the fallback bundle in
+        // `self.parse_sess.dcx` could be used, but the lock in `DiagCtxt` prevents this.
+        // See `<rustc_errors::SilentEmitter as Translate>::fallback_fluent_bundle`.
+        let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+            rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+            false,
+        );
+        self.raw_psess.dcx.make_silent(fallback_bundle, None);
     }
 
     pub(crate) fn span_to_filename(&self, span: Span) -> FileName {
-        self.parse_sess.source_map().span_to_filename(span).into()
+        self.raw_psess.source_map().span_to_filename(span).into()
     }
 
     pub(crate) fn span_to_file_contents(&self, span: Span) -> Lrc<rustc_span::SourceFile> {
-        self.parse_sess
+        self.raw_psess
             .source_map()
             .lookup_source_file(span.data().lo)
     }
 
     pub(crate) fn span_to_first_line_string(&self, span: Span) -> String {
-        let file_lines = self.parse_sess.source_map().span_to_lines(span).ok();
+        let file_lines = self.raw_psess.source_map().span_to_lines(span).ok();
 
         match file_lines {
             Some(fl) => fl
@@ -258,7 +235,7 @@ impl ParseSess {
     }
 
     pub(crate) fn line_of_byte_pos(&self, pos: BytePos) -> usize {
-        self.parse_sess.source_map().lookup_char_pos(pos).line
+        self.raw_psess.source_map().lookup_char_pos(pos).line
     }
 
     // TODO(calebcartwright): Preemptive, currently unused addition
@@ -271,15 +248,15 @@ impl ParseSess {
     }
 
     pub(crate) fn span_to_debug_info(&self, span: Span) -> String {
-        self.parse_sess.source_map().span_to_diagnostic_string(span)
+        self.raw_psess.source_map().span_to_diagnostic_string(span)
     }
 
     pub(crate) fn inner(&self) -> &RawParseSess {
-        &self.parse_sess
+        &self.raw_psess
     }
 
     pub(crate) fn snippet_provider(&self, span: Span) -> SnippetProvider {
-        let source_file = self.parse_sess.source_map().lookup_char_pos(span.lo()).file;
+        let source_file = self.raw_psess.source_map().lookup_char_pos(span.lo()).file;
         SnippetProvider::new(
             source_file.start_pos,
             source_file.end_position(),
@@ -288,7 +265,7 @@ impl ParseSess {
     }
 
     pub(crate) fn get_original_snippet(&self, file_name: &FileName) -> Option<Lrc<String>> {
-        self.parse_sess
+        self.raw_psess
             .source_map()
             .get_source_file(&file_name.into())
             .and_then(|source_file| source_file.src.clone())
@@ -308,23 +285,23 @@ impl ParseSess {
     }
 
     pub(super) fn has_errors(&self) -> bool {
-        self.parse_sess.dcx.has_errors().is_some()
+        self.raw_psess.dcx.has_errors().is_some()
     }
 
     pub(super) fn reset_errors(&self) {
-        self.parse_sess.dcx.reset_err_count();
+        self.raw_psess.dcx.reset_err_count();
     }
 }
 
 impl LineRangeUtils for ParseSess {
     fn lookup_line_range(&self, span: Span) -> LineRange {
         let snippet = self
-            .parse_sess
+            .raw_psess
             .source_map()
             .span_to_snippet(span)
             .unwrap_or_default();
-        let lo = self.parse_sess.source_map().lookup_line(span.lo()).unwrap();
-        let hi = self.parse_sess.source_map().lookup_line(span.hi()).unwrap();
+        let lo = self.raw_psess.source_map().lookup_line(span.lo()).unwrap();
+        let hi = self.raw_psess.source_map().lookup_line(span.hi()).unwrap();
 
         debug_assert_eq!(
             lo.sf.name, hi.sf.name,
@@ -383,6 +360,7 @@ mod tests {
         }
 
         fn build_diagnostic(level: DiagnosticLevel, span: Option<MultiSpan>) -> DiagInner {
+            #[allow(rustc::untranslatable_diagnostic)] // no translation needed for empty string
             let mut diag = DiagInner::new(level, "");
             diag.messages.clear();
             if let Some(span) = span {
diff --git a/src/tools/rustfmt/src/reorder.rs b/src/tools/rustfmt/src/reorder.rs
index 3e14f9f1272..fdbed939af5 100644
--- a/src/tools/rustfmt/src/reorder.rs
+++ b/src/tools/rustfmt/src/reorder.rs
@@ -263,13 +263,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         item_kind: ReorderableItemKind,
         in_group: bool,
     ) -> usize {
-        let mut last = self.parse_sess.lookup_line_range(items[0].span());
+        let mut last = self.psess.lookup_line_range(items[0].span());
         let item_length = items
             .iter()
             .take_while(|ppi| {
                 item_kind.is_same_item_kind(&***ppi)
                     && (!in_group || {
-                        let current = self.parse_sess.lookup_line_range(ppi.span());
+                        let current = self.psess.lookup_line_range(ppi.span());
                         let in_same_group = current.lo < last.hi + 2;
                         last = current;
                         in_same_group
diff --git a/src/tools/rustfmt/src/rewrite.rs b/src/tools/rustfmt/src/rewrite.rs
index 4a3bd129d16..e2498a3500a 100644
--- a/src/tools/rustfmt/src/rewrite.rs
+++ b/src/tools/rustfmt/src/rewrite.rs
@@ -26,7 +26,7 @@ impl<T: Rewrite> Rewrite for ptr::P<T> {
 
 #[derive(Clone)]
 pub(crate) struct RewriteContext<'a> {
-    pub(crate) parse_sess: &'a ParseSess,
+    pub(crate) psess: &'a ParseSess,
     pub(crate) config: &'a Config,
     pub(crate) inside_macro: Rc<Cell<bool>>,
     // Force block indent style even if we are using visual indent style.
diff --git a/src/tools/rustfmt/src/source_file.rs b/src/tools/rustfmt/src/source_file.rs
index 512a8593c27..6376bc49b69 100644
--- a/src/tools/rustfmt/src/source_file.rs
+++ b/src/tools/rustfmt/src/source_file.rs
@@ -49,7 +49,7 @@ where
 }
 
 pub(crate) fn write_file<T>(
-    parse_sess: Option<&ParseSess>,
+    psess: Option<&ParseSess>,
     filename: &FileName,
     formatted_text: &str,
     out: &mut T,
@@ -90,7 +90,7 @@ where
     let original_text = if newline_style != NewlineStyle::Auto && *filename != FileName::Stdin {
         Lrc::new(fs::read_to_string(ensure_real_path(filename))?)
     } else {
-        match parse_sess.and_then(|sess| sess.get_original_snippet(filename)) {
+        match psess.and_then(|psess| psess.get_original_snippet(filename)) {
             Some(ori) => ori,
             None => Lrc::new(fs::read_to_string(ensure_real_path(filename))?),
         }
diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs
index d4218cff75a..b91d9b47cb6 100644
--- a/src/tools/rustfmt/src/utils.rs
+++ b/src/tools/rustfmt/src/utils.rs
@@ -362,7 +362,7 @@ macro_rules! out_of_file_lines_range {
             && !$self
                 .config
                 .file_lines()
-                .intersects(&$self.parse_sess.lookup_line_range($span))
+                .intersects(&$self.psess.lookup_line_range($span))
     };
 }
 
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index bc5accefd92..47f772b485d 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -71,7 +71,7 @@ impl SnippetProvider {
 
 pub(crate) struct FmtVisitor<'a> {
     parent_context: Option<&'a RewriteContext<'a>>,
-    pub(crate) parse_sess: &'a ParseSess,
+    pub(crate) psess: &'a ParseSess,
     pub(crate) buffer: String,
     pub(crate) last_pos: BytePos,
     // FIXME: use an RAII util or closure for indenting
@@ -113,10 +113,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
     }
 
     fn visit_stmt(&mut self, stmt: &Stmt<'_>, include_empty_semi: bool) {
-        debug!(
-            "visit_stmt: {}",
-            self.parse_sess.span_to_debug_info(stmt.span())
-        );
+        debug!("visit_stmt: {}", self.psess.span_to_debug_info(stmt.span()));
 
         if stmt.is_empty() {
             // If the statement is empty, just skip over it. Before that, make sure any comment
@@ -217,10 +214,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         inner_attrs: Option<&[ast::Attribute]>,
         has_braces: bool,
     ) {
-        debug!(
-            "visit_block: {}",
-            self.parse_sess.span_to_debug_info(b.span),
-        );
+        debug!("visit_block: {}", self.psess.span_to_debug_info(b.span));
 
         // Check if this block has braces.
         let brace_compensation = BytePos(if has_braces { 1 } else { 0 });
@@ -744,10 +738,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         // do not take into account the lines with attributes as part of the skipped range
         let attrs_end = attrs
             .iter()
-            .map(|attr| self.parse_sess.line_of_byte_pos(attr.span.hi()))
+            .map(|attr| self.psess.line_of_byte_pos(attr.span.hi()))
             .max()
             .unwrap_or(1);
-        let first_line = self.parse_sess.line_of_byte_pos(main_span.lo());
+        let first_line = self.psess.line_of_byte_pos(main_span.lo());
         // Statement can start after some newlines and/or spaces
         // or it can be on the same line as the last attribute.
         // So here we need to take a minimum between the two.
@@ -758,8 +752,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
     }
 
     pub(crate) fn from_context(ctx: &'a RewriteContext<'_>) -> FmtVisitor<'a> {
-        let mut visitor = FmtVisitor::from_parse_sess(
-            ctx.parse_sess,
+        let mut visitor = FmtVisitor::from_psess(
+            ctx.psess,
             ctx.config,
             ctx.snippet_provider,
             ctx.report.clone(),
@@ -769,8 +763,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         visitor
     }
 
-    pub(crate) fn from_parse_sess(
-        parse_session: &'a ParseSess,
+    pub(crate) fn from_psess(
+        psess: &'a ParseSess,
         config: &'a Config,
         snippet_provider: &'a SnippetProvider,
         report: FormatReport,
@@ -786,7 +780,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         skip_context.macros.extend(macro_names);
         FmtVisitor {
             parent_context: None,
-            parse_sess: parse_session,
+            psess,
             buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2),
             last_pos: BytePos(0),
             block_indent: Indent::empty(),
@@ -814,12 +808,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
     pub(crate) fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool {
         for attr in attrs {
             if attr.has_name(depr_skip_annotation()) {
-                let file_name = self.parse_sess.span_to_filename(attr.span);
+                let file_name = self.psess.span_to_filename(attr.span);
                 self.report.append(
                     file_name,
                     vec![FormattingError::from_span(
                         attr.span,
-                        self.parse_sess,
+                        self.psess,
                         ErrorKind::DeprecatedAttr,
                     )],
                 );
@@ -828,12 +822,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     ast::AttrKind::Normal(ref normal)
                         if self.is_unknown_rustfmt_attr(&normal.item.path.segments) =>
                     {
-                        let file_name = self.parse_sess.span_to_filename(attr.span);
+                        let file_name = self.psess.span_to_filename(attr.span);
                         self.report.append(
                             file_name,
                             vec![FormattingError::from_span(
                                 attr.span,
-                                self.parse_sess,
+                                self.psess,
                                 ErrorKind::BadAttr,
                             )],
                         );
@@ -1007,7 +1001,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
 
     pub(crate) fn get_context(&self) -> RewriteContext<'_> {
         RewriteContext {
-            parse_sess: self.parse_sess,
+            psess: self.psess,
             config: self.config,
             inside_macro: Rc::new(Cell::new(false)),
             use_block: Cell::new(false),
diff --git a/src/tools/rustfmt/tests/rustfmt/main.rs b/src/tools/rustfmt/tests/rustfmt/main.rs
index 7dcf7c8416e..e66fad1e7fa 100644
--- a/src/tools/rustfmt/tests/rustfmt/main.rs
+++ b/src/tools/rustfmt/tests/rustfmt/main.rs
@@ -176,7 +176,7 @@ fn rustfmt_emits_error_on_line_overflow_true() {
 #[test]
 #[allow(non_snake_case)]
 fn dont_emit_ICE() {
-    let files = ["tests/target/issue_5728.rs", "tests/target/issue_5729.rs"];
+    let files = ["tests/target/issue_5728.rs", "tests/target/issue_5729.rs", "tests/target/issue_6082.rs"];
 
     for file in files {
         let args = [file];
diff --git a/src/tools/rustfmt/tests/target/issue_6082.rs b/src/tools/rustfmt/tests/target/issue_6082.rs
new file mode 100644
index 00000000000..58e512c710e
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_6082.rs
@@ -0,0 +1,5 @@
+macro_rules! test {
+    ($T:ident, $b:lifetime) => {
+        Box<$T<$b>>
+    };
+}
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index cd3976ea657..91bbf5041ff 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -183,8 +183,8 @@
 "ui/async-await/issue-67651.rs",
 "ui/async-await/issue-67765-async-diagnostic.rs",
 "ui/async-await/issue-68112.rs",
-"ui/async-await/issue-68523.rs",
 "ui/async-await/issue-68523-start.rs",
+"ui/async-await/issue-68523.rs",
 "ui/async-await/issue-69446-fnmut-capture.rs",
 "ui/async-await/issue-70594.rs",
 "ui/async-await/issue-70818.rs",
@@ -342,8 +342,8 @@
 "ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs",
 "ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.rs",
 "ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs",
-"ui/borrowck/issue-54499-field-mutation-of-moved-out.rs",
 "ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.rs",
+"ui/borrowck/issue-54499-field-mutation-of-moved-out.rs",
 "ui/borrowck/issue-54499-field-mutation-of-never-init.rs",
 "ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.rs",
 "ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs",
@@ -360,9 +360,9 @@
 "ui/borrowck/issue-71546.rs",
 "ui/borrowck/issue-7573.rs",
 "ui/borrowck/issue-80772.rs",
+"ui/borrowck/issue-81365-1.rs",
 "ui/borrowck/issue-81365-10.rs",
 "ui/borrowck/issue-81365-11.rs",
-"ui/borrowck/issue-81365-1.rs",
 "ui/borrowck/issue-81365-2.rs",
 "ui/borrowck/issue-81365-3.rs",
 "ui/borrowck/issue-81365-4.rs",
@@ -392,6 +392,9 @@
 "ui/borrowck/issue-95079-missing-move-in-nested-closure.rs",
 "ui/box/issue-82446.rs",
 "ui/box/issue-95036.rs",
+"ui/c-variadic/issue-32201.rs",
+"ui/c-variadic/issue-86053-1.rs",
+"ui/c-variadic/issue-86053-2.rs",
 "ui/cast/issue-106883-is-empty.rs",
 "ui/cast/issue-10991.rs",
 "ui/cast/issue-17444.rs",
@@ -399,19 +402,19 @@
 "ui/cast/issue-85586.rs",
 "ui/cast/issue-88621.rs",
 "ui/cast/issue-89497.rs",
+"ui/closure-expected-type/issue-24421.rs",
 "ui/closure_context/issue-26046-fn-mut.rs",
 "ui/closure_context/issue-26046-fn-once.rs",
 "ui/closure_context/issue-42065.rs",
-"ui/closure-expected-type/issue-24421.rs",
 "ui/closures/2229_closure_analysis/issue-118144.rs",
 "ui/closures/2229_closure_analysis/issue-87378.rs",
 "ui/closures/2229_closure_analysis/issue-87987.rs",
 "ui/closures/2229_closure_analysis/issue-88118-2.rs",
-"ui/closures/2229_closure_analysis/issue_88118.rs",
 "ui/closures/2229_closure_analysis/issue-88476.rs",
 "ui/closures/2229_closure_analysis/issue-89606.rs",
 "ui/closures/2229_closure_analysis/issue-90465.rs",
 "ui/closures/2229_closure_analysis/issue-92724-needsdrop-query-cycle.rs",
+"ui/closures/2229_closure_analysis/issue_88118.rs",
 "ui/closures/2229_closure_analysis/match/issue-87097.rs",
 "ui/closures/2229_closure_analysis/match/issue-87426.rs",
 "ui/closures/2229_closure_analysis/match/issue-87988.rs",
@@ -644,8 +647,8 @@
 "ui/const-generics/issues/issue-99641.rs",
 "ui/const-generics/parser-error-recovery/issue-89013-no-assoc.rs",
 "ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs",
-"ui/const-generics/parser-error-recovery/issue-89013.rs",
 "ui/const-generics/parser-error-recovery/issue-89013-type.rs",
+"ui/const-generics/parser-error-recovery/issue-89013.rs",
 "ui/const-generics/type-dependent/issue-61936.rs",
 "ui/const-generics/type-dependent/issue-63695.rs",
 "ui/const-generics/type-dependent/issue-67144-1.rs",
@@ -689,13 +692,13 @@
 "ui/consts/const-eval/issue-91827-extern-types-field-offset.rs",
 "ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs",
 "ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs",
+"ui/consts/const-mut-refs/issue-76510.rs",
 "ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.rs",
 "ui/consts/const_in_pattern/issue-44333.rs",
 "ui/consts/const_in_pattern/issue-53708.rs",
 "ui/consts/const_in_pattern/issue-62614.rs",
 "ui/consts/const_in_pattern/issue-65466.rs",
 "ui/consts/const_in_pattern/issue-73431.rs",
-"ui/consts/const-mut-refs/issue-76510.rs",
 "ui/consts/control-flow/issue-46843.rs",
 "ui/consts/control-flow/issue-50577.rs",
 "ui/consts/extra-const-ub/issue-100771.rs",
@@ -714,9 +717,9 @@
 "ui/consts/issue-17074.rs",
 "ui/consts/issue-17458.rs",
 "ui/consts/issue-17718-borrow-interior.rs",
-"ui/consts/issue-17718-constants-not-static.rs",
 "ui/consts/issue-17718-const-bad-values.rs",
 "ui/consts/issue-17718-const-borrow.rs",
+"ui/consts/issue-17718-constants-not-static.rs",
 "ui/consts/issue-17718-references.rs",
 "ui/consts/issue-17718.rs",
 "ui/consts/issue-17756.rs",
@@ -841,9 +844,6 @@
 "ui/coroutine/issue-91477.rs",
 "ui/coroutine/issue-93161.rs",
 "ui/cross-crate/issue-64872/issue-64872.rs",
-"ui/c-variadic/issue-32201.rs",
-"ui/c-variadic/issue-86053-1.rs",
-"ui/c-variadic/issue-86053-2.rs",
 "ui/cycle-trait/issue-12511.rs",
 "ui/debuginfo/issue-105386-debuginfo-ub.rs",
 "ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs",
@@ -902,15 +902,6 @@
 "ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs",
 "ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs",
 "ui/drop/auxiliary/issue-10028.rs",
-"ui/dropck/issue-24805-dropck-itemless.rs",
-"ui/dropck/issue-28498-ugeh-with-lifetime-param.rs",
-"ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs",
-"ui/dropck/issue-28498-ugeh-with-trait-bound.rs",
-"ui/dropck/issue-29844.rs",
-"ui/dropck/issue-34053.rs",
-"ui/dropck/issue-38868.rs",
-"ui/dropck/issue-54943-1.rs",
-"ui/dropck/issue-54943-2.rs",
 "ui/drop/issue-100276.rs",
 "ui/drop/issue-10028.rs",
 "ui/drop/issue-103107.rs",
@@ -929,6 +920,15 @@
 "ui/drop/issue-90752-raw-ptr-shenanigans.rs",
 "ui/drop/issue-90752.rs",
 "ui/drop/issue-979.rs",
+"ui/dropck/issue-24805-dropck-itemless.rs",
+"ui/dropck/issue-28498-ugeh-with-lifetime-param.rs",
+"ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs",
+"ui/dropck/issue-28498-ugeh-with-trait-bound.rs",
+"ui/dropck/issue-29844.rs",
+"ui/dropck/issue-34053.rs",
+"ui/dropck/issue-38868.rs",
+"ui/dropck/issue-54943-1.rs",
+"ui/dropck/issue-54943-2.rs",
 "ui/dst/issue-113447.rs",
 "ui/dst/issue-90528-unsizing-not-suggestion-110063.rs",
 "ui/dst/issue-90528-unsizing-suggestion-1.rs",
@@ -1014,14 +1014,14 @@
 "ui/fn/issue-3904.rs",
 "ui/fn/issue-39259.rs",
 "ui/fn/issue-80179.rs",
-"ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs",
-"ui/foreign/issue-91370-foreign-fn-block-impl.rs",
-"ui/foreign/issue-99276-same-type-lifetimes.rs",
-"ui/for/issue-20605.rs",
 "ui/for-loop-while/issue-1257.rs",
 "ui/for-loop-while/issue-2216.rs",
 "ui/for-loop-while/issue-51345.rs",
 "ui/for-loop-while/issue-69841.rs",
+"ui/for/issue-20605.rs",
+"ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs",
+"ui/foreign/issue-91370-foreign-fn-block-impl.rs",
+"ui/foreign/issue-99276-same-type-lifetimes.rs",
 "ui/function-pointer/issue-102289.rs",
 "ui/functions-closures/closure-expected-type/issue-38714.rs",
 "ui/generic-associated-types/bugs/issue-100013.rs",
@@ -1084,8 +1084,8 @@
 "ui/generic-associated-types/issue-87258_b.rs",
 "ui/generic-associated-types/issue-87429-2.rs",
 "ui/generic-associated-types/issue-87429-associated-type-default.rs",
-"ui/generic-associated-types/issue-87429.rs",
 "ui/generic-associated-types/issue-87429-specialization.rs",
+"ui/generic-associated-types/issue-87429.rs",
 "ui/generic-associated-types/issue-87748.rs",
 "ui/generic-associated-types/issue-87750.rs",
 "ui/generic-associated-types/issue-88287.rs",
@@ -1095,9 +1095,9 @@
 "ui/generic-associated-types/issue-88595.rs",
 "ui/generic-associated-types/issue-89008.rs",
 "ui/generic-associated-types/issue-89352.rs",
-"ui/generic-associated-types/issue-90014.rs",
-"ui/generic-associated-types/issue-90014-tait2.rs",
 "ui/generic-associated-types/issue-90014-tait.rs",
+"ui/generic-associated-types/issue-90014-tait2.rs",
+"ui/generic-associated-types/issue-90014.rs",
 "ui/generic-associated-types/issue-90729.rs",
 "ui/generic-associated-types/issue-91139.rs",
 "ui/generic-associated-types/issue-91883.rs",
@@ -1119,8 +1119,8 @@
 "ui/generics/issue-333.rs",
 "ui/generics/issue-59508-1.rs",
 "ui/generics/issue-59508.rs",
-"ui/generics/issue-61631-default-type-param-cannot-reference-self.rs",
 "ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.rs",
+"ui/generics/issue-61631-default-type-param-cannot-reference-self.rs",
 "ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs",
 "ui/generics/issue-79605.rs",
 "ui/generics/issue-80512-param-reordering-with-defaults.rs",
@@ -1179,9 +1179,6 @@
 "ui/hygiene/issue-47312.rs",
 "ui/hygiene/issue-61574-const-parameters.rs",
 "ui/hygiene/issue-77523-def-site-async-await.rs",
-"ui/implied-bounds/issue-100690.rs",
-"ui/implied-bounds/issue-101951.rs",
-"ui/implied-bounds/issue-110161.rs",
 "ui/impl-trait/explicit-generic-args-with-impl-trait/issue-87718.rs",
 "ui/impl-trait/in-trait/issue-102140.rs",
 "ui/impl-trait/in-trait/issue-102301.rs",
@@ -1261,6 +1258,9 @@
 "ui/impl-trait/issues/issue-92305.rs",
 "ui/impl-trait/issues/issue-93788.rs",
 "ui/impl-trait/issues/issue-99348-impl-compatibility.rs",
+"ui/implied-bounds/issue-100690.rs",
+"ui/implied-bounds/issue-101951.rs",
+"ui/implied-bounds/issue-110161.rs",
 "ui/imports/auxiliary/issue-114682-2-extern.rs",
 "ui/imports/auxiliary/issue-114682-3-extern.rs",
 "ui/imports/auxiliary/issue-114682-4-extern.rs",
@@ -1368,8 +1368,8 @@
 "ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.rs",
 "ui/inference/need_type_info/issue-109905.rs",
 "ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.rs",
-"ui/infinite/issue-41731-infinite-macro-println.rs",
 "ui/infinite/issue-41731-infinite-macro-print.rs",
+"ui/infinite/issue-41731-infinite-macro-println.rs",
 "ui/intrinsics/issue-28575.rs",
 "ui/intrinsics/issue-84297-reifying-copy.rs",
 "ui/invalid/issue-114435-layout-type-err.rs",
@@ -1386,8 +1386,8 @@
 "ui/issues/auxiliary/issue-11508.rs",
 "ui/issues/auxiliary/issue-11529.rs",
 "ui/issues/auxiliary/issue-11680.rs",
-"ui/issues/auxiliary/issue-12133-dylib2.rs",
 "ui/issues/auxiliary/issue-12133-dylib.rs",
+"ui/issues/auxiliary/issue-12133-dylib2.rs",
 "ui/issues/auxiliary/issue-12133-rlib.rs",
 "ui/issues/auxiliary/issue-12612-1.rs",
 "ui/issues/auxiliary/issue-12612-2.rs",
@@ -1554,8 +1554,8 @@
 "ui/issues/issue-13497-2.rs",
 "ui/issues/issue-13497.rs",
 "ui/issues/issue-13507-2.rs",
-"ui/issues/issue-13620.rs",
 "ui/issues/issue-1362.rs",
+"ui/issues/issue-13620.rs",
 "ui/issues/issue-13665.rs",
 "ui/issues/issue-13703.rs",
 "ui/issues/issue-13763.rs",
@@ -1649,8 +1649,8 @@
 "ui/issues/issue-16819.rs",
 "ui/issues/issue-16922-rpass.rs",
 "ui/issues/issue-16939.rs",
-"ui/issues/issue-16966.rs",
 "ui/issues/issue-1696.rs",
+"ui/issues/issue-16966.rs",
 "ui/issues/issue-16994.rs",
 "ui/issues/issue-17001.rs",
 "ui/issues/issue-17033.rs",
@@ -1729,8 +1729,8 @@
 "ui/issues/issue-18952.rs",
 "ui/issues/issue-18959.rs",
 "ui/issues/issue-18988.rs",
-"ui/issues/issue-19001.rs",
 "ui/issues/issue-1900.rs",
+"ui/issues/issue-19001.rs",
 "ui/issues/issue-19037.rs",
 "ui/issues/issue-19086.rs",
 "ui/issues/issue-19097.rs",
@@ -1826,8 +1826,8 @@
 "ui/issues/issue-21622.rs",
 "ui/issues/issue-21634.rs",
 "ui/issues/issue-21655.rs",
-"ui/issues/issue-21701.rs",
 "ui/issues/issue-2170-exe.rs",
+"ui/issues/issue-21701.rs",
 "ui/issues/issue-21763.rs",
 "ui/issues/issue-21891.rs",
 "ui/issues/issue-2190-1.rs",
@@ -1863,15 +1863,15 @@
 "ui/issues/issue-22777.rs",
 "ui/issues/issue-22781.rs",
 "ui/issues/issue-22789.rs",
-"ui/issues/issue-22814.rs",
 "ui/issues/issue-2281-part1.rs",
+"ui/issues/issue-22814.rs",
 "ui/issues/issue-2284.rs",
 "ui/issues/issue-22864-1.rs",
 "ui/issues/issue-22864-2.rs",
 "ui/issues/issue-22872.rs",
 "ui/issues/issue-22874.rs",
-"ui/issues/issue-22886.rs",
 "ui/issues/issue-2288.rs",
+"ui/issues/issue-22886.rs",
 "ui/issues/issue-22894.rs",
 "ui/issues/issue-22933-1.rs",
 "ui/issues/issue-22933-2.rs",
@@ -1884,9 +1884,9 @@
 "ui/issues/issue-23073.rs",
 "ui/issues/issue-2311-2.rs",
 "ui/issues/issue-2311.rs",
+"ui/issues/issue-2312.rs",
 "ui/issues/issue-23122-1.rs",
 "ui/issues/issue-23122-2.rs",
-"ui/issues/issue-2312.rs",
 "ui/issues/issue-2316-c.rs",
 "ui/issues/issue-23173.rs",
 "ui/issues/issue-23189.rs",
@@ -1917,8 +1917,8 @@
 "ui/issues/issue-23649-2.rs",
 "ui/issues/issue-23649-3.rs",
 "ui/issues/issue-23699.rs",
-"ui/issues/issue-23808.rs",
 "ui/issues/issue-2380-b.rs",
+"ui/issues/issue-23808.rs",
 "ui/issues/issue-2383.rs",
 "ui/issues/issue-23891.rs",
 "ui/issues/issue-23898.rs",
@@ -1981,8 +1981,8 @@
 "ui/issues/issue-25746-bool-transmute.rs",
 "ui/issues/issue-25757.rs",
 "ui/issues/issue-25810.rs",
-"ui/issues/issue-25901.rs",
 "ui/issues/issue-2590.rs",
+"ui/issues/issue-25901.rs",
 "ui/issues/issue-26056.rs",
 "ui/issues/issue-26093.rs",
 "ui/issues/issue-26095.rs",
@@ -2041,10 +2041,10 @@
 "ui/issues/issue-28433.rs",
 "ui/issues/issue-28472.rs",
 "ui/issues/issue-2848.rs",
+"ui/issues/issue-2849.rs",
 "ui/issues/issue-28498-must-work-ex1.rs",
 "ui/issues/issue-28498-must-work-ex2.rs",
 "ui/issues/issue-28498-ugeh-ex1.rs",
-"ui/issues/issue-2849.rs",
 "ui/issues/issue-28550.rs",
 "ui/issues/issue-28561.rs",
 "ui/issues/issue-28568.rs",
@@ -2062,8 +2062,8 @@
 "ui/issues/issue-28999.rs",
 "ui/issues/issue-29030.rs",
 "ui/issues/issue-29037.rs",
-"ui/issues/issue-29048.rs",
 "ui/issues/issue-2904.rs",
+"ui/issues/issue-29048.rs",
 "ui/issues/issue-29053.rs",
 "ui/issues/issue-29071-2.rs",
 "ui/issues/issue-29071.rs",
@@ -2075,8 +2075,8 @@
 "ui/issues/issue-2935.rs",
 "ui/issues/issue-29466.rs",
 "ui/issues/issue-29485.rs",
-"ui/issues/issue-29516.rs",
 "ui/issues/issue-2951.rs",
+"ui/issues/issue-29516.rs",
 "ui/issues/issue-29522.rs",
 "ui/issues/issue-29540.rs",
 "ui/issues/issue-29663.rs",
@@ -2101,10 +2101,10 @@
 "ui/issues/issue-30255.rs",
 "ui/issues/issue-3026.rs",
 "ui/issues/issue-3029.rs",
-"ui/issues/issue-30371.rs",
 "ui/issues/issue-3037.rs",
-"ui/issues/issue-30380.rs",
+"ui/issues/issue-30371.rs",
 "ui/issues/issue-3038.rs",
+"ui/issues/issue-30380.rs",
 "ui/issues/issue-3052.rs",
 "ui/issues/issue-30530.rs",
 "ui/issues/issue-30589.rs",
@@ -2226,8 +2226,8 @@
 "ui/issues/issue-37131.rs",
 "ui/issues/issue-37311-type-length-limit/issue-37311.rs",
 "ui/issues/issue-37510.rs",
-"ui/issues/issue-37534.rs",
 "ui/issues/issue-3753.rs",
+"ui/issues/issue-37534.rs",
 "ui/issues/issue-37576.rs",
 "ui/issues/issue-3763.rs",
 "ui/issues/issue-37665.rs",
@@ -2254,8 +2254,8 @@
 "ui/issues/issue-3888-2.rs",
 "ui/issues/issue-38919.rs",
 "ui/issues/issue-38942.rs",
-"ui/issues/issue-38954.rs",
 "ui/issues/issue-3895.rs",
+"ui/issues/issue-38954.rs",
 "ui/issues/issue-38987.rs",
 "ui/issues/issue-39089.rs",
 "ui/issues/issue-39175.rs",
@@ -2265,8 +2265,8 @@
 "ui/issues/issue-39687.rs",
 "ui/issues/issue-39709.rs",
 "ui/issues/issue-3979-2.rs",
-"ui/issues/issue-3979.rs",
 "ui/issues/issue-3979-xcrate.rs",
+"ui/issues/issue-3979.rs",
 "ui/issues/issue-39808.rs",
 "ui/issues/issue-39827.rs",
 "ui/issues/issue-39848.rs",
@@ -2341,9 +2341,9 @@
 "ui/issues/issue-43250.rs",
 "ui/issues/issue-43291.rs",
 "ui/issues/issue-4333.rs",
+"ui/issues/issue-4335.rs",
 "ui/issues/issue-43355.rs",
 "ui/issues/issue-43357.rs",
-"ui/issues/issue-4335.rs",
 "ui/issues/issue-43420-no-over-suggest.rs",
 "ui/issues/issue-43424.rs",
 "ui/issues/issue-43431.rs",
@@ -2372,8 +2372,8 @@
 "ui/issues/issue-44851.rs",
 "ui/issues/issue-4517.rs",
 "ui/issues/issue-4541.rs",
-"ui/issues/issue-45425.rs",
 "ui/issues/issue-4542.rs",
+"ui/issues/issue-45425.rs",
 "ui/issues/issue-4545.rs",
 "ui/issues/issue-45510.rs",
 "ui/issues/issue-45562.rs",
@@ -2402,8 +2402,8 @@
 "ui/issues/issue-47309.rs",
 "ui/issues/issue-4734.rs",
 "ui/issues/issue-4735.rs",
-"ui/issues/issue-47364.rs",
 "ui/issues/issue-4736.rs",
+"ui/issues/issue-47364.rs",
 "ui/issues/issue-47377.rs",
 "ui/issues/issue-47380.rs",
 "ui/issues/issue-47486.rs",
@@ -2412,8 +2412,8 @@
 "ui/issues/issue-47638.rs",
 "ui/issues/issue-47673.rs",
 "ui/issues/issue-47703-1.rs",
-"ui/issues/issue-47703.rs",
 "ui/issues/issue-47703-tuple.rs",
+"ui/issues/issue-47703.rs",
 "ui/issues/issue-47715.rs",
 "ui/issues/issue-47722.rs",
 "ui/issues/issue-48006.rs",
@@ -2561,8 +2561,8 @@
 "ui/issues/issue-59756.rs",
 "ui/issues/issue-5988.rs",
 "ui/issues/issue-5997-outer-generic-parameter/issue-5997-enum.rs",
-"ui/issues/issue-5997-outer-generic-parameter/issue-5997.rs",
 "ui/issues/issue-5997-outer-generic-parameter/issue-5997-struct.rs",
+"ui/issues/issue-5997-outer-generic-parameter/issue-5997.rs",
 "ui/issues/issue-60218.rs",
 "ui/issues/issue-60622.rs",
 "ui/issues/issue-60989.rs",
@@ -2837,8 +2837,8 @@
 "ui/lint/unused/issue-103320-must-use-ops.rs",
 "ui/lint/unused/issue-104397.rs",
 "ui/lint/unused/issue-105061-array-lint.rs",
-"ui/lint/unused/issue-105061.rs",
 "ui/lint/unused/issue-105061-should-lint.rs",
+"ui/lint/unused/issue-105061.rs",
 "ui/lint/unused/issue-117142-invalid-remove-parens.rs",
 "ui/lint/unused/issue-117284-arg-in-macro.rs",
 "ui/lint/unused/issue-119383-if-let-guard.rs",
@@ -2862,8 +2862,8 @@
 "ui/lint/use-redundant/issue-92904.rs",
 "ui/loops/issue-43162.rs",
 "ui/loops/issue-50576.rs",
-"ui/loops/issue-69225-layout-repeated-checked-add.rs",
 "ui/loops/issue-69225-SCEVAddExpr-wrap-flag.rs",
+"ui/loops/issue-69225-layout-repeated-checked-add.rs",
 "ui/loops/issue-82916.rs",
 "ui/lowering/issue-121108.rs",
 "ui/lowering/issue-96847.rs",
@@ -3016,7 +3016,6 @@
 "ui/mir/issue-29227.rs",
 "ui/mir/issue-46845.rs",
 "ui/mir/issue-60390.rs",
-"ui/mir/issue66339.rs",
 "ui/mir/issue-66851.rs",
 "ui/mir/issue-66930.rs",
 "ui/mir/issue-67639-normalization-ice.rs",
@@ -3043,6 +3042,7 @@
 "ui/mir/issue-92893.rs",
 "ui/mir/issue-99852.rs",
 "ui/mir/issue-99866.rs",
+"ui/mir/issue66339.rs",
 "ui/mir/validate/issue-95978-validator-lifetime-comparison.rs",
 "ui/mismatched_types/issue-106182.rs",
 "ui/mismatched_types/issue-112036.rs",
@@ -3053,10 +3053,10 @@
 "ui/mismatched_types/issue-26480.rs",
 "ui/mismatched_types/issue-35030.rs",
 "ui/mismatched_types/issue-36053-2.rs",
-"ui/mismatched_types/issue-38371.rs",
 "ui/mismatched_types/issue-38371-unfixable.rs",
-"ui/mismatched_types/issue-47706.rs",
+"ui/mismatched_types/issue-38371.rs",
 "ui/mismatched_types/issue-47706-trait.rs",
+"ui/mismatched_types/issue-47706.rs",
 "ui/mismatched_types/issue-74918-missing-lifetime.rs",
 "ui/mismatched_types/issue-75361-mismatched-impl.rs",
 "ui/mismatched_types/issue-84976.rs",
@@ -3414,8 +3414,8 @@
 "ui/parser/issues/issue-73568-lifetime-after-mut.rs",
 "ui/parser/issues/issue-75599.rs",
 "ui/parser/issues/issue-76437-async.rs",
-"ui/parser/issues/issue-76437-const-async.rs",
 "ui/parser/issues/issue-76437-const-async-unsafe.rs",
+"ui/parser/issues/issue-76437-const-async.rs",
 "ui/parser/issues/issue-76437-const.rs",
 "ui/parser/issues/issue-76437-pub-crate-unsafe.rs",
 "ui/parser/issues/issue-76437-unsafe.rs",
@@ -3561,16 +3561,10 @@
 "ui/privacy/issue-57264-2.rs",
 "ui/privacy/issue-75062-fieldless-tuple-struct.rs",
 "ui/privacy/issue-75906.rs",
-"ui/privacy/issue-75907_b.rs",
 "ui/privacy/issue-75907.rs",
+"ui/privacy/issue-75907_b.rs",
 "ui/privacy/issue-79593.rs",
 "ui/privacy/issue-92755.rs",
-"ui/process/issue-13304.rs",
-"ui/process/issue-14456.rs",
-"ui/process/issue-14940.rs",
-"ui/process/issue-16272.rs",
-"ui/process/issue-20091.rs",
-"ui/process/issue-30490.rs",
 "ui/proc-macro/auxiliary/issue-104884.rs",
 "ui/proc-macro/auxiliary/issue-107113.rs",
 "ui/proc-macro/auxiliary/issue-118809.rs",
@@ -3619,8 +3613,14 @@
 "ui/proc-macro/issue-86781-bad-inner-doc.rs",
 "ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs",
 "ui/proc-macro/issue-91800.rs",
-"ui/ptr_ops/issue-80309.rs",
+"ui/process/issue-13304.rs",
+"ui/process/issue-14456.rs",
+"ui/process/issue-14940.rs",
+"ui/process/issue-16272.rs",
+"ui/process/issue-20091.rs",
+"ui/process/issue-30490.rs",
 "ui/ptr_ops/issue-80309-safe.rs",
+"ui/ptr_ops/issue-80309.rs",
 "ui/pub/issue-33174-restricted-type-in-public-interface.rs",
 "ui/query-system/issue-83479.rs",
 "ui/range/issue-54505-no-literals.rs",
@@ -3698,8 +3698,8 @@
 "ui/resolve/issue-21221-3.rs",
 "ui/resolve/issue-21221-4.rs",
 "ui/resolve/issue-22692.rs",
-"ui/resolve/issue-23305.rs",
 "ui/resolve/issue-2330.rs",
+"ui/resolve/issue-23305.rs",
 "ui/resolve/issue-2356.rs",
 "ui/resolve/issue-23716.rs",
 "ui/resolve/issue-24968.rs",
@@ -3820,10 +3820,6 @@
 "ui/span/issue-25199.rs",
 "ui/span/issue-26656.rs",
 "ui/span/issue-27522.rs",
-"ui/span/issue28498-reject-ex1.rs",
-"ui/span/issue28498-reject-lifetime-param.rs",
-"ui/span/issue28498-reject-passed-to-fn.rs",
-"ui/span/issue28498-reject-trait-bound.rs",
 "ui/span/issue-29106.rs",
 "ui/span/issue-29595.rs",
 "ui/span/issue-33884.rs",
@@ -3838,6 +3834,10 @@
 "ui/span/issue-43927-non-ADT-derive.rs",
 "ui/span/issue-71363.rs",
 "ui/span/issue-81800.rs",
+"ui/span/issue28498-reject-ex1.rs",
+"ui/span/issue28498-reject-lifetime-param.rs",
+"ui/span/issue28498-reject-passed-to-fn.rs",
+"ui/span/issue28498-reject-trait-bound.rs",
 "ui/specialization/issue-111232.rs",
 "ui/specialization/issue-33017.rs",
 "ui/specialization/issue-35376.rs",
@@ -4124,8 +4124,8 @@
 "ui/traits/object/issue-44454-3.rs",
 "ui/traits/suggest-dereferences/issue-39029.rs",
 "ui/traits/suggest-dereferences/issue-62530.rs",
-"ui/traits/trait-upcasting/issue-11515.rs",
 "ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs",
+"ui/traits/trait-upcasting/issue-11515.rs",
 "ui/traits/vtable/issue-91807.rs",
 "ui/traits/vtable/issue-97381.rs",
 "ui/transmutability/arrays/issue-103783-array-length.rs",
@@ -4163,8 +4163,8 @@
 "ui/type-alias-impl-trait/issue-58951.rs",
 "ui/type-alias-impl-trait/issue-60371.rs",
 "ui/type-alias-impl-trait/issue-60407.rs",
-"ui/type-alias-impl-trait/issue-60564.rs",
 "ui/type-alias-impl-trait/issue-60564-working.rs",
+"ui/type-alias-impl-trait/issue-60564.rs",
 "ui/type-alias-impl-trait/issue-60662.rs",
 "ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs",
 "ui/type-alias-impl-trait/issue-63263-closure-return.rs",
@@ -4208,10 +4208,26 @@
 "ui/type-alias/issue-62263-self-in-atb.rs",
 "ui/type-alias/issue-62305-self-assoc-ty.rs",
 "ui/type-alias/issue-62364-self-ty-arg.rs",
+"ui/type-inference/issue-113283-alllocator-trait-eq.rs",
+"ui/type-inference/issue-30225.rs",
 "ui/type/ascription/issue-34255-1.rs",
 "ui/type/ascription/issue-47666.rs",
 "ui/type/ascription/issue-54516.rs",
 "ui/type/ascription/issue-60933.rs",
+"ui/type/issue-100584.rs",
+"ui/type/issue-101866.rs",
+"ui/type/issue-102598.rs",
+"ui/type/issue-103271.rs",
+"ui/type/issue-58355.rs",
+"ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs",
+"ui/type/issue-91268.rs",
+"ui/type/issue-94187-verbose-type-name.rs",
+"ui/type/type-check/issue-116967-cannot-coerce-returned-result.rs",
+"ui/type/type-check/issue-22897.rs",
+"ui/type/type-check/issue-40294.rs",
+"ui/type/type-check/issue-41314.rs",
+"ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs",
+"ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs",
 "ui/typeck/auxiliary/issue-29181.rs",
 "ui/typeck/auxiliary/issue-36708.rs",
 "ui/typeck/auxiliary/issue-81943-lib.rs",
@@ -4316,25 +4332,9 @@
 "ui/typeck/issue-96738.rs",
 "ui/typeck/issue-98260.rs",
 "ui/typeck/issue-98982.rs",
-"ui/type-inference/issue-113283-alllocator-trait-eq.rs",
-"ui/type-inference/issue-30225.rs",
-"ui/type/issue-100584.rs",
-"ui/type/issue-101866.rs",
-"ui/type/issue-102598.rs",
-"ui/type/issue-103271.rs",
-"ui/type/issue-58355.rs",
-"ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs",
-"ui/type/issue-91268.rs",
-"ui/type/issue-94187-verbose-type-name.rs",
 "ui/typeof/issue-100183.rs",
 "ui/typeof/issue-29184.rs",
 "ui/typeof/issue-42060.rs",
-"ui/type/type-check/issue-116967-cannot-coerce-returned-result.rs",
-"ui/type/type-check/issue-22897.rs",
-"ui/type/type-check/issue-40294.rs",
-"ui/type/type-check/issue-41314.rs",
-"ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs",
-"ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs",
 "ui/unboxed-closures/issue-18652.rs",
 "ui/unboxed-closures/issue-18661.rs",
 "ui/unboxed-closures/issue-30906.rs",
@@ -4355,6 +4355,11 @@
 "ui/unsafe/issue-47412.rs",
 "ui/unsafe/issue-85435-unsafe-op-in-let-under-unsafe-under-closure.rs",
 "ui/unsafe/issue-87414-query-cycle.rs",
+"ui/unsized-locals/issue-30276-feature-flagged.rs",
+"ui/unsized-locals/issue-30276.rs",
+"ui/unsized-locals/issue-50940-with-feature.rs",
+"ui/unsized-locals/issue-50940.rs",
+"ui/unsized-locals/issue-67981.rs",
 "ui/unsized/issue-115203.rs",
 "ui/unsized/issue-115809.rs",
 "ui/unsized/issue-30355.rs",
@@ -4367,11 +4372,6 @@
 "ui/unsized/issue-91801.rs",
 "ui/unsized/issue-91803.rs",
 "ui/unsized/issue-97732.rs",
-"ui/unsized-locals/issue-30276-feature-flagged.rs",
-"ui/unsized-locals/issue-30276.rs",
-"ui/unsized-locals/issue-50940.rs",
-"ui/unsized-locals/issue-50940-with-feature.rs",
-"ui/unsized-locals/issue-67981.rs",
 "ui/use/issue-18986.rs",
 "ui/use/issue-60976-extern-use-primitive-type.rs",
 "ui/wf/issue-103573.rs",
diff --git a/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs b/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs
index 394f95e9144..a0773c85bef 100644
--- a/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs
+++ b/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs
@@ -84,10 +84,16 @@ pub fn check(tests_path: impl AsRef<Path>, bad: &mut bool) {
                 }
             });
 
-            let Some((test_name, _)) = test.to_str().map(|s| s.split_once('.')).flatten() else {
+            let Some(test_name) = test.file_stem().map(OsStr::to_str).flatten() else {
                 continue;
             };
 
+            assert!(
+                !test_name.contains('.'),
+                "test name cannot contain dots '.': `{}`",
+                test.display()
+            );
+
             test_info.insert(test_name.to_string(), (test, expected_revisions));
         }
 
@@ -98,14 +104,20 @@ pub fn check(tests_path: impl AsRef<Path>, bad: &mut bool) {
         for sibling in files_under_inspection.iter().filter(|f| {
             f.extension().map(OsStr::to_str).flatten().is_some_and(|ext| EXTENSIONS.contains(&ext))
         }) {
-            let filename_components = sibling.to_str().unwrap().split('.').collect::<Vec<_>>();
-            let file_prefix = filename_components[0];
-
-            let Some((test_path, expected_revisions)) = test_info.get(file_prefix) else {
+            let Some(filename) = sibling.file_name().map(OsStr::to_str).flatten() else {
                 continue;
             };
 
-            match filename_components[..] {
+            let filename_components = filename.split('.').collect::<Vec<_>>();
+            let [file_prefix, ..] = &filename_components[..] else {
+                continue;
+            };
+
+            let Some((test_path, expected_revisions)) = test_info.get(*file_prefix) else {
+                continue;
+            };
+
+            match &filename_components[..] {
                 // Cannot have a revision component, skip.
                 [] | [_] => return,
                 [_, _] if !expected_revisions.is_empty() => {
@@ -120,9 +132,9 @@ pub fn check(tests_path: impl AsRef<Path>, bad: &mut bool) {
                 [_, _] => return,
                 [_, found_revision, .., extension] => {
                     if !IGNORES.contains(&found_revision)
-                        && !expected_revisions.contains(found_revision)
+                        && !expected_revisions.contains(*found_revision)
                         // This is from `//@ stderr-per-bitwidth`
-                        && !(extension == "stderr" && ["32bit", "64bit"].contains(&found_revision))
+                        && !(*extension == "stderr" && ["32bit", "64bit"].contains(&found_revision))
                     {
                         // Found some unexpected revision-esque component that is not a known
                         // compare-mode or expected revision.
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index a9c5be913ba..39b14adfea4 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -18,7 +18,7 @@ const ENTRY_LIMIT: usize = 900;
 // FIXME: The following limits should be reduced eventually.
 
 const ISSUES_ENTRY_LIMIT: usize = 1750;
-const ROOT_ENTRY_LIMIT: usize = 872;
+const ROOT_ENTRY_LIMIT: usize = 866;
 
 const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
     "rs",     // test source files
@@ -34,8 +34,8 @@ const EXTENSION_EXCEPTION_PATHS: &[&str] = &[
     "tests/ui/asm/named-asm-labels.s", // loading an external asm file to test named labels lint
     "tests/ui/codegen/mismatched-data-layout.json", // testing mismatched data layout w/ custom targets
     "tests/ui/check-cfg/my-awesome-platform.json",  // testing custom targets with cfgs
-    "tests/ui/commandline-argfile-badutf8.args",    // passing args via a file
-    "tests/ui/commandline-argfile.args",            // passing args via a file
+    "tests/ui/argfile/commandline-argfile-badutf8.args", // passing args via a file
+    "tests/ui/argfile/commandline-argfile.args",    // passing args via a file
     "tests/ui/crate-loading/auxiliary/libfoo.rlib", // testing loading a manually created rlib
     "tests/ui/include-macros/data.bin", // testing including data with the include macros
     "tests/ui/include-macros/file.txt", // testing including data with the include macros
@@ -104,9 +104,18 @@ pub fn check(path: &Path, bless: bool, bad: &mut bool) {
 
     // the list of files in ui tests that are allowed to start with `issue-XXXX`
     // BTreeSet because we would like a stable ordering so --bless works
-    let allowed_issue_names = BTreeSet::from(
-        include!("issues.txt").map(|path| path.replace("/", std::path::MAIN_SEPARATOR_STR)),
-    );
+    let issues_list =
+        include!("issues.txt").map(|path| path.replace("/", std::path::MAIN_SEPARATOR_STR));
+    let issues: Vec<String> = Vec::from(issues_list.clone());
+    let is_sorted = issues.windows(2).all(|w| w[0] < w[1]);
+    if !is_sorted && !bless {
+        tidy_error!(
+            bad,
+            "`src/tools/tidy/src/issues.txt` is not in order, mostly because you modified it manually,
+            please only update it with command `x test tidy --bless`"
+        );
+    }
+    let allowed_issue_names = BTreeSet::from(issues_list);
 
     let mut remaining_issue_names: BTreeSet<String> = allowed_issue_names.clone();
 
@@ -190,7 +199,11 @@ pub fn check(path: &Path, bless: bool, bad: &mut bool) {
         let blessed_issues_path = tidy_src.join("issues_blessed.txt");
         let mut blessed_issues_txt = fs::File::create(&blessed_issues_path).unwrap();
         blessed_issues_txt.write(issues_txt_header.as_bytes()).unwrap();
-        for filename in allowed_issue_names.difference(&remaining_issue_names) {
+        // If we changed paths to use the OS separator, reassert Unix chauvinism for blessing.
+        for filename in allowed_issue_names
+            .difference(&remaining_issue_names)
+            .map(|s| s.replace(std::path::MAIN_SEPARATOR_STR, "/"))
+        {
             write!(blessed_issues_txt, "\"{filename}\",\n").unwrap();
         }
         write!(blessed_issues_txt, "]\n").unwrap();
diff --git a/tests/assembly/stack-protector/stack-protector-target-support.rs b/tests/assembly/stack-protector/stack-protector-target-support.rs
index 5fa93b3617e..df8a0dce40b 100644
--- a/tests/assembly/stack-protector/stack-protector-target-support.rs
+++ b/tests/assembly/stack-protector/stack-protector-target-support.rs
@@ -149,7 +149,7 @@
 //@ [r71] needs-llvm-components: webassembly
 //@ [r72] compile-flags:--target wasm32-unknown-unknown
 //@ [r72] needs-llvm-components: webassembly
-//@ [r73] compile-flags:--target wasm32-wasi
+//@ [r73] compile-flags:--target wasm32-wasip1
 //@ [r73] needs-llvm-components: webassembly
 //@ [r74] compile-flags:--target wasm32-wasi-preview1-threads
 //@ [r74] needs-llvm-components: webassembly
diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs
index 4051957c222..b0f8ebd5920 100644
--- a/tests/assembly/targets/targets-elf.rs
+++ b/tests/assembly/targets/targets-elf.rs
@@ -234,6 +234,9 @@
 //@ revisions: loongarch64_unknown_linux_gnu
 //@ [loongarch64_unknown_linux_gnu] compile-flags: --target loongarch64-unknown-linux-gnu
 //@ [loongarch64_unknown_linux_gnu] needs-llvm-components: loongarch
+//@ revisions: loongarch64_unknown_linux_musl
+//@ [loongarch64_unknown_linux_musl] compile-flags: --target loongarch64-unknown-linux-musl
+//@ [loongarch64_unknown_linux_musl] needs-llvm-components: loongarch
 //@ revisions: loongarch64_unknown_none
 //@ [loongarch64_unknown_none] compile-flags: --target loongarch64-unknown-none
 //@ [loongarch64_unknown_none] needs-llvm-components: loongarch
@@ -486,6 +489,9 @@
 //@ revisions: wasm32_wasi
 //@ [wasm32_wasi] compile-flags: --target wasm32-wasi
 //@ [wasm32_wasi] needs-llvm-components: webassembly
+//@ revisions: wasm32_wasip1
+//@ [wasm32_wasip1] compile-flags: --target wasm32-wasip1
+//@ [wasm32_wasip1] needs-llvm-components: webassembly
 //@ revisions: wasm32_wasi_preview1_threads
 //@ [wasm32_wasi_preview1_threads] compile-flags: --target wasm32-wasi-preview1-threads
 //@ [wasm32_wasi_preview1_threads] needs-llvm-components: webassembly
diff --git a/tests/assembly/targets/targets-pe.rs b/tests/assembly/targets/targets-pe.rs
index 63b07ee4d1a..6415aee6fae 100644
--- a/tests/assembly/targets/targets-pe.rs
+++ b/tests/assembly/targets/targets-pe.rs
@@ -12,6 +12,9 @@
 //@ revisions: aarch64_uwp_windows_msvc
 //@ [aarch64_uwp_windows_msvc] compile-flags: --target aarch64-uwp-windows-msvc
 //@ [aarch64_uwp_windows_msvc] needs-llvm-components: aarch64
+//@ revisions: arm64ec_pc_windows_msvc
+//@ [arm64ec_pc_windows_msvc] compile-flags: --target arm64ec-pc-windows-msvc
+//@ [arm64ec_pc_windows_msvc] needs-llvm-components: aarch64
 //@ revisions: avr_unknown_gnu_atmega328
 //@ [avr_unknown_gnu_atmega328] compile-flags: --target avr-unknown-gnu-atmega328
 //@ [avr_unknown_gnu_atmega328] needs-llvm-components: avr
diff --git a/tests/codegen/asm-goto.rs b/tests/codegen/asm-goto.rs
new file mode 100644
index 00000000000..e522d0da5b4
--- /dev/null
+++ b/tests/codegen/asm-goto.rs
@@ -0,0 +1,51 @@
+//@ compile-flags: -O
+//@ only-x86_64
+
+#![crate_type = "rlib"]
+#![feature(asm_goto)]
+
+use std::arch::asm;
+
+#[no_mangle]
+pub extern "C" fn panicky() {}
+
+struct Foo;
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        println!();
+    }
+}
+
+// CHECK-LABEL: @asm_goto
+#[no_mangle]
+pub unsafe fn asm_goto() {
+    // CHECK: callbr void asm sideeffect alignstack inteldialect "
+    // CHECK-NEXT: to label %[[FALLTHROUGHBB:[a-b0-9]+]] [label %[[JUMPBB:[a-b0-9]+]]]
+    asm!("jmp {}", label {});
+}
+
+// CHECK-LABEL: @asm_goto_with_outputs
+#[no_mangle]
+pub unsafe fn asm_goto_with_outputs() -> u64 {
+    let out: u64;
+    // CHECK: [[RES:%[0-9]+]] = callbr i64 asm sideeffect alignstack inteldialect "
+    // CHECK-NEXT: to label %[[FALLTHROUGHBB:[a-b0-9]+]] [label %[[JUMPBB:[a-b0-9]+]]]
+    asm!("{} /* {} */", out(reg) out, label { return 1; });
+    // CHECK: [[JUMPBB]]:
+    // CHECK-NEXT: [[RET:%.+]] = phi i64 [ [[RES]], %[[FALLTHROUGHBB]] ], [ 1, %start ]
+    // CHECK-NEXT: ret i64 [[RET]]
+    out
+}
+
+// CHECK-LABEL: @asm_goto_noreturn
+#[no_mangle]
+pub unsafe fn asm_goto_noreturn() -> u64 {
+    let out: u64;
+    // CHECK: callbr void asm sideeffect alignstack inteldialect "
+    // CHECK-NEXT: to label %unreachable [label %[[JUMPBB:[a-b0-9]+]]]
+    asm!("jmp {}", label { return 1; }, options(noreturn));
+    // CHECK: [[JUMPBB]]:
+    // CHECK-NEXT: ret i64 1
+    out
+}
diff --git a/tests/codegen/cffi/c-variadic.rs b/tests/codegen/cffi/c-variadic.rs
index 74aed36a8a1..914d1623ed2 100644
--- a/tests/codegen/cffi/c-variadic.rs
+++ b/tests/codegen/cffi/c-variadic.rs
@@ -1,4 +1,4 @@
-//@ ignore-wasm32-bare compiled with panic=abort by default
+//@ needs-unwind
 //@ compile-flags: -C no-prepopulate-passes -Copt-level=0
 //
 
diff --git a/tests/codegen/dst-offset.rs b/tests/codegen/dst-offset.rs
new file mode 100644
index 00000000000..f0157e5a106
--- /dev/null
+++ b/tests/codegen/dst-offset.rs
@@ -0,0 +1,84 @@
+//! This file tests that we correctly generate GEP instructions for DST
+//! field offsets.
+//@ compile-flags: -C no-prepopulate-passes -Copt-level=0
+
+#![crate_type = "lib"]
+
+#![feature(extern_types)]
+
+use std::ptr::addr_of;
+
+// Hack to get the correct type for usize
+// CHECK: @helper([[USIZE:i[0-9]+]] %_1)
+#[no_mangle]
+pub fn helper(_: usize) {
+}
+
+struct Dst<T: ?Sized> {
+    x: u32,
+    y: u8,
+    z: T,
+}
+
+// CHECK: @dst_dyn_trait_offset(ptr align {{[0-9]+}} [[DATA_PTR:%.+]], ptr align {{[0-9]+}} [[VTABLE_PTR:%.+]])
+#[no_mangle]
+pub fn dst_dyn_trait_offset(s: &Dst<dyn Drop>) -> &dyn Drop {
+// The alignment of dyn trait is unknown, so we compute the offset based on align from the vtable.
+
+// CHECK: [[SIZE_PTR:%[0-9]+]] = getelementptr inbounds {{.+}} [[VTABLE_PTR]]
+// CHECK: load [[USIZE]], ptr [[SIZE_PTR]]
+// CHECK: [[ALIGN_PTR:%[0-9]+]] = getelementptr inbounds {{.+}} [[VTABLE_PTR]]
+// CHECK: load [[USIZE]], ptr [[ALIGN_PTR]]
+
+// CHECK: getelementptr inbounds i8, ptr [[DATA_PTR]]
+// CHECK-NEXT: insertvalue
+// CHECK-NEXT: insertvalue
+// CHECK-NEXT: ret
+    &s.z
+}
+
+// CHECK-LABEL: @dst_slice_offset
+#[no_mangle]
+pub fn dst_slice_offset(s: &Dst<[u16]>) -> &[u16] {
+// The alignment of [u16] is known, so we generate a GEP directly.
+
+// CHECK: start:
+// CHECK-NEXT: getelementptr inbounds i8, {{.+}}, [[USIZE]] 6
+// CHECK-NEXT: insertvalue
+// CHECK-NEXT: insertvalue
+// CHECK-NEXT: ret
+    &s.z
+}
+
+#[repr(packed)]
+struct PackedDstSlice {
+    x: u32,
+    y: u8,
+    z: [u16],
+}
+
+// CHECK-LABEL: @packed_dst_slice_offset
+#[no_mangle]
+pub fn packed_dst_slice_offset(s: &PackedDstSlice) -> *const [u16] {
+// The alignment of [u16] is known, so we generate a GEP directly.
+
+// CHECK: start:
+// CHECK-NEXT: getelementptr inbounds i8, {{.+}}, [[USIZE]] 5
+// CHECK-NEXT: insertvalue
+// CHECK-NEXT: insertvalue
+// CHECK-NEXT: ret
+    addr_of!(s.z)
+}
+
+extern {
+    pub type Extern;
+}
+
+// CHECK-LABEL: @dst_extern
+#[no_mangle]
+pub fn dst_extern(s: &Dst<Extern>) -> &Extern {
+// Computing the alignment of an extern type is currently unsupported and just panics.
+
+// CHECK: call void @{{.+}}panic
+    &s.z
+}
diff --git a/tests/codegen/enum/uninhabited_enum_default_branch.rs b/tests/codegen/enum/uninhabited_enum_default_branch.rs
new file mode 100644
index 00000000000..5f318f18dec
--- /dev/null
+++ b/tests/codegen/enum/uninhabited_enum_default_branch.rs
@@ -0,0 +1,24 @@
+//@ compile-flags: -O
+
+#![crate_type = "lib"]
+
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Int(u32);
+
+const A: Int = Int(201);
+const B: Int = Int(270);
+const C: Int = Int(153);
+
+// CHECK-LABEL: @foo(
+// CHECK-SAME: [[TMP0:%.*]])
+// CHECK-NEXT:  start:
+// CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[TMP0]], -201
+// CHECK-NEXT:    icmp ult i32 [[TMP1]], 70
+// CHECK-NEXT:    icmp eq i32 [[TMP0]], 153
+// CHECK-NEXT:    [[SPEC_SELECT:%.*]] = or i1
+// CHECK-NEXT:    ret i1 [[SPEC_SELECT]]
+#[no_mangle]
+pub fn foo(x: Int) -> bool {
+    (x >= A && x <= B)
+        || x == C
+}
diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs
index b75c188f51a..e6e2f645714 100644
--- a/tests/codegen/function-arguments.rs
+++ b/tests/codegen/function-arguments.rs
@@ -2,6 +2,7 @@
 #![crate_type = "lib"]
 #![feature(dyn_star)]
 #![feature(generic_nonzero)]
+#![feature(allocator_api)]
 
 use std::mem::MaybeUninit;
 use std::num::NonZero;
@@ -182,6 +183,15 @@ pub fn _box(x: Box<i32>) -> Box<i32> {
   x
 }
 
+// With a custom allocator, it should *not* have `noalias`. (See
+// <https://github.com/rust-lang/miri/issues/3341> for why.) The second argument is the allocator,
+// which is a reference here that still carries `noalias` as usual.
+// CHECK: @_box_custom(ptr noundef nonnull align 4 %x.0, ptr noalias noundef nonnull readonly align 1 %x.1)
+#[no_mangle]
+pub fn _box_custom(x: Box<i32, &std::alloc::Global>) {
+  drop(x)
+}
+
 // CHECK: noundef nonnull align 4 ptr @notunpin_box(ptr noundef nonnull align 4 %x)
 #[no_mangle]
 pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> {
diff --git a/tests/codegen/zst-offset.rs b/tests/codegen/zst-offset.rs
index 65d9cf39c4c..b623d492d9d 100644
--- a/tests/codegen/zst-offset.rs
+++ b/tests/codegen/zst-offset.rs
@@ -13,7 +13,7 @@ pub fn helper(_: usize) {
 // CHECK-LABEL: @scalar_layout
 #[no_mangle]
 pub fn scalar_layout(s: &(u64, ())) {
-// CHECK: getelementptr i8, {{.+}}, [[USIZE]] 8
+// CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 8
     let x = &s.1;
     witness(&x); // keep variable in an alloca
 }
@@ -22,7 +22,7 @@ pub fn scalar_layout(s: &(u64, ())) {
 // CHECK-LABEL: @scalarpair_layout
 #[no_mangle]
 pub fn scalarpair_layout(s: &(u64, u32, ())) {
-// CHECK: getelementptr i8, {{.+}}, [[USIZE]] 12
+// CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 12
     let x = &s.2;
     witness(&x); // keep variable in an alloca
 }
@@ -34,7 +34,7 @@ pub struct U64x4(u64, u64, u64, u64);
 // CHECK-LABEL: @vector_layout
 #[no_mangle]
 pub fn vector_layout(s: &(U64x4, ())) {
-// CHECK: getelementptr i8, {{.+}}, [[USIZE]] 32
+// CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 32
     let x = &s.1;
     witness(&x); // keep variable in an alloca
 }
diff --git a/tests/debuginfo/mutex.rs b/tests/debuginfo/mutex.rs
index 1201da0dd7b..affc1558ffa 100644
--- a/tests/debuginfo/mutex.rs
+++ b/tests/debuginfo/mutex.rs
@@ -10,7 +10,7 @@
 //
 // cdb-command:dx m,d
 // cdb-check:m,d              [Type: std::sync::mutex::Mutex<i32>]
-// cdb-check:    [...] inner            [Type: std::sys::locks::mutex::windows::Mutex]
+// cdb-check:    [...] inner            [Type: std::sys::locks::mutex::futex::Mutex]
 // cdb-check:    [...] poison           [Type: std::sync::poison::Flag]
 // cdb-check:    [...] data             : 0 [Type: core::cell::UnsafeCell<i32>]
 
diff --git a/tests/debuginfo/rwlock-read.rs b/tests/debuginfo/rwlock-read.rs
index 7abbfd70ffb..76dbc73a1e9 100644
--- a/tests/debuginfo/rwlock-read.rs
+++ b/tests/debuginfo/rwlock-read.rs
@@ -16,7 +16,7 @@
 // cdb-command:dx r
 // cdb-check:r                [Type: std::sync::rwlock::RwLockReadGuard<i32>]
 // cdb-check:    [...] data             : NonNull([...]: 0) [Type: core::ptr::non_null::NonNull<i32>]
-// cdb-check:    [...] inner_lock       : [...] [Type: std::sys::locks::rwlock::windows::RwLock *]
+// cdb-check:    [...] inner_lock       : [...] [Type: std::sys::locks::rwlock::futex::RwLock *]
 
 #[allow(unused_variables)]
 
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff
index 080478ea884..bd346af6d16 100644
--- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff
@@ -69,7 +69,7 @@
           StorageLive(_6);
           _6 = ((*_1).4: std::option::Option<usize>);
           _7 = discriminant(_6);
-          switchInt(move _7) -> [1: bb4, otherwise: bb6];
+          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9];
       }
   
       bb4: {
@@ -135,5 +135,9 @@
           StorageDead(_6);
           return;
       }
+  
+      bb9: {
+          unreachable;
+      }
   }
   
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff
index ff8933fca8b..422cbeaa224 100644
--- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff
@@ -69,7 +69,7 @@
           StorageLive(_6);
           _6 = ((*_1).4: std::option::Option<usize>);
           _7 = discriminant(_6);
-          switchInt(move _7) -> [1: bb4, otherwise: bb6];
+          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9];
       }
   
       bb4: {
@@ -135,5 +135,9 @@
           StorageDead(_6);
           return;
       }
+  
+      bb9: {
+          unreachable;
+      }
   }
   
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir
index f7be8b75db7..bc12002490a 100644
--- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir
@@ -33,13 +33,13 @@ fn num_to_digit(_1: char) -> u32 {
         _3 = &_2;
         StorageLive(_4);
         _4 = discriminant(_2);
-        StorageDead(_3);
-        StorageDead(_2);
-        switchInt(move _4) -> [1: bb2, otherwise: bb7];
+        switchInt(move _4) -> [1: bb2, 0: bb6, otherwise: bb8];
     }
 
     bb2: {
         StorageDead(_4);
+        StorageDead(_3);
+        StorageDead(_2);
         StorageLive(_5);
         _5 = char::methods::<impl char>::to_digit(move _1, const 8_u32) -> [return: bb3, unwind unreachable];
     }
@@ -47,7 +47,7 @@ fn num_to_digit(_1: char) -> u32 {
     bb3: {
         StorageLive(_6);
         _6 = discriminant(_5);
-        switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb6];
+        switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb8];
     }
 
     bb4: {
@@ -58,20 +58,22 @@ fn num_to_digit(_1: char) -> u32 {
         _0 = move ((_5 as Some).0: u32);
         StorageDead(_6);
         StorageDead(_5);
-        goto -> bb8;
+        goto -> bb7;
     }
 
     bb6: {
-        unreachable;
+        StorageDead(_4);
+        StorageDead(_3);
+        StorageDead(_2);
+        _0 = const 0_u32;
+        goto -> bb7;
     }
 
     bb7: {
-        StorageDead(_4);
-        _0 = const 0_u32;
-        goto -> bb8;
+        return;
     }
 
     bb8: {
-        return;
+        unreachable;
     }
 }
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir
index e76fe992ac7..6c7e10a4525 100644
--- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir
@@ -33,13 +33,13 @@ fn num_to_digit(_1: char) -> u32 {
         _3 = &_2;
         StorageLive(_4);
         _4 = discriminant(_2);
-        StorageDead(_3);
-        StorageDead(_2);
-        switchInt(move _4) -> [1: bb2, otherwise: bb7];
+        switchInt(move _4) -> [1: bb2, 0: bb6, otherwise: bb8];
     }
 
     bb2: {
         StorageDead(_4);
+        StorageDead(_3);
+        StorageDead(_2);
         StorageLive(_5);
         _5 = char::methods::<impl char>::to_digit(move _1, const 8_u32) -> [return: bb3, unwind continue];
     }
@@ -47,7 +47,7 @@ fn num_to_digit(_1: char) -> u32 {
     bb3: {
         StorageLive(_6);
         _6 = discriminant(_5);
-        switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb6];
+        switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb8];
     }
 
     bb4: {
@@ -58,20 +58,22 @@ fn num_to_digit(_1: char) -> u32 {
         _0 = move ((_5 as Some).0: u32);
         StorageDead(_6);
         StorageDead(_5);
-        goto -> bb8;
+        goto -> bb7;
     }
 
     bb6: {
-        unreachable;
+        StorageDead(_4);
+        StorageDead(_3);
+        StorageDead(_2);
+        _0 = const 0_u32;
+        goto -> bb7;
     }
 
     bb7: {
-        StorageDead(_4);
-        _0 = const 0_u32;
-        goto -> bb8;
+        return;
     }
 
     bb8: {
-        return;
+        unreachable;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
index 5c586fbc2fc..84181462f67 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
@@ -58,16 +58,20 @@
 +         _2 = const Option::<Layout>::None;
           StorageLive(_10);
 -         _10 = discriminant(_2);
--         switchInt(move _10) -> [0: bb1, 1: bb2, otherwise: bb6];
+-         switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb1];
 +         _10 = const 0_isize;
-+         switchInt(const 0_isize) -> [0: bb1, 1: bb2, otherwise: bb6];
++         switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb1];
       }
   
       bb1: {
-          _11 = option::unwrap_failed() -> unwind unreachable;
+          unreachable;
       }
   
       bb2: {
+          _11 = option::unwrap_failed() -> unwind unreachable;
+      }
+  
+      bb3: {
 -         _1 = move ((_2 as Some).0: std::alloc::Layout);
 +         _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }};
           StorageDead(_10);
@@ -82,21 +86,21 @@
 +         _7 = const {ALLOC1<imm>: &std::alloc::Global};
           StorageLive(_8);
 -         _8 = _1;
--         _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb3, unwind unreachable];
+-         _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind unreachable];
 +         _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }};
-+         _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb3, unwind unreachable];
++         _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable];
       }
   
-      bb3: {
+      bb4: {
           StorageDead(_8);
           StorageDead(_7);
           StorageLive(_12);
           StorageLive(_15);
           _12 = discriminant(_6);
-          switchInt(move _12) -> [0: bb5, 1: bb4, otherwise: bb6];
+          switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1];
       }
   
-      bb4: {
+      bb5: {
           _15 = const "called `Result::unwrap()` on an `Err` value";
           StorageLive(_16);
           StorageLive(_17);
@@ -106,7 +110,7 @@
           _14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable;
       }
   
-      bb5: {
+      bb6: {
           _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
           StorageDead(_15);
           StorageDead(_12);
@@ -127,10 +131,6 @@
 +         nop;
           return;
       }
-  
-      bb6: {
-          unreachable;
-      }
   }
 + 
 + ALLOC0 (size: 8, align: 4) {
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff
index bfb2319dac1..820d02e26cd 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff
@@ -43,9 +43,9 @@
 +         _2 = const Option::<Layout>::None;
           StorageLive(_10);
 -         _10 = discriminant(_2);
--         switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb5];
+-         switchInt(move _10) -> [0: bb3, 1: bb4, otherwise: bb2];
 +         _10 = const 0_isize;
-+         switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb5];
++         switchInt(const 0_isize) -> [0: bb3, 1: bb4, otherwise: bb2];
       }
   
       bb1: {
@@ -68,10 +68,14 @@
       }
   
       bb2: {
-          _11 = option::unwrap_failed() -> unwind continue;
+          unreachable;
       }
   
       bb3: {
+          _11 = option::unwrap_failed() -> unwind continue;
+      }
+  
+      bb4: {
 -         _1 = move ((_2 as Some).0: std::alloc::Layout);
 +         _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }};
           StorageDead(_10);
@@ -86,19 +90,15 @@
 +         _7 = const {ALLOC1<imm>: &std::alloc::Global};
           StorageLive(_8);
 -         _8 = _1;
--         _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind continue];
+-         _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb5, unwind continue];
 +         _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }};
-+         _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind continue];
-      }
-  
-      bb4: {
-          StorageDead(_8);
-          StorageDead(_7);
-          _5 = Result::<NonNull<[u8]>, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue];
++         _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue];
       }
   
       bb5: {
-          unreachable;
+          StorageDead(_8);
+          StorageDead(_7);
+          _5 = Result::<NonNull<[u8]>, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue];
       }
   }
 + 
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
index ce55a8265e5..f478f7cb903 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
@@ -58,16 +58,20 @@
 +         _2 = const Option::<Layout>::None;
           StorageLive(_10);
 -         _10 = discriminant(_2);
--         switchInt(move _10) -> [0: bb1, 1: bb2, otherwise: bb6];
+-         switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb1];
 +         _10 = const 0_isize;
-+         switchInt(const 0_isize) -> [0: bb1, 1: bb2, otherwise: bb6];
++         switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb1];
       }
   
       bb1: {
-          _11 = option::unwrap_failed() -> unwind unreachable;
+          unreachable;
       }
   
       bb2: {
+          _11 = option::unwrap_failed() -> unwind unreachable;
+      }
+  
+      bb3: {
 -         _1 = move ((_2 as Some).0: std::alloc::Layout);
 +         _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }};
           StorageDead(_10);
@@ -82,21 +86,21 @@
 +         _7 = const {ALLOC1<imm>: &std::alloc::Global};
           StorageLive(_8);
 -         _8 = _1;
--         _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb3, unwind unreachable];
+-         _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind unreachable];
 +         _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }};
-+         _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb3, unwind unreachable];
++         _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable];
       }
   
-      bb3: {
+      bb4: {
           StorageDead(_8);
           StorageDead(_7);
           StorageLive(_12);
           StorageLive(_15);
           _12 = discriminant(_6);
-          switchInt(move _12) -> [0: bb5, 1: bb4, otherwise: bb6];
+          switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1];
       }
   
-      bb4: {
+      bb5: {
           _15 = const "called `Result::unwrap()` on an `Err` value";
           StorageLive(_16);
           StorageLive(_17);
@@ -106,7 +110,7 @@
           _14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable;
       }
   
-      bb5: {
+      bb6: {
           _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
           StorageDead(_15);
           StorageDead(_12);
@@ -127,10 +131,6 @@
 +         nop;
           return;
       }
-  
-      bb6: {
-          unreachable;
-      }
   }
 + 
 + ALLOC0 (size: 16, align: 8) {
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff
index ddf4223bb49..1fba8b5059a 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff
@@ -43,9 +43,9 @@
 +         _2 = const Option::<Layout>::None;
           StorageLive(_10);
 -         _10 = discriminant(_2);
--         switchInt(move _10) -> [0: bb2, 1: bb3, otherwise: bb5];
+-         switchInt(move _10) -> [0: bb3, 1: bb4, otherwise: bb2];
 +         _10 = const 0_isize;
-+         switchInt(const 0_isize) -> [0: bb2, 1: bb3, otherwise: bb5];
++         switchInt(const 0_isize) -> [0: bb3, 1: bb4, otherwise: bb2];
       }
   
       bb1: {
@@ -68,10 +68,14 @@
       }
   
       bb2: {
-          _11 = option::unwrap_failed() -> unwind continue;
+          unreachable;
       }
   
       bb3: {
+          _11 = option::unwrap_failed() -> unwind continue;
+      }
+  
+      bb4: {
 -         _1 = move ((_2 as Some).0: std::alloc::Layout);
 +         _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }};
           StorageDead(_10);
@@ -86,19 +90,15 @@
 +         _7 = const {ALLOC1<imm>: &std::alloc::Global};
           StorageLive(_8);
 -         _8 = _1;
--         _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind continue];
+-         _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb5, unwind continue];
 +         _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }};
-+         _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind continue];
-      }
-  
-      bb4: {
-          StorageDead(_8);
-          StorageDead(_7);
-          _5 = Result::<NonNull<[u8]>, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue];
++         _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue];
       }
   
       bb5: {
-          unreachable;
+          StorageDead(_8);
+          StorageDead(_7);
+          _5 = Result::<NonNull<[u8]>, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue];
       }
   }
 + 
diff --git a/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff
index ab3d91ab918..d0abebff214 100644
--- a/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff
+++ b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff
@@ -52,17 +52,21 @@
           StorageLive(_9);
           StorageLive(_10);
           _8 = discriminant(_1);
-          switchInt(move _8) -> [0: bb5, 1: bb4, otherwise: bb6];
+          switchInt(move _8) -> [0: bb6, 1: bb5, otherwise: bb1];
       }
   
       bb1: {
+          unreachable;
+      }
+  
+      bb2: {
           _7 = ((_2 as Continue).0: i32);
           _0 = Result::<i32, i32>::Ok(_7);
           StorageDead(_2);
           return;
       }
   
-      bb2: {
+      bb3: {
           _5 = ((_2 as Break).0: std::result::Result<std::convert::Infallible, i32>);
           StorageLive(_6);
           _6 = _5;
@@ -73,34 +77,30 @@
           return;
       }
   
-      bb3: {
+      bb4: {
           StorageDead(_10);
           StorageDead(_9);
           StorageDead(_8);
           StorageDead(_3);
           _4 = discriminant(_2);
--         switchInt(move _4) -> [0: bb1, 1: bb2, otherwise: bb6];
-+         goto -> bb1;
+-         switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb1];
++         goto -> bb2;
       }
   
-      bb4: {
+      bb5: {
           _10 = ((_1 as Err).0: i32);
           StorageLive(_11);
           _11 = Result::<Infallible, i32>::Err(_10);
           _2 = ControlFlow::<Result<Infallible, i32>, i32>::Break(move _11);
           StorageDead(_11);
--         goto -> bb3;
+-         goto -> bb4;
 +         goto -> bb7;
       }
   
-      bb5: {
+      bb6: {
           _9 = ((_1 as Ok).0: i32);
           _2 = ControlFlow::<Result<Infallible, i32>, i32>::Continue(_9);
-          goto -> bb3;
-      }
-  
-      bb6: {
-          unreachable;
+          goto -> bb4;
 +     }
 + 
 +     bb7: {
@@ -109,7 +109,7 @@
 +         StorageDead(_8);
 +         StorageDead(_3);
 +         _4 = discriminant(_2);
-+         goto -> bb2;
++         goto -> bb3;
       }
   }
   
diff --git a/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff b/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff
index 1ac527e9338..f7495862992 100644
--- a/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff
+++ b/tests/mir-opt/separate_const_switch.too_complex.JumpThreading.diff
@@ -27,54 +27,54 @@
       bb0: {
           StorageLive(_2);
           _3 = discriminant(_1);
-          switchInt(move _3) -> [0: bb2, 1: bb1, otherwise: bb7];
+          switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
       }
   
       bb1: {
-          _5 = ((_1 as Err).0: usize);
-          _2 = ControlFlow::<usize, i32>::Break(_5);
--         goto -> bb3;
-+         goto -> bb8;
+          unreachable;
       }
   
       bb2: {
-          _4 = ((_1 as Ok).0: i32);
-          _2 = ControlFlow::<usize, i32>::Continue(_4);
-          goto -> bb3;
+          _5 = ((_1 as Err).0: usize);
+          _2 = ControlFlow::<usize, i32>::Break(_5);
+-         goto -> bb4;
++         goto -> bb8;
       }
   
       bb3: {
-          _6 = discriminant(_2);
--         switchInt(move _6) -> [0: bb5, 1: bb4, otherwise: bb7];
-+         goto -> bb5;
+          _4 = ((_1 as Ok).0: i32);
+          _2 = ControlFlow::<usize, i32>::Continue(_4);
+          goto -> bb4;
       }
   
       bb4: {
+          _6 = discriminant(_2);
+-         switchInt(move _6) -> [0: bb6, 1: bb5, otherwise: bb1];
++         goto -> bb6;
+      }
+  
+      bb5: {
           StorageLive(_8);
           _8 = ((_2 as Break).0: usize);
           _0 = const Option::<i32>::None;
           StorageDead(_8);
-          goto -> bb6;
-      }
-  
-      bb5: {
-          _7 = ((_2 as Continue).0: i32);
-          _0 = Option::<i32>::Some(_7);
-          goto -> bb6;
+          goto -> bb7;
       }
   
       bb6: {
-          StorageDead(_2);
-          return;
+          _7 = ((_2 as Continue).0: i32);
+          _0 = Option::<i32>::Some(_7);
+          goto -> bb7;
       }
   
       bb7: {
-          unreachable;
+          StorageDead(_2);
+          return;
 +     }
 + 
 +     bb8: {
 +         _6 = discriminant(_2);
-+         goto -> bb4;
++         goto -> bb5;
       }
   }
   
diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff
index 1566d7197ac..c520a159f47 100644
--- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff
+++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff
@@ -23,12 +23,12 @@
           StorageDead(_3);
           StorageDead(_2);
           _5 = discriminant((_1.0: std::option::Option<u8>));
-          switchInt(move _5) -> [1: bb1, otherwise: bb3];
+          switchInt(move _5) -> [1: bb1, 0: bb3, otherwise: bb5];
       }
   
       bb1: {
           _4 = discriminant((_1.1: std::option::Option<T>));
-          switchInt(move _4) -> [0: bb2, otherwise: bb3];
+          switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb5];
       }
   
       bb2: {
@@ -46,5 +46,9 @@
           StorageDead(_1);
           return;
       }
+  
+      bb5: {
+          unreachable;
+      }
   }
   
diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff
index ba5262b0ee1..686581591fc 100644
--- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff
+++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff
@@ -23,12 +23,12 @@
           StorageDead(_3);
           StorageDead(_2);
           _5 = discriminant((_1.0: std::option::Option<u8>));
-          switchInt(move _5) -> [1: bb1, otherwise: bb3];
+          switchInt(move _5) -> [1: bb1, 0: bb3, otherwise: bb5];
       }
   
       bb1: {
           _4 = discriminant((_1.1: std::option::Option<T>));
-          switchInt(move _4) -> [0: bb2, otherwise: bb3];
+          switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb5];
       }
   
       bb2: {
@@ -46,5 +46,9 @@
           StorageDead(_1);
           return;
       }
+  
+      bb5: {
+          unreachable;
+      }
   }
   
diff --git a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff
similarity index 91%
rename from tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff
rename to tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff
index 5a3544f8538..1b7517c8d01 100644
--- a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff
+++ b/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff
@@ -31,7 +31,7 @@
           _4 = &(_1.1: Test3);
           _5 = discriminant((*_4));
 -         switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb2, otherwise: bb1];
-+         switchInt(move _5) -> [0: bb12, 1: bb12, 2: bb5, 3: bb2, otherwise: bb12];
++         switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb5, 3: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -73,7 +73,7 @@
           StorageLive(_9);
           _10 = discriminant((_1.1: Test3));
 -         switchInt(move _10) -> [0: bb8, 1: bb9, 2: bb10, 3: bb7, otherwise: bb1];
-+         switchInt(move _10) -> [0: bb12, 1: bb12, 2: bb10, 3: bb7, otherwise: bb12];
++         switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb10, 3: bb7, otherwise: bb1];
       }
   
       bb7: {
@@ -110,10 +110,6 @@
           _0 = const ();
           StorageDead(_1);
           return;
-+     }
-+ 
-+     bb12: {
-+         unreachable;
       }
   }
   
diff --git a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..1b7517c8d01
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,115 @@
+- // MIR for `byref` before UninhabitedEnumBranching
++ // MIR for `byref` after UninhabitedEnumBranching
+  
+  fn byref() -> () {
+      let mut _0: ();
+      let _1: Plop;
+      let mut _2: Test3;
+      let _3: &str;
+      let mut _4: &Test3;
+      let mut _5: isize;
+      let _6: &str;
+      let _7: &str;
+      let _8: &str;
+      let _9: &str;
+      let mut _10: isize;
+      let _11: &str;
+      let _12: &str;
+      let _13: &str;
+      scope 1 {
+          debug plop => _1;
+      }
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test3::C;
+          _1 = Plop { xx: const 51_u32, test3: move _2 };
+          StorageDead(_2);
+          StorageLive(_3);
+          StorageLive(_4);
+          _4 = &(_1.1: Test3);
+          _5 = discriminant((*_4));
+-         switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb2, otherwise: bb1];
++         switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb5, 3: bb2, otherwise: bb1];
+      }
+  
+      bb1: {
+          unreachable;
+      }
+  
+      bb2: {
+          StorageLive(_8);
+          _8 = const "D";
+          _3 = &(*_8);
+          StorageDead(_8);
+          goto -> bb6;
+      }
+  
+      bb3: {
+          _3 = const "A(Empty)";
+          goto -> bb6;
+      }
+  
+      bb4: {
+          StorageLive(_6);
+          _6 = const "B(Empty)";
+          _3 = &(*_6);
+          StorageDead(_6);
+          goto -> bb6;
+      }
+  
+      bb5: {
+          StorageLive(_7);
+          _7 = const "C";
+          _3 = &(*_7);
+          StorageDead(_7);
+          goto -> bb6;
+      }
+  
+      bb6: {
+          StorageDead(_4);
+          StorageDead(_3);
+          StorageLive(_9);
+          _10 = discriminant((_1.1: Test3));
+-         switchInt(move _10) -> [0: bb8, 1: bb9, 2: bb10, 3: bb7, otherwise: bb1];
++         switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb10, 3: bb7, otherwise: bb1];
+      }
+  
+      bb7: {
+          StorageLive(_13);
+          _13 = const "D";
+          _9 = &(*_13);
+          StorageDead(_13);
+          goto -> bb11;
+      }
+  
+      bb8: {
+          _9 = const "A(Empty)";
+          goto -> bb11;
+      }
+  
+      bb9: {
+          StorageLive(_11);
+          _11 = const "B(Empty)";
+          _9 = &(*_11);
+          StorageDead(_11);
+          goto -> bb11;
+      }
+  
+      bb10: {
+          StorageLive(_12);
+          _12 = const "C";
+          _9 = &(*_12);
+          StorageDead(_12);
+          goto -> bb11;
+      }
+  
+      bb11: {
+          StorageDead(_9);
+          _0 = const ();
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff
similarity index 82%
rename from tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.diff
rename to tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff
index 121374553ed..f9a43480917 100644
--- a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.diff
+++ b/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff
@@ -13,8 +13,7 @@
           StorageLive(_2);
           _2 = Test2::D;
           _3 = discriminant(_2);
--         switchInt(move _3) -> [4: bb3, 5: bb2, otherwise: bb1];
-+         switchInt(move _3) -> [4: bb3, 5: bb2, otherwise: bb5];
+          switchInt(move _3) -> [4: bb3, 5: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -39,10 +38,6 @@
           StorageDead(_1);
           _0 = const ();
           return;
-+     }
-+ 
-+     bb5: {
-+         unreachable;
       }
   }
   
diff --git a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..f9a43480917
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,43 @@
+- // MIR for `custom_discriminant` before UninhabitedEnumBranching
++ // MIR for `custom_discriminant` after UninhabitedEnumBranching
+  
+  fn custom_discriminant() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test2;
+      let mut _3: isize;
+      let _4: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test2::D;
+          _3 = discriminant(_2);
+          switchInt(move _3) -> [4: bb3, 5: bb2, otherwise: bb1];
+      }
+  
+      bb1: {
+          unreachable;
+      }
+  
+      bb2: {
+          StorageLive(_4);
+          _4 = const "E";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb4;
+      }
+  
+      bb3: {
+          _1 = const "D";
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff
new file mode 100644
index 00000000000..383fde4d787
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff
@@ -0,0 +1,53 @@
+- // MIR for `otherwise_t1` before UninhabitedEnumBranching
++ // MIR for `otherwise_t1` after UninhabitedEnumBranching
+  
+  fn otherwise_t1() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test1;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test1::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
++         switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5];
+      }
+  
+      bb1: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb4;
+      }
+  
+      bb2: {
+          _1 = const "A(Empty)";
+          goto -> bb4;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(Empty)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb5: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..383fde4d787
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,53 @@
+- // MIR for `otherwise_t1` before UninhabitedEnumBranching
++ // MIR for `otherwise_t1` after UninhabitedEnumBranching
+  
+  fn otherwise_t1() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test1;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test1::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
++         switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5];
+      }
+  
+      bb1: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb4;
+      }
+  
+      bb2: {
+          _1 = const "A(Empty)";
+          goto -> bb4;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(Empty)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb5: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff
new file mode 100644
index 00000000000..3a2dc19db71
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff
@@ -0,0 +1,44 @@
+- // MIR for `otherwise_t2` before UninhabitedEnumBranching
++ // MIR for `otherwise_t2` after UninhabitedEnumBranching
+  
+  fn otherwise_t2() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test2;
+      let mut _3: isize;
+      let _4: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test2::D;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [4: bb2, otherwise: bb1];
++         switchInt(move _3) -> [4: bb2, 5: bb1, otherwise: bb4];
+      }
+  
+      bb1: {
+          StorageLive(_4);
+          _4 = const "E";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb3;
+      }
+  
+      bb2: {
+          _1 = const "D";
+          goto -> bb3;
+      }
+  
+      bb3: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb4: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..3a2dc19db71
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,44 @@
+- // MIR for `otherwise_t2` before UninhabitedEnumBranching
++ // MIR for `otherwise_t2` after UninhabitedEnumBranching
+  
+  fn otherwise_t2() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test2;
+      let mut _3: isize;
+      let _4: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test2::D;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [4: bb2, otherwise: bb1];
++         switchInt(move _3) -> [4: bb2, 5: bb1, otherwise: bb4];
+      }
+  
+      bb1: {
+          StorageLive(_4);
+          _4 = const "E";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb3;
+      }
+  
+      bb2: {
+          _1 = const "D";
+          goto -> bb3;
+      }
+  
+      bb3: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb4: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff
new file mode 100644
index 00000000000..5dc1e2b73f6
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff
@@ -0,0 +1,53 @@
+- // MIR for `otherwise_t3` before UninhabitedEnumBranching
++ // MIR for `otherwise_t3` after UninhabitedEnumBranching
+  
+  fn otherwise_t3() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test3;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test3::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
++         switchInt(move _3) -> [0: bb5, 1: bb5, otherwise: bb1];
+      }
+  
+      bb1: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb4;
+      }
+  
+      bb2: {
+          _1 = const "A(Empty)";
+          goto -> bb4;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(Empty)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb5: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..5dc1e2b73f6
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,53 @@
+- // MIR for `otherwise_t3` before UninhabitedEnumBranching
++ // MIR for `otherwise_t3` after UninhabitedEnumBranching
+  
+  fn otherwise_t3() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test3;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test3::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
++         switchInt(move _3) -> [0: bb5, 1: bb5, otherwise: bb1];
+      }
+  
+      bb1: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb4;
+      }
+  
+      bb2: {
+          _1 = const "A(Empty)";
+          goto -> bb4;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(Empty)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb5: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff
new file mode 100644
index 00000000000..1352dda4971
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff
@@ -0,0 +1,48 @@
+- // MIR for `otherwise_t4` before UninhabitedEnumBranching
++ // MIR for `otherwise_t4` after UninhabitedEnumBranching
+  
+  fn otherwise_t4() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test4;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test4::C;
+          _3 = discriminant(_2);
+          switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
+      }
+  
+      bb1: {
+          StorageLive(_5);
+          _5 = const "CD";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb4;
+      }
+  
+      bb2: {
+          _1 = const "A(i32)";
+          goto -> bb4;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(i32)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..1352dda4971
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,48 @@
+- // MIR for `otherwise_t4` before UninhabitedEnumBranching
++ // MIR for `otherwise_t4` after UninhabitedEnumBranching
+  
+  fn otherwise_t4() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test4;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test4::C;
+          _3 = discriminant(_2);
+          switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
+      }
+  
+      bb1: {
+          StorageLive(_5);
+          _5 = const "CD";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb4;
+      }
+  
+      bb2: {
+          _1 = const "A(i32)";
+          goto -> bb4;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(i32)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff
new file mode 100644
index 00000000000..40dd961fbac
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff
@@ -0,0 +1,62 @@
+- // MIR for `otherwise_t4_uninhabited_default` before UninhabitedEnumBranching
++ // MIR for `otherwise_t4_uninhabited_default` after UninhabitedEnumBranching
+  
+  fn otherwise_t4_uninhabited_default() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test4;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+      let _6: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test4::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1];
++         switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: bb6];
+      }
+  
+      bb1: {
+          StorageLive(_6);
+          _6 = const "D";
+          _1 = &(*_6);
+          StorageDead(_6);
+          goto -> bb5;
+      }
+  
+      bb2: {
+          _1 = const "A(i32)";
+          goto -> bb5;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(i32)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb5;
+      }
+  
+      bb4: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb5;
+      }
+  
+      bb5: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb6: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..40dd961fbac
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,62 @@
+- // MIR for `otherwise_t4_uninhabited_default` before UninhabitedEnumBranching
++ // MIR for `otherwise_t4_uninhabited_default` after UninhabitedEnumBranching
+  
+  fn otherwise_t4_uninhabited_default() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test4;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+      let _6: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test4::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1];
++         switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: bb6];
+      }
+  
+      bb1: {
+          StorageLive(_6);
+          _6 = const "D";
+          _1 = &(*_6);
+          StorageDead(_6);
+          goto -> bb5;
+      }
+  
+      bb2: {
+          _1 = const "A(i32)";
+          goto -> bb5;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(i32)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb5;
+      }
+  
+      bb4: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb5;
+      }
+  
+      bb5: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb6: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff
new file mode 100644
index 00000000000..ac39f6be6c6
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff
@@ -0,0 +1,75 @@
+- // MIR for `otherwise_t4_uninhabited_default_2` before UninhabitedEnumBranching
++ // MIR for `otherwise_t4_uninhabited_default_2` after UninhabitedEnumBranching
+  
+  fn otherwise_t4_uninhabited_default_2() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test4;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+      let _6: &str;
+      let _7: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test4::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, otherwise: bb1];
++         switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: bb8];
+      }
+  
+      bb1: {
+          StorageLive(_7);
+          _7 = const "A(other)D";
+          _1 = &(*_7);
+          StorageDead(_7);
+          goto -> bb7;
+      }
+  
+      bb2: {
+          switchInt(((_2 as A).0: i32)) -> [1: bb3, 2: bb4, otherwise: bb1];
+      }
+  
+      bb3: {
+          _1 = const "A(1)";
+          goto -> bb7;
+      }
+  
+      bb4: {
+          StorageLive(_4);
+          _4 = const "A(2)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb7;
+      }
+  
+      bb5: {
+          StorageLive(_5);
+          _5 = const "B(i32)";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb7;
+      }
+  
+      bb6: {
+          StorageLive(_6);
+          _6 = const "C";
+          _1 = &(*_6);
+          StorageDead(_6);
+          goto -> bb7;
+      }
+  
+      bb7: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb8: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..ac39f6be6c6
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,75 @@
+- // MIR for `otherwise_t4_uninhabited_default_2` before UninhabitedEnumBranching
++ // MIR for `otherwise_t4_uninhabited_default_2` after UninhabitedEnumBranching
+  
+  fn otherwise_t4_uninhabited_default_2() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test4;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+      let _6: &str;
+      let _7: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test4::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, otherwise: bb1];
++         switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: bb8];
+      }
+  
+      bb1: {
+          StorageLive(_7);
+          _7 = const "A(other)D";
+          _1 = &(*_7);
+          StorageDead(_7);
+          goto -> bb7;
+      }
+  
+      bb2: {
+          switchInt(((_2 as A).0: i32)) -> [1: bb3, 2: bb4, otherwise: bb1];
+      }
+  
+      bb3: {
+          _1 = const "A(1)";
+          goto -> bb7;
+      }
+  
+      bb4: {
+          StorageLive(_4);
+          _4 = const "A(2)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb7;
+      }
+  
+      bb5: {
+          StorageLive(_5);
+          _5 = const "B(i32)";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb7;
+      }
+  
+      bb6: {
+          StorageLive(_6);
+          _6 = const "C";
+          _1 = &(*_6);
+          StorageDead(_6);
+          goto -> bb7;
+      }
+  
+      bb7: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb8: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff
new file mode 100644
index 00000000000..8180428a6f4
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff
@@ -0,0 +1,66 @@
+- // MIR for `otherwise_t5_uninhabited_default` before UninhabitedEnumBranching
++ // MIR for `otherwise_t5_uninhabited_default` after UninhabitedEnumBranching
+  
+  fn otherwise_t5_uninhabited_default() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test5<T>;
+      let mut _3: i8;
+      let _4: &str;
+      let _5: &str;
+      let _6: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test5::<T>::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, otherwise: bb1];
++         switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: bb7];
+      }
+  
+      bb1: {
+          StorageLive(_6);
+          _6 = const "D";
+          _1 = &(*_6);
+          StorageDead(_6);
+          goto -> bb5;
+      }
+  
+      bb2: {
+          _1 = const "A(T)";
+          goto -> bb5;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(T)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb5;
+      }
+  
+      bb4: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb5;
+      }
+  
+      bb5: {
+          drop(_2) -> [return: bb6, unwind unreachable];
+      }
+  
+      bb6: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
++     }
++ 
++     bb7: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..b13d5816aed
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,70 @@
+- // MIR for `otherwise_t5_uninhabited_default` before UninhabitedEnumBranching
++ // MIR for `otherwise_t5_uninhabited_default` after UninhabitedEnumBranching
+  
+  fn otherwise_t5_uninhabited_default() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test5<T>;
+      let mut _3: i8;
+      let _4: &str;
+      let _5: &str;
+      let _6: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test5::<T>::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, otherwise: bb1];
++         switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: bb8];
+      }
+  
+      bb1: {
+          StorageLive(_6);
+          _6 = const "D";
+          _1 = &(*_6);
+          StorageDead(_6);
+          goto -> bb5;
+      }
+  
+      bb2: {
+          _1 = const "A(T)";
+          goto -> bb5;
+      }
+  
+      bb3: {
+          StorageLive(_4);
+          _4 = const "B(T)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb5;
+      }
+  
+      bb4: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb5;
+      }
+  
+      bb5: {
+          drop(_2) -> [return: bb6, unwind: bb7];
+      }
+  
+      bb6: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
+      }
+  
+      bb7 (cleanup): {
+          resume;
++     }
++ 
++     bb8: {
++         unreachable;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_enum_branching.rs b/tests/mir-opt/uninhabited_enum_branching.rs
index 08eca57afc6..6de001be979 100644
--- a/tests/mir-opt/uninhabited_enum_branching.rs
+++ b/tests/mir-opt/uninhabited_enum_branching.rs
@@ -1,4 +1,6 @@
 //@ unit-test: UninhabitedEnumBranching
+// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+
 enum Empty {}
 
 // test matching an enum with uninhabited variants
@@ -23,6 +25,21 @@ enum Test3 {
     D,
 }
 
+enum Test4 {
+    A(i32),
+    B(i32),
+    C,
+    D,
+}
+
+#[repr(i8)]
+enum Test5<T> {
+    A(T) = -1,
+    B(T) = 0,
+    C = 5,
+    D = 3,
+}
+
 struct Plop {
     xx: u32,
     test3: Test3,
@@ -46,8 +63,8 @@ fn simple() {
 fn custom_discriminant() {
     // CHECK-LABEL: fn custom_discriminant(
     // CHECK: [[discr:_.*]] = discriminant(
-    // CHECK: switchInt(move [[discr]]) -> [4: bb3, 5: bb2, otherwise: bb5];
-    // CHECK: bb5: {
+    // CHECK: switchInt(move [[discr]]) -> [4: bb3, 5: bb2, otherwise: [[unreachable:bb.*]]];
+    // CHECK: [[unreachable]]: {
     // CHECK-NEXT: unreachable;
     match Test2::D {
         Test2::D => "D",
@@ -55,6 +72,111 @@ fn custom_discriminant() {
     };
 }
 
+// EMIT_MIR uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.diff
+fn otherwise_t1() {
+    // CHECK-LABEL: fn otherwise_t1(
+    // CHECK: [[discr:_.*]] = discriminant(
+    // CHECK: switchInt(move [[discr]]) -> [0: bb5, 1: bb5, 2: bb1, otherwise: [[unreachable:bb.*]]];
+    // CHECK: [[unreachable]]: {
+    // CHECK-NEXT: unreachable;
+    match Test1::C {
+        Test1::A(_) => "A(Empty)",
+        Test1::B(_) => "B(Empty)",
+        _ => "C",
+    };
+}
+
+// EMIT_MIR uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.diff
+fn otherwise_t2() {
+    // CHECK-LABEL: fn otherwise_t2(
+    // CHECK: [[discr:_.*]] = discriminant(
+    // CHECK: switchInt(move [[discr]]) -> [4: bb2, 5: bb1, otherwise: [[unreachable:bb.*]]];
+    // CHECK: [[unreachable]]: {
+    // CHECK-NEXT: unreachable;
+    match Test2::D {
+        Test2::D => "D",
+        _ => "E",
+    };
+}
+
+// EMIT_MIR uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.diff
+fn otherwise_t3() {
+    // CHECK-LABEL: fn otherwise_t3(
+    // CHECK: [[discr:_.*]] = discriminant(
+    // CHECK: switchInt(move [[discr]]) -> [0: bb5, 1: bb5, otherwise: bb1];
+    // CHECK: bb1: {
+    // CHECK-NOT: unreachable;
+    // CHECK: }
+    // CHECK: bb5: {
+    // CHECK-NEXT: unreachable;
+    match Test3::C {
+        Test3::A(_) => "A(Empty)",
+        Test3::B(_) => "B(Empty)",
+        _ => "C",
+    };
+}
+
+// EMIT_MIR uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.diff
+fn otherwise_t4_uninhabited_default() {
+    // CHECK-LABEL: fn otherwise_t4_uninhabited_default(
+    // CHECK: [[discr:_.*]] = discriminant(
+    // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: [[unreachable:bb.*]]];
+    // CHECK: [[unreachable]]: {
+    // CHECK-NEXT: unreachable;
+    match Test4::C {
+        Test4::A(_) => "A(i32)",
+        Test4::B(_) => "B(i32)",
+        Test4::C => "C",
+        _ => "D",
+    };
+}
+
+// EMIT_MIR uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.diff
+fn otherwise_t4_uninhabited_default_2() {
+    // CHECK-LABEL: fn otherwise_t4_uninhabited_default_2(
+    // CHECK: [[discr:_.*]] = discriminant(
+    // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: [[unreachable:bb.*]]];
+    // CHECK: [[unreachable]]: {
+    // CHECK-NEXT: unreachable;
+    match Test4::C {
+        Test4::A(1) => "A(1)",
+        Test4::A(2) => "A(2)",
+        Test4::B(_) => "B(i32)",
+        Test4::C => "C",
+        _ => "A(other)D",
+    };
+}
+
+// EMIT_MIR uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.diff
+fn otherwise_t4() {
+    // CHECK-LABEL: fn otherwise_t4(
+    // CHECK: [[discr:_.*]] = discriminant(
+    // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, otherwise: [[unreachable:bb.*]]];
+    // CHECK: [[unreachable]]: {
+    // CHECK-NOT: unreachable;
+    // CHECK: }
+    match Test4::C {
+        Test4::A(_) => "A(i32)",
+        Test4::B(_) => "B(i32)",
+        _ => "CD",
+    };
+}
+
+// EMIT_MIR uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.diff
+fn otherwise_t5_uninhabited_default<T>() {
+    // CHECK-LABEL: fn otherwise_t5_uninhabited_default(
+    // CHECK: [[discr:_.*]] = discriminant(
+    // CHECK: switchInt(move [[discr]]) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: [[unreachable:bb.*]]];
+    // CHECK: [[unreachable]]: {
+    // CHECK-NEXT: unreachable;
+    match Test5::<T>::C {
+        Test5::A(_) => "A(T)",
+        Test5::B(_) => "B(T)",
+        Test5::C => "C",
+        _ => "D",
+    };
+}
+
 // EMIT_MIR uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff
 fn byref() {
     // CHECK-LABEL: fn byref(
@@ -69,6 +191,9 @@ fn byref() {
         Test3::D => "D",
     };
 
+    // CHECK: [[unreachable]]: {
+    // CHECK-NEXT: unreachable;
+
     // CHECK: [[discr:_.*]] = discriminant(
     // CHECK: switchInt(move [[discr]]) -> [0: [[unreachable]], 1: [[unreachable]], 2: bb10, 3: bb7, otherwise: [[unreachable]]];
     match plop.test3 {
@@ -77,13 +202,17 @@ fn byref() {
         Test3::C => "C",
         Test3::D => "D",
     };
-
-    // CHECK: [[unreachable]]: {
-    // CHECK-NEXT: unreachable;
 }
 
 fn main() {
     simple();
     custom_discriminant();
+    otherwise_t1();
+    otherwise_t2();
+    otherwise_t3();
+    otherwise_t4_uninhabited_default();
+    otherwise_t4_uninhabited_default_2();
+    otherwise_t4();
+    otherwise_t5_uninhabited_default::<i32>();
     byref();
 }
diff --git a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff
similarity index 89%
rename from tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.diff
rename to tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff
index 6ce61e15287..674d3a25504 100644
--- a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.diff
+++ b/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff
@@ -15,7 +15,7 @@
           _2 = Test1::C;
           _3 = discriminant(_2);
 -         switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb2, otherwise: bb1];
-+         switchInt(move _3) -> [0: bb6, 1: bb6, 2: bb2, otherwise: bb6];
++         switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -48,10 +48,6 @@
           StorageDead(_1);
           _0 = const ();
           return;
-+     }
-+ 
-+     bb6: {
-+         unreachable;
       }
   }
   
diff --git a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff
new file mode 100644
index 00000000000..674d3a25504
--- /dev/null
+++ b/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff
@@ -0,0 +1,53 @@
+- // MIR for `simple` before UninhabitedEnumBranching
++ // MIR for `simple` after UninhabitedEnumBranching
+  
+  fn simple() -> () {
+      let mut _0: ();
+      let _1: &str;
+      let mut _2: Test1;
+      let mut _3: isize;
+      let _4: &str;
+      let _5: &str;
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = Test1::C;
+          _3 = discriminant(_2);
+-         switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb2, otherwise: bb1];
++         switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1];
+      }
+  
+      bb1: {
+          unreachable;
+      }
+  
+      bb2: {
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
+          goto -> bb5;
+      }
+  
+      bb3: {
+          _1 = const "A(Empty)";
+          goto -> bb5;
+      }
+  
+      bb4: {
+          StorageLive(_4);
+          _4 = const "B(Empty)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb5;
+      }
+  
+      bb5: {
+          StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff
index 79948139f88..28a8c251d95 100644
--- a/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff
+++ b/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff
@@ -9,7 +9,7 @@
       bb0: {
           _2 = discriminant(_1);
 -         switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1];
-+         switchInt(move _2) -> [0: bb5, 1: bb3, otherwise: bb1];
++         switchInt(move _2) -> [0: bb5, 1: bb3, 2: bb1, otherwise: bb5];
       }
   
       bb1: {
diff --git a/tests/run-make-fulldeps/issue-19371/foo.rs b/tests/run-make-fulldeps/issue-19371/foo.rs
index a0bbe3851e8..327c99a02c6 100644
--- a/tests/run-make-fulldeps/issue-19371/foo.rs
+++ b/tests/run-make-fulldeps/issue-19371/foo.rs
@@ -56,7 +56,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
         file_loader: None,
         locale_resources: &[],
         lint_caps: Default::default(),
-        parse_sess_created: None,
+        psess_created: None,
         hash_untracked_state: None,
         register_lints: None,
         override_queries: None,
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks
index d4a3d447901..1d8fc96ad50 100644
--- a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks
@@ -1,2 +1,7 @@
 CHECK: cmake_plus_one_cxx_global_asm
-CHECK: lfence
+CHECK-NEXT: movl
+CHECK-NEXT: lfence
+CHECK-NEXT: incl
+CHECK-NEXT: shlq    $0x0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.with_frame_pointers.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.with_frame_pointers.checks
new file mode 100644
index 00000000000..485e20e3111
--- /dev/null
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.with_frame_pointers.checks
@@ -0,0 +1,7 @@
+CHECK: print
+CHECK:      lfence
+CHECK:      popq
+CHECK:      popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.checks b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.without_frame_pointers.checks
similarity index 100%
rename from tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.checks
rename to tests/run-make/x86_64-fortanix-unknown-sgx-lvi/print.without_frame_pointers.checks
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh
index 04a34724518..a36ad916beb 100644
--- a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh
@@ -34,8 +34,9 @@ function check {
       ${enclave} > ${asm}
     ${filecheck} --input-file ${asm} ${checks}
 
-    if [ "${func_re}" != "rust_plus_one_global_asm" &&
-         "${func_re}" != "cmake_plus_one_c_global_asm" ]; then
+    if [ "${func_re}" != "rust_plus_one_global_asm" ] &&
+         [ "${func_re}" != "cmake_plus_one_c_global_asm" ] &&
+         [ "${func_re}" != "cmake_plus_one_cxx_global_asm" ]; then
         # The assembler cannot avoid explicit `ret` instructions. Sequences
         # of `shlq $0x0, (%rsp); lfence; retq` are used instead.
         # https://www.intel.com/content/www/us/en/developer/articles/technical/
@@ -48,7 +49,8 @@ build
 
 check "unw_getcontext" unw_getcontext.checks
 check "__libunwind_Registers_x86_64_jumpto" jumpto.checks
-check 'std::io::stdio::_print::[[:alnum:]]+' print.checks
+check 'std::io::stdio::_print::[[:alnum:]]+' print.with_frame_pointers.checks ||
+    check 'std::io::stdio::_print::[[:alnum:]]+' print.without_frame_pointers.checks
 check rust_plus_one_global_asm rust_plus_one_global_asm.checks
 
 check cc_plus_one_c cc_plus_one_c.checks
diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-badutf8-windows.rs b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8-windows.rs
new file mode 100644
index 00000000000..eba17ca6f7e
--- /dev/null
+++ b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8-windows.rs
@@ -0,0 +1,17 @@
+// Check to see if we can get parameters from an @argsfile file
+//
+// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path
+// separators. This test uses backslash as the path separator for the command
+// line arguments and is only run on windows.
+//
+//@ only-windows
+//@ compile-flags: --cfg cmdline_set @{{src-base}}\argfile\commandline-argfile-badutf8.args
+
+#[cfg(not(cmdline_set))]
+compile_error!("cmdline_set not set");
+
+#[cfg(not(unbroken))]
+compile_error!("unbroken not set");
+
+fn main() {
+}
diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-badutf8-windows.stderr b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8-windows.stderr
new file mode 100644
index 00000000000..b4c0d4c20d7
--- /dev/null
+++ b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8-windows.stderr
@@ -0,0 +1,2 @@
+error: failed to load argument file: UTF-8 error in $DIR/commandline-argfile-badutf8.args
+
diff --git a/tests/rustdoc-ui/commandline-argfile-badutf8.args b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8.args
similarity index 100%
rename from tests/rustdoc-ui/commandline-argfile-badutf8.args
rename to tests/rustdoc-ui/argfile/commandline-argfile-badutf8.args
diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-badutf8.rs b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8.rs
new file mode 100644
index 00000000000..1b2e52af762
--- /dev/null
+++ b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8.rs
@@ -0,0 +1,18 @@
+// Check to see if we can get parameters from an @argsfile file
+//
+// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path
+// separators. We have a duplicated version of this test that uses backslash as
+// the path separator for the command line arguments that is only run on
+// windows.
+//
+//@ ignore-windows
+//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile-badutf8.args
+
+#[cfg(not(cmdline_set))]
+compile_error!("cmdline_set not set");
+
+#[cfg(not(unbroken))]
+compile_error!("unbroken not set");
+
+fn main() {
+}
diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-badutf8.stderr b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8.stderr
new file mode 100644
index 00000000000..b4c0d4c20d7
--- /dev/null
+++ b/tests/rustdoc-ui/argfile/commandline-argfile-badutf8.stderr
@@ -0,0 +1,2 @@
+error: failed to load argument file: UTF-8 error in $DIR/commandline-argfile-badutf8.args
+
diff --git a/tests/rustdoc-ui/commandline-argfile-missing.rs b/tests/rustdoc-ui/argfile/commandline-argfile-missing-windows.rs
similarity index 55%
rename from tests/rustdoc-ui/commandline-argfile-missing.rs
rename to tests/rustdoc-ui/argfile/commandline-argfile-missing-windows.rs
index bb9644d66ce..24cfd25ccad 100644
--- a/tests/rustdoc-ui/commandline-argfile-missing.rs
+++ b/tests/rustdoc-ui/argfile/commandline-argfile-missing-windows.rs
@@ -1,8 +1,13 @@
 // Check to see if we can get parameters from an @argsfile file
 //
+// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path
+// separators. This test uses backslash as the path separator for the command
+// line arguments and is only run on windows.
+//
+//@ only-windows
 //@ normalize-stderr-test: "os error \d+" -> "os error $$ERR"
 //@ normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING "
-//@ compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args
+//@ compile-flags: --cfg cmdline_set @{{src-base}}\argfile\commandline-argfile-missing.args
 
 #[cfg(not(cmdline_set))]
 compile_error!("cmdline_set not set");
diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-missing-windows.stderr b/tests/rustdoc-ui/argfile/commandline-argfile-missing-windows.stderr
new file mode 100644
index 00000000000..28a20debf1c
--- /dev/null
+++ b/tests/rustdoc-ui/argfile/commandline-argfile-missing-windows.stderr
@@ -0,0 +1,2 @@
+error: failed to load argument file: IO error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR)
+
diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-missing.rs b/tests/rustdoc-ui/argfile/commandline-argfile-missing.rs
new file mode 100644
index 00000000000..fe6a849b0c8
--- /dev/null
+++ b/tests/rustdoc-ui/argfile/commandline-argfile-missing.rs
@@ -0,0 +1,20 @@
+// Check to see if we can get parameters from an @argsfile file
+//
+// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path
+// separators. We have a duplicated version of this test that uses backslash as
+// the path separator for the command line arguments that is only run on
+// windows.
+//
+//@ ignore-windows
+//@ normalize-stderr-test: "os error \d+" -> "os error $$ERR"
+//@ normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING "
+//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile-missing.args
+
+#[cfg(not(cmdline_set))]
+compile_error!("cmdline_set not set");
+
+#[cfg(not(unbroken))]
+compile_error!("unbroken not set");
+
+fn main() {
+}
diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-missing.stderr b/tests/rustdoc-ui/argfile/commandline-argfile-missing.stderr
new file mode 100644
index 00000000000..28a20debf1c
--- /dev/null
+++ b/tests/rustdoc-ui/argfile/commandline-argfile-missing.stderr
@@ -0,0 +1,2 @@
+error: failed to load argument file: IO error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR)
+
diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-multiple-windows.rs b/tests/rustdoc-ui/argfile/commandline-argfile-multiple-windows.rs
new file mode 100644
index 00000000000..84c050d84e2
--- /dev/null
+++ b/tests/rustdoc-ui/argfile/commandline-argfile-multiple-windows.rs
@@ -0,0 +1,20 @@
+// Check to see if we can get parameters from an @argsfile file
+//
+// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path
+// separators. This test uses backslash as the path separator for the command
+// line arguments and is only run on windows.
+//
+//@ only-windows
+//@ normalize-stderr-test: "os error \d+" -> "os error $$ERR"
+//@ normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING "
+//@ normalize-stderr-test: "commandline-argfile-missing2.args:[^(]*" -> "commandline-argfile-missing2.args: $$FILE_MISSING "
+//@ compile-flags: --cfg cmdline_set @{{src-base}}\argfile\commandline-argfile-missing.args @{{src-base}}\argfile\commandline-argfile-badutf8.args @{{src-base}}\argfile\commandline-argfile-missing2.args
+
+#[cfg(not(cmdline_set))]
+compile_error!("cmdline_set not set");
+
+#[cfg(not(unbroken))]
+compile_error!("unbroken not set");
+
+fn main() {
+}
diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-multiple-windows.stderr b/tests/rustdoc-ui/argfile/commandline-argfile-multiple-windows.stderr
new file mode 100644
index 00000000000..ad3b445c958
--- /dev/null
+++ b/tests/rustdoc-ui/argfile/commandline-argfile-multiple-windows.stderr
@@ -0,0 +1,6 @@
+error: failed to load argument file: IO error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR)
+
+error: failed to load argument file: UTF-8 error in $DIR/commandline-argfile-badutf8.args
+
+error: failed to load argument file: IO error: $DIR/commandline-argfile-missing2.args: $FILE_MISSING (os error $ERR)
+
diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-multiple.rs b/tests/rustdoc-ui/argfile/commandline-argfile-multiple.rs
new file mode 100644
index 00000000000..f658ee34fbb
--- /dev/null
+++ b/tests/rustdoc-ui/argfile/commandline-argfile-multiple.rs
@@ -0,0 +1,21 @@
+// Check to see if we can get parameters from an @argsfile file
+//
+// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path
+// separators. We have a duplicated version of this test that uses backslash as
+// the path separator for the command line arguments that is only run on
+// windows.
+//
+//@ ignore-windows
+//@ normalize-stderr-test: "os error \d+" -> "os error $$ERR"
+//@ normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING "
+//@ normalize-stderr-test: "commandline-argfile-missing2.args:[^(]*" -> "commandline-argfile-missing2.args: $$FILE_MISSING "
+//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile-missing.args @{{src-base}}/argfile/commandline-argfile-badutf8.args @{{src-base}}/argfile/commandline-argfile-missing2.args
+
+#[cfg(not(cmdline_set))]
+compile_error!("cmdline_set not set");
+
+#[cfg(not(unbroken))]
+compile_error!("unbroken not set");
+
+fn main() {
+}
diff --git a/tests/rustdoc-ui/argfile/commandline-argfile-multiple.stderr b/tests/rustdoc-ui/argfile/commandline-argfile-multiple.stderr
new file mode 100644
index 00000000000..ad3b445c958
--- /dev/null
+++ b/tests/rustdoc-ui/argfile/commandline-argfile-multiple.stderr
@@ -0,0 +1,6 @@
+error: failed to load argument file: IO error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR)
+
+error: failed to load argument file: UTF-8 error in $DIR/commandline-argfile-badutf8.args
+
+error: failed to load argument file: IO error: $DIR/commandline-argfile-missing2.args: $FILE_MISSING (os error $ERR)
+
diff --git a/tests/rustdoc-ui/commandline-argfile.args b/tests/rustdoc-ui/argfile/commandline-argfile.args
similarity index 100%
rename from tests/rustdoc-ui/commandline-argfile.args
rename to tests/rustdoc-ui/argfile/commandline-argfile.args
diff --git a/tests/rustdoc-ui/commandline-argfile.rs b/tests/rustdoc-ui/argfile/commandline-argfile.rs
similarity index 72%
rename from tests/rustdoc-ui/commandline-argfile.rs
rename to tests/rustdoc-ui/argfile/commandline-argfile.rs
index d71bc72562b..b0b314f53ce 100644
--- a/tests/rustdoc-ui/commandline-argfile.rs
+++ b/tests/rustdoc-ui/argfile/commandline-argfile.rs
@@ -1,7 +1,7 @@
 // Check to see if we can get parameters from an @argsfile file
 //
 //@ check-pass
-//@ compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile.args
+//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile.args
 
 #[cfg(not(cmdline_set))]
 compile_error!("cmdline_set not set");
diff --git a/tests/rustdoc-ui/commandline-argfile-badutf8.rs b/tests/rustdoc-ui/commandline-argfile-badutf8.rs
deleted file mode 100644
index b3a19fa6274..00000000000
--- a/tests/rustdoc-ui/commandline-argfile-badutf8.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Check to see if we can get parameters from an @argsfile file
-//
-//@ compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args
-
-#[cfg(not(cmdline_set))]
-compile_error!("cmdline_set not set");
-
-#[cfg(not(unbroken))]
-compile_error!("unbroken not set");
-
-fn main() {
-}
diff --git a/tests/rustdoc-ui/commandline-argfile-badutf8.stderr b/tests/rustdoc-ui/commandline-argfile-badutf8.stderr
deleted file mode 100644
index 9af6fc0a518..00000000000
--- a/tests/rustdoc-ui/commandline-argfile-badutf8.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-error: Failed to load argument file: Utf8 error in $DIR/commandline-argfile-badutf8.args
-
diff --git a/tests/rustdoc-ui/commandline-argfile-missing.stderr b/tests/rustdoc-ui/commandline-argfile-missing.stderr
deleted file mode 100644
index 179ad831004..00000000000
--- a/tests/rustdoc-ui/commandline-argfile-missing.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-error: Failed to load argument file: IO Error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR)
-
diff --git a/tests/rustdoc-ui/issue-110629-private-type-cycle-dyn.stderr b/tests/rustdoc-ui/issue-110629-private-type-cycle-dyn.stderr
index d056dde00ea..9394b019e11 100644
--- a/tests/rustdoc-ui/issue-110629-private-type-cycle-dyn.stderr
+++ b/tests/rustdoc-ui/issue-110629-private-type-cycle-dyn.stderr
@@ -8,17 +8,11 @@ LL | type Bar<'a, 'b> = Box<dyn PartialEq<Bar<'a, 'b>>>;
    = note: type aliases cannot be recursive
    = help: consider using a struct, enum, or union instead to break the cycle
    = help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
-note: cycle used when collecting item types in top-level module
+note: cycle used when checking that `Bar` is well-formed
   --> $DIR/issue-110629-private-type-cycle-dyn.rs:1:1
    |
-LL | / type Bar<'a, 'b> = Box<dyn PartialEq<Bar<'a, 'b>>>;
-LL | |
-LL | |
-LL | | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
-...  |
-LL | |     assert!(bar(&meh) == bar(&muh));
-LL | | }
-   | |_^
+LL | type Bar<'a, 'b> = Box<dyn PartialEq<Bar<'a, 'b>>>;
+   | ^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error: aborting due to 1 previous error
diff --git a/tests/rustdoc-ui/issues/issue-105742.stderr b/tests/rustdoc-ui/issues/issue-105742.stderr
index d5a9031075f..0f01bc59759 100644
--- a/tests/rustdoc-ui/issues/issue-105742.stderr
+++ b/tests/rustdoc-ui/issues/issue-105742.stderr
@@ -464,38 +464,6 @@ help: add missing generic argument
 LL |     Output = <Self as SVec>::Item> as SVec>::Item<T>,
    |                                                  +++
 
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:61:38
-   |
-LL |     fn len(&self) -> <Self as SVec>::Item;
-   |                                      ^^^^ expected 1 lifetime argument
-   |
-note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-105742.rs:59:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^ --
-help: add missing lifetime argument
-   |
-LL |     fn len(&self) -> <Self as SVec>::Item<'_>;
-   |                                          ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
-  --> $DIR/issue-105742.rs:61:38
-   |
-LL |     fn len(&self) -> <Self as SVec>::Item;
-   |                                      ^^^^ expected 1 generic argument
-   |
-note: associated type defined here, with 1 generic parameter: `T`
-  --> $DIR/issue-105742.rs:59:10
-   |
-LL |     type Item<'a, T>;
-   |          ^^^^     -
-help: add missing generic argument
-   |
-LL |     fn len(&self) -> <Self as SVec>::Item<T>;
-   |                                          +++
-
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:15:21
    |
@@ -632,6 +600,38 @@ help: add missing generic argument
 LL |     Output = <Self as SVec>::Item> as SVec>::Item<T>,
    |                                                  +++
 
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:61:38
+   |
+LL |     fn len(&self) -> <Self as SVec>::Item;
+   |                                      ^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-105742.rs:59:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^ --
+help: add missing lifetime argument
+   |
+LL |     fn len(&self) -> <Self as SVec>::Item<'_>;
+   |                                          ++++
+
+error[E0107]: missing generics for associated type `SVec::Item`
+  --> $DIR/issue-105742.rs:61:38
+   |
+LL |     fn len(&self) -> <Self as SVec>::Item;
+   |                                      ^^^^ expected 1 generic argument
+   |
+note: associated type defined here, with 1 generic parameter: `T`
+  --> $DIR/issue-105742.rs:59:10
+   |
+LL |     type Item<'a, T>;
+   |          ^^^^     -
+help: add missing generic argument
+   |
+LL |     fn len(&self) -> <Self as SVec>::Item<T>;
+   |                                          +++
+
 error: aborting due to 37 previous errors
 
 Some errors have detailed explanations: E0038, E0107.
diff --git a/tests/rustdoc-ui/not-wf-ambiguous-normalization.rs b/tests/rustdoc-ui/not-wf-ambiguous-normalization.rs
index 16e2c7d60b8..9f7d6db5d26 100644
--- a/tests/rustdoc-ui/not-wf-ambiguous-normalization.rs
+++ b/tests/rustdoc-ui/not-wf-ambiguous-normalization.rs
@@ -12,7 +12,7 @@ struct DefaultAllocator;
 // `<DefaultAllocator as Allocator>::Buffer` to be ambiguous,
 // which caused an ICE with `-Znormalize-docs`.
 impl<T> Allocator for DefaultAllocator {
-    //~^ ERROR: type annotations needed
+    //~^ ERROR: the type parameter `T` is not constrained
     type Buffer = ();
 }
 
diff --git a/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr b/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr
index 01034018e22..55ab144b924 100644
--- a/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr
+++ b/tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr
@@ -1,9 +1,9 @@
-error[E0282]: type annotations needed
-  --> $DIR/not-wf-ambiguous-normalization.rs:14:23
+error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/not-wf-ambiguous-normalization.rs:14:6
    |
 LL | impl<T> Allocator for DefaultAllocator {
-   |                       ^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
+   |      ^ unconstrained type parameter
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0282`.
+For more information about this error, try `rustc --explain E0207`.
diff --git a/tests/rustdoc/invalid.crate.name.rs b/tests/rustdoc/invalid$crate$name.rs
similarity index 100%
rename from tests/rustdoc/invalid.crate.name.rs
rename to tests/rustdoc/invalid$crate$name.rs
diff --git a/tests/ui-fulldeps/fluent-messages/test.rs b/tests/ui-fulldeps/fluent-messages/test.rs
index 2316a533469..2cd22b99e83 100644
--- a/tests/ui-fulldeps/fluent-messages/test.rs
+++ b/tests/ui-fulldeps/fluent-messages/test.rs
@@ -5,15 +5,15 @@
 extern crate rustc_errors;
 extern crate rustc_fluent_macro;
 
-/// Copy of the relevant `DiagnosticMessage` variant constructed by `fluent_messages` as it
-/// expects `crate::DiagnosticMessage` to exist.
-pub enum DiagnosticMessage {
+/// Copy of the relevant `DiagMessage` variant constructed by `fluent_messages` as it
+/// expects `crate::DiagMessage` to exist.
+pub enum DiagMessage {
     FluentIdentifier(std::borrow::Cow<'static, str>, Option<std::borrow::Cow<'static, str>>),
 }
 
-/// Copy of the relevant `SubdiagnosticMessage` variant constructed by `fluent_messages` as it
-/// expects `crate::SubdiagnosticMessage` to exist.
-pub enum SubdiagnosticMessage {
+/// Copy of the relevant `SubdiagMessage` variant constructed by `fluent_messages` as it
+/// expects `crate::SubdiagMessage` to exist.
+pub enum SubdiagMessage {
     FluentAttr(std::borrow::Cow<'static, str>),
 }
 
diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs
index 8dcc34d4f60..f73fdc0882f 100644
--- a/tests/ui-fulldeps/internal-lints/diagnostics.rs
+++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs
@@ -1,4 +1,5 @@
 //@ compile-flags: -Z unstable-options
+//@ ignore-stage1
 
 #![crate_type = "lib"]
 #![feature(rustc_attrs)]
@@ -13,8 +14,8 @@ extern crate rustc_session;
 extern crate rustc_span;
 
 use rustc_errors::{
-    AddToDiagnostic, Diag, EmissionGuarantee, DiagCtxt, IntoDiagnostic, Level,
-    SubdiagnosticMessageOp,
+    AddToDiagnostic, DecorateLint, Diag, DiagCtxt, DiagInner, DiagMessage, EmissionGuarantee,
+    IntoDiagnostic, Level, SubdiagMessageOp,
 };
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::Span;
@@ -55,7 +56,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for TranslatableInIntoDiagn
 pub struct UntranslatableInAddToDiagnostic;
 
 impl AddToDiagnostic for UntranslatableInAddToDiagnostic {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
@@ -68,7 +69,7 @@ impl AddToDiagnostic for UntranslatableInAddToDiagnostic {
 pub struct TranslatableInAddToDiagnostic;
 
 impl AddToDiagnostic for TranslatableInAddToDiagnostic {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagnosticMessageOp<G>>(
+    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
@@ -77,6 +78,31 @@ impl AddToDiagnostic for TranslatableInAddToDiagnostic {
     }
 }
 
+pub struct UntranslatableInDecorateLint;
+
+impl<'a> DecorateLint<'a, ()> for UntranslatableInDecorateLint {
+    fn decorate_lint<'b, >(self, diag: &'b mut Diag<'a, ()>) {
+        diag.note("untranslatable diagnostic");
+        //~^ ERROR diagnostics should be created using translatable messages
+    }
+
+    fn msg(&self) -> DiagMessage {
+        unreachable!();
+    }
+}
+
+pub struct TranslatableInDecorateLint;
+
+impl<'a> DecorateLint<'a, ()> for TranslatableInDecorateLint {
+    fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
+        diag.note(crate::fluent_generated::no_crate_note);
+    }
+
+    fn msg(&self) -> DiagMessage {
+        unreachable!();
+    }
+}
+
 pub fn make_diagnostics<'a>(dcx: &'a DiagCtxt) {
     let _diag = dcx.struct_err(crate::fluent_generated::no_crate_example);
     //~^ ERROR diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
@@ -86,9 +112,11 @@ pub fn make_diagnostics<'a>(dcx: &'a DiagCtxt) {
     //~^^ ERROR diagnostics should be created using translatable messages
 }
 
-// Check that `rustc_lint_diagnostics`-annotated functions aren't themselves linted.
+// Check that `rustc_lint_diagnostics`-annotated functions aren't themselves linted for
+// `diagnostic_outside_of_impl`.
 
 #[rustc_lint_diagnostics]
 pub fn skipped_because_of_annotation<'a>(dcx: &'a DiagCtxt) {
+    #[allow(rustc::untranslatable_diagnostic)]
     let _diag = dcx.struct_err("untranslatable diagnostic"); // okay!
 }
diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.stderr b/tests/ui-fulldeps/internal-lints/diagnostics.stderr
index 1b1ad7d5892..b8fbee1ff00 100644
--- a/tests/ui-fulldeps/internal-lints/diagnostics.stderr
+++ b/tests/ui-fulldeps/internal-lints/diagnostics.stderr
@@ -1,44 +1,50 @@
 error: diagnostics should be created using translatable messages
-  --> $DIR/diagnostics.rs:42:9
+  --> $DIR/diagnostics.rs:43:9
    |
 LL |         Diag::new(dcx, level, "untranslatable diagnostic")
    |         ^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/diagnostics.rs:6:9
+  --> $DIR/diagnostics.rs:7:9
    |
 LL | #![deny(rustc::untranslatable_diagnostic)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostics should be created using translatable messages
-  --> $DIR/diagnostics.rs:63:14
+  --> $DIR/diagnostics.rs:64:14
+   |
+LL |         diag.note("untranslatable diagnostic");
+   |              ^^^^
+
+error: diagnostics should be created using translatable messages
+  --> $DIR/diagnostics.rs:85:14
    |
 LL |         diag.note("untranslatable diagnostic");
    |              ^^^^
 
 error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
-  --> $DIR/diagnostics.rs:81:21
+  --> $DIR/diagnostics.rs:107:21
    |
 LL |     let _diag = dcx.struct_err(crate::fluent_generated::no_crate_example);
    |                     ^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/diagnostics.rs:7:9
+  --> $DIR/diagnostics.rs:8:9
    |
 LL | #![deny(rustc::diagnostic_outside_of_impl)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
-  --> $DIR/diagnostics.rs:84:21
+  --> $DIR/diagnostics.rs:110:21
    |
 LL |     let _diag = dcx.struct_err("untranslatable diagnostic");
    |                     ^^^^^^^^^^
 
 error: diagnostics should be created using translatable messages
-  --> $DIR/diagnostics.rs:84:21
+  --> $DIR/diagnostics.rs:110:21
    |
 LL |     let _diag = dcx.struct_err("untranslatable diagnostic");
    |                     ^^^^^^^^^^
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs
index 8ffc4669ee2..ef70e64ed7e 100644
--- a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs
+++ b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs
@@ -18,7 +18,6 @@ extern crate rustc_driver;
 
 use rustc_parse::new_parser_from_file;
 use rustc_session::parse::ParseSess;
-use rustc_span::source_map::FilePathMapping;
 use std::path::Path;
 
 #[path = "mod_dir_simple/test.rs"]
@@ -31,13 +30,10 @@ pub fn main() {
 }
 
 fn parse() {
-    let parse_session = ParseSess::new(
-        vec![rustc_parse::DEFAULT_LOCALE_RESOURCE],
-        FilePathMapping::empty()
-    );
+    let psess = ParseSess::new(vec![rustc_parse::DEFAULT_LOCALE_RESOURCE]);
 
     let path = Path::new(file!());
     let path = path.canonicalize().unwrap();
-    let mut parser = new_parser_from_file(&parse_session, &path, None);
+    let mut parser = new_parser_from_file(&psess, &path, None);
     let _ = parser.parse_crate_mod();
 }
diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
index e1c326c6a91..475a69f4ad0 100644
--- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -38,16 +38,16 @@ use rustc_ast::*;
 use rustc_ast_pretty::pprust;
 use rustc_parse::new_parser_from_source_str;
 use rustc_session::parse::ParseSess;
-use rustc_span::source_map::{FilePathMapping, Spanned};
+use rustc_span::source_map::Spanned;
 use rustc_span::symbol::Ident;
 use rustc_span::{FileName, DUMMY_SP};
 use thin_vec::{thin_vec, ThinVec};
 
-fn parse_expr(ps: &ParseSess, src: &str) -> Option<P<Expr>> {
+fn parse_expr(psess: &ParseSess, src: &str) -> Option<P<Expr>> {
     let src_as_string = src.to_string();
 
     let mut p =
-        new_parser_from_source_str(ps, FileName::Custom(src_as_string.clone()), src_as_string);
+        new_parser_from_source_str(psess, FileName::Custom(src_as_string.clone()), src_as_string);
     p.parse_expr().map_err(|e| e.cancel()).ok()
 }
 
@@ -225,7 +225,7 @@ fn main() {
 }
 
 fn run() {
-    let ps = ParseSess::new(vec![rustc_parse::DEFAULT_LOCALE_RESOURCE], FilePathMapping::empty());
+    let psess = ParseSess::new(vec![rustc_parse::DEFAULT_LOCALE_RESOURCE]);
 
     iter_exprs(2, &mut |mut e| {
         // If the pretty printer is correct, then `parse(print(e))` should be identical to `e`,
@@ -234,7 +234,7 @@ fn run() {
         println!("printed: {}", printed);
 
         // Ignore expressions with chained comparisons that fail to parse
-        if let Some(mut parsed) = parse_expr(&ps, &printed) {
+        if let Some(mut parsed) = parse_expr(&psess, &printed) {
             // We want to know if `parsed` is structurally identical to `e`, ignoring trivial
             // differences like placement of `Paren`s or the exact ranges of node spans.
             // Unfortunately, there is no easy way to make this comparison. Instead, we add `Paren`s
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs
index 90bea03ffd5..40df9cc5dca 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs
@@ -19,7 +19,7 @@ extern crate rustc_macros;
 extern crate rustc_session;
 extern crate rustc_span;
 
-use rustc_errors::{Applicability, DiagnosticMessage, SubdiagnosticMessage};
+use rustc_errors::{Applicability, DiagMessage, SubdiagMessage};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::Span;
 
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index f2f42f05481..11070972394 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -25,7 +25,7 @@ extern crate rustc_middle;
 use rustc_middle::ty::Ty;
 
 extern crate rustc_errors;
-use rustc_errors::{Applicability, DiagnosticMessage, ErrCode, MultiSpan, SubdiagnosticMessage};
+use rustc_errors::{Applicability, DiagMessage, ErrCode, MultiSpan, SubdiagMessage};
 
 extern crate rustc_session;
 
diff --git a/tests/ui-fulldeps/session-diagnostic/invalid-variable.rs b/tests/ui-fulldeps/session-diagnostic/invalid-variable.rs
index ba529e42e78..cbe9e3f4ef4 100644
--- a/tests/ui-fulldeps/session-diagnostic/invalid-variable.rs
+++ b/tests/ui-fulldeps/session-diagnostic/invalid-variable.rs
@@ -10,7 +10,7 @@ extern crate rustc_fluent_macro;
 extern crate rustc_macros;
 extern crate rustc_errors;
 use rustc_macros::Diagnostic;
-use rustc_errors::{SubdiagnosticMessage, DiagnosticMessage};
+use rustc_errors::{DiagMessage, SubdiagMessage};
 extern crate rustc_session;
 
 rustc_fluent_macro::fluent_messages! { "./example.ftl" }
diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
index 15e3b212d90..163af7ff0e2 100644
--- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
@@ -17,7 +17,7 @@ extern crate rustc_macros;
 extern crate rustc_session;
 extern crate rustc_span;
 
-use rustc_errors::{Applicability, DiagnosticMessage, SubdiagnosticMessage};
+use rustc_errors::{Applicability, DiagMessage, SubdiagMessage};
 use rustc_macros::Subdiagnostic;
 use rustc_span::Span;
 
diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs
index fcf31aa970c..3ee4542810c 100644
--- a/tests/ui/abi/compatibility.rs
+++ b/tests/ui/abi/compatibility.rs
@@ -39,13 +39,13 @@
 //@ revisions: loongarch64
 //@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
 //@[loongarch64] needs-llvm-components: loongarch
-//@[loongarch64] min-llvm-version: 17
+//@[loongarch64] min-llvm-version: 18
 //@ revisions: wasm
 //@[wasm] compile-flags: --target wasm32-unknown-unknown
 //@[wasm] needs-llvm-components: webassembly
-//@ revisions: wasi
-//@[wasi] compile-flags: --target wasm32-wasi
-//@[wasi] needs-llvm-components: webassembly
+//@ revisions: wasip1
+//@[wasip1] compile-flags: --target wasm32-wasip1
+//@[wasip1] needs-llvm-components: webassembly
 //@ revisions: bpf
 //@[bpf] compile-flags: --target bpfeb-unknown-none
 //@[bpf] needs-llvm-components: bpf
@@ -160,6 +160,7 @@ mod prelude {
         pub _marker: PhantomData<T>,
     }
 
+    #[lang = "global_alloc_ty"]
     pub struct Global;
 
     #[lang = "owned_box"]
diff --git a/tests/ui/abi/extern/extern-call-deep2.rs b/tests/ui/abi/extern/extern-call-deep2.rs
index 80c492e3022..c021bc22348 100644
--- a/tests/ui/abi/extern/extern-call-deep2.rs
+++ b/tests/ui/abi/extern/extern-call-deep2.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_must_use)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 #![feature(rustc_private)]
 
 extern crate libc;
diff --git a/tests/ui/abi/extern/extern-call-scrub.rs b/tests/ui/abi/extern/extern-call-scrub.rs
index 873f5d2e774..7edf8975ad8 100644
--- a/tests/ui/abi/extern/extern-call-scrub.rs
+++ b/tests/ui/abi/extern/extern-call-scrub.rs
@@ -4,7 +4,7 @@
 // make sure the stack pointers are maintained properly in both
 // directions
 
-//@ ignore-emscripten no threads support
+//@ needs-threads
 #![feature(rustc_private)]
 
 extern crate libc;
diff --git a/tests/ui/abi/foreign/foreign-call-no-runtime.rs b/tests/ui/abi/foreign/foreign-call-no-runtime.rs
index 7f847d55721..42d8d7b1d25 100644
--- a/tests/ui/abi/foreign/foreign-call-no-runtime.rs
+++ b/tests/ui/abi/foreign/foreign-call-no-runtime.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 #![feature(rustc_private)]
 
diff --git a/tests/ui/argfile/commandline-argfile-badutf8-windows.rs b/tests/ui/argfile/commandline-argfile-badutf8-windows.rs
new file mode 100644
index 00000000000..eba17ca6f7e
--- /dev/null
+++ b/tests/ui/argfile/commandline-argfile-badutf8-windows.rs
@@ -0,0 +1,17 @@
+// Check to see if we can get parameters from an @argsfile file
+//
+// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path
+// separators. This test uses backslash as the path separator for the command
+// line arguments and is only run on windows.
+//
+//@ only-windows
+//@ compile-flags: --cfg cmdline_set @{{src-base}}\argfile\commandline-argfile-badutf8.args
+
+#[cfg(not(cmdline_set))]
+compile_error!("cmdline_set not set");
+
+#[cfg(not(unbroken))]
+compile_error!("unbroken not set");
+
+fn main() {
+}
diff --git a/tests/ui/argfile/commandline-argfile-badutf8-windows.stderr b/tests/ui/argfile/commandline-argfile-badutf8-windows.stderr
new file mode 100644
index 00000000000..b4c0d4c20d7
--- /dev/null
+++ b/tests/ui/argfile/commandline-argfile-badutf8-windows.stderr
@@ -0,0 +1,2 @@
+error: failed to load argument file: UTF-8 error in $DIR/commandline-argfile-badutf8.args
+
diff --git a/tests/ui/commandline-argfile-badutf8.args b/tests/ui/argfile/commandline-argfile-badutf8.args
similarity index 100%
rename from tests/ui/commandline-argfile-badutf8.args
rename to tests/ui/argfile/commandline-argfile-badutf8.args
diff --git a/tests/ui/argfile/commandline-argfile-badutf8.rs b/tests/ui/argfile/commandline-argfile-badutf8.rs
new file mode 100644
index 00000000000..1b2e52af762
--- /dev/null
+++ b/tests/ui/argfile/commandline-argfile-badutf8.rs
@@ -0,0 +1,18 @@
+// Check to see if we can get parameters from an @argsfile file
+//
+// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path
+// separators. We have a duplicated version of this test that uses backslash as
+// the path separator for the command line arguments that is only run on
+// windows.
+//
+//@ ignore-windows
+//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile-badutf8.args
+
+#[cfg(not(cmdline_set))]
+compile_error!("cmdline_set not set");
+
+#[cfg(not(unbroken))]
+compile_error!("unbroken not set");
+
+fn main() {
+}
diff --git a/tests/ui/argfile/commandline-argfile-badutf8.stderr b/tests/ui/argfile/commandline-argfile-badutf8.stderr
new file mode 100644
index 00000000000..b4c0d4c20d7
--- /dev/null
+++ b/tests/ui/argfile/commandline-argfile-badutf8.stderr
@@ -0,0 +1,2 @@
+error: failed to load argument file: UTF-8 error in $DIR/commandline-argfile-badutf8.args
+
diff --git a/tests/ui/commandline-argfile-missing.rs b/tests/ui/argfile/commandline-argfile-missing-windows.rs
similarity index 55%
rename from tests/ui/commandline-argfile-missing.rs
rename to tests/ui/argfile/commandline-argfile-missing-windows.rs
index bb9644d66ce..24cfd25ccad 100644
--- a/tests/ui/commandline-argfile-missing.rs
+++ b/tests/ui/argfile/commandline-argfile-missing-windows.rs
@@ -1,8 +1,13 @@
 // Check to see if we can get parameters from an @argsfile file
 //
+// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path
+// separators. This test uses backslash as the path separator for the command
+// line arguments and is only run on windows.
+//
+//@ only-windows
 //@ normalize-stderr-test: "os error \d+" -> "os error $$ERR"
 //@ normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING "
-//@ compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args
+//@ compile-flags: --cfg cmdline_set @{{src-base}}\argfile\commandline-argfile-missing.args
 
 #[cfg(not(cmdline_set))]
 compile_error!("cmdline_set not set");
diff --git a/tests/ui/argfile/commandline-argfile-missing-windows.stderr b/tests/ui/argfile/commandline-argfile-missing-windows.stderr
new file mode 100644
index 00000000000..28a20debf1c
--- /dev/null
+++ b/tests/ui/argfile/commandline-argfile-missing-windows.stderr
@@ -0,0 +1,2 @@
+error: failed to load argument file: IO error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR)
+
diff --git a/tests/ui/argfile/commandline-argfile-missing.rs b/tests/ui/argfile/commandline-argfile-missing.rs
new file mode 100644
index 00000000000..fe6a849b0c8
--- /dev/null
+++ b/tests/ui/argfile/commandline-argfile-missing.rs
@@ -0,0 +1,20 @@
+// Check to see if we can get parameters from an @argsfile file
+//
+// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path
+// separators. We have a duplicated version of this test that uses backslash as
+// the path separator for the command line arguments that is only run on
+// windows.
+//
+//@ ignore-windows
+//@ normalize-stderr-test: "os error \d+" -> "os error $$ERR"
+//@ normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING "
+//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile-missing.args
+
+#[cfg(not(cmdline_set))]
+compile_error!("cmdline_set not set");
+
+#[cfg(not(unbroken))]
+compile_error!("unbroken not set");
+
+fn main() {
+}
diff --git a/tests/ui/argfile/commandline-argfile-missing.stderr b/tests/ui/argfile/commandline-argfile-missing.stderr
new file mode 100644
index 00000000000..28a20debf1c
--- /dev/null
+++ b/tests/ui/argfile/commandline-argfile-missing.stderr
@@ -0,0 +1,2 @@
+error: failed to load argument file: IO error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR)
+
diff --git a/tests/ui/argfile/commandline-argfile-multiple-windows.rs b/tests/ui/argfile/commandline-argfile-multiple-windows.rs
new file mode 100644
index 00000000000..84c050d84e2
--- /dev/null
+++ b/tests/ui/argfile/commandline-argfile-multiple-windows.rs
@@ -0,0 +1,20 @@
+// Check to see if we can get parameters from an @argsfile file
+//
+// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path
+// separators. This test uses backslash as the path separator for the command
+// line arguments and is only run on windows.
+//
+//@ only-windows
+//@ normalize-stderr-test: "os error \d+" -> "os error $$ERR"
+//@ normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING "
+//@ normalize-stderr-test: "commandline-argfile-missing2.args:[^(]*" -> "commandline-argfile-missing2.args: $$FILE_MISSING "
+//@ compile-flags: --cfg cmdline_set @{{src-base}}\argfile\commandline-argfile-missing.args @{{src-base}}\argfile\commandline-argfile-badutf8.args @{{src-base}}\argfile\commandline-argfile-missing2.args
+
+#[cfg(not(cmdline_set))]
+compile_error!("cmdline_set not set");
+
+#[cfg(not(unbroken))]
+compile_error!("unbroken not set");
+
+fn main() {
+}
diff --git a/tests/ui/argfile/commandline-argfile-multiple-windows.stderr b/tests/ui/argfile/commandline-argfile-multiple-windows.stderr
new file mode 100644
index 00000000000..ad3b445c958
--- /dev/null
+++ b/tests/ui/argfile/commandline-argfile-multiple-windows.stderr
@@ -0,0 +1,6 @@
+error: failed to load argument file: IO error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR)
+
+error: failed to load argument file: UTF-8 error in $DIR/commandline-argfile-badutf8.args
+
+error: failed to load argument file: IO error: $DIR/commandline-argfile-missing2.args: $FILE_MISSING (os error $ERR)
+
diff --git a/tests/ui/argfile/commandline-argfile-multiple.rs b/tests/ui/argfile/commandline-argfile-multiple.rs
new file mode 100644
index 00000000000..f658ee34fbb
--- /dev/null
+++ b/tests/ui/argfile/commandline-argfile-multiple.rs
@@ -0,0 +1,21 @@
+// Check to see if we can get parameters from an @argsfile file
+//
+// Path replacement in .stderr files (i.e. `$DIR`) doesn't handle mixed path
+// separators. We have a duplicated version of this test that uses backslash as
+// the path separator for the command line arguments that is only run on
+// windows.
+//
+//@ ignore-windows
+//@ normalize-stderr-test: "os error \d+" -> "os error $$ERR"
+//@ normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING "
+//@ normalize-stderr-test: "commandline-argfile-missing2.args:[^(]*" -> "commandline-argfile-missing2.args: $$FILE_MISSING "
+//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile-missing.args @{{src-base}}/argfile/commandline-argfile-badutf8.args @{{src-base}}/argfile/commandline-argfile-missing2.args
+
+#[cfg(not(cmdline_set))]
+compile_error!("cmdline_set not set");
+
+#[cfg(not(unbroken))]
+compile_error!("unbroken not set");
+
+fn main() {
+}
diff --git a/tests/ui/argfile/commandline-argfile-multiple.stderr b/tests/ui/argfile/commandline-argfile-multiple.stderr
new file mode 100644
index 00000000000..ad3b445c958
--- /dev/null
+++ b/tests/ui/argfile/commandline-argfile-multiple.stderr
@@ -0,0 +1,6 @@
+error: failed to load argument file: IO error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR)
+
+error: failed to load argument file: UTF-8 error in $DIR/commandline-argfile-badutf8.args
+
+error: failed to load argument file: IO error: $DIR/commandline-argfile-missing2.args: $FILE_MISSING (os error $ERR)
+
diff --git a/tests/ui/commandline-argfile.args b/tests/ui/argfile/commandline-argfile.args
similarity index 100%
rename from tests/ui/commandline-argfile.args
rename to tests/ui/argfile/commandline-argfile.args
diff --git a/tests/ui/commandline-argfile.rs b/tests/ui/argfile/commandline-argfile.rs
similarity index 72%
rename from tests/ui/commandline-argfile.rs
rename to tests/ui/argfile/commandline-argfile.rs
index 8577312a3c4..387a8d033b3 100644
--- a/tests/ui/commandline-argfile.rs
+++ b/tests/ui/argfile/commandline-argfile.rs
@@ -1,7 +1,7 @@
 // Check to see if we can get parameters from an @argsfile file
 //
 //@ build-pass
-//@ compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile.args
+//@ compile-flags: --cfg cmdline_set @{{src-base}}/argfile/commandline-argfile.args
 
 #[cfg(not(cmdline_set))]
 compile_error!("cmdline_set not set");
diff --git a/tests/ui/asm/aarch64/parse-error.stderr b/tests/ui/asm/aarch64/parse-error.stderr
index 46984a1fe1c..539c134472f 100644
--- a/tests/ui/asm/aarch64/parse-error.stderr
+++ b/tests/ui/asm/aarch64/parse-error.stderr
@@ -130,17 +130,17 @@ LL |         asm!("{1}", in("x0") foo, const bar);
    |                     |
    |                     explicit register argument
 
-error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""`
+error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""`
   --> $DIR/parse-error.rs:66:29
    |
 LL |         asm!("", options(), "");
-   |                             ^^ expected one of 9 possible tokens
+   |                             ^^ expected one of 10 possible tokens
 
-error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
+error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
   --> $DIR/parse-error.rs:68:33
    |
 LL |         asm!("{}", in(reg) foo, "{}", out(reg) foo);
-   |                                 ^^^^ expected one of 9 possible tokens
+   |                                 ^^^^ expected one of 10 possible tokens
 
 error: asm template must be a string literal
   --> $DIR/parse-error.rs:70:14
diff --git a/tests/ui/asm/parse-error.rs b/tests/ui/asm/parse-error.rs
index 6f32293511b..a0251c6763b 100644
--- a/tests/ui/asm/parse-error.rs
+++ b/tests/ui/asm/parse-error.rs
@@ -142,3 +142,5 @@ global_asm!(format!("{{{}}}", 0), const FOO);
 //~^ ERROR asm template must be a string literal
 global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
 //~^ ERROR asm template must be a string literal
+global_asm!("{}", label {});
+//~^ ERROR expected operand, options, or additional template string
diff --git a/tests/ui/asm/parse-error.stderr b/tests/ui/asm/parse-error.stderr
index 075d28e176a..80ee5191dbb 100644
--- a/tests/ui/asm/parse-error.stderr
+++ b/tests/ui/asm/parse-error.stderr
@@ -176,17 +176,17 @@ LL |         asm!("{a}", a = const foo, a = const bar);
    |
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
 
-error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""`
+error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""`
   --> $DIR/parse-error.rs:82:29
    |
 LL |         asm!("", options(), "");
-   |                             ^^ expected one of 9 possible tokens
+   |                             ^^ expected one of 10 possible tokens
 
-error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
+error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
   --> $DIR/parse-error.rs:84:33
    |
 LL |         asm!("{}", in(reg) foo, "{}", out(reg) foo);
-   |                                 ^^^^ expected one of 9 possible tokens
+   |                                 ^^^^ expected one of 10 possible tokens
 
 error: asm template must be a string literal
   --> $DIR/parse-error.rs:86:14
@@ -362,6 +362,12 @@ LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
    |
    = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
 
+error: expected operand, options, or additional template string
+  --> $DIR/parse-error.rs:145:19
+   |
+LL | global_asm!("{}", label {});
+   |                   ^^^^^^^^ expected operand, options, or additional template string
+
 error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/parse-error.rs:39:37
    |
@@ -407,6 +413,6 @@ LL |     let mut bar = 0;
 LL |         asm!("{a}", a = const foo, a = const bar);
    |                                              ^^^ non-constant value
 
-error: aborting due to 63 previous errors
+error: aborting due to 64 previous errors
 
 For more information about this error, try `rustc --explain E0435`.
diff --git a/tests/ui/asm/x86_64/bad-options.rs b/tests/ui/asm/x86_64/bad-options.rs
index a6d5022ecf1..f9cc13cfc5a 100644
--- a/tests/ui/asm/x86_64/bad-options.rs
+++ b/tests/ui/asm/x86_64/bad-options.rs
@@ -1,5 +1,7 @@
 //@ only-x86_64
 
+#![feature(asm_unwind, asm_goto)]
+
 use std::arch::{asm, global_asm};
 
 fn main() {
@@ -14,6 +16,8 @@ fn main() {
         //~^ ERROR asm with the `pure` option must have at least one output
         asm!("{}", out(reg) foo, options(noreturn));
         //~^ ERROR asm outputs are not allowed with the `noreturn` option
+        asm!("{}", label {}, options(may_unwind));
+        //~^ ERROR asm labels are not allowed with the `may_unwind` option
     }
 
     unsafe {
diff --git a/tests/ui/asm/x86_64/bad-options.stderr b/tests/ui/asm/x86_64/bad-options.stderr
index e2351840eef..aa167e7913c 100644
--- a/tests/ui/asm/x86_64/bad-options.stderr
+++ b/tests/ui/asm/x86_64/bad-options.stderr
@@ -1,35 +1,41 @@
 error: the `nomem` and `readonly` options are mutually exclusive
-  --> $DIR/bad-options.rs:8:18
+  --> $DIR/bad-options.rs:10:18
    |
 LL |         asm!("", options(nomem, readonly));
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `pure` and `noreturn` options are mutually exclusive
-  --> $DIR/bad-options.rs:10:18
+  --> $DIR/bad-options.rs:12:18
    |
 LL |         asm!("", options(pure, nomem, noreturn));
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: asm with the `pure` option must have at least one output
-  --> $DIR/bad-options.rs:10:18
+  --> $DIR/bad-options.rs:12:18
    |
 LL |         asm!("", options(pure, nomem, noreturn));
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: asm with the `pure` option must have at least one output
-  --> $DIR/bad-options.rs:13:33
+  --> $DIR/bad-options.rs:15:33
    |
 LL |         asm!("{}", in(reg) foo, options(pure, nomem));
    |                                 ^^^^^^^^^^^^^^^^^^^^
 
 error: asm outputs are not allowed with the `noreturn` option
-  --> $DIR/bad-options.rs:15:20
+  --> $DIR/bad-options.rs:17:20
    |
 LL |         asm!("{}", out(reg) foo, options(noreturn));
    |                    ^^^^^^^^^^^^
 
+error: asm labels are not allowed with the `may_unwind` option
+  --> $DIR/bad-options.rs:19:20
+   |
+LL |         asm!("{}", label {}, options(may_unwind));
+   |                    ^^^^^^^^
+
 error: asm with `clobber_abi` must specify explicit registers for outputs
-  --> $DIR/bad-options.rs:22:20
+  --> $DIR/bad-options.rs:26:20
    |
 LL |         asm!("{}", out(reg) foo, clobber_abi("C"));
    |                    ^^^^^^^^^^^^  ---------------- clobber_abi
@@ -37,7 +43,7 @@ LL |         asm!("{}", out(reg) foo, clobber_abi("C"));
    |                    generic outputs
 
 error: asm with `clobber_abi` must specify explicit registers for outputs
-  --> $DIR/bad-options.rs:24:20
+  --> $DIR/bad-options.rs:28:20
    |
 LL |         asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C"));
    |                    ^^^^^^^^^^^^  ----------------  ---------------- clobber_abi
@@ -46,43 +52,43 @@ LL |         asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C"));
    |                    generic outputs
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
-  --> $DIR/bad-options.rs:31:25
+  --> $DIR/bad-options.rs:35:25
    |
 LL | global_asm!("", options(nomem));
    |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `readonly`
-  --> $DIR/bad-options.rs:33:25
+  --> $DIR/bad-options.rs:37:25
    |
 LL | global_asm!("", options(readonly));
    |                         ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn`
-  --> $DIR/bad-options.rs:35:25
+  --> $DIR/bad-options.rs:39:25
    |
 LL | global_asm!("", options(noreturn));
    |                         ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `pure`
-  --> $DIR/bad-options.rs:37:25
+  --> $DIR/bad-options.rs:41:25
    |
 LL | global_asm!("", options(pure));
    |                         ^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `nostack`
-  --> $DIR/bad-options.rs:39:25
+  --> $DIR/bad-options.rs:43:25
    |
 LL | global_asm!("", options(nostack));
    |                         ^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags`
-  --> $DIR/bad-options.rs:41:25
+  --> $DIR/bad-options.rs:45:25
    |
 LL | global_asm!("", options(preserves_flags));
    |                         ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: invalid ABI for `clobber_abi`
-  --> $DIR/bad-options.rs:20:18
+  --> $DIR/bad-options.rs:24:18
    |
 LL |         asm!("", clobber_abi("foo"));
    |                  ^^^^^^^^^^^^^^^^^^
@@ -90,12 +96,12 @@ LL |         asm!("", clobber_abi("foo"));
    = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
 
 error: `C` ABI specified multiple times
-  --> $DIR/bad-options.rs:24:52
+  --> $DIR/bad-options.rs:28:52
    |
 LL |         asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C"));
    |                                  ----------------  ^^^^^^^^^^^^^^^^
    |                                  |
    |                                  previously specified here
 
-error: aborting due to 15 previous errors
+error: aborting due to 16 previous errors
 
diff --git a/tests/ui/asm/x86_64/goto.mirunsafeck.stderr b/tests/ui/asm/x86_64/goto.mirunsafeck.stderr
new file mode 100644
index 00000000000..fe189c14f0a
--- /dev/null
+++ b/tests/ui/asm/x86_64/goto.mirunsafeck.stderr
@@ -0,0 +1,23 @@
+warning: unreachable statement
+  --> $DIR/goto.rs:99:9
+   |
+LL | /         asm!(
+LL | |             "jmp {}",
+LL | |             label {
+LL | |                 return;
+LL | |             },
+LL | |             options(noreturn)
+LL | |         );
+   | |_________- any code following this expression is unreachable
+LL |           unreachable!();
+   |           ^^^^^^^^^^^^^^ unreachable statement
+   |
+note: the lint level is defined here
+  --> $DIR/goto.rs:89:8
+   |
+LL | #[warn(unreachable_code)]
+   |        ^^^^^^^^^^^^^^^^
+   = note: this warning originates in the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/asm/x86_64/goto.rs b/tests/ui/asm/x86_64/goto.rs
new file mode 100644
index 00000000000..6a567efbb2c
--- /dev/null
+++ b/tests/ui/asm/x86_64/goto.rs
@@ -0,0 +1,111 @@
+//@ only-x86_64
+//@ run-pass
+//@ needs-asm-support
+//@ revisions: mirunsafeck thirunsafeck
+//@ [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![deny(unreachable_code)]
+#![feature(asm_goto)]
+
+use std::arch::asm;
+
+fn goto_fallthough() {
+    unsafe {
+        asm!(
+            "/* {} */",
+            label {
+                unreachable!();
+            }
+        )
+    }
+}
+
+fn goto_jump() {
+    unsafe {
+        let mut value = false;
+        asm!(
+            "jmp {}",
+            label {
+                value = true;
+            }
+        );
+        assert!(value);
+    }
+}
+
+// asm goto with outputs cause miscompilation in LLVM. UB can be triggered
+// when outputs are used inside the label block when optimisation is enabled.
+// See: https://github.com/llvm/llvm-project/issues/74483
+/*
+fn goto_out_fallthrough() {
+    unsafe {
+        let mut out: usize;
+        asm!(
+            "lea {}, [{} + 1]",
+            "/* {} */",
+            out(reg) out,
+            in(reg) 0x12345678usize,
+            label {
+                unreachable!();
+            }
+        );
+        assert_eq!(out, 0x12345679);
+    }
+}
+
+fn goto_out_jump() {
+    unsafe {
+        let mut value = false;
+        let mut out: usize;
+        asm!(
+            "lea {}, [{} + 1]",
+            "jmp {}",
+            out(reg) out,
+            in(reg) 0x12345678usize,
+            label {
+                value = true;
+                assert_eq!(out, 0x12345679);
+            }
+        );
+        assert!(value);
+    }
+}
+*/
+
+fn goto_noreturn() {
+    unsafe {
+        let a;
+        asm!(
+            "jmp {}",
+            label {
+                a = 1;
+            },
+            options(noreturn)
+        );
+        assert_eq!(a, 1);
+    }
+}
+
+#[warn(unreachable_code)]
+fn goto_noreturn_diverge() {
+    unsafe {
+        asm!(
+            "jmp {}",
+            label {
+                return;
+            },
+            options(noreturn)
+        );
+        unreachable!();
+        //~^ WARN unreachable statement
+    }
+}
+
+fn main() {
+    goto_fallthough();
+    goto_jump();
+    // goto_out_fallthrough();
+    // goto_out_jump();
+    goto_noreturn();
+    goto_noreturn_diverge();
+}
diff --git a/tests/ui/asm/x86_64/goto.thirunsafeck.stderr b/tests/ui/asm/x86_64/goto.thirunsafeck.stderr
new file mode 100644
index 00000000000..fe189c14f0a
--- /dev/null
+++ b/tests/ui/asm/x86_64/goto.thirunsafeck.stderr
@@ -0,0 +1,23 @@
+warning: unreachable statement
+  --> $DIR/goto.rs:99:9
+   |
+LL | /         asm!(
+LL | |             "jmp {}",
+LL | |             label {
+LL | |                 return;
+LL | |             },
+LL | |             options(noreturn)
+LL | |         );
+   | |_________- any code following this expression is unreachable
+LL |           unreachable!();
+   |           ^^^^^^^^^^^^^^ unreachable statement
+   |
+note: the lint level is defined here
+  --> $DIR/goto.rs:89:8
+   |
+LL | #[warn(unreachable_code)]
+   |        ^^^^^^^^^^^^^^^^
+   = note: this warning originates in the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr
index a2ad4cbde01..a495e94bd9a 100644
--- a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr
+++ b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr
@@ -26,17 +26,11 @@ note: ...which requires computing normalized predicates of `Foo`...
 LL | struct Foo {
    | ^^^^^^^^^^
    = note: ...which again requires computing predicates of `Foo`, completing the cycle
-note: cycle used when collecting item types in top-level module
-  --> $DIR/cycle-iat-inside-of-adt.rs:3:1
+note: cycle used when checking that `Foo` is well-formed
+  --> $DIR/cycle-iat-inside-of-adt.rs:7:1
    |
-LL | / #![feature(inherent_associated_types)]
-LL | | #![allow(incomplete_features)]
-LL | | // FIXME(inherent_associated_types): This should pass.
-LL | |
-...  |
-LL | |
-LL | | fn main() {}
-   | |____________^
+LL | struct Foo {
+   | ^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr
index b3d55fea14b..e7292c08ebd 100644
--- a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr
+++ b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr
@@ -20,19 +20,23 @@ note: ...which requires computing normalized predicates of `user`...
 LL | fn user<T>() where S<T>::P: std::fmt::Debug {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires computing predicates of `user`, completing the cycle
-note: cycle used when collecting item types in top-level module
-  --> $DIR/cycle-iat-inside-of-where-predicate.rs:3:1
+note: cycle used when checking that `user` is well-formed
+  --> $DIR/cycle-iat-inside-of-where-predicate.rs:8:1
    |
-LL | / #![feature(inherent_associated_types)]
-LL | | #![allow(incomplete_features)]
-LL | |
-LL | | // FIXME(inherent_associated_types): This shouldn't lead to a cycle error.
-...  |
-LL | |
-LL | | fn main() {}
-   | |____________^
+LL | fn user<T>() where S<T>::P: std::fmt::Debug {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
-error: aborting due to 1 previous error
+error[E0392]: type parameter `T` is never used
+  --> $DIR/cycle-iat-inside-of-where-predicate.rs:10:10
+   |
+LL | struct S<T>;
+   |          ^ unused type parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
 
-For more information about this error, try `rustc --explain E0391`.
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0391, E0392.
+For more information about an error, try `rustc --explain E0391`.
diff --git a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr
index b8366b15a8a..72d3f5c6d4d 100644
--- a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr
+++ b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr
@@ -20,16 +20,6 @@ help: add missing generic argument
 LL | impl<T> Windows<T> {
    |                +++
 
-error[E0658]: inherent associated types are unstable
-  --> $DIR/issue-109071.rs:8:5
-   |
-LL |     type Item = &[T];
-   |     ^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
-   = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
 error[E0223]: ambiguous associated type
   --> $DIR/issue-109071.rs:15:22
    |
@@ -43,6 +33,16 @@ LL |     fn T() -> Option<<Windows<T> as IntoAsyncIterator>::Item> {}
 LL |     fn T() -> Option<<Windows<T> as IntoIterator>::Item> {}
    |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+error[E0658]: inherent associated types are unstable
+  --> $DIR/issue-109071.rs:8:5
+   |
+LL |     type Item = &[T];
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
+   = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
 error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0107, E0223, E0637, E0658.
diff --git a/tests/ui/associated-type-bounds/duplicate.stderr b/tests/ui/associated-type-bounds/duplicate.stderr
index 9816d11a40a..6345ef4b798 100644
--- a/tests/ui/associated-type-bounds/duplicate.stderr
+++ b/tests/ui/associated-type-bounds/duplicate.stderr
@@ -198,6 +198,17 @@ LL | fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> {
    |                              |
    |                              `Item` bound here first
 
+error[E0282]: type annotations needed
+  --> $DIR/duplicate.rs:136:5
+   |
+LL |     iter::empty()
+   |     ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty`
+   |
+help: consider specifying the generic argument
+   |
+LL |     iter::empty::<T>()
+   |                +++++
+
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
   --> $DIR/duplicate.rs:139:42
    |
@@ -206,6 +217,17 @@ LL | fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> {
    |                              |
    |                              `Item` bound here first
 
+error[E0282]: type annotations needed
+  --> $DIR/duplicate.rs:141:5
+   |
+LL |     iter::empty()
+   |     ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty`
+   |
+help: consider specifying the generic argument
+   |
+LL |     iter::empty::<T>()
+   |                +++++
+
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
   --> $DIR/duplicate.rs:144:45
    |
@@ -214,6 +236,17 @@ LL | fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> {
    |                              |
    |                              `Item` bound here first
 
+error[E0282]: type annotations needed
+  --> $DIR/duplicate.rs:146:5
+   |
+LL |     iter::empty()
+   |     ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty`
+   |
+help: consider specifying the generic argument
+   |
+LL |     iter::empty::<T>()
+   |                +++++
+
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
   --> $DIR/duplicate.rs:149:40
    |
@@ -376,6 +409,16 @@ LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
+  --> $DIR/duplicate.rs:197:34
+   |
+LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
+   |                      ----------  ^^^^^^^^^^ re-bound here
+   |                      |
+   |                      `Item` bound here first
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
   --> $DIR/duplicate.rs:201:34
    |
@@ -394,6 +437,16 @@ LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
+  --> $DIR/duplicate.rs:201:34
+   |
+LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
+   |                      ----------  ^^^^^^^^^^ re-bound here
+   |                      |
+   |                      `Item` bound here first
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
   --> $DIR/duplicate.rs:205:37
    |
@@ -412,6 +465,16 @@ LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
+  --> $DIR/duplicate.rs:205:37
+   |
+LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
+   |                      -------------  ^^^^^^^^^^^^^ re-bound here
+   |                      |
+   |                      `Item` bound here first
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
   --> $DIR/duplicate.rs:211:29
    |
@@ -454,6 +517,16 @@ LL |     Self: Iterator<Item: Copy, Item: Send>,
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
+  --> $DIR/duplicate.rs:229:32
+   |
+LL |     Self: Iterator<Item: Copy, Item: Send>,
+   |                    ----------  ^^^^^^^^^^ re-bound here
+   |                    |
+   |                    `Item` bound here first
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
   --> $DIR/duplicate.rs:237:32
    |
@@ -472,6 +545,16 @@ LL |     Self: Iterator<Item: Copy, Item: Copy>,
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
+  --> $DIR/duplicate.rs:237:32
+   |
+LL |     Self: Iterator<Item: Copy, Item: Copy>,
+   |                    ----------  ^^^^^^^^^^ re-bound here
+   |                    |
+   |                    `Item` bound here first
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
   --> $DIR/duplicate.rs:245:35
    |
@@ -490,6 +573,16 @@ LL |     Self: Iterator<Item: 'static, Item: 'static>,
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
+  --> $DIR/duplicate.rs:245:35
+   |
+LL |     Self: Iterator<Item: 'static, Item: 'static>,
+   |                    -------------  ^^^^^^^^^^^^^ re-bound here
+   |                    |
+   |                    `Item` bound here first
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
   --> $DIR/duplicate.rs:252:34
    |
@@ -514,99 +607,6 @@ LL |     type A: Iterator<Item: 'static, Item: 'static>;
    |                      |
    |                      `Item` bound here first
 
-error[E0282]: type annotations needed
-  --> $DIR/duplicate.rs:136:5
-   |
-LL |     iter::empty()
-   |     ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty`
-   |
-help: consider specifying the generic argument
-   |
-LL |     iter::empty::<T>()
-   |                +++++
-
-error[E0282]: type annotations needed
-  --> $DIR/duplicate.rs:141:5
-   |
-LL |     iter::empty()
-   |     ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty`
-   |
-help: consider specifying the generic argument
-   |
-LL |     iter::empty::<T>()
-   |                +++++
-
-error[E0282]: type annotations needed
-  --> $DIR/duplicate.rs:146:5
-   |
-LL |     iter::empty()
-   |     ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty`
-   |
-help: consider specifying the generic argument
-   |
-LL |     iter::empty::<T>()
-   |                +++++
-
-error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:197:34
-   |
-LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
-   |                      ----------  ^^^^^^^^^^ re-bound here
-   |                      |
-   |                      `Item` bound here first
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:201:34
-   |
-LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
-   |                      ----------  ^^^^^^^^^^ re-bound here
-   |                      |
-   |                      `Item` bound here first
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:205:37
-   |
-LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
-   |                      -------------  ^^^^^^^^^^^^^ re-bound here
-   |                      |
-   |                      `Item` bound here first
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:229:32
-   |
-LL |     Self: Iterator<Item: Copy, Item: Send>,
-   |                    ----------  ^^^^^^^^^^ re-bound here
-   |                    |
-   |                    `Item` bound here first
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:237:32
-   |
-LL |     Self: Iterator<Item: Copy, Item: Copy>,
-   |                    ----------  ^^^^^^^^^^ re-bound here
-   |                    |
-   |                    `Item` bound here first
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:245:35
-   |
-LL |     Self: Iterator<Item: 'static, Item: 'static>,
-   |                    -------------  ^^^^^^^^^^^^^ re-bound here
-   |                    |
-   |                    `Item` bound here first
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
 error: aborting due to 72 previous errors
 
 Some errors have detailed explanations: E0282, E0719.
diff --git a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr
index 2a308f83731..03d72f2ae2c 100644
--- a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr
+++ b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr
@@ -1,11 +1,8 @@
-error[E0191]: the value of the associated types `Item`, `Item`, `IntoIter` and `IntoIter` in `IntoIterator` must be specified
+error[E0191]: the value of the associated types `Item` and `IntoIter` in `IntoIterator` must be specified
   --> $DIR/overlaping-bound-suggestion.rs:7:13
    |
 LL |     inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::Core,
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |             |                  |
-   |             |                  associated types `Item`, `IntoIter` must be specified
-   |             associated types `Item`, `IntoIter` must be specified
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated types: `IntoIterator<Item: IntoIterator<Item: >, Item = Type, IntoIter = Type>`
 
 error[E0223]: ambiguous associated type
   --> $DIR/overlaping-bound-suggestion.rs:7:13
diff --git a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
index d361643f024..c5260adbed4 100644
--- a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
+++ b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
@@ -9,6 +9,23 @@ help: if there were a type named `Example` that implemented `Get`, you could use
 LL | fn get<T:Get,U:Get>(x: T, y: U) -> <Example as Get>::Value {}
    |                                    ~~~~~~~~~~~~~~~~~~~~~~~
 
+error[E0223]: ambiguous associated type
+  --> $DIR/associated-types-in-ambiguous-context.rs:13:23
+   |
+LL |     fn grab(&self) -> Grab::Value;
+   |                       ^^^^^^^^^^^ help: use fully-qualified syntax: `<Self as Grab>::Value`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/associated-types-in-ambiguous-context.rs:16:22
+   |
+LL |     fn get(&self) -> Get::Value;
+   |                      ^^^^^^^^^^
+   |
+help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path
+   |
+LL |     fn get(&self) -> <Example as Get>::Value;
+   |                      ~~~~~~~~~~~~~~~~~~~~~~~
+
 error[E0223]: ambiguous associated type
   --> $DIR/associated-types-in-ambiguous-context.rs:22:17
    |
@@ -33,23 +50,6 @@ LL | type X = <OsString as Deref>::Target;
    |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~
      and N other candidates
 
-error[E0223]: ambiguous associated type
-  --> $DIR/associated-types-in-ambiguous-context.rs:13:23
-   |
-LL |     fn grab(&self) -> Grab::Value;
-   |                       ^^^^^^^^^^^ help: use fully-qualified syntax: `<Self as Grab>::Value`
-
-error[E0223]: ambiguous associated type
-  --> $DIR/associated-types-in-ambiguous-context.rs:16:22
-   |
-LL |     fn get(&self) -> Get::Value;
-   |                      ^^^^^^^^^^
-   |
-help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path
-   |
-LL |     fn get(&self) -> <Example as Get>::Value;
-   |                      ~~~~~~~~~~~~~~~~~~~~~~~
-
 error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0223`.
diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.rs b/tests/ui/associated-types/hr-associated-type-projection-1.rs
index 3df3f68ab1e..d7fc5d122c3 100644
--- a/tests/ui/associated-types/hr-associated-type-projection-1.rs
+++ b/tests/ui/associated-types/hr-associated-type-projection-1.rs
@@ -11,8 +11,8 @@ where
 }
 
 impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
-    //~^ type mismatch resolving `<T as Deref>::Target == T`
     type Item = T;
+    //~^ type mismatch resolving `<T as Deref>::Target == T`
 }
 
 pub fn main() {
diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.stderr b/tests/ui/associated-types/hr-associated-type-projection-1.stderr
index 65221718ee6..b871bb51ae3 100644
--- a/tests/ui/associated-types/hr-associated-type-projection-1.stderr
+++ b/tests/ui/associated-types/hr-associated-type-projection-1.stderr
@@ -1,10 +1,10 @@
 error[E0271]: type mismatch resolving `<T as Deref>::Target == T`
-  --> $DIR/hr-associated-type-projection-1.rs:13:33
+  --> $DIR/hr-associated-type-projection-1.rs:14:17
    |
 LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
-   |      -                          ^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type
-   |      |
-   |      expected this type parameter
+   |      - expected this type parameter
+LL |     type Item = T;
+   |                 ^ expected type parameter `T`, found associated type
    |
    = note: expected type parameter `T`
              found associated type `<T as Deref>::Target`
diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr
index acf6bb2810c..f1c8f83e30c 100644
--- a/tests/ui/associated-types/issue-38821.stderr
+++ b/tests/ui/associated-types/issue-38821.stderr
@@ -1,22 +1,3 @@
-error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied
-  --> $DIR/issue-38821.rs:23:17
-   |
-LL | #[derive(Debug, Copy, Clone)]
-   |                 ^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
-   |
-note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
-  --> $DIR/issue-38821.rs:9:18
-   |
-LL | impl<T: NotNull> IntoNullable for T {
-   |         -------  ^^^^^^^^^^^^     ^
-   |         |
-   |         unsatisfied trait bound introduced here
-   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider further restricting the associated type
-   |
-LL |     Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>, <Col as Expression>::SqlType: NotNull,
-   |                                                                       +++++++++++++++++++++++++++++++++++++++
-
 error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied
   --> $DIR/issue-38821.rs:40:1
    |
@@ -129,6 +110,25 @@ LL | impl<T: NotNull> IntoNullable for T {
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 
+error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied
+  --> $DIR/issue-38821.rs:23:17
+   |
+LL | #[derive(Debug, Copy, Clone)]
+   |                 ^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`, which is required by `<Col as Expression>::SqlType: IntoNullable`
+   |
+note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
+  --> $DIR/issue-38821.rs:9:18
+   |
+LL | impl<T: NotNull> IntoNullable for T {
+   |         -------  ^^^^^^^^^^^^     ^
+   |         |
+   |         unsatisfied trait bound introduced here
+   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider further restricting the associated type
+   |
+LL |     Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>, <Col as Expression>::SqlType: NotNull,
+   |                                                                       +++++++++++++++++++++++++++++++++++++++
+
 error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied
   --> $DIR/issue-38821.rs:23:17
    |
diff --git a/tests/ui/associated-types/substs-ppaux.normal.stderr b/tests/ui/associated-types/substs-ppaux.normal.stderr
index 93118616f02..a2647f66835 100644
--- a/tests/ui/associated-types/substs-ppaux.normal.stderr
+++ b/tests/ui/associated-types/substs-ppaux.normal.stderr
@@ -70,13 +70,12 @@ help: use parentheses to call this function
 LL |     let x: () = foo::<'static>();
    |                               ++
 
-error[E0277]: the size for values of type `str` cannot be known at compilation time
+error[E0277]: the trait bound `str: Foo<'_, '_, u8>` is not satisfied
   --> $DIR/substs-ppaux.rs:49:6
    |
 LL |     <str as Foo<u8>>::bar;
-   |      ^^^ doesn't have a size known at compile-time
+   |      ^^^ the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'_, '_, u8>`
    |
-   = help: the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'_, '_, u8>`
 note: required for `str` to implement `Foo<'_, '_, u8>`
   --> $DIR/substs-ppaux.rs:11:17
    |
diff --git a/tests/ui/associated-types/substs-ppaux.rs b/tests/ui/associated-types/substs-ppaux.rs
index d32cdd24658..077ca764e24 100644
--- a/tests/ui/associated-types/substs-ppaux.rs
+++ b/tests/ui/associated-types/substs-ppaux.rs
@@ -47,6 +47,6 @@ fn foo<'z>() where &'z (): Sized {
     //[normal]~| found fn item `fn() {foo::<'static>}`
 
     <str as Foo<u8>>::bar;
-    //[verbose]~^ ERROR the size for values of type
-    //[normal]~^^ ERROR the size for values of type
+    //[verbose]~^ ERROR the trait bound `str: Foo<'?0, '?1, u8>` is not satisfied
+    //[normal]~^^ ERROR the trait bound `str: Foo<'_, '_, u8>` is not satisfied
 }
diff --git a/tests/ui/associated-types/substs-ppaux.verbose.stderr b/tests/ui/associated-types/substs-ppaux.verbose.stderr
index 13d3156fb80..d32f44ccd64 100644
--- a/tests/ui/associated-types/substs-ppaux.verbose.stderr
+++ b/tests/ui/associated-types/substs-ppaux.verbose.stderr
@@ -70,13 +70,12 @@ help: use parentheses to call this function
 LL |     let x: () = foo::<'static>();
    |                               ++
 
-error[E0277]: the size for values of type `str` cannot be known at compilation time
+error[E0277]: the trait bound `str: Foo<'?0, '?1, u8>` is not satisfied
   --> $DIR/substs-ppaux.rs:49:6
    |
 LL |     <str as Foo<u8>>::bar;
-   |      ^^^ doesn't have a size known at compile-time
+   |      ^^^ the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'?0, '?1, u8>`
    |
-   = help: the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'?0, '?1, u8>`
 note: required for `str` to implement `Foo<'?0, '?1, u8>`
   --> $DIR/substs-ppaux.rs:11:17
    |
diff --git a/tests/ui/async-await/async-closures/signature-deduction.rs b/tests/ui/async-await/async-closures/signature-deduction.rs
new file mode 100644
index 00000000000..031dab10296
--- /dev/null
+++ b/tests/ui/async-await/async-closures/signature-deduction.rs
@@ -0,0 +1,10 @@
+//@ check-pass
+//@ edition: 2021
+
+#![feature(async_closure)]
+
+async fn foo(x: impl async Fn(&str) -> &str) {}
+
+fn main() {
+    foo(async |x| x);
+}
diff --git a/tests/ui/async-await/async-error-span.stderr b/tests/ui/async-await/async-error-span.stderr
index 2ec968ffc03..44f1583f4cc 100644
--- a/tests/ui/async-await/async-error-span.stderr
+++ b/tests/ui/async-await/async-error-span.stderr
@@ -5,7 +5,6 @@ LL | fn get_future() -> impl Future<Output = ()> {
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future
    |
    = help: the trait `Future` is not implemented for `()`
-   = note: () must be a future or must implement `IntoFuture` to be awaited
 
 error[E0282]: type annotations needed
   --> $DIR/async-error-span.rs:13:9
diff --git a/tests/ui/async-await/async-outside-of-await-issue-121096.rs b/tests/ui/async-await/async-outside-of-await-issue-121096.rs
new file mode 100644
index 00000000000..e3999035ef9
--- /dev/null
+++ b/tests/ui/async-await/async-outside-of-await-issue-121096.rs
@@ -0,0 +1,9 @@
+//@ edition:2021
+
+fn main() {
+    async {
+        use std::ops::Add;
+        let _ = 1.add(3);
+    }.await
+    //~^ ERROR `await` is only allowed inside `async` functions and blocks
+}
diff --git a/tests/ui/async-await/async-outside-of-await-issue-121096.stderr b/tests/ui/async-await/async-outside-of-await-issue-121096.stderr
new file mode 100644
index 00000000000..b0677a83864
--- /dev/null
+++ b/tests/ui/async-await/async-outside-of-await-issue-121096.stderr
@@ -0,0 +1,12 @@
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+  --> $DIR/async-outside-of-await-issue-121096.rs:7:7
+   |
+LL | fn main() {
+   |    ---- this is not `async`
+...
+LL |     }.await
+   |       ^^^^^ only allowed inside `async` functions and blocks
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0728`.
diff --git a/tests/ui/async-await/coroutine-not-future.stderr b/tests/ui/async-await/coroutine-not-future.stderr
index 130c5ef526b..580217fb4f8 100644
--- a/tests/ui/async-await/coroutine-not-future.stderr
+++ b/tests/ui/async-await/coroutine-not-future.stderr
@@ -49,7 +49,6 @@ LL |     takes_future(returns_coroutine());
    |     required by a bound introduced by this call
    |
    = help: the trait `Future` is not implemented for `impl Coroutine<Yield = (), Return = ()>`
-   = note: impl Coroutine<Yield = (), Return = ()> must be a future or must implement `IntoFuture` to be awaited
 note: required by a bound in `takes_future`
   --> $DIR/coroutine-not-future.rs:17:26
    |
@@ -69,7 +68,6 @@ LL | |     });
    | |_____^ `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}` is not a future
    |
    = help: the trait `Future` is not implemented for `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}`
-   = note: {coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23} must be a future or must implement `IntoFuture` to be awaited
 note: required by a bound in `takes_future`
   --> $DIR/coroutine-not-future.rs:17:26
    |
diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.rs b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.rs
index 2bbe82270bd..5baa4f10c44 100644
--- a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.rs
+++ b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.rs
@@ -17,5 +17,5 @@ impl Signed for i32 { }
 fn main() {
     is_defaulted::<&'static i32>();
     is_defaulted::<&'static u32>();
-    //~^ ERROR `u32: Signed` is not satisfied
+    //~^ ERROR the trait bound `&'static u32: Defaulted` is not satisfied
 }
diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
index e699422ae2b..47bb1a059be 100644
--- a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
+++ b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
@@ -1,8 +1,8 @@
-error[E0277]: the trait bound `u32: Signed` is not satisfied
+error[E0277]: the trait bound `&'static u32: Defaulted` is not satisfied
   --> $DIR/typeck-default-trait-impl-precedence.rs:19:20
    |
 LL |     is_defaulted::<&'static u32>();
-   |                    ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`, which is required by `&'static u32: Defaulted`
+   |                    ^^^^^^^^^^^^ the trait `Signed` is not implemented for `&'static u32`, which is required by `&'static u32: Defaulted`
    |
 note: required for `&'static u32` to implement `Defaulted`
   --> $DIR/typeck-default-trait-impl-precedence.rs:10:19
diff --git a/tests/ui/box/unit/unique-send-2.rs b/tests/ui/box/unit/unique-send-2.rs
index 20474fee4d8..d3cbeefab37 100644
--- a/tests/ui/box/unit/unique-send-2.rs
+++ b/tests/ui/box/unit/unique-send-2.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_must_use)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::sync::mpsc::{channel, Sender};
 use std::thread;
diff --git a/tests/ui/check-cfg/mix.rs b/tests/ui/check-cfg/mix.rs
index ba30bc1e69b..69156ab6763 100644
--- a/tests/ui/check-cfg/mix.rs
+++ b/tests/ui/check-cfg/mix.rs
@@ -74,6 +74,8 @@ fn test_cfg_macro() {
     //~^ WARNING unexpected `cfg` condition value
     //~| WARNING unexpected `cfg` condition value
     //~| WARNING unexpected `cfg` condition value
+    cfg!(target_feature = "zebra");
+    //~^ WARNING unexpected `cfg` condition value
 }
 
 fn main() {}
diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr
index 77643f227d9..007f9de0331 100644
--- a/tests/ui/check-cfg/mix.stderr
+++ b/tests/ui/check-cfg/mix.stderr
@@ -245,5 +245,14 @@ LL |     cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra"));
    = help: to expect this configuration use `--check-cfg=cfg(feature, values("zebra"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
-warning: 26 warnings emitted
+warning: unexpected `cfg` condition value: `zebra`
+  --> $DIR/mix.rs:77:10
+   |
+LL |     cfg!(target_feature = "zebra");
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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` and 187 more
+   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+
+warning: 27 warnings emitted
 
diff --git a/tests/ui/check-cfg/well-known-values.rs b/tests/ui/check-cfg/well-known-values.rs
index 859a36c604c..fa062a3fe2e 100644
--- a/tests/ui/check-cfg/well-known-values.rs
+++ b/tests/ui/check-cfg/well-known-values.rs
@@ -6,6 +6,7 @@
 //
 //@ check-pass
 //@ compile-flags: --check-cfg=cfg() -Z unstable-options
+//@ compile-flags: -Zcheck-cfg-all-expected
 
 #![feature(cfg_overflow_checks)]
 #![feature(cfg_relocation_model)]
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index 01fc3f83f16..cf18503b74b 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -1,5 +1,5 @@
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:25:5
+  --> $DIR/well-known-values.rs:26:5
    |
 LL |     clippy = "_UNEXPECTED_VALUE",
    |     ^^^^^^----------------------
@@ -11,7 +11,7 @@ LL |     clippy = "_UNEXPECTED_VALUE",
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
-  --> $DIR/well-known-values.rs:27:5
+  --> $DIR/well-known-values.rs:28:5
    |
 LL |     debug_assertions = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^----------------------
@@ -22,7 +22,7 @@ LL |     debug_assertions = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:29:5
+  --> $DIR/well-known-values.rs:30:5
    |
 LL |     doc = "_UNEXPECTED_VALUE",
    |     ^^^----------------------
@@ -33,7 +33,7 @@ LL |     doc = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:31:5
+  --> $DIR/well-known-values.rs:32:5
    |
 LL |     doctest = "_UNEXPECTED_VALUE",
    |     ^^^^^^^----------------------
@@ -44,7 +44,7 @@ LL |     doctest = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:33:5
+  --> $DIR/well-known-values.rs:34:5
    |
 LL |     miri = "_UNEXPECTED_VALUE",
    |     ^^^^----------------------
@@ -55,7 +55,7 @@ LL |     miri = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:35:5
+  --> $DIR/well-known-values.rs:36:5
    |
 LL |     overflow_checks = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^----------------------
@@ -66,7 +66,7 @@ LL |     overflow_checks = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:37:5
+  --> $DIR/well-known-values.rs:38:5
    |
 LL |     panic = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -75,7 +75,7 @@ LL |     panic = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:39:5
+  --> $DIR/well-known-values.rs:40:5
    |
 LL |     proc_macro = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^----------------------
@@ -86,7 +86,7 @@ LL |     proc_macro = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:41:5
+  --> $DIR/well-known-values.rs:42:5
    |
 LL |     relocation_model = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -95,7 +95,7 @@ LL |     relocation_model = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:43:5
+  --> $DIR/well-known-values.rs:44:5
    |
 LL |     sanitize = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -104,7 +104,7 @@ LL |     sanitize = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:45:5
+  --> $DIR/well-known-values.rs:46:5
    |
 LL |     target_abi = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -113,16 +113,16 @@ LL |     target_abi = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:47:5
+  --> $DIR/well-known-values.rs:48:5
    |
 LL |     target_arch = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_arch` are: `aarch64`, `arm`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64`
+   = note: expected values for `target_arch` are: `aarch64`, `arm`, `arm64ec`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64`
    = 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`
-  --> $DIR/well-known-values.rs:49:5
+  --> $DIR/well-known-values.rs:50:5
    |
 LL |     target_endian = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -131,7 +131,7 @@ LL |     target_endian = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:51:5
+  --> $DIR/well-known-values.rs:52:5
    |
 LL |     target_env = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -140,7 +140,7 @@ LL |     target_env = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:53:5
+  --> $DIR/well-known-values.rs:54:5
    |
 LL |     target_family = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -149,16 +149,16 @@ LL |     target_family = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:55:5
+  --> $DIR/well-known-values.rs:56:5
    |
 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`, `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`, `lahfsahf`, `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`, `prfchw`, `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`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `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`, `prfchw`, `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`
-  --> $DIR/well-known-values.rs:57:5
+  --> $DIR/well-known-values.rs:58:5
    |
 LL |     target_has_atomic = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -167,7 +167,7 @@ LL |     target_has_atomic = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:59:5
+  --> $DIR/well-known-values.rs:60:5
    |
 LL |     target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -176,7 +176,7 @@ LL |     target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:61:5
+  --> $DIR/well-known-values.rs:62:5
    |
 LL |     target_has_atomic_load_store = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -185,7 +185,7 @@ LL |     target_has_atomic_load_store = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:63:5
+  --> $DIR/well-known-values.rs:64:5
    |
 LL |     target_os = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -194,7 +194,7 @@ LL |     target_os = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:65:5
+  --> $DIR/well-known-values.rs:66:5
    |
 LL |     target_pointer_width = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -203,7 +203,7 @@ LL |     target_pointer_width = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:67:5
+  --> $DIR/well-known-values.rs:68:5
    |
 LL |     target_thread_local = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^----------------------
@@ -214,7 +214,7 @@ LL |     target_thread_local = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:69:5
+  --> $DIR/well-known-values.rs:70:5
    |
 LL |     target_vendor = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -223,7 +223,7 @@ LL |     target_vendor = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:71:5
+  --> $DIR/well-known-values.rs:72:5
    |
 LL |     test = "_UNEXPECTED_VALUE",
    |     ^^^^----------------------
@@ -234,7 +234,7 @@ LL |     test = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:73:5
+  --> $DIR/well-known-values.rs:74:5
    |
 LL |     unix = "_UNEXPECTED_VALUE",
    |     ^^^^----------------------
@@ -245,7 +245,7 @@ LL |     unix = "_UNEXPECTED_VALUE",
    = 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`
-  --> $DIR/well-known-values.rs:75:5
+  --> $DIR/well-known-values.rs:76:5
    |
 LL |     windows = "_UNEXPECTED_VALUE",
    |     ^^^^^^^----------------------
@@ -256,7 +256,7 @@ LL |     windows = "_UNEXPECTED_VALUE",
    = 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: `linuz`
-  --> $DIR/well-known-values.rs:81:7
+  --> $DIR/well-known-values.rs:82:7
    |
 LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux`
    |       ^^^^^^^^^^^^-------
diff --git a/tests/ui/closures/issue-78720.rs b/tests/ui/closures/issue-78720.rs
index 0e1f78ae3c6..0c4f337ba57 100644
--- a/tests/ui/closures/issue-78720.rs
+++ b/tests/ui/closures/issue-78720.rs
@@ -1,7 +1,7 @@
 fn server() -> impl {
-//~^ ERROR at least one trait must be specified
+    //~^ ERROR at least one trait must be specified
+    //~| ERROR type annotations needed
     ().map2(|| "")
-    //~^ ERROR type annotations needed
 }
 
 trait FilterBase2 {
diff --git a/tests/ui/closures/issue-78720.stderr b/tests/ui/closures/issue-78720.stderr
index d8d3811af5a..2f57c7616f1 100644
--- a/tests/ui/closures/issue-78720.stderr
+++ b/tests/ui/closures/issue-78720.stderr
@@ -23,10 +23,10 @@ LL | struct Map2<Segment2, F> {
    |                     +++
 
 error[E0282]: type annotations needed
-  --> $DIR/issue-78720.rs:3:5
+  --> $DIR/issue-78720.rs:1:16
    |
-LL |     ().map2(|| "")
-   |     ^^^^^^^^^^^^^^ cannot infer type
+LL | fn server() -> impl {
+   |                ^^^^ cannot infer type
 
 error[E0308]: mismatched types
   --> $DIR/issue-78720.rs:8:39
diff --git a/tests/ui/codegen/duplicated-path-in-error.rs b/tests/ui/codegen/duplicated-path-in-error.rs
new file mode 100644
index 00000000000..cff20dd9bd6
--- /dev/null
+++ b/tests/ui/codegen/duplicated-path-in-error.rs
@@ -0,0 +1,7 @@
+//@ only-linux
+//@ compile-flags: -Zcodegen-backend=/non-existing-one.so
+
+// This test ensures that the error of the "not found dylib" doesn't duplicate
+// the path of the dylib.
+
+fn main() {}
diff --git a/tests/ui/codegen/duplicated-path-in-error.stderr b/tests/ui/codegen/duplicated-path-in-error.stderr
new file mode 100644
index 00000000000..d0d34e2f934
--- /dev/null
+++ b/tests/ui/codegen/duplicated-path-in-error.stderr
@@ -0,0 +1,2 @@
+error: couldn't load codegen backend /non-existing-one.so: cannot open shared object file: No such file or directory
+
diff --git a/tests/ui/codegen/init-large-type.rs b/tests/ui/codegen/init-large-type.rs
index 34b40693ab1..b9fc6612e16 100644
--- a/tests/ui/codegen/init-large-type.rs
+++ b/tests/ui/codegen/init-large-type.rs
@@ -7,8 +7,7 @@
 // optimisation.
 
 //@ pretty-expanded FIXME #23616
-//@ ignore-emscripten no threads support
-
+//@ needs-threads
 #![feature(intrinsics)]
 
 use std::{mem, thread};
diff --git a/tests/ui/codegen/issue-28950.rs b/tests/ui/codegen/issue-28950.rs
index 8e55172af6d..0a706c588d5 100644
--- a/tests/ui/codegen/issue-28950.rs
+++ b/tests/ui/codegen/issue-28950.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no threads
+//@ needs-threads
 //@ compile-flags: -O
 
 // Tests that the `vec!` macro does not overflow the stack when it is
diff --git a/tests/ui/coherence/coherence-orphan.stderr b/tests/ui/coherence/coherence-orphan.stderr
index b1bb75bfe51..48843f7cd18 100644
--- a/tests/ui/coherence/coherence-orphan.stderr
+++ b/tests/ui/coherence/coherence-orphan.stderr
@@ -10,17 +10,6 @@ LL | impl TheTrait<usize> for isize {}
    |
    = note: define and implement a trait or new type instead
 
-error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
-  --> $DIR/coherence-orphan.rs:20:1
-   |
-LL | impl !Send for Vec<isize> {}
-   | ^^^^^^^^^^^^^^^----------
-   | |              |
-   | |              `Vec` is not defined in the current crate
-   | impl doesn't use only types from inside the current crate
-   |
-   = note: define and implement a trait or new type instead
-
 error[E0046]: not all trait items implemented, missing: `the_fn`
   --> $DIR/coherence-orphan.rs:10:1
    |
@@ -45,6 +34,17 @@ LL | impl TheTrait<isize> for TheType {}
    |
    = help: implement the missing item: `fn the_fn(&self) { todo!() }`
 
+error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
+  --> $DIR/coherence-orphan.rs:20:1
+   |
+LL | impl !Send for Vec<isize> {}
+   | ^^^^^^^^^^^^^^^----------
+   | |              |
+   | |              `Vec` is not defined in the current crate
+   | impl doesn't use only types from inside the current crate
+   |
+   = note: define and implement a trait or new type instead
+
 error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0046, E0117.
diff --git a/tests/ui/command/need-crate-arg-ignore-tidy.x.rs b/tests/ui/command/need-crate-arg-ignore-tidy$x.rs
similarity index 100%
rename from tests/ui/command/need-crate-arg-ignore-tidy.x.rs
rename to tests/ui/command/need-crate-arg-ignore-tidy$x.rs
diff --git a/tests/ui/command/need-crate-arg-ignore-tidy.x.stderr b/tests/ui/command/need-crate-arg-ignore-tidy$x.stderr
similarity index 68%
rename from tests/ui/command/need-crate-arg-ignore-tidy.x.stderr
rename to tests/ui/command/need-crate-arg-ignore-tidy$x.stderr
index 89f7210c048..28f6d31b1ce 100644
--- a/tests/ui/command/need-crate-arg-ignore-tidy.x.stderr
+++ b/tests/ui/command/need-crate-arg-ignore-tidy$x.stderr
@@ -1,4 +1,4 @@
-error: invalid character `'.'` in crate name: `need_crate_arg_ignore_tidy.x`
+error: invalid character `'$'` in crate name: `need_crate_arg_ignore_tidy$x`
    |
    = help: you can either pass `--crate-name` on the command line or add `#![crate_name="…"]` to set the crate name
 
diff --git a/tests/ui/commandline-argfile-badutf8.rs b/tests/ui/commandline-argfile-badutf8.rs
deleted file mode 100644
index b3a19fa6274..00000000000
--- a/tests/ui/commandline-argfile-badutf8.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Check to see if we can get parameters from an @argsfile file
-//
-//@ compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args
-
-#[cfg(not(cmdline_set))]
-compile_error!("cmdline_set not set");
-
-#[cfg(not(unbroken))]
-compile_error!("unbroken not set");
-
-fn main() {
-}
diff --git a/tests/ui/commandline-argfile-badutf8.stderr b/tests/ui/commandline-argfile-badutf8.stderr
deleted file mode 100644
index 9af6fc0a518..00000000000
--- a/tests/ui/commandline-argfile-badutf8.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-error: Failed to load argument file: Utf8 error in $DIR/commandline-argfile-badutf8.args
-
diff --git a/tests/ui/commandline-argfile-missing.stderr b/tests/ui/commandline-argfile-missing.stderr
deleted file mode 100644
index 179ad831004..00000000000
--- a/tests/ui/commandline-argfile-missing.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-error: Failed to load argument file: IO Error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR)
-
diff --git a/tests/ui/const-generics/generic_arg_infer/in-signature.stderr b/tests/ui/const-generics/generic_arg_infer/in-signature.stderr
index b32018a6a2d..fcac95732d1 100644
--- a/tests/ui/const-generics/generic_arg_infer/in-signature.stderr
+++ b/tests/ui/const-generics/generic_arg_infer/in-signature.stderr
@@ -74,26 +74,6 @@ LL | static TY_STATIC_MIXED: Bar<_, _> = Bar::<i32, 3>(0);
    |                         not allowed in type signatures
    |                         help: replace with the correct type: `Bar<i32, 3>`
 
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
-  --> $DIR/in-signature.rs:35:21
-   |
-LL |     const ARR: [u8; _];
-   |                     ^ not allowed in type signatures
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
-  --> $DIR/in-signature.rs:39:25
-   |
-LL |     const ARR: Bar<i32, _>;
-   |                         ^ not allowed in type signatures
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
-  --> $DIR/in-signature.rs:43:20
-   |
-LL |     const ARR: Bar<_, _>;
-   |                    ^  ^ not allowed in type signatures
-   |                    |
-   |                    not allowed in type signatures
-
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
   --> $DIR/in-signature.rs:51:23
    |
@@ -114,6 +94,26 @@ LL |     type Assoc = Bar<_, _>;
    |                      |
    |                      not allowed in type signatures
 
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
+  --> $DIR/in-signature.rs:35:21
+   |
+LL |     const ARR: [u8; _];
+   |                     ^ not allowed in type signatures
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
+  --> $DIR/in-signature.rs:39:25
+   |
+LL |     const ARR: Bar<i32, _>;
+   |                         ^ not allowed in type signatures
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
+  --> $DIR/in-signature.rs:43:20
+   |
+LL |     const ARR: Bar<_, _>;
+   |                    ^  ^ not allowed in type signatures
+   |                    |
+   |                    not allowed in type signatures
+
 error: aborting due to 15 previous errors
 
 For more information about this error, try `rustc --explain E0121`.
diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.rs
index 6256000b491..9cdb4158d2b 100644
--- a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.rs
+++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.rs
@@ -20,6 +20,7 @@ where
     //~^^^ ERROR: function takes 1 generic argument but 2 generic arguments were supplied
     //~^^^^ ERROR: unconstrained generic constant
     //~^^^^^ ERROR: unconstrained generic constant `{const expr}`
+    //~^^^^^^ ERROR: unconstrained generic constant `{const expr}`
 }
 
 fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.stderr b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.stderr
index 6001d824787..14c58f8d0da 100644
--- a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.stderr
@@ -58,7 +58,15 @@ error: unconstrained generic constant `{const expr}`
 LL |     foo::<_, L>([(); L + 1 + L]);
    |     ^^^^^^^^^^^
 
-error: aborting due to 5 previous errors
+error: unconstrained generic constant `{const expr}`
+  --> $DIR/issue_114151.rs:17:5
+   |
+LL |     foo::<_, L>([(); L + 1 + L]);
+   |     ^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0107, E0308.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/const-generics/issues/issue-68366.full.stderr b/tests/ui/const-generics/issues/issue-68366.full.stderr
index ca9eb801dfc..dc20af77310 100644
--- a/tests/ui/const-generics/issues/issue-68366.full.stderr
+++ b/tests/ui/const-generics/issues/issue-68366.full.stderr
@@ -1,5 +1,14 @@
+error: `Option<usize>` is forbidden as the type of a const generic parameter
+  --> $DIR/issue-68366.rs:9:25
+   |
+LL | struct Collatz<const N: Option<usize>>;
+   |                         ^^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
+
 error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/issue-68366.rs:11:7
+  --> $DIR/issue-68366.rs:12:7
    |
 LL | impl <const N: usize> Collatz<{Some(N)}> {}
    |       ^^^^^^^^^^^^^^ unconstrained const parameter
@@ -8,7 +17,7 @@ LL | impl <const N: usize> Collatz<{Some(N)}> {}
    = note: proving the result of expressions other than the parameter are unique is not supported
 
 error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/issue-68366.rs:17:6
+  --> $DIR/issue-68366.rs:19:6
    |
 LL | impl<const N: usize> Foo {}
    |      ^^^^^^^^^^^^^^ unconstrained const parameter
@@ -16,6 +25,17 @@ LL | impl<const N: usize> Foo {}
    = note: expressions using a const parameter must map each value to a distinct output value
    = note: proving the result of expressions other than the parameter are unique is not supported
 
-error: aborting due to 2 previous errors
+error: overly complex generic constant
+  --> $DIR/issue-68366.rs:12:31
+   |
+LL | impl <const N: usize> Collatz<{Some(N)}> {}
+   |                               ^-------^
+   |                                |
+   |                                struct/enum construction is not supported in generic constants
+   |
+   = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0207`.
diff --git a/tests/ui/const-generics/issues/issue-68366.min.stderr b/tests/ui/const-generics/issues/issue-68366.min.stderr
index ecf24a356de..78e49f46e1a 100644
--- a/tests/ui/const-generics/issues/issue-68366.min.stderr
+++ b/tests/ui/const-generics/issues/issue-68366.min.stderr
@@ -1,5 +1,5 @@
 error: generic parameters may not be used in const operations
-  --> $DIR/issue-68366.rs:11:37
+  --> $DIR/issue-68366.rs:12:37
    |
 LL | impl <const N: usize> Collatz<{Some(N)}> {}
    |                                     ^ cannot perform const operation using `N`
@@ -7,8 +7,17 @@ LL | impl <const N: usize> Collatz<{Some(N)}> {}
    = help: const parameters may only be used as standalone arguments, i.e. `N`
    = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
 
+error: `Option<usize>` is forbidden as the type of a const generic parameter
+  --> $DIR/issue-68366.rs:9:25
+   |
+LL | struct Collatz<const N: Option<usize>>;
+   |                         ^^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
+
 error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/issue-68366.rs:11:7
+  --> $DIR/issue-68366.rs:12:7
    |
 LL | impl <const N: usize> Collatz<{Some(N)}> {}
    |       ^^^^^^^^^^^^^^ unconstrained const parameter
@@ -17,7 +26,7 @@ LL | impl <const N: usize> Collatz<{Some(N)}> {}
    = note: proving the result of expressions other than the parameter are unique is not supported
 
 error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/issue-68366.rs:17:6
+  --> $DIR/issue-68366.rs:19:6
    |
 LL | impl<const N: usize> Foo {}
    |      ^^^^^^^^^^^^^^ unconstrained const parameter
@@ -25,6 +34,6 @@ LL | impl<const N: usize> Foo {}
    = note: expressions using a const parameter must map each value to a distinct output value
    = note: proving the result of expressions other than the parameter are unique is not supported
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0207`.
diff --git a/tests/ui/const-generics/issues/issue-68366.rs b/tests/ui/const-generics/issues/issue-68366.rs
index d3e57a021a6..d9d5e21857b 100644
--- a/tests/ui/const-generics/issues/issue-68366.rs
+++ b/tests/ui/const-generics/issues/issue-68366.rs
@@ -7,10 +7,12 @@
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Collatz<const N: Option<usize>>;
+//~^ ERROR: `Option<usize>` is forbidden
 
 impl <const N: usize> Collatz<{Some(N)}> {}
 //~^ ERROR the const parameter
 //[min]~^^ generic parameters may not be used in const operations
+//[full]~^^^ ERROR overly complex
 
 struct Foo;
 
diff --git a/tests/ui/const-generics/issues/issue-71202.rs b/tests/ui/const-generics/issues/issue-71202.rs
index 57fd72b1284..0f955414d84 100644
--- a/tests/ui/const-generics/issues/issue-71202.rs
+++ b/tests/ui/const-generics/issues/issue-71202.rs
@@ -25,7 +25,7 @@ impl<T: Copy> DataHolder<T> {
         }
 
         <IsCopy<T>>::VALUE
-    } as usize] = [];
+    } as usize] = []; //~ ERROR unconstrained generic constant
 }
 
 fn main() {}
diff --git a/tests/ui/const-generics/issues/issue-71202.stderr b/tests/ui/const-generics/issues/issue-71202.stderr
index 2aa9e344067..437b808c893 100644
--- a/tests/ui/const-generics/issues/issue-71202.stderr
+++ b/tests/ui/const-generics/issues/issue-71202.stderr
@@ -29,5 +29,30 @@ LL | |     } as usize] = [];
                    <IsCopy<T>>::VALUE
                } as usize]:`
 
-error: aborting due to 1 previous error
+error: unconstrained generic constant
+  --> $DIR/issue-71202.rs:28:19
+   |
+LL |     } as usize] = [];
+   |                   ^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); 1 - {
+                   trait NotCopy {
+                       const VALUE: bool = false;
+                   }
+           
+                   impl<__Type: ?Sized> NotCopy for __Type {}
+           
+                   struct IsCopy<__Type: ?Sized>(PhantomData<__Type>);
+           
+                   impl<__Type> IsCopy<__Type>
+                   where
+                       __Type: Sized + Copy,
+                   {
+                       const VALUE: bool = true;
+                   }
+           
+                   <IsCopy<T>>::VALUE
+               } as usize]:`
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/consts/const-eval/infinite_loop.stderr b/tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr
similarity index 91%
rename from tests/ui/consts/const-eval/infinite_loop.stderr
rename to tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr
index 37cd94bf7b7..d664ae88323 100644
--- a/tests/ui/consts/const-eval/infinite_loop.stderr
+++ b/tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr
@@ -1,5 +1,5 @@
 error: constant evaluation is taking a long time
-  --> $DIR/infinite_loop.rs:12:9
+  --> $DIR/infinite_loop.rs:15:9
    |
 LL | /         while n != 0 {
 LL | |
@@ -10,7 +10,7 @@ LL | |         }
    = 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/infinite_loop.rs:10:18
+  --> $DIR/infinite_loop.rs:13:18
    |
 LL |       let s = [(); {
    |  __________________^
diff --git a/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr b/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr
new file mode 100644
index 00000000000..d664ae88323
--- /dev/null
+++ b/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr
@@ -0,0 +1,27 @@
+error: constant evaluation is taking a long time
+  --> $DIR/infinite_loop.rs:15:9
+   |
+LL | /         while n != 0 {
+LL | |
+LL | |             n = if n % 2 == 0 { n / 2 } else { 3 * n + 1 };
+LL | |         }
+   | |_________^
+   |
+   = 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/infinite_loop.rs:13:18
+   |
+LL |       let s = [(); {
+   |  __________________^
+LL | |         let mut n = 113383; // #20 in https://oeis.org/A006884
+LL | |         while n != 0 {
+LL | |
+...  |
+LL | |         n
+LL | |     }];
+   | |_____^
+   = note: `#[deny(long_running_const_eval)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/consts/const-eval/infinite_loop.rs b/tests/ui/consts/const-eval/infinite_loop.rs
index 44456f1ce47..f8cb79b63db 100644
--- a/tests/ui/consts/const-eval/infinite_loop.rs
+++ b/tests/ui/consts/const-eval/infinite_loop.rs
@@ -1,8 +1,11 @@
 //! This test tests two things at once:
 //! 1. we error if a const evaluation hits the deny-by-default lint limit
 //! 2. we do not ICE on invalid follow-up code
+//! 3. no ICE when run with `-Z unstable-options` (issue 122177)
 
-//@ compile-flags: -Z tiny-const-eval-limit
+//@revisions: eval_limit no_ice
+//@[no_ice] compile-flags: -Z tiny-const-eval-limit -Z unstable-options
+//@[eval_limit] compile-flags: -Z tiny-const-eval-limit
 
 fn main() {
     // Tests the Collatz conjecture with an incorrect base case (0 instead of 1).
diff --git a/tests/ui/consts/different-fn-ptr-binders-during-ctfe.rs b/tests/ui/consts/different-fn-ptr-binders-during-ctfe.rs
new file mode 100644
index 00000000000..b378542e573
--- /dev/null
+++ b/tests/ui/consts/different-fn-ptr-binders-during-ctfe.rs
@@ -0,0 +1,6 @@
+const fn cmp(x: fn(&'static ()), y: for<'a> fn(&'a ())) -> bool {
+    x == y
+    //~^ ERROR pointers cannot be reliably compared during const eval
+}
+
+fn main() {}
diff --git a/tests/ui/consts/different-fn-ptr-binders-during-ctfe.stderr b/tests/ui/consts/different-fn-ptr-binders-during-ctfe.stderr
new file mode 100644
index 00000000000..43a7b9ce66c
--- /dev/null
+++ b/tests/ui/consts/different-fn-ptr-binders-during-ctfe.stderr
@@ -0,0 +1,10 @@
+error: pointers cannot be reliably compared during const eval
+  --> $DIR/different-fn-ptr-binders-during-ctfe.rs:2:5
+   |
+LL |     x == y
+   |     ^^^^^^
+   |
+   = note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/consts/issue-103790.stderr b/tests/ui/consts/issue-103790.stderr
index 55bc9675401..abe7366483b 100644
--- a/tests/ui/consts/issue-103790.stderr
+++ b/tests/ui/consts/issue-103790.stderr
@@ -48,17 +48,11 @@ note: ...which requires computing type of `S::S`...
 LL | struct S<const S: (), const S: S = { S }>;
    |                                ^
    = note: ...which again requires computing type of `S`, completing the cycle
-note: cycle used when collecting item types in top-level module
-  --> $DIR/issue-103790.rs:1:1
+note: cycle used when checking that `S` is well-formed
+  --> $DIR/issue-103790.rs:4:1
    |
-LL | / #![feature(generic_const_exprs)]
-LL | | #![allow(incomplete_features)]
-LL | |
-LL | | struct S<const S: (), const S: S = { S }>;
-...  |
-LL | |
-LL | | fn main() {}
-   | |____________^
+LL | struct S<const S: (), const S: S = { S }>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error: `()` is forbidden as the type of a const generic parameter
diff --git a/tests/ui/consts/issue-36163.stderr b/tests/ui/consts/issue-36163.stderr
index de70a457f16..8a7a0981f41 100644
--- a/tests/ui/consts/issue-36163.stderr
+++ b/tests/ui/consts/issue-36163.stderr
@@ -20,17 +20,11 @@ note: ...which requires const-evaluating + checking `A`...
 LL | const A: isize = Foo::B as isize;
    |                  ^^^^^^^^^^^^^^^
    = note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle
-note: cycle used when collecting item types in top-level module
-  --> $DIR/issue-36163.rs:1:1
+note: cycle used when checking that `Foo` is well-formed
+  --> $DIR/issue-36163.rs:3:1
    |
-LL | / const A: isize = Foo::B as isize;
-LL | |
-LL | | enum Foo {
-LL | |     B = A,
-LL | | }
-LL | |
-LL | | fn main() {}
-   | |____________^
+LL | enum Foo {
+   | ^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/coroutine/gen_block_is_no_future.stderr b/tests/ui/coroutine/gen_block_is_no_future.stderr
index f9e23e45b44..fb2f2ba5597 100644
--- a/tests/ui/coroutine/gen_block_is_no_future.stderr
+++ b/tests/ui/coroutine/gen_block_is_no_future.stderr
@@ -5,7 +5,6 @@ LL | fn foo() -> impl std::future::Future {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^ `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21}` is not a future
    |
    = help: the trait `Future` is not implemented for `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21}`
-   = note: {gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21} must be a future or must implement `IntoFuture` to be awaited
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coroutine/smoke.rs b/tests/ui/coroutine/smoke.rs
index 0ed56982c9b..17d98a52a1c 100644
--- a/tests/ui/coroutine/smoke.rs
+++ b/tests/ui/coroutine/smoke.rs
@@ -3,7 +3,7 @@
 //@ revisions: default nomiropt
 //@[nomiropt]compile-flags: -Z mir-opt-level=0
 
-//@ ignore-emscripten no threads support
+//@ needs-threads
 //@ compile-flags: --test
 
 #![feature(coroutines, coroutine_trait)]
diff --git a/tests/ui/crate-loading/missing-std.stderr b/tests/ui/crate-loading/missing-std.stderr
index 70bcae1e0ed..3eb6c2946d3 100644
--- a/tests/ui/crate-loading/missing-std.stderr
+++ b/tests/ui/crate-loading/missing-std.stderr
@@ -8,8 +8,6 @@ LL | extern crate core;
    = help: consider downloading the target with `rustup target add x86_64-unknown-uefi`
    = help: consider building the standard library from source with `cargo build -Zbuild-std`
 
-error: requires `sized` lang_item
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0463`.
diff --git a/tests/ui/cross-crate/cci_capture_clause.rs b/tests/ui/cross-crate/cci_capture_clause.rs
index 99736ad185d..73e1020d7cf 100644
--- a/tests/ui/cross-crate/cci_capture_clause.rs
+++ b/tests/ui/cross-crate/cci_capture_clause.rs
@@ -5,7 +5,7 @@
 // that use capture clauses.
 
 //@ pretty-expanded FIXME #23616
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 extern crate cci_capture_clause;
 
diff --git a/tests/ui/cycle-trait/cycle-trait-default-type-trait.stderr b/tests/ui/cycle-trait/cycle-trait-default-type-trait.stderr
index e8be9b0b913..c0b935567f8 100644
--- a/tests/ui/cycle-trait/cycle-trait-default-type-trait.stderr
+++ b/tests/ui/cycle-trait/cycle-trait-default-type-trait.stderr
@@ -5,15 +5,11 @@ LL | trait Foo<X = Box<dyn Foo>> {
    |                       ^^^
    |
    = note: ...which immediately requires computing type of `Foo::X` again
-note: cycle used when collecting item types in top-level module
+note: cycle used when checking that `Foo` is well-formed
   --> $DIR/cycle-trait-default-type-trait.rs:4:1
    |
-LL | / trait Foo<X = Box<dyn Foo>> {
-LL | |
-LL | | }
-LL | |
-LL | | fn main() { }
-   | |_____________^
+LL | trait Foo<X = Box<dyn Foo>> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr b/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr
index 8645b4ebccf..2e11a59c3a4 100644
--- a/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr
+++ b/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr
@@ -5,7 +5,7 @@ LL | trait Chromosome: Chromosome {
    |                   ^^^^^^^^^^
    |
    = note: ...which immediately requires computing the super predicates of `Chromosome` again
-note: cycle used when collecting item types in top-level module
+note: cycle used when checking that `Chromosome` is well-formed
   --> $DIR/cycle-trait-supertrait-direct.rs:3:1
    |
 LL | / trait Chromosome: Chromosome {
diff --git a/tests/ui/cycle-trait/issue-12511.stderr b/tests/ui/cycle-trait/issue-12511.stderr
index bc56b9904f5..0246bf21983 100644
--- a/tests/ui/cycle-trait/issue-12511.stderr
+++ b/tests/ui/cycle-trait/issue-12511.stderr
@@ -10,7 +10,7 @@ note: ...which requires computing the super predicates of `T2`...
 LL | trait T2 : T1 {
    |            ^^
    = note: ...which again requires computing the super predicates of `T1`, completing the cycle
-note: cycle used when collecting item types in top-level module
+note: cycle used when checking that `T1` is well-formed
   --> $DIR/issue-12511.rs:1:1
    |
 LL | / trait T1 : T2 {
diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/not-supported.stderr
index f235767d50a..324b79f3c53 100644
--- a/tests/ui/delegation/not-supported.stderr
+++ b/tests/ui/delegation/not-supported.stderr
@@ -70,14 +70,14 @@ LL |         fn foo(&self, x: i32) -> i32 { x }
 LL |         reuse Trait::foo;
    |                      ^^^
 
-error: delegation with early bound generics is not supported yet
+error[E0049]: method `foo2` has 0 type parameters but its trait declaration has 1 type parameter
   --> $DIR/not-supported.rs:49:22
    |
 LL |         fn foo2<T>(&self, x: T) -> T { x }
-   |         ---------------------------- callee defined here
+   |                 - expected 1 type parameter
 ...
 LL |         reuse Trait::foo2 { &self.0 }
-   |                      ^^^^
+   |                      ^^^^ found 0 type parameters
 
 error: delegation with early bound generics is not supported yet
   --> $DIR/not-supported.rs:52:29
@@ -88,6 +88,15 @@ LL |         fn foo3<'a: 'a>(_: &'a u32) {}
 LL |         reuse <F as Trait>::foo3;
    |                             ^^^^
 
+error[E0195]: lifetime parameters or bounds on method `foo3` do not match the trait declaration
+  --> $DIR/not-supported.rs:52:29
+   |
+LL |         fn foo3<'a: 'a>(_: &'a u32) {}
+   |                -------- lifetimes in impl do not match this method in trait
+...
+LL |         reuse <F as Trait>::foo3;
+   |                             ^^^^ lifetimes do not match method in trait
+
 error: delegation with early bound generics is not supported yet
   --> $DIR/not-supported.rs:59:22
    |
@@ -97,6 +106,15 @@ LL |         fn foo(&self, x: i32) -> i32 { x }
 LL |         reuse Trait::foo { &self.0 }
    |                      ^^^
 
+error: delegation with early bound generics is not supported yet
+  --> $DIR/not-supported.rs:49:22
+   |
+LL |         fn foo2<T>(&self, x: T) -> T { x }
+   |         ---------------------------- callee defined here
+...
+LL |         reuse Trait::foo2 { &self.0 }
+   |                      ^^^^
+
 error: delegation with early bound generics is not supported yet
   --> $DIR/not-supported.rs:74:21
    |
@@ -160,24 +178,6 @@ LL |         pub reuse to_reuse2::foo;
 LL |     reuse to_reuse1::foo;
    |                      ^^^
 
-error[E0049]: method `foo2` has 0 type parameters but its trait declaration has 1 type parameter
-  --> $DIR/not-supported.rs:49:22
-   |
-LL |         fn foo2<T>(&self, x: T) -> T { x }
-   |                 - expected 1 type parameter
-...
-LL |         reuse Trait::foo2 { &self.0 }
-   |                      ^^^^ found 0 type parameters
-
-error[E0195]: lifetime parameters or bounds on method `foo3` do not match the trait declaration
-  --> $DIR/not-supported.rs:52:29
-   |
-LL |         fn foo3<'a: 'a>(_: &'a u32) {}
-   |                -------- lifetimes in impl do not match this method in trait
-...
-LL |         reuse <F as Trait>::foo3;
-   |                             ^^^^ lifetimes do not match method in trait
-
 error: aborting due to 19 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0049, E0195.
diff --git a/tests/ui/diagnostic_namespace/existing_proc_macros.rs b/tests/ui/diagnostic_namespace/existing_proc_macros.rs
index 2bc58aea8fc..014ec46f1b9 100644
--- a/tests/ui/diagnostic_namespace/existing_proc_macros.rs
+++ b/tests/ui/diagnostic_namespace/existing_proc_macros.rs
@@ -1,4 +1,3 @@
-#![feature(diagnostic_namespace)]
 //@ check-pass
 //@ aux-build:proc-macro-helper.rs
 
diff --git a/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.rs b/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.rs
deleted file mode 100644
index b08e291621f..00000000000
--- a/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-#[diagnostic::non_existing_attribute]
-//~^ERROR `#[diagnostic]` attribute name space is experimental [E0658]
-//~|WARNING unknown diagnostic attribute [unknown_or_malformed_diagnostic_attributes]
-pub trait Bar {
-}
-
-#[diagnostic::non_existing_attribute(with_option = "foo")]
-//~^ERROR `#[diagnostic]` attribute name space is experimental [E0658]
-//~|WARNING unknown diagnostic attribute [unknown_or_malformed_diagnostic_attributes]
-struct Foo;
-
-fn main() {
-}
diff --git a/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.stderr b/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.stderr
deleted file mode 100644
index 38424c13d86..00000000000
--- a/tests/ui/diagnostic_namespace/feature-gate-diagnostic_namespace.stderr
+++ /dev/null
@@ -1,37 +0,0 @@
-error[E0658]: `#[diagnostic]` attribute name space is experimental
-  --> $DIR/feature-gate-diagnostic_namespace.rs:1:3
-   |
-LL | #[diagnostic::non_existing_attribute]
-   |   ^^^^^^^^^^
-   |
-   = note: see issue #111996 <https://github.com/rust-lang/rust/issues/111996> for more information
-   = help: add `#![feature(diagnostic_namespace)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `#[diagnostic]` attribute name space is experimental
-  --> $DIR/feature-gate-diagnostic_namespace.rs:7:3
-   |
-LL | #[diagnostic::non_existing_attribute(with_option = "foo")]
-   |   ^^^^^^^^^^
-   |
-   = note: see issue #111996 <https://github.com/rust-lang/rust/issues/111996> for more information
-   = help: add `#![feature(diagnostic_namespace)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-warning: unknown diagnostic attribute
-  --> $DIR/feature-gate-diagnostic_namespace.rs:1:15
-   |
-LL | #[diagnostic::non_existing_attribute]
-   |               ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
-
-warning: unknown diagnostic attribute
-  --> $DIR/feature-gate-diagnostic_namespace.rs:7:15
-   |
-LL | #[diagnostic::non_existing_attribute(with_option = "foo")]
-   |               ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors; 2 warnings emitted
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs
index 95465701bf8..f6957b1448d 100644
--- a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs
+++ b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.rs
@@ -1,4 +1,3 @@
-#![feature(diagnostic_namespace)]
 //@ check-pass
 #[diagnostic::non_existing_attribute]
 //~^WARN unknown diagnostic attribute
diff --git a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr
index 753077b365e..c073ec9b103 100644
--- a/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr
+++ b/tests/ui/diagnostic_namespace/non_existing_attributes_accepted.stderr
@@ -1,5 +1,5 @@
 warning: unknown diagnostic attribute
-  --> $DIR/non_existing_attributes_accepted.rs:3:15
+  --> $DIR/non_existing_attributes_accepted.rs:2:15
    |
 LL | #[diagnostic::non_existing_attribute]
    |               ^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | #[diagnostic::non_existing_attribute]
    = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
 
 warning: unknown diagnostic attribute
-  --> $DIR/non_existing_attributes_accepted.rs:8:15
+  --> $DIR/non_existing_attributes_accepted.rs:7:15
    |
 LL | #[diagnostic::non_existing_attribute(with_option = "foo")]
    |               ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs b/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs
index 884bab2800a..512ef6330e5 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/auxiliary/other.rs
@@ -1,5 +1,3 @@
-#![feature(diagnostic_namespace)]
-
 #[diagnostic::on_unimplemented(
     message = "Message",
     note = "Note",
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs
index eb985c062f3..30a85ff2199 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.rs
@@ -1,5 +1,3 @@
-#![feature(diagnostic_namespace)]
-
 #[diagnostic::on_unimplemented(
     on(_Self = "&str"),
     //~^WARN malformed `on_unimplemented` attribute
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr
index 75a701f0b5f..e34b917f67e 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_accept_options_of_the_internal_rustc_attribute.stderr
@@ -1,5 +1,5 @@
 warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:24:1
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:22:1
    |
 LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl
    = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:2:5
    |
 LL |     on(_Self = "&str"),
    |     ^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -15,7 +15,7 @@ LL |     on(_Self = "&str"),
    = help: only `message`, `note` and `label` are allowed as options
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:8:5
    |
 LL |     parent_label = "in this scope",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -23,7 +23,7 @@ LL |     parent_label = "in this scope",
    = help: only `message`, `note` and `label` are allowed as options
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:11:5
    |
 LL |     append_const_msg
    |     ^^^^^^^^^^^^^^^^ invalid option found here
@@ -31,7 +31,7 @@ LL |     append_const_msg
    = help: only `message`, `note` and `label` are allowed as options
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:32
    |
 LL | #[diagnostic::on_unimplemented = "Message"]
    |                                ^^^^^^^^^^^ invalid option found here
@@ -39,7 +39,7 @@ LL | #[diagnostic::on_unimplemented = "Message"]
    = help: only `message`, `note` and `label` are allowed as options
 
 warning: there is no parameter `from_desugaring` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -47,7 +47,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `direct` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -55,7 +55,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `cause` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -63,7 +63,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `integral` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,7 +71,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `integer` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -79,7 +79,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `float` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -87,7 +87,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `_Self` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -95,7 +95,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `crate_local` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -103,7 +103,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `Trait` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -111,7 +111,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `ItemContext` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -119,7 +119,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:4:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:2:5
    |
 LL |     on(_Self = "&str"),
    |     ^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -128,7 +128,7 @@ LL |     on(_Self = "&str"),
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:10:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:8:5
    |
 LL |     parent_label = "in this scope",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -137,7 +137,7 @@ LL |     parent_label = "in this scope",
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:13:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:11:5
    |
 LL |     append_const_msg
    |     ^^^^^^^^^^^^^^^^ invalid option found here
@@ -146,7 +146,7 @@ LL |     append_const_msg
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: trait has `()` and `i32` as params
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:61:15
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:59:15
    |
 LL |     takes_foo(());
    |     --------- ^^ trait has `()` and `i32` as params
@@ -156,18 +156,18 @@ LL |     takes_foo(());
    = help: the trait `Foo<i32>` is not implemented for `()`
    = note: trait has `()` and `i32` as params
 help: this trait has no implementations, consider adding one
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:1
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:15:1
    |
 LL | trait Foo<T> {}
    | ^^^^^^^^^^^^
 note: required by a bound in `takes_foo`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:22
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:54:22
    |
 LL | fn takes_foo(_: impl Foo<i32>) {}
    |                      ^^^^^^^^ required by this bound in `takes_foo`
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:19:32
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:17:32
    |
 LL | #[diagnostic::on_unimplemented = "Message"]
    |                                ^^^^^^^^^^^ invalid option found here
@@ -176,7 +176,7 @@ LL | #[diagnostic::on_unimplemented = "Message"]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: the trait bound `(): Bar` is not satisfied
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:61:15
    |
 LL |     takes_bar(());
    |     --------- ^^ the trait `Bar` is not implemented for `()`
@@ -185,13 +185,13 @@ LL |     takes_bar(());
    |
    = help: the trait `Bar` is implemented for `i32`
 note: required by a bound in `takes_bar`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:57:22
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:55:22
    |
 LL | fn takes_bar(_: impl Bar) {}
    |                      ^^^ required by this bound in `takes_bar`
 
 warning: there is no parameter `from_desugaring` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -200,7 +200,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `direct` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -209,7 +209,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `cause` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -218,7 +218,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `integral` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -227,7 +227,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `integer` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:31:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:5
    |
 LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -236,7 +236,7 @@ LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `float` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -245,7 +245,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `_Self` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -254,7 +254,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `crate_local` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -263,7 +263,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `Trait` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -272,7 +272,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: there is no parameter `ItemContext` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:42:5
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:40:5
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -281,7 +281,7 @@ LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: {from_desugaring}{direct}{cause}{integral}{integer}
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:65:15
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15
    |
 LL |     takes_baz(());
    |     --------- ^^ {float}{_Self}{crate_local}{Trait}{ItemContext}
@@ -290,12 +290,12 @@ LL |     takes_baz(());
    |
    = help: the trait `Baz` is not implemented for `()`
 help: this trait has no implementations, consider adding one
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:54:1
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:52:1
    |
 LL | trait Baz {}
    | ^^^^^^^^^
 note: required by a bound in `takes_baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:58:22
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:22
    |
 LL | fn takes_baz(_: impl Baz) {}
    |                      ^^^ required by this bound in `takes_baz`
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs
index 12fe988170a..b4234066bb1 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.rs
@@ -1,5 +1,3 @@
-#![feature(diagnostic_namespace)]
-
 #[diagnostic::on_unimplemented(unsupported = "foo")]
 //~^WARN malformed `on_unimplemented` attribute
 //~|WARN malformed `on_unimplemented` attribute
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr
index 11263580b15..dc0c1948236 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/do_not_fail_parsing_on_invalid_options_1.stderr
@@ -1,5 +1,5 @@
 warning: `#[diagnostic::on_unimplemented]` can only be applied to trait definitions
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:8:1
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:6:1
    |
 LL | #[diagnostic::on_unimplemented(message = "Baz")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | #[diagnostic::on_unimplemented(message = "Baz")]
    = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:1:32
    |
 LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
    |                                ^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -15,7 +15,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
    = help: only `message`, `note` and `label` are allowed as options
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:12:50
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:10:50
    |
 LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
    |                                                  ^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -23,7 +23,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
    = help: only `message`, `note` and `label` are allowed as options
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:17:50
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:50
    |
 LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))]
    |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -31,7 +31,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message
    = help: only `message`, `note` and `label` are allowed as options
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:22:32
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:20:32
    |
 LL | #[diagnostic::on_unimplemented = "boom"]
    |                                ^^^^^^^^ invalid option found here
@@ -39,7 +39,7 @@ LL | #[diagnostic::on_unimplemented = "boom"]
    = help: only `message`, `note` and `label` are allowed as options
 
 warning: missing options for `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:26:1
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:24:1
    |
 LL | #[diagnostic::on_unimplemented]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -47,7 +47,7 @@ LL | #[diagnostic::on_unimplemented]
    = help: at least one of the `message`, `note` and `label` options are expected
 
 warning: there is no parameter `DoesNotExist` on trait `Test`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:32
    |
 LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -55,7 +55,7 @@ LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:3:32
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:1:32
    |
 LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
    |                                ^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -64,7 +64,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: the trait bound `i32: Foo` is not satisfied
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:41:14
    |
 LL |     take_foo(1_i32);
    |     -------- ^^^^^ the trait `Foo` is not implemented for `i32`
@@ -72,18 +72,18 @@ LL |     take_foo(1_i32);
    |     required by a bound introduced by this call
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:6:1
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:4:1
    |
 LL | trait Foo {}
    | ^^^^^^^^^
 note: required by a bound in `take_foo`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:21
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:21
    |
 LL | fn take_foo(_: impl Foo) {}
    |                     ^^^ required by this bound in `take_foo`
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:12:50
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:10:50
    |
 LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
    |                                                  ^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -92,7 +92,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: Boom
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:14
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14
    |
 LL |     take_baz(1_i32);
    |     -------- ^^^^^ the trait `Baz` is not implemented for `i32`
@@ -100,18 +100,18 @@ LL |     take_baz(1_i32);
    |     required by a bound introduced by this call
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:1
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:13:1
    |
 LL | trait Baz {}
    | ^^^^^^^^^
 note: required by a bound in `take_baz`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:21
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:35:21
    |
 LL | fn take_baz(_: impl Baz) {}
    |                     ^^^ required by this bound in `take_baz`
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:17:50
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:15:50
    |
 LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))]
    |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -120,7 +120,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: Boom
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:15
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:15
    |
 LL |     take_boom(1_i32);
    |     --------- ^^^^^ the trait `Boom` is not implemented for `i32`
@@ -128,18 +128,18 @@ LL |     take_boom(1_i32);
    |     required by a bound introduced by this call
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:20:1
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:18:1
    |
 LL | trait Boom {}
    | ^^^^^^^^^^
 note: required by a bound in `take_boom`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:22
    |
 LL | fn take_boom(_: impl Boom) {}
    |                      ^^^^ required by this bound in `take_boom`
 
 warning: missing options for `on_unimplemented` attribute
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:26:1
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:24:1
    |
 LL | #[diagnostic::on_unimplemented]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -148,7 +148,7 @@ LL | #[diagnostic::on_unimplemented]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: the trait bound `i32: Whatever` is not satisfied
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:19
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:19
    |
 LL |     take_whatever(1_i32);
    |     ------------- ^^^^^ the trait `Whatever` is not implemented for `i32`
@@ -156,18 +156,18 @@ LL |     take_whatever(1_i32);
    |     required by a bound introduced by this call
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:1
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:27:1
    |
 LL | trait Whatever {}
    | ^^^^^^^^^^^^^^
 note: required by a bound in `take_whatever`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:39:26
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:26
    |
 LL | fn take_whatever(_: impl Whatever) {}
    |                          ^^^^^^^^ required by this bound in `take_whatever`
 
 warning: there is no parameter `DoesNotExist` on trait `Test`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:32
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:32
    |
 LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -176,7 +176,7 @@ LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: {DoesNotExist}
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:51:15
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:15
    |
 LL |     take_test(());
    |     --------- ^^ the trait `Test` is not implemented for `()`
@@ -184,12 +184,12 @@ LL |     take_test(());
    |     required by a bound introduced by this call
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:1
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:32:1
    |
 LL | trait Test {}
    | ^^^^^^^^^^
 note: required by a bound in `take_test`
-  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:40:22
+  --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22
    |
 LL | fn take_test(_: impl Test) {}
    |                      ^^^^ required by this bound in `take_test`
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.rs b/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.rs
deleted file mode 100644
index 609a840c118..00000000000
--- a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-#[diagnostic::on_unimplemented(message = "Foo")]
-//~^ERROR `#[diagnostic]` attribute name space is experimental [E0658]
-pub trait Bar {
-}
-
-fn main() {
-}
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.stderr
deleted file mode 100644
index 719322fa0f5..00000000000
--- a/tests/ui/diagnostic_namespace/on_unimplemented/feature-gate-diagnostic_on_unimplemented.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0658]: `#[diagnostic]` attribute name space is experimental
-  --> $DIR/feature-gate-diagnostic_on_unimplemented.rs:1:3
-   |
-LL | #[diagnostic::on_unimplemented(message = "Foo")]
-   |   ^^^^^^^^^^
-   |
-   = note: see issue #111996 <https://github.com/rust-lang/rust/issues/111996> for more information
-   = help: add `#![feature(diagnostic_namespace)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs
index 0893f29c4a3..5b25fb234bc 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs
@@ -1,5 +1,3 @@
-#![feature(diagnostic_namespace)]
-
 #[diagnostic::on_unimplemented(
     if(Self = "()"),
     //~^WARN malformed `on_unimplemented` attribute
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr
index e00846da77b..56d125e20e5 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.stderr
@@ -1,5 +1,5 @@
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:4:5
+  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:2:5
    |
 LL |     if(Self = "()"),
    |     ^^^^^^^^^^^^^^^ invalid option found here
@@ -8,7 +8,7 @@ LL |     if(Self = "()"),
    = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
 
 warning: `message` is ignored due to previous definition of `message`
-  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:10:32
+  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:8:32
    |
 LL |     message = "custom message",
    |     -------------------------- `message` is first declared here
@@ -17,7 +17,7 @@ LL | #[diagnostic::on_unimplemented(message = "fallback!!")]
    |                                ^^^^^^^^^^^^^^^^^^^^^^ `message` is already declared here
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:4:5
+  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:2:5
    |
 LL |     if(Self = "()"),
    |     ^^^^^^^^^^^^^^^ invalid option found here
@@ -26,7 +26,7 @@ LL |     if(Self = "()"),
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: `message` is ignored due to previous definition of `message`
-  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:10:32
+  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:8:32
    |
 LL |     message = "custom message",
    |     -------------------------- `message` is first declared here
@@ -37,7 +37,7 @@ LL | #[diagnostic::on_unimplemented(message = "fallback!!")]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: custom message
-  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:20:15
+  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:18:15
    |
 LL |     takes_foo(());
    |     --------- ^^ fallback label
@@ -48,12 +48,12 @@ LL |     takes_foo(());
    = note: custom note
    = note: fallback note
 help: this trait has no implementations, consider adding one
-  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:15:1
+  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:13:1
    |
 LL | trait Foo {}
    | ^^^^^^^^^
 note: required by a bound in `takes_foo`
-  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:17:22
+  --> $DIR/ignore_unsupported_options_and_continue_to_use_fallback.rs:15:22
    |
 LL | fn takes_foo(_: impl Foo) {}
    |                      ^^^ required by this bound in `takes_foo`
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs
index 34cdb99c754..a5982f6492c 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.rs
@@ -1,5 +1,3 @@
-#![feature(diagnostic_namespace)]
-
 #[diagnostic::on_unimplemented(message = "Foo", label = "Bar", note = "Baz", note = "Boom")]
 trait Foo {}
 
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr
index c72321d4617..93a0d0b3f41 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/multiple_notes.stderr
@@ -1,5 +1,5 @@
 error[E0277]: Foo
-  --> $DIR/multiple_notes.rs:14:15
+  --> $DIR/multiple_notes.rs:12:15
    |
 LL |     takes_foo(());
    |     --------- ^^ Bar
@@ -10,18 +10,18 @@ LL |     takes_foo(());
    = note: Baz
    = note: Boom
 help: this trait has no implementations, consider adding one
-  --> $DIR/multiple_notes.rs:4:1
+  --> $DIR/multiple_notes.rs:2:1
    |
 LL | trait Foo {}
    | ^^^^^^^^^
 note: required by a bound in `takes_foo`
-  --> $DIR/multiple_notes.rs:10:22
+  --> $DIR/multiple_notes.rs:8:22
    |
 LL | fn takes_foo(_: impl Foo) {}
    |                      ^^^ required by this bound in `takes_foo`
 
 error[E0277]: Bar
-  --> $DIR/multiple_notes.rs:16:15
+  --> $DIR/multiple_notes.rs:14:15
    |
 LL |     takes_bar(());
    |     --------- ^^ Foo
@@ -32,12 +32,12 @@ LL |     takes_bar(());
    = note: Baz
    = note: Baz2
 help: this trait has no implementations, consider adding one
-  --> $DIR/multiple_notes.rs:8:1
+  --> $DIR/multiple_notes.rs:6:1
    |
 LL | trait Bar {}
    | ^^^^^^^^^
 note: required by a bound in `takes_bar`
-  --> $DIR/multiple_notes.rs:11:22
+  --> $DIR/multiple_notes.rs:9:22
    |
 LL | fn takes_bar(_: impl Bar) {}
    |                      ^^^ required by this bound in `takes_bar`
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs
index 797edbc9ec5..7ca03127759 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.rs
@@ -1,5 +1,3 @@
-#![feature(diagnostic_namespace)]
-
 #[diagnostic::on_unimplemented(message = "Foo", label = "Bar", note = "Baz")]
 trait Foo {}
 
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr
index de57f7044bf..6b17f40c6dd 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/on_unimplemented_simple.stderr
@@ -1,5 +1,5 @@
 error[E0277]: Foo
-  --> $DIR/on_unimplemented_simple.rs:9:15
+  --> $DIR/on_unimplemented_simple.rs:7:15
    |
 LL |     takes_foo(());
    |     --------- ^^ Bar
@@ -9,12 +9,12 @@ LL |     takes_foo(());
    = help: the trait `Foo` is not implemented for `()`
    = note: Baz
 help: this trait has no implementations, consider adding one
-  --> $DIR/on_unimplemented_simple.rs:4:1
+  --> $DIR/on_unimplemented_simple.rs:2:1
    |
 LL | trait Foo {}
    | ^^^^^^^^^
 note: required by a bound in `takes_foo`
-  --> $DIR/on_unimplemented_simple.rs:6:22
+  --> $DIR/on_unimplemented_simple.rs:4:22
    |
 LL | fn takes_foo(_: impl Foo) {}
    |                      ^^^ required by this bound in `takes_foo`
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs
index a7becd2f88f..8c0b8150417 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.rs
@@ -1,5 +1,3 @@
-#![feature(diagnostic_namespace)]
-
 #[diagnostic::on_unimplemented(
     message = "first message",
     label = "first label",
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr
index d30754dcf10..43ab6bf25a1 100644
--- a/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/report_warning_on_duplicated_options.stderr
@@ -1,5 +1,5 @@
 warning: `message` is ignored due to previous definition of `message`
-  --> $DIR/report_warning_on_duplicated_options.rs:9:5
+  --> $DIR/report_warning_on_duplicated_options.rs:7:5
    |
 LL |     message = "first message",
    |     ------------------------- `message` is first declared here
@@ -10,7 +10,7 @@ LL |     message = "second message",
    = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
 
 warning: `label` is ignored due to previous definition of `label`
-  --> $DIR/report_warning_on_duplicated_options.rs:12:5
+  --> $DIR/report_warning_on_duplicated_options.rs:10:5
    |
 LL |     label = "first label",
    |     --------------------- `label` is first declared here
@@ -19,7 +19,7 @@ LL |     label = "second label",
    |     ^^^^^^^^^^^^^^^^^^^^^^ `label` is already declared here
 
 warning: `message` is ignored due to previous definition of `message`
-  --> $DIR/report_warning_on_duplicated_options.rs:9:5
+  --> $DIR/report_warning_on_duplicated_options.rs:7:5
    |
 LL |     message = "first message",
    |     ------------------------- `message` is first declared here
@@ -30,7 +30,7 @@ LL |     message = "second message",
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 warning: `label` is ignored due to previous definition of `label`
-  --> $DIR/report_warning_on_duplicated_options.rs:12:5
+  --> $DIR/report_warning_on_duplicated_options.rs:10:5
    |
 LL |     label = "first label",
    |     --------------------- `label` is first declared here
@@ -41,7 +41,7 @@ LL |     label = "second label",
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: first message
-  --> $DIR/report_warning_on_duplicated_options.rs:23:15
+  --> $DIR/report_warning_on_duplicated_options.rs:21:15
    |
 LL |     takes_foo(());
    |     --------- ^^ first label
@@ -52,12 +52,12 @@ LL |     takes_foo(());
    = note: custom note
    = note: second note
 help: this trait has no implementations, consider adding one
-  --> $DIR/report_warning_on_duplicated_options.rs:17:1
+  --> $DIR/report_warning_on_duplicated_options.rs:15:1
    |
 LL | trait Foo {}
    | ^^^^^^^^^
 note: required by a bound in `takes_foo`
-  --> $DIR/report_warning_on_duplicated_options.rs:20:22
+  --> $DIR/report_warning_on_duplicated_options.rs:18:22
    |
 LL | fn takes_foo(_: impl Foo) {}
    |                      ^^^ required by this bound in `takes_foo`
diff --git a/tests/ui/diagnostic_namespace/requires_path.rs b/tests/ui/diagnostic_namespace/requires_path.rs
index e8d6ca73ad0..4f3a1319caf 100644
--- a/tests/ui/diagnostic_namespace/requires_path.rs
+++ b/tests/ui/diagnostic_namespace/requires_path.rs
@@ -1,5 +1,3 @@
-#![feature(diagnostic_namespace)]
-
 #[diagnostic]
 //~^ERROR cannot find attribute `diagnostic` in this scope
 pub struct Bar;
diff --git a/tests/ui/diagnostic_namespace/requires_path.stderr b/tests/ui/diagnostic_namespace/requires_path.stderr
index 5d07d3a22d5..e02aacac8c1 100644
--- a/tests/ui/diagnostic_namespace/requires_path.stderr
+++ b/tests/ui/diagnostic_namespace/requires_path.stderr
@@ -1,5 +1,5 @@
 error: cannot find attribute `diagnostic` in this scope
-  --> $DIR/requires_path.rs:3:3
+  --> $DIR/requires_path.rs:1:3
    |
 LL | #[diagnostic]
    |   ^^^^^^^^^^
diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.stderr
index dc93762c9b1..b349332bcb9 100644
--- a/tests/ui/did_you_mean/bad-assoc-ty.stderr
+++ b/tests/ui/did_you_mean/bad-assoc-ty.stderr
@@ -272,6 +272,17 @@ help: use type parameters instead
 LL | struct L<F, T>(F) where F: Fn() -> T;
    |           +++                      ~
 
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/bad-assoc-ty.rs:82:38
+   |
+LL |     fn foo<F>(_: F) where F: Fn() -> _ {}
+   |                                      ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL |     fn foo<F, T>(_: F) where F: Fn() -> T {}
+   |             +++                         ~
+
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
   --> $DIR/bad-assoc-ty.rs:62:30
    |
@@ -305,28 +316,6 @@ help: use type parameters instead
 LL | union O<F, T> where F: Fn() -> T {
    |          +++                   ~
 
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for traits
-  --> $DIR/bad-assoc-ty.rs:77:29
-   |
-LL | trait P<F> where F: Fn() -> _ {
-   |                             ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL | trait P<F, T> where F: Fn() -> T {
-   |          +++                   ~
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/bad-assoc-ty.rs:82:38
-   |
-LL |     fn foo<F>(_: F) where F: Fn() -> _ {}
-   |                                      ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |     fn foo<F, T>(_: F) where F: Fn() -> T {}
-   |             +++                         ~
-
 error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
   --> $DIR/bad-assoc-ty.rs:73:5
    |
@@ -339,6 +328,17 @@ help: wrap the field type in `ManuallyDrop<...>`
 LL |     foo: std::mem::ManuallyDrop<F>,
    |          +++++++++++++++++++++++ +
 
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for traits
+  --> $DIR/bad-assoc-ty.rs:77:29
+   |
+LL | trait P<F> where F: Fn() -> _ {
+   |                             ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | trait P<F, T> where F: Fn() -> T {
+   |          +++                   ~
+
 error: aborting due to 29 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0121, E0223, E0740.
diff --git a/tests/ui/duplicate/duplicate-type-parameter.rs b/tests/ui/duplicate/duplicate-type-parameter.rs
index 2751b3c8dc0..c2064b423f1 100644
--- a/tests/ui/duplicate/duplicate-type-parameter.rs
+++ b/tests/ui/duplicate/duplicate-type-parameter.rs
@@ -23,7 +23,6 @@ trait Qux<T,T> {}
 
 impl<T,T> Qux<T,T> for Option<T> {}
 //~^ ERROR the name `T` is already used
-//~^^ ERROR the type parameter `T` is not constrained
 
 fn main() {
 }
diff --git a/tests/ui/duplicate/duplicate-type-parameter.stderr b/tests/ui/duplicate/duplicate-type-parameter.stderr
index 628f898d5c8..f23f2460a8a 100644
--- a/tests/ui/duplicate/duplicate-type-parameter.stderr
+++ b/tests/ui/duplicate/duplicate-type-parameter.stderr
@@ -54,13 +54,6 @@ LL | impl<T,T> Qux<T,T> for Option<T> {}
    |      |
    |      first use of `T`
 
-error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/duplicate-type-parameter.rs:24:8
-   |
-LL | impl<T,T> Qux<T,T> for Option<T> {}
-   |        ^ unconstrained type parameter
+error: aborting due to 7 previous errors
 
-error: aborting due to 8 previous errors
-
-Some errors have detailed explanations: E0207, E0403.
-For more information about an error, try `rustc --explain E0207`.
+For more information about this error, try `rustc --explain E0403`.
diff --git a/tests/ui/error-codes/E0374.stderr b/tests/ui/error-codes/E0374.stderr
index 77f351b28ef..71eec4c16fd 100644
--- a/tests/ui/error-codes/E0374.stderr
+++ b/tests/ui/error-codes/E0374.stderr
@@ -1,3 +1,11 @@
+error[E0392]: type parameter `T` is never used
+  --> $DIR/E0374.rs:4:12
+   |
+LL | struct Foo<T: ?Sized> {
+   |            ^ unused type parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+
 error[E0374]: the trait `CoerceUnsized` may only be implemented for a coercion between structures
   --> $DIR/E0374.rs:8:1
    |
@@ -7,14 +15,6 @@ LL | |     where T: CoerceUnsized<U> {}
    |
    = note: expected a single field to be coerced, none found
 
-error[E0392]: type parameter `T` is never used
-  --> $DIR/E0374.rs:4:12
-   |
-LL | struct Foo<T: ?Sized> {
-   |            ^ unused type parameter
-   |
-   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
-
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0374, E0392.
diff --git a/tests/ui/error-codes/E0375.stderr b/tests/ui/error-codes/E0375.stderr
index d5340022d68..af720bd40e7 100644
--- a/tests/ui/error-codes/E0375.stderr
+++ b/tests/ui/error-codes/E0375.stderr
@@ -1,12 +1,3 @@
-error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions
-  --> $DIR/E0375.rs:10:12
-   |
-LL | impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {}
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions
-   |
-   = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced
-   = note: currently, 2 fields need coercions: `b` (`T` to `U`), `c` (`U` to `T`)
-
 error[E0277]: the size for values of type `T` cannot be known at compilation time
   --> $DIR/E0375.rs:6:8
    |
@@ -32,6 +23,15 @@ help: the `Box` type always has a statically known size and allocates its conten
 LL |     b: Box<T>,
    |        ++++ +
 
+error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions
+  --> $DIR/E0375.rs:10:12
+   |
+LL | impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions
+   |
+   = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced
+   = note: currently, 2 fields need coercions: `b` (`T` to `U`), `c` (`U` to `T`)
+
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0277, E0375.
diff --git a/tests/ui/error-codes/E0657.rs b/tests/ui/error-codes/E0657.rs
index cb11de13f73..212c1d9e581 100644
--- a/tests/ui/error-codes/E0657.rs
+++ b/tests/ui/error-codes/E0657.rs
@@ -8,7 +8,7 @@ impl<T> Id<T> for T {}
 
 fn free_fn_capture_hrtb_in_impl_trait()
     -> Box<for<'a> Id<impl Lt<'a>>>
-        //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level [E0657]
+        //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
 {
     Box::new(())
 }
@@ -17,7 +17,7 @@ struct Foo;
 impl Foo {
     fn impl_fn_capture_hrtb_in_impl_trait()
         -> Box<for<'a> Id<impl Lt<'a>>>
-            //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level
+            //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
     {
         Box::new(())
     }
diff --git a/tests/ui/error-codes/E0657.stderr b/tests/ui/error-codes/E0657.stderr
index df76b45a589..c539007cdcf 100644
--- a/tests/ui/error-codes/E0657.stderr
+++ b/tests/ui/error-codes/E0657.stderr
@@ -1,14 +1,26 @@
-error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
   --> $DIR/E0657.rs:10:31
    |
 LL |     -> Box<for<'a> Id<impl Lt<'a>>>
    |                               ^^
+   |
+note: lifetime declared here
+  --> $DIR/E0657.rs:10:16
+   |
+LL |     -> Box<for<'a> Id<impl Lt<'a>>>
+   |                ^^
 
-error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
   --> $DIR/E0657.rs:19:35
    |
 LL |         -> Box<for<'a> Id<impl Lt<'a>>>
    |                                   ^^
+   |
+note: lifetime declared here
+  --> $DIR/E0657.rs:19:20
+   |
+LL |         -> Box<for<'a> Id<impl Lt<'a>>>
+   |                    ^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/error-codes/E0719.stderr b/tests/ui/error-codes/E0719.stderr
index f048a8aabd4..7e8329db1f4 100644
--- a/tests/ui/error-codes/E0719.stderr
+++ b/tests/ui/error-codes/E0719.stderr
@@ -16,6 +16,16 @@ LL | trait Foo: Iterator<Item = i32, Item = i32> {}
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
+  --> $DIR/E0719.rs:1:33
+   |
+LL | trait Foo: Iterator<Item = i32, Item = i32> {}
+   |                     ----------  ^^^^^^^^^^ re-bound here
+   |                     |
+   |                     `Item` bound here first
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
   --> $DIR/E0719.rs:8:42
    |
@@ -24,16 +34,6 @@ LL | fn test() -> Box<dyn Iterator<Item = (), Item = Unit>> {
    |                               |
    |                               `Item` bound here first
 
-error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/E0719.rs:1:33
-   |
-LL | trait Foo: Iterator<Item = i32, Item = i32> {}
-   |                     ----------  ^^^^^^^^^^ re-bound here
-   |                     |
-   |                     `Item` bound here first
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
   --> $DIR/E0719.rs:14:38
    |
diff --git a/tests/ui/feature-gates/feature-gate-asm_goto.rs b/tests/ui/feature-gates/feature-gate-asm_goto.rs
new file mode 100644
index 00000000000..beac4590349
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-asm_goto.rs
@@ -0,0 +1,10 @@
+//@ only-x86_64
+
+use std::arch::asm;
+
+fn main() {
+    unsafe {
+        asm!("jmp {}", label {});
+        //~^ ERROR label operands for inline assembly are unstable
+    }
+}
diff --git a/tests/ui/feature-gates/feature-gate-asm_goto.stderr b/tests/ui/feature-gates/feature-gate-asm_goto.stderr
new file mode 100644
index 00000000000..62fd1a320d3
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-asm_goto.stderr
@@ -0,0 +1,13 @@
+error[E0658]: label operands for inline assembly are unstable
+  --> $DIR/feature-gate-asm_goto.rs:7:24
+   |
+LL |         asm!("jmp {}", label {});
+   |                        ^^^^^^^^
+   |
+   = note: see issue #119364 <https://github.com/rust-lang/rust/issues/119364> for more information
+   = help: add `#![feature(asm_goto)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr
index 7dfd79c7286..d8a85c8838d 100644
--- a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr
+++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr
@@ -18,6 +18,14 @@ LL |     type Bop = impl std::fmt::Debug;
    = help: add `#![feature(impl_trait_in_assoc_type)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
+error: unconstrained opaque type
+  --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:6:16
+   |
+LL |     type Bar = impl std::fmt::Debug;
+   |                ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Bar` must be used in combination with a concrete type within the same impl
+
 error[E0658]: inherent associated types are unstable
   --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:14:5
    |
@@ -28,14 +36,6 @@ LL |     type Bop = impl std::fmt::Debug;
    = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: unconstrained opaque type
-  --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:6:16
-   |
-LL |     type Bar = impl std::fmt::Debug;
-   |                ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `Bar` must be used in combination with a concrete type within the same impl
-
 error: unconstrained opaque type
   --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:14:16
    |
diff --git a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr
index 7fc726409ce..5e62221628d 100644
--- a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr
+++ b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr
@@ -74,7 +74,6 @@ LL | fn use_for() where i32: Iterator {
    |                    ^^^^^^^^^^^^^ `i32` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `i32`
-   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = help: see issue #48214
    = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
 
diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
index 5d598ec2969..c3f161469e3 100644
--- a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
+++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
@@ -56,26 +56,6 @@ LL | impl Fn<()> for Foo {
    |
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0183]: manual implementations of `FnOnce` are experimental
-  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6
-   |
-LL | impl FnOnce() for Foo1 {
-   |      ^^^^^^^^ manual implementations of `FnOnce` are experimental
-   |
-   = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
-
-error[E0229]: associated type bindings are not allowed here
-  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6
-   |
-LL | impl FnOnce() for Foo1 {
-   |      ^^^^^^^^ associated type not allowed here
-   |
-help: parenthesized trait syntax expands to `FnOnce<(), Output=()>`
-  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6
-   |
-LL | impl FnOnce() for Foo1 {
-   |      ^^^^^^^^
-
 error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:26:6
    |
@@ -94,24 +74,6 @@ LL | impl FnMut<()> for Bar {
    |
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
-error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change
-  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:35:6
-   |
-LL | impl FnOnce<()> for Baz {
-   |      ^^^^^^^^^^
-   |
-   = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
-   = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0183]: manual implementations of `FnOnce` are experimental
-  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:35:6
-   |
-LL | impl FnOnce<()> for Baz {
-   |      ^^^^^^^^^^ manual implementations of `FnOnce` are experimental
-   |
-   = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
-
 error[E0277]: expected a `FnMut()` closure, found `Foo`
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:9:17
    |
@@ -135,6 +97,44 @@ LL |     extern "rust-call" fn call(self, args: ()) -> () {}
    = note: expected signature `extern "rust-call" fn(&Foo, ()) -> _`
               found signature `extern "rust-call" fn(Foo, ())`
 
+error[E0183]: manual implementations of `FnOnce` are experimental
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6
+   |
+LL | impl FnOnce() for Foo1 {
+   |      ^^^^^^^^ manual implementations of `FnOnce` are experimental
+   |
+   = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6
+   |
+LL | impl FnOnce() for Foo1 {
+   |      ^^^^^^^^ associated type not allowed here
+   |
+help: parenthesized trait syntax expands to `FnOnce<(), Output=()>`
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6
+   |
+LL | impl FnOnce() for Foo1 {
+   |      ^^^^^^^^
+
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:35:6
+   |
+LL | impl FnOnce<()> for Baz {
+   |      ^^^^^^^^^^
+   |
+   = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
+   = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0183]: manual implementations of `FnOnce` are experimental
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:35:6
+   |
+LL | impl FnOnce<()> for Baz {
+   |      ^^^^^^^^^^ manual implementations of `FnOnce` are experimental
+   |
+   = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
+
 error[E0046]: not all trait items implemented, missing: `Output`
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:1
    |
diff --git a/tests/ui/for/issue-20605.current.stderr b/tests/ui/for/issue-20605.current.stderr
index c8d39afdeb9..9e706601ef5 100644
--- a/tests/ui/for/issue-20605.current.stderr
+++ b/tests/ui/for/issue-20605.current.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the size for values of type `dyn Iterator<Item = &'a mut u8>` cannot be known at compilation time
+error[E0277]: `dyn Iterator<Item = &'a mut u8>` is not an iterator
   --> $DIR/issue-20605.rs:5:17
    |
 LL |     for item in *things { *item = 0 }
diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr
index a44faa5491d..f9c3848476c 100644
--- a/tests/ui/for/issue-20605.next.stderr
+++ b/tests/ui/for/issue-20605.next.stderr
@@ -1,8 +1,10 @@
-error[E0277]: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
+error[E0277]: `dyn Iterator<Item = &'a mut u8>` is not an iterator
   --> $DIR/issue-20605.rs:5:17
    |
 LL |     for item in *things { *item = 0 }
-   |                 ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
+   |                 ^^^^^^^ `dyn Iterator<Item = &'a mut u8>` is not an iterator
+   |
+   = help: the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
 
 error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
   --> $DIR/issue-20605.rs:5:17
diff --git a/tests/ui/for/issue-20605.rs b/tests/ui/for/issue-20605.rs
index 4a9f62b6612..1c01de967cc 100644
--- a/tests/ui/for/issue-20605.rs
+++ b/tests/ui/for/issue-20605.rs
@@ -3,8 +3,8 @@
 
 fn changer<'a>(mut things: Box<dyn Iterator<Item=&'a mut u8>>) {
     for item in *things { *item = 0 }
-    //[current]~^ ERROR the size for values of type
-    //[next]~^^ ERROR the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
+    //[current]~^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator
+    //[next]~^^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator
     //[next]~| ERROR the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
     //[next]~| ERROR the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
     //[next]~| ERROR the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
diff --git a/tests/ui/generic-associated-types/bugs/issue-87735.stderr b/tests/ui/generic-associated-types/bugs/issue-87735.stderr
index b80e3e798bd..d8005065238 100644
--- a/tests/ui/generic-associated-types/bugs/issue-87735.stderr
+++ b/tests/ui/generic-associated-types/bugs/issue-87735.stderr
@@ -4,6 +4,91 @@ error[E0207]: the type parameter `U` is not constrained by the impl trait, self
 LL | impl<'b, T, U> AsRef2 for Foo<T>
    |             ^ unconstrained type parameter
 
-error: aborting due to 1 previous error
+error[E0309]: the parameter type `U` may not live long enough
+  --> $DIR/issue-87735.rs:34:21
+   |
+LL |   type Output<'a> = FooRef<'a, U> where Self: 'a;
+   |               --    ^^^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds...
+   |               |
+   |               the parameter type `U` must be valid for the lifetime `'a` as defined here...
+   |
+note: ...that is required by this bound
+  --> $DIR/issue-87735.rs:23:22
+   |
+LL | struct FooRef<'a, U>(&'a [U]);
+   |                      ^^^^^^^
+help: consider adding an explicit lifetime bound
+   |
+LL |   type Output<'a> = FooRef<'a, U> where Self: 'a, U: 'a;
+   |                                                 +++++++
 
-For more information about this error, try `rustc --explain E0207`.
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/issue-87735.rs:31:15
+   |
+LL | impl<'b, T, U> AsRef2 for Foo<T>
+   |      -- the parameter type `T` must be valid for the lifetime `'b` as defined here...
+...
+LL |     T: AsRef2<Output<'b> = &'b [U]>,
+   |               ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
+   |
+note: ...that is required by this bound
+  --> $DIR/issue-87735.rs:7:31
+   |
+LL |   type Output<'a> where Self: 'a;
+   |                               ^^
+help: consider adding an explicit lifetime bound
+   |
+LL |     T: AsRef2<Output<'b> = &'b [U]> + 'b,
+   |                                     ++++
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/issue-87735.rs:36:31
+   |
+LL | impl<'b, T, U> AsRef2 for Foo<T>
+   |      -- the parameter type `T` must be valid for the lifetime `'b` as defined here...
+...
+LL |   fn as_ref2<'a>(&'a self) -> Self::Output<'a> {
+   |                               ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
+   |
+note: ...that is required by this bound
+  --> $DIR/issue-87735.rs:7:31
+   |
+LL |   type Output<'a> where Self: 'a;
+   |                               ^^
+help: consider adding an explicit lifetime bound
+   |
+LL |     T: AsRef2<Output<'b> = &'b [U]> + 'b,
+   |                                     ++++
+
+error: lifetime may not live long enough
+  --> $DIR/issue-87735.rs:37:5
+   |
+LL | impl<'b, T, U> AsRef2 for Foo<T>
+   |      -- lifetime `'b` defined here
+...
+LL |   fn as_ref2<'a>(&'a self) -> Self::Output<'a> {
+   |              -- lifetime `'a` defined here
+LL |     FooRef(self.0.as_ref2())
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-87735.rs:37:12
+   |
+LL | impl<'b, T, U> AsRef2 for Foo<T>
+   |      -- lifetime `'b` defined here
+...
+LL |   fn as_ref2<'a>(&'a self) -> Self::Output<'a> {
+   |              -- lifetime `'a` defined here
+LL |     FooRef(self.0.as_ref2())
+   |            ^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+help: `'b` and `'a` must be the same: replace one with the other
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0207, E0309.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/generic-associated-types/bugs/issue-88526.stderr b/tests/ui/generic-associated-types/bugs/issue-88526.stderr
index ba87ac9185d..5da3e3ff64a 100644
--- a/tests/ui/generic-associated-types/bugs/issue-88526.stderr
+++ b/tests/ui/generic-associated-types/bugs/issue-88526.stderr
@@ -4,6 +4,20 @@ error[E0207]: the type parameter `I` is not constrained by the impl trait, self
 LL | impl<'q, Q, I, F> A for TestB<Q, F>
    |             ^ unconstrained type parameter
 
-error: aborting due to 1 previous error
+error[E0309]: the parameter type `F` may not live long enough
+  --> $DIR/issue-88526.rs:16:18
+   |
+LL |     type I<'a> = &'a F;
+   |            --    ^^^^^ ...so that the reference type `&'a F` does not outlive the data it points at
+   |            |
+   |            the parameter type `F` must be valid for the lifetime `'a` as defined here...
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL |     type I<'a> = &'a F where F: 'a;
+   |                        +++++++++++
 
-For more information about this error, try `rustc --explain E0207`.
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0207, E0309.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
index 8589d008a6b..65854ed7158 100644
--- a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
+++ b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
@@ -1,3 +1,23 @@
+error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
+  --> $DIR/gat-trait-path-missing-lifetime.rs:8:10
+   |
+LL |   fn foo<'a>(t : Self::Y<'a>) -> Self::Y<'a> { t }
+   |          -- expected 0 type parameters
+...
+LL |   fn foo<'a, T1: X<Y = T1>>(t : T1) -> T1::Y<'a> {
+   |          ^^  ^^
+   |          |
+   |          found 1 type parameter
+
+error[E0046]: not all trait items implemented, missing: `Y`
+  --> $DIR/gat-trait-path-missing-lifetime.rs:7:1
+   |
+LL |   type Y<'a>;
+   |   ---------- `Y` from trait
+...
+LL | impl<T> X for T {
+   | ^^^^^^^^^^^^^^^ missing `Y` in implementation
+
 error[E0107]: missing generics for associated type `X::Y`
   --> $DIR/gat-trait-path-missing-lifetime.rs:8:20
    |
@@ -31,26 +51,6 @@ help: add missing lifetime argument
 LL |   fn foo<'a, T1: X<Y<'a> = T1>>(t : T1) -> T1::Y<'a> {
    |                     ++++
 
-error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
-  --> $DIR/gat-trait-path-missing-lifetime.rs:8:10
-   |
-LL |   fn foo<'a>(t : Self::Y<'a>) -> Self::Y<'a> { t }
-   |          -- expected 0 type parameters
-...
-LL |   fn foo<'a, T1: X<Y = T1>>(t : T1) -> T1::Y<'a> {
-   |          ^^  ^^
-   |          |
-   |          found 1 type parameter
-
-error[E0046]: not all trait items implemented, missing: `Y`
-  --> $DIR/gat-trait-path-missing-lifetime.rs:7:1
-   |
-LL |   type Y<'a>;
-   |   ---------- `Y` from trait
-...
-LL | impl<T> X for T {
-   | ^^^^^^^^^^^^^^^ missing `Y` in implementation
-
 error: lifetime may not live long enough
   --> $DIR/gat-trait-path-missing-lifetime.rs:8:3
    |
diff --git a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
index bad2ae9c918..fcd3e7d9aac 100644
--- a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
+++ b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
@@ -53,22 +53,6 @@ note: associated type defined here, with 0 generic parameters
 LL |   type Y<'a>;
    |        ^
 
-error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
-  --> $DIR/gat-trait-path-parenthesised-args.rs:18:27
-   |
-LL | fn bar<'a>(arg: Box<dyn X<Y() = ()>>) {}
-   |                           ^ expected 1 lifetime argument
-   |
-note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/gat-trait-path-parenthesised-args.rs:2:8
-   |
-LL |   type Y<'a>;
-   |        ^ --
-help: add missing lifetime argument
-   |
-LL | fn bar<'a>(arg: Box<dyn X<Y('_) = ()>>) {}
-   |                             ++
-
 error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
   --> $DIR/gat-trait-path-parenthesised-args.rs:5:27
    |
@@ -154,6 +138,22 @@ LL |   type Y<'a>;
    |        ^ ...because it contains the generic associated type `Y`
    = help: consider moving `Y` to another trait
 
+error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
+  --> $DIR/gat-trait-path-parenthesised-args.rs:18:27
+   |
+LL | fn bar<'a>(arg: Box<dyn X<Y() = ()>>) {}
+   |                           ^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/gat-trait-path-parenthesised-args.rs:2:8
+   |
+LL |   type Y<'a>;
+   |        ^ --
+help: add missing lifetime argument
+   |
+LL | fn bar<'a>(arg: Box<dyn X<Y('_) = ()>>) {}
+   |                             ++
+
 error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
   --> $DIR/gat-trait-path-parenthesised-args.rs:18:27
    |
diff --git a/tests/ui/generic-associated-types/issue-80433.stderr b/tests/ui/generic-associated-types/issue-80433.stderr
index 2bbf87ff1ff..1ca080f5df2 100644
--- a/tests/ui/generic-associated-types/issue-80433.stderr
+++ b/tests/ui/generic-associated-types/issue-80433.stderr
@@ -1,3 +1,14 @@
+error: missing required bound on `Output`
+  --> $DIR/issue-80433.rs:7:5
+   |
+LL |     type Output<'a>;
+   |     ^^^^^^^^^^^^^^^-
+   |                    |
+   |                    help: add the required where clause: `where Self: 'a`
+   |
+   = note: this bound is currently required to ensure that impls have maximum flexibility
+   = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
+
 error[E0107]: missing generics for associated type `TestMut::Output`
   --> $DIR/issue-80433.rs:21:47
    |
@@ -14,17 +25,6 @@ help: add missing lifetime argument
 LL | fn test_simpler<'a>(dst: &'a mut impl TestMut<Output<'a> = &'a mut f32>)
    |                                                     ++++
 
-error: missing required bound on `Output`
-  --> $DIR/issue-80433.rs:7:5
-   |
-LL |     type Output<'a>;
-   |     ^^^^^^^^^^^^^^^-
-   |                    |
-   |                    help: add the required where clause: `where Self: 'a`
-   |
-   = note: this bound is currently required to ensure that impls have maximum flexibility
-   = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
-
 error[E0499]: cannot borrow `*dst` as mutable more than once at a time
   --> $DIR/issue-80433.rs:25:10
    |
diff --git a/tests/ui/generic-associated-types/missing_lifetime_args.stderr b/tests/ui/generic-associated-types/missing_lifetime_args.stderr
index 5980c60c51c..18c2d8c7eed 100644
--- a/tests/ui/generic-associated-types/missing_lifetime_args.stderr
+++ b/tests/ui/generic-associated-types/missing_lifetime_args.stderr
@@ -14,42 +14,6 @@ help: add missing lifetime arguments
 LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y<'_, '_> = (&'c u32, &'d u32)>>) {}
    |                                 ++++++++
 
-error[E0107]: struct takes 3 lifetime arguments but 2 lifetime arguments were supplied
-  --> $DIR/missing_lifetime_args.rs:17:26
-   |
-LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b>) {}
-   |                          ^^^ --  -- supplied 2 lifetime arguments
-   |                          |
-   |                          expected 3 lifetime arguments
-   |
-note: struct defined here, with 3 lifetime parameters: `'a`, `'b`, `'c`
-  --> $DIR/missing_lifetime_args.rs:5:8
-   |
-LL | struct Foo<'a, 'b, 'c> {
-   |        ^^^ --  --  --
-help: add missing lifetime argument
-   |
-LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b, 'a>) {}
-   |                                    ++++
-
-error[E0107]: struct takes 3 lifetime arguments but 1 lifetime argument was supplied
-  --> $DIR/missing_lifetime_args.rs:20:16
-   |
-LL | fn f<'a>(_arg: Foo<'a>) {}
-   |                ^^^ -- supplied 1 lifetime argument
-   |                |
-   |                expected 3 lifetime arguments
-   |
-note: struct defined here, with 3 lifetime parameters: `'a`, `'b`, `'c`
-  --> $DIR/missing_lifetime_args.rs:5:8
-   |
-LL | struct Foo<'a, 'b, 'c> {
-   |        ^^^ --  --  --
-help: add missing lifetime arguments
-   |
-LL | fn f<'a>(_arg: Foo<'a, 'a, 'a>) {}
-   |                      ++++++++
-
 error[E0107]: missing generics for associated type `X::Y`
   --> $DIR/missing_lifetime_args.rs:11:32
    |
@@ -99,6 +63,42 @@ LL |     type Y<'a, 'b>;
    |          ^ ...because it contains the generic associated type `Y`
    = help: consider moving `Y` to another trait
 
+error[E0107]: struct takes 3 lifetime arguments but 2 lifetime arguments were supplied
+  --> $DIR/missing_lifetime_args.rs:17:26
+   |
+LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b>) {}
+   |                          ^^^ --  -- supplied 2 lifetime arguments
+   |                          |
+   |                          expected 3 lifetime arguments
+   |
+note: struct defined here, with 3 lifetime parameters: `'a`, `'b`, `'c`
+  --> $DIR/missing_lifetime_args.rs:5:8
+   |
+LL | struct Foo<'a, 'b, 'c> {
+   |        ^^^ --  --  --
+help: add missing lifetime argument
+   |
+LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b, 'a>) {}
+   |                                    ++++
+
+error[E0107]: struct takes 3 lifetime arguments but 1 lifetime argument was supplied
+  --> $DIR/missing_lifetime_args.rs:20:16
+   |
+LL | fn f<'a>(_arg: Foo<'a>) {}
+   |                ^^^ -- supplied 1 lifetime argument
+   |                |
+   |                expected 3 lifetime arguments
+   |
+note: struct defined here, with 3 lifetime parameters: `'a`, `'b`, `'c`
+  --> $DIR/missing_lifetime_args.rs:5:8
+   |
+LL | struct Foo<'a, 'b, 'c> {
+   |        ^^^ --  --  --
+help: add missing lifetime arguments
+   |
+LL | fn f<'a>(_arg: Foo<'a, 'a, 'a>) {}
+   |                      ++++++++
+
 error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0038, E0107.
diff --git a/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.rs b/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.rs
index cd3acf9bc41..f74d7cf2811 100644
--- a/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.rs
+++ b/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.rs
@@ -1,16 +1,10 @@
 trait Foo {
+    //~^ ERROR cycle detected
     type Context<'c>
     where
         Self: 'c;
 }
 
 impl Foo for Box<dyn Foo> {}
-//~^ ERROR `Foo` cannot be made into an object
-//~| ERROR `Foo` cannot be made into an object
-//~| ERROR cycle detected
-//~| ERROR cycle detected
-//~| ERROR cycle detected
-//~| ERROR the trait bound `Box<(dyn Foo + 'static)>: Foo` is not satisfied
-//~| ERROR not all trait items implemented
 
 fn main() {}
diff --git a/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.stderr b/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.stderr
index 8e6b69f7461..29b226f16cb 100644
--- a/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.stderr
+++ b/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.stderr
@@ -1,119 +1,22 @@
-error[E0391]: cycle detected when computing type of `<impl at $DIR/unknown-lifetime-ice-119827.rs:7:1: 7:26>`
-  --> $DIR/unknown-lifetime-ice-119827.rs:7:1
-   |
-LL | impl Foo for Box<dyn Foo> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...which requires finding trait impls of `Foo`...
+error[E0391]: cycle detected when finding trait impls of `Foo`
   --> $DIR/unknown-lifetime-ice-119827.rs:1:1
    |
 LL | trait Foo {
    | ^^^^^^^^^
-   = note: ...which again requires computing type of `<impl at $DIR/unknown-lifetime-ice-119827.rs:7:1: 7:26>`, completing the cycle
-note: cycle used when collecting item types in top-level module
-  --> $DIR/unknown-lifetime-ice-119827.rs:1:1
    |
-LL | / trait Foo {
-LL | |     type Context<'c>
-LL | |     where
-LL | |         Self: 'c;
-...  |
-LL | |
-LL | | fn main() {}
-   | |____________^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error[E0391]: cycle detected when computing type of `<impl at $DIR/unknown-lifetime-ice-119827.rs:7:1: 7:26>`
-  --> $DIR/unknown-lifetime-ice-119827.rs:7:1
+note: ...which requires computing type of `<impl at $DIR/unknown-lifetime-ice-119827.rs:8:1: 8:26>`...
+  --> $DIR/unknown-lifetime-ice-119827.rs:8:1
    |
 LL | impl Foo for Box<dyn Foo> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: ...which immediately requires computing type of `<impl at $DIR/unknown-lifetime-ice-119827.rs:7:1: 7:26>` again
-note: cycle used when collecting item types in top-level module
+   = note: ...which again requires finding trait impls of `Foo`, completing the cycle
+note: cycle used when checking that `Foo` is well-formed
   --> $DIR/unknown-lifetime-ice-119827.rs:1:1
    |
-LL | / trait Foo {
-LL | |     type Context<'c>
-LL | |     where
-LL | |         Self: 'c;
-...  |
-LL | |
-LL | | fn main() {}
-   | |____________^
+LL | trait Foo {
+   | ^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
-error[E0391]: cycle detected when computing type of `<impl at $DIR/unknown-lifetime-ice-119827.rs:7:1: 7:26>`
-  --> $DIR/unknown-lifetime-ice-119827.rs:7:1
-   |
-LL | impl Foo for Box<dyn Foo> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: ...which immediately requires computing type of `<impl at $DIR/unknown-lifetime-ice-119827.rs:7:1: 7:26>` again
-note: cycle used when collecting item types in top-level module
-  --> $DIR/unknown-lifetime-ice-119827.rs:1:1
-   |
-LL | / trait Foo {
-LL | |     type Context<'c>
-LL | |     where
-LL | |         Self: 'c;
-...  |
-LL | |
-LL | | fn main() {}
-   | |____________^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+error: aborting due to 1 previous error
 
-error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/unknown-lifetime-ice-119827.rs:7:22
-   |
-LL | impl Foo for Box<dyn Foo> {}
-   |                      ^^^ `Foo` cannot be made into an object
-   |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/unknown-lifetime-ice-119827.rs:2:10
-   |
-LL | trait Foo {
-   |       --- this trait cannot be made into an object...
-LL |     type Context<'c>
-   |          ^^^^^^^ ...because it contains the generic associated type `Context`
-   = help: consider moving `Context` to another trait
-   = help: only type `{type error}` implements the trait, consider using it directly instead
-
-error[E0277]: the trait bound `Box<(dyn Foo + 'static)>: Foo` is not satisfied
-  --> $DIR/unknown-lifetime-ice-119827.rs:7:14
-   |
-LL | impl Foo for Box<dyn Foo> {}
-   |              ^^^^^^^^^^^^ the trait `Foo` is not implemented for `Box<(dyn Foo + 'static)>`
-   |
-   = help: the trait `Foo` is implemented for `Box<(dyn Foo + 'static)>`
-
-error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/unknown-lifetime-ice-119827.rs:7:14
-   |
-LL | impl Foo for Box<dyn Foo> {}
-   |              ^^^^^^^^^^^^ `Foo` cannot be made into an object
-   |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/unknown-lifetime-ice-119827.rs:2:10
-   |
-LL | trait Foo {
-   |       --- this trait cannot be made into an object...
-LL |     type Context<'c>
-   |          ^^^^^^^ ...because it contains the generic associated type `Context`
-   = help: consider moving `Context` to another trait
-   = help: only type `std::boxed::Box<(dyn Foo + 'static)>` implements the trait, consider using it directly instead
-
-error[E0046]: not all trait items implemented, missing: `Context`
-  --> $DIR/unknown-lifetime-ice-119827.rs:7:1
-   |
-LL |     type Context<'c>
-   |     ---------------- `Context` from trait
-...
-LL | impl Foo for Box<dyn Foo> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Context` in implementation
-
-error: aborting due to 7 previous errors
-
-Some errors have detailed explanations: E0038, E0046, E0277, E0391.
-For more information about an error, try `rustc --explain E0038`.
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs
index 33b99259dfe..9d067229b6d 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs
@@ -1,6 +1,7 @@
 // Test various non-exhaustive matches for `X..`, `..=X` and `..X` ranges.
 
 #![feature(exclusive_range_pattern)]
+#![allow(non_contiguous_range_endpoints)]
 
 fn main() {}
 
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
index 1e68235303b..6b20a820b73 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:14:8
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:15:8
    |
 LL |     m!(0f32, f32::NEG_INFINITY..);
    |        ^^^^ pattern `_` not covered
@@ -11,7 +11,7 @@ LL |         match $s { $($t)+ => {}, _ => todo!() }
    |                                ++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:15:8
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:16:8
    |
 LL |     m!(0f32, ..f32::INFINITY);
    |        ^^^^ pattern `_` not covered
@@ -23,7 +23,7 @@ LL |         match $s { $($t)+ => {}, _ => todo!() }
    |                                ++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:24:8
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:25:8
    |
 LL |     m!('a', ..core::char::MAX);
    |        ^^^ pattern `'\u{10ffff}'` not covered
@@ -35,7 +35,7 @@ LL |         match $s { $($t)+ => {}, '\u{10ffff}' => todo!() }
    |                                +++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `'\u{10fffe}'..='\u{10ffff}'` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:25:8
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8
    |
 LL |     m!('a', ..ALMOST_MAX);
    |        ^^^ pattern `'\u{10fffe}'..='\u{10ffff}'` not covered
@@ -47,7 +47,7 @@ LL |         match $s { $($t)+ => {}, '\u{10fffe}'..='\u{10ffff}' => todo!() }
    |                                ++++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `'\0'` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8
    |
 LL |     m!('a', ALMOST_MIN..);
    |        ^^^ pattern `'\0'` not covered
@@ -59,7 +59,7 @@ LL |         match $s { $($t)+ => {}, '\0' => todo!() }
    |                                +++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8
    |
 LL |     m!('a', ..=ALMOST_MAX);
    |        ^^^ pattern `'\u{10ffff}'` not covered
@@ -71,7 +71,7 @@ LL |         match $s { $($t)+ => {}, '\u{10ffff}' => todo!() }
    |                                +++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `'b'` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8
    |
 LL |     m!('a', ..=VAL | VAL_2..);
    |        ^^^ pattern `'b'` not covered
@@ -83,7 +83,7 @@ LL |         match $s { $($t)+ => {}, 'b' => todo!() }
    |                                ++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `'b'` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:30:8
    |
 LL |     m!('a', ..VAL_1 | VAL_2..);
    |        ^^^ pattern `'b'` not covered
@@ -95,7 +95,7 @@ LL |         match $s { $($t)+ => {}, 'b' => todo!() }
    |                                ++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:39:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:40:12
    |
 LL |         m!(0, ..u8::MAX);
    |            ^ pattern `u8::MAX` not covered
@@ -107,7 +107,7 @@ LL |         match $s { $($t)+ => {}, u8::MAX => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `254_u8..=u8::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:40:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `254_u8..=u8::MAX` not covered
@@ -119,7 +119,7 @@ LL |         match $s { $($t)+ => {}, 254_u8..=u8::MAX => todo!() }
    |                                +++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_u8` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `0_u8` not covered
@@ -131,7 +131,7 @@ LL |         match $s { $($t)+ => {}, 0_u8 => todo!() }
    |                                +++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `u8::MAX` not covered
@@ -143,7 +143,7 @@ LL |         match $s { $($t)+ => {}, u8::MAX => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u8` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_u8` not covered
@@ -155,7 +155,7 @@ LL |         match $s { $($t)+ => {}, 43_u8 => todo!() }
    |                                ++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u8` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:45:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_u8` not covered
@@ -167,7 +167,7 @@ LL |         match $s { $($t)+ => {}, 43_u8 => todo!() }
    |                                ++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u16::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:52:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:53:12
    |
 LL |         m!(0, ..u16::MAX);
    |            ^ pattern `u16::MAX` not covered
@@ -179,7 +179,7 @@ LL |         match $s { $($t)+ => {}, u16::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `65534_u16..=u16::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:53:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `65534_u16..=u16::MAX` not covered
@@ -191,7 +191,7 @@ LL |         match $s { $($t)+ => {}, 65534_u16..=u16::MAX => todo!() }
    |                                +++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_u16` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `0_u16` not covered
@@ -203,7 +203,7 @@ LL |         match $s { $($t)+ => {}, 0_u16 => todo!() }
    |                                ++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u16::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `u16::MAX` not covered
@@ -215,7 +215,7 @@ LL |         match $s { $($t)+ => {}, u16::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u16` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_u16` not covered
@@ -227,7 +227,7 @@ LL |         match $s { $($t)+ => {}, 43_u16 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u16` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:58:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_u16` not covered
@@ -239,7 +239,7 @@ LL |         match $s { $($t)+ => {}, 43_u16 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u32::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:65:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:66:12
    |
 LL |         m!(0, ..u32::MAX);
    |            ^ pattern `u32::MAX` not covered
@@ -251,7 +251,7 @@ LL |         match $s { $($t)+ => {}, u32::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `4294967294_u32..=u32::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:66:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `4294967294_u32..=u32::MAX` not covered
@@ -263,7 +263,7 @@ LL |         match $s { $($t)+ => {}, 4294967294_u32..=u32::MAX => todo!() }
    |                                ++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_u32` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `0_u32` not covered
@@ -275,7 +275,7 @@ LL |         match $s { $($t)+ => {}, 0_u32 => todo!() }
    |                                ++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u32::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `u32::MAX` not covered
@@ -287,7 +287,7 @@ LL |         match $s { $($t)+ => {}, u32::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u32` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_u32` not covered
@@ -299,7 +299,7 @@ LL |         match $s { $($t)+ => {}, 43_u32 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u32` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:71:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_u32` not covered
@@ -311,7 +311,7 @@ LL |         match $s { $($t)+ => {}, 43_u32 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u64::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:78:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:79:12
    |
 LL |         m!(0, ..u64::MAX);
    |            ^ pattern `u64::MAX` not covered
@@ -323,7 +323,7 @@ LL |         match $s { $($t)+ => {}, u64::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `18446744073709551614_u64..=u64::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:79:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `18446744073709551614_u64..=u64::MAX` not covered
@@ -335,7 +335,7 @@ LL |         match $s { $($t)+ => {}, 18446744073709551614_u64..=u64::MAX => tod
    |                                ++++++++++++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_u64` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `0_u64` not covered
@@ -347,7 +347,7 @@ LL |         match $s { $($t)+ => {}, 0_u64 => todo!() }
    |                                ++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u64::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `u64::MAX` not covered
@@ -359,7 +359,7 @@ LL |         match $s { $($t)+ => {}, u64::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u64` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_u64` not covered
@@ -371,7 +371,7 @@ LL |         match $s { $($t)+ => {}, 43_u64 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u64` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:84:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_u64` not covered
@@ -383,7 +383,7 @@ LL |         match $s { $($t)+ => {}, 43_u64 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:91:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:92:12
    |
 LL |         m!(0, ..u128::MAX);
    |            ^ pattern `u128::MAX` not covered
@@ -395,7 +395,7 @@ LL |         match $s { $($t)+ => {}, u128::MAX => todo!() }
    |                                ++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454_u128..=u128::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:92:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `340282366920938463463374607431768211454_u128..=u128::MAX` not covered
@@ -407,7 +407,7 @@ LL |         match $s { $($t)+ => {}, 340282366920938463463374607431768211454_u1
    |                                +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_u128` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `0_u128` not covered
@@ -419,7 +419,7 @@ LL |         match $s { $($t)+ => {}, 0_u128 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `u128::MAX` not covered
@@ -431,7 +431,7 @@ LL |         match $s { $($t)+ => {}, u128::MAX => todo!() }
    |                                ++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u128` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_u128` not covered
@@ -443,7 +443,7 @@ LL |         match $s { $($t)+ => {}, 43_u128 => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_u128` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:97:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_u128` not covered
@@ -455,7 +455,7 @@ LL |         match $s { $($t)+ => {}, 43_u128 => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:107:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:108:12
    |
 LL |         m!(0, ..i8::MAX);
    |            ^ pattern `i8::MAX` not covered
@@ -467,7 +467,7 @@ LL |         match $s { $($t)+ => {}, i8::MAX => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `126_i8..=i8::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:108:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `126_i8..=i8::MAX` not covered
@@ -479,7 +479,7 @@ LL |         match $s { $($t)+ => {}, 126_i8..=i8::MAX => todo!() }
    |                                +++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i8::MIN` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `i8::MIN` not covered
@@ -491,7 +491,7 @@ LL |         match $s { $($t)+ => {}, i8::MIN => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `i8::MAX` not covered
@@ -503,7 +503,7 @@ LL |         match $s { $($t)+ => {}, i8::MAX => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i8` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_i8` not covered
@@ -515,7 +515,7 @@ LL |         match $s { $($t)+ => {}, 43_i8 => todo!() }
    |                                ++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i8` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:113:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_i8` not covered
@@ -527,7 +527,7 @@ LL |         match $s { $($t)+ => {}, 43_i8 => todo!() }
    |                                ++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i16::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:120:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:121:12
    |
 LL |         m!(0, ..i16::MAX);
    |            ^ pattern `i16::MAX` not covered
@@ -539,7 +539,7 @@ LL |         match $s { $($t)+ => {}, i16::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `32766_i16..=i16::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:121:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `32766_i16..=i16::MAX` not covered
@@ -551,7 +551,7 @@ LL |         match $s { $($t)+ => {}, 32766_i16..=i16::MAX => todo!() }
    |                                +++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i16::MIN` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `i16::MIN` not covered
@@ -563,7 +563,7 @@ LL |         match $s { $($t)+ => {}, i16::MIN => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i16::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `i16::MAX` not covered
@@ -575,7 +575,7 @@ LL |         match $s { $($t)+ => {}, i16::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i16` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_i16` not covered
@@ -587,7 +587,7 @@ LL |         match $s { $($t)+ => {}, 43_i16 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i16` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:126:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_i16` not covered
@@ -599,7 +599,7 @@ LL |         match $s { $($t)+ => {}, 43_i16 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i32::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:133:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:134:12
    |
 LL |         m!(0, ..i32::MAX);
    |            ^ pattern `i32::MAX` not covered
@@ -611,7 +611,7 @@ LL |         match $s { $($t)+ => {}, i32::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `2147483646_i32..=i32::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:134:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `2147483646_i32..=i32::MAX` not covered
@@ -623,7 +623,7 @@ LL |         match $s { $($t)+ => {}, 2147483646_i32..=i32::MAX => todo!() }
    |                                ++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i32::MIN` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `i32::MIN` not covered
@@ -635,7 +635,7 @@ LL |         match $s { $($t)+ => {}, i32::MIN => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i32::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `i32::MAX` not covered
@@ -647,7 +647,7 @@ LL |         match $s { $($t)+ => {}, i32::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i32` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_i32` not covered
@@ -659,7 +659,7 @@ LL |         match $s { $($t)+ => {}, 43_i32 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i32` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:139:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_i32` not covered
@@ -671,7 +671,7 @@ LL |         match $s { $($t)+ => {}, 43_i32 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i64::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:146:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:147:12
    |
 LL |         m!(0, ..i64::MAX);
    |            ^ pattern `i64::MAX` not covered
@@ -683,7 +683,7 @@ LL |         match $s { $($t)+ => {}, i64::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `9223372036854775806_i64..=i64::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:147:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `9223372036854775806_i64..=i64::MAX` not covered
@@ -695,7 +695,7 @@ LL |         match $s { $($t)+ => {}, 9223372036854775806_i64..=i64::MAX => todo
    |                                +++++++++++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i64::MIN` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `i64::MIN` not covered
@@ -707,7 +707,7 @@ LL |         match $s { $($t)+ => {}, i64::MIN => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i64::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `i64::MAX` not covered
@@ -719,7 +719,7 @@ LL |         match $s { $($t)+ => {}, i64::MAX => todo!() }
    |                                +++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i64` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_i64` not covered
@@ -731,7 +731,7 @@ LL |         match $s { $($t)+ => {}, 43_i64 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i64` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:152:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_i64` not covered
@@ -743,7 +743,7 @@ LL |         match $s { $($t)+ => {}, 43_i64 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i128::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:159:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:160:12
    |
 LL |         m!(0, ..i128::MAX);
    |            ^ pattern `i128::MAX` not covered
@@ -755,7 +755,7 @@ LL |         match $s { $($t)+ => {}, i128::MAX => todo!() }
    |                                ++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726_i128..=i128::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:160:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12
    |
 LL |         m!(0, ..ALMOST_MAX);
    |            ^ pattern `170141183460469231731687303715884105726_i128..=i128::MAX` not covered
@@ -767,7 +767,7 @@ LL |         match $s { $($t)+ => {}, 170141183460469231731687303715884105726_i1
    |                                +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i128::MIN` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12
    |
 LL |         m!(0, ALMOST_MIN..);
    |            ^ pattern `i128::MIN` not covered
@@ -779,7 +779,7 @@ LL |         match $s { $($t)+ => {}, i128::MIN => todo!() }
    |                                ++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i128::MAX` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
    |            ^ pattern `i128::MAX` not covered
@@ -791,7 +791,7 @@ LL |         match $s { $($t)+ => {}, i128::MAX => todo!() }
    |                                ++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i128` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12
    |
 LL |         m!(0, ..=VAL | VAL_2..);
    |            ^ pattern `43_i128` not covered
@@ -803,7 +803,7 @@ LL |         match $s { $($t)+ => {}, 43_i128 => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `43_i128` not covered
-  --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12
+  --> $DIR/half-open-range-pats-exhaustive-fail.rs:165:12
    |
 LL |         m!(0, ..VAL_1 | VAL_2..);
    |            ^ pattern `43_i128` not covered
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions0.rs b/tests/ui/half-open-range-patterns/range_pat_interactions0.rs
index 7a82f9ce89a..53b6b89ed16 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions0.rs
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions0.rs
@@ -1,4 +1,5 @@
 //@ run-pass
+#![allow(non_contiguous_range_endpoints)]
 #![feature(exclusive_range_pattern)]
 #![feature(inline_const_pat)]
 
diff --git a/tests/ui/hashmap/hashmap-memory.rs b/tests/ui/hashmap/hashmap-memory.rs
index 0b1e09f5344..6db5d2e7bef 100644
--- a/tests/ui/hashmap/hashmap-memory.rs
+++ b/tests/ui/hashmap/hashmap-memory.rs
@@ -4,7 +4,7 @@
 #![allow(non_camel_case_types)]
 #![allow(dead_code)]
 #![allow(unused_mut)]
-//@ ignore-emscripten No support for threads
+//@ needs-threads
 
 /**
    A somewhat reduced test case to expose some Valgrind issues.
diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs b/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs
index 06c3d9ad434..a9ea657f10e 100644
--- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs
+++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs
@@ -2,19 +2,19 @@
 use std::fmt::Debug;
 
 fn a() -> impl Fn(&u8) -> (impl Debug + '_) {
-    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     |x| x
     //~^ ERROR lifetime may not live long enough
 }
 
 fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) {
-    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     |x| x
     //~^ ERROR lifetime may not live long enough
 }
 
 fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) {
-    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     |x| x
     //~^ ERROR lifetime may not live long enough
 }
diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr
index ebab9940493..bdb099619b7 100644
--- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr
+++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr
@@ -10,7 +10,7 @@ help: consider using the `'static` lifetime, but this is uncommon unless you're
 LL | fn d() -> impl Fn() -> (impl Debug + 'static) {
    |                                      ~~~~~~~
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/impl-fn-hrtb-bounds.rs:4:41
    |
 LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) {
@@ -22,7 +22,16 @@ note: lifetime declared here
 LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) {
    |                   ^
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error: lifetime may not live long enough
+  --> $DIR/impl-fn-hrtb-bounds.rs:6:9
+   |
+LL |     |x| x
+   |      -- ^ returning this value requires that `'1` must outlive `'2`
+   |      ||
+   |      |return type of closure is impl Debug + '2
+   |      has type `&'1 u8`
+
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/impl-fn-hrtb-bounds.rs:10:52
    |
 LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) {
@@ -34,7 +43,16 @@ note: lifetime declared here
 LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) {
    |                    ^^
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error: lifetime may not live long enough
+  --> $DIR/impl-fn-hrtb-bounds.rs:12:9
+   |
+LL |     |x| x
+   |      -- ^ returning this value requires that `'1` must outlive `'2`
+   |      ||
+   |      |return type of closure is impl Debug + '2
+   |      has type `&'1 u8`
+
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/impl-fn-hrtb-bounds.rs:16:52
    |
 LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) {
@@ -46,24 +64,6 @@ note: lifetime declared here
 LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) {
    |                    ^^
 
-error: lifetime may not live long enough
-  --> $DIR/impl-fn-hrtb-bounds.rs:6:9
-   |
-LL |     |x| x
-   |      -- ^ returning this value requires that `'1` must outlive `'2`
-   |      ||
-   |      |return type of closure is impl Debug + '2
-   |      has type `&'1 u8`
-
-error: lifetime may not live long enough
-  --> $DIR/impl-fn-hrtb-bounds.rs:12:9
-   |
-LL |     |x| x
-   |      -- ^ returning this value requires that `'1` must outlive `'2`
-   |      ||
-   |      |return type of closure is impl Debug + '2
-   |      has type `&'1 u8`
-
 error: lifetime may not live long enough
   --> $DIR/impl-fn-hrtb-bounds.rs:18:9
    |
@@ -75,4 +75,5 @@ LL |     |x| x
 
 error: aborting due to 7 previous errors
 
-For more information about this error, try `rustc --explain E0106`.
+Some errors have detailed explanations: E0106, E0657.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs
index a4a1f1dcee1..ef9d8733509 100644
--- a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs
+++ b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs
@@ -3,7 +3,7 @@ use std::fmt::Debug;
 
 fn a() -> impl Fn(&u8) -> impl Debug + '_ {
     //~^ ERROR ambiguous `+` in a type
-    //~| ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    //~| ERROR cannot capture higher-ranked lifetime from outer `impl Trait`
     |x| x
     //~^ ERROR lifetime may not live long enough
 }
diff --git a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr
index e18e89700b4..3881b37a0cb 100644
--- a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr
+++ b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr
@@ -10,7 +10,7 @@ error: ambiguous `+` in a type
 LL | fn b() -> impl Fn() -> impl Debug + Send {
    |                        ^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + Send)`
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/impl-fn-parsing-ambiguities.rs:4:40
    |
 LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ {
@@ -33,3 +33,4 @@ LL |     |x| x
 
 error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/impl-trait/implicit-capture-late.stderr b/tests/ui/impl-trait/implicit-capture-late.stderr
index 2fb5ebb6541..080750f8497 100644
--- a/tests/ui/impl-trait/implicit-capture-late.stderr
+++ b/tests/ui/impl-trait/implicit-capture-late.stderr
@@ -1,4 +1,10 @@
-error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
+  --> $DIR/implicit-capture-late.rs:10:55
+   |
+LL | fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> {
+   |                                                       ^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope
+   |
+note: lifetime declared here
   --> $DIR/implicit-capture-late.rs:10:36
    |
 LL | fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> {
diff --git a/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs
new file mode 100644
index 00000000000..6f0dbd752b0
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs
@@ -0,0 +1,18 @@
+struct Wrapper<'rom>(T);
+//~^ ERROR cannot find type `T` in this scope
+
+trait Foo {
+    fn bar() -> Wrapper<impl Sized>;
+    //~^ ERROR missing lifetime specifier
+    //~| ERROR struct takes 0 generic arguments but 1 generic argument was supplied
+}
+
+impl Foo for () {
+    fn bar() -> i32 {
+        //~^ ERROR method `bar` has an incompatible type for trait
+        //~| ERROR method `bar` has an incompatible return type for trait
+        0
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr
new file mode 100644
index 00000000000..d30557c8a7b
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr
@@ -0,0 +1,67 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/opaque-and-lifetime-mismatch.rs:5:24
+   |
+LL |     fn bar() -> Wrapper<impl Sized>;
+   |                        ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values
+   |
+LL |     fn bar() -> Wrapper<'static, impl Sized>;
+   |                         ++++++++
+
+error[E0412]: cannot find type `T` in this scope
+  --> $DIR/opaque-and-lifetime-mismatch.rs:1:22
+   |
+LL | struct Wrapper<'rom>(T);
+   |                      ^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | struct Wrapper<'rom, T>(T);
+   |                    +++
+
+error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied
+  --> $DIR/opaque-and-lifetime-mismatch.rs:5:17
+   |
+LL |     fn bar() -> Wrapper<impl Sized>;
+   |                 ^^^^^^^ ---------- help: remove this generic argument
+   |                 |
+   |                 expected 0 generic arguments
+   |
+note: struct defined here, with 0 generic parameters
+  --> $DIR/opaque-and-lifetime-mismatch.rs:1:8
+   |
+LL | struct Wrapper<'rom>(T);
+   |        ^^^^^^^
+
+error[E0053]: method `bar` has an incompatible return type for trait
+  --> $DIR/opaque-and-lifetime-mismatch.rs:11:17
+   |
+LL |     fn bar() -> i32 {
+   |                 ^^^
+   |                 |
+   |                 expected `Wrapper<'static>`, found `i32`
+   |                 return type in trait
+
+error[E0053]: method `bar` has an incompatible type for trait
+  --> $DIR/opaque-and-lifetime-mismatch.rs:11:17
+   |
+LL |     fn bar() -> i32 {
+   |                 ^^^
+   |                 |
+   |                 expected `Wrapper<'static>`, found `i32`
+   |                 help: change the output type to match the trait: `Wrapper<'static>`
+   |
+note: type in trait
+  --> $DIR/opaque-and-lifetime-mismatch.rs:5:17
+   |
+LL |     fn bar() -> Wrapper<impl Sized>;
+   |                 ^^^^^^^^^^^^^^^^^^^
+   = note: expected signature `fn() -> Wrapper<'static>`
+              found signature `fn() -> i32`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0053, E0106, E0107, E0412.
+For more information about an error, try `rustc --explain E0053`.
diff --git a/tests/ui/impl-trait/in-trait/rpitit-cycle-in-generics-of.rs b/tests/ui/impl-trait/in-trait/rpitit-cycle-in-generics-of.rs
new file mode 100644
index 00000000000..882497d1015
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/rpitit-cycle-in-generics-of.rs
@@ -0,0 +1,18 @@
+//@ check-pass
+
+// Check that we don't hit a query cycle when:
+// 1. Computing generics_of, which requires...
+// 2. Calling resolve_bound_vars, which requires...
+// 3. Calling associated_items, which requires...
+// 4. Calling associated_type_for_impl_trait_in_trait, which requires...
+// 5. Computing generics_of, which cycles.
+
+pub trait Foo<'a> {
+    type Assoc;
+
+    fn demo<T>(other: T) -> impl Foo<'a, Assoc = Self::Assoc>
+    where
+        T: Foo<'a, Assoc = ()>;
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/issues/issue-54895.rs b/tests/ui/impl-trait/issues/issue-54895.rs
index 8d7a1d56f83..13c0038ce43 100644
--- a/tests/ui/impl-trait/issues/issue-54895.rs
+++ b/tests/ui/impl-trait/issues/issue-54895.rs
@@ -13,7 +13,7 @@ impl<'a> Trait<'a> for X {
 }
 
 fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
-    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     X(())
 }
 
diff --git a/tests/ui/impl-trait/issues/issue-54895.stderr b/tests/ui/impl-trait/issues/issue-54895.stderr
index 999ffd52141..64b425328e3 100644
--- a/tests/ui/impl-trait/issues/issue-54895.stderr
+++ b/tests/ui/impl-trait/issues/issue-54895.stderr
@@ -1,4 +1,4 @@
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/issue-54895.rs:15:53
    |
 LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
@@ -12,3 +12,4 @@ LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/impl-trait/issues/issue-67830.rs b/tests/ui/impl-trait/issues/issue-67830.rs
index 6dc8935c777..939eca82a8f 100644
--- a/tests/ui/impl-trait/issues/issue-67830.rs
+++ b/tests/ui/impl-trait/issues/issue-67830.rs
@@ -19,7 +19,7 @@ where
 
 struct A;
 fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
-    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     Wrap(|a| Some(a).into_iter())
     //~^ ERROR implementation of `FnOnce` is not general enough
     //~| ERROR implementation of `FnOnce` is not general enough
diff --git a/tests/ui/impl-trait/issues/issue-67830.stderr b/tests/ui/impl-trait/issues/issue-67830.stderr
index 546198b8a10..ef513a40cf3 100644
--- a/tests/ui/impl-trait/issues/issue-67830.stderr
+++ b/tests/ui/impl-trait/issues/issue-67830.stderr
@@ -1,4 +1,4 @@
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/issue-67830.rs:21:62
    |
 LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
@@ -31,3 +31,4 @@ LL |     Wrap(|a| Some(a).into_iter())
 
 error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/impl-trait/issues/issue-83919.stderr b/tests/ui/impl-trait/issues/issue-83919.stderr
index 200257235fe..b0bd6ed116b 100644
--- a/tests/ui/impl-trait/issues/issue-83919.stderr
+++ b/tests/ui/impl-trait/issues/issue-83919.stderr
@@ -5,7 +5,6 @@ LL |     fn get_fut(&self) -> Self::Fut {
    |                          ^^^^^^^^^ `{integer}` is not a future
    |
    = help: the trait `Future` is not implemented for `{integer}`
-   = note: {integer} must be a future or must implement `IntoFuture` to be awaited
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/issues/issue-86800.rs b/tests/ui/impl-trait/issues/issue-86800.rs
index ae6e198c2ad..172ab04f58d 100644
--- a/tests/ui/impl-trait/issues/issue-86800.rs
+++ b/tests/ui/impl-trait/issues/issue-86800.rs
@@ -1,12 +1,6 @@
 #![feature(type_alias_impl_trait)]
 
 //@ edition:2021
-//@ compile-flags:-Z treat-err-as-bug=2
-//@ error-pattern: due to `-Z treat-err-as-bug=2
-//@ failure-status:101
-//@ normalize-stderr-test ".*note: .*\n\n" -> ""
-//@ normalize-stderr-test "thread 'rustc' panicked.*:\n.*\n" -> ""
-//@ rustc-env:RUST_BACKTRACE=0
 
 use std::future::Future;
 
@@ -29,6 +23,7 @@ struct Context {
 type TransactionResult<O> = Result<O, ()>;
 
 type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
+//~^ ERROR unconstrained opaque type
 
 fn execute_transaction_fut<'f, F, O>(
     f: F,
@@ -37,6 +32,7 @@ where
     F: FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O> + 'f
 {
     f
+    //~^ ERROR expected generic lifetime parameter, found `'_`
 }
 
 impl Context {
@@ -44,6 +40,7 @@ impl Context {
         &self, f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>
     ) -> TransactionResult<O>
     {
+        //~^ ERROR expected generic lifetime parameter, found `'_`
         let mut conn = Connection {};
         let mut transaction = TestTransaction { conn: &mut conn };
         f(&mut transaction).await
diff --git a/tests/ui/impl-trait/issues/issue-86800.stderr b/tests/ui/impl-trait/issues/issue-86800.stderr
index 7af4846a959..146d2f67942 100644
--- a/tests/ui/impl-trait/issues/issue-86800.stderr
+++ b/tests/ui/impl-trait/issues/issue-86800.stderr
@@ -1,11 +1,13 @@
 error: unconstrained opaque type
-  --> $DIR/issue-86800.rs:31:34
+  --> $DIR/issue-86800.rs:25:34
    |
 LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-error: internal compiler error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/issue-86800.rs:39:5
+   = note: `TransactionFuture` must be used in combination with a concrete type within the same module
+
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/issue-86800.rs:34:5
    |
 LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
    |                        --- this generic parameter must be used with a generic lifetime parameter
@@ -13,9 +15,20 @@ LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResu
 LL |     f
    |     ^
 
-error: the compiler unexpectedly panicked. this is a bug.
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/issue-86800.rs:42:5
+   |
+LL |   type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
+   |                          --- this generic parameter must be used with a generic lifetime parameter
+...
+LL | /     {
+LL | |
+LL | |         let mut conn = Connection {};
+LL | |         let mut transaction = TestTransaction { conn: &mut conn };
+LL | |         f(&mut transaction).await
+LL | |     }
+   | |_____^
 
-query stack during panic:
-#0 [mir_borrowck] borrow-checking `execute_transaction_fut`
-#1 [type_of_opaque] computing type of opaque `execute_transaction_fut::{opaque#0}`
-end of query stack
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/issues/issue-87340.rs b/tests/ui/impl-trait/issues/issue-87340.rs
index 705a4addcb7..b1baaaa6ba5 100644
--- a/tests/ui/impl-trait/issues/issue-87340.rs
+++ b/tests/ui/impl-trait/issues/issue-87340.rs
@@ -9,6 +9,8 @@ impl<T> X for () {
     //~^ ERROR `T` is not constrained by the impl trait, self type, or predicates
     type I = impl Sized;
     fn f() -> Self::I {}
+    //~^ ERROR type annotations needed
+    //~| ERROR type annotations needed
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/issues/issue-87340.stderr b/tests/ui/impl-trait/issues/issue-87340.stderr
index 8513cb2881e..1be4087be42 100644
--- a/tests/ui/impl-trait/issues/issue-87340.stderr
+++ b/tests/ui/impl-trait/issues/issue-87340.stderr
@@ -4,6 +4,19 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
 LL | impl<T> X for () {
    |      ^ unconstrained type parameter
 
-error: aborting due to 1 previous error
+error[E0282]: type annotations needed
+  --> $DIR/issue-87340.rs:11:23
+   |
+LL |     fn f() -> Self::I {}
+   |                       ^^ cannot infer type for type parameter `T`
 
-For more information about this error, try `rustc --explain E0207`.
+error[E0282]: type annotations needed
+  --> $DIR/issue-87340.rs:11:15
+   |
+LL |     fn f() -> Self::I {}
+   |               ^^^^^^^ cannot infer type for type parameter `T`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0207, E0282.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/impl-trait/issues/issue-88236-2.rs b/tests/ui/impl-trait/issues/issue-88236-2.rs
index f4354d1b2ae..7ff08d8174f 100644
--- a/tests/ui/impl-trait/issues/issue-88236-2.rs
+++ b/tests/ui/impl-trait/issues/issue-88236-2.rs
@@ -13,17 +13,17 @@ impl<'a> Hrtb<'a> for &'a () {
 }
 
 fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
-//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
 
 fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
-    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     &()
     //~^ ERROR implementation of `Hrtb` is not general enough
     //~| ERROR implementation of `Hrtb` is not general enough
 }
 
 fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
-    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     x
     //~^ ERROR implementation of `Hrtb` is not general enough
     //~| ERROR implementation of `Hrtb` is not general enough
diff --git a/tests/ui/impl-trait/issues/issue-88236-2.stderr b/tests/ui/impl-trait/issues/issue-88236-2.stderr
index 1e63338d6d1..09fd58056a5 100644
--- a/tests/ui/impl-trait/issues/issue-88236-2.stderr
+++ b/tests/ui/impl-trait/issues/issue-88236-2.stderr
@@ -1,4 +1,4 @@
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/issue-88236-2.rs:15:61
    |
 LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
@@ -10,7 +10,7 @@ note: lifetime declared here
 LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
    |                            ^^
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/issue-88236-2.rs:18:80
    |
 LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
@@ -22,18 +22,6 @@ note: lifetime declared here
 LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
    |                                               ^^
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
-  --> $DIR/issue-88236-2.rs:25:78
-   |
-LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
-   |                                                                              ^^
-   |
-note: lifetime declared here
-  --> $DIR/issue-88236-2.rs:25:45
-   |
-LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
-   |                                             ^^
-
 error: implementation of `Hrtb` is not general enough
   --> $DIR/issue-88236-2.rs:20:5
    |
@@ -52,6 +40,18 @@ LL |     &()
    = note: `Hrtb<'a>` would have to be implemented for the type `&()`
    = note: ...but `Hrtb<'0>` is actually implemented for the type `&'0 ()`, for some specific lifetime `'0`
 
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
+  --> $DIR/issue-88236-2.rs:25:78
+   |
+LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+   |                                                                              ^^
+   |
+note: lifetime declared here
+  --> $DIR/issue-88236-2.rs:25:45
+   |
+LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
+   |                                             ^^
+
 error: lifetime may not live long enough
   --> $DIR/issue-88236-2.rs:27:5
    |
@@ -90,3 +90,4 @@ LL |     x
 
 error: aborting due to 8 previous errors
 
+For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/impl-trait/issues/issue-88236.rs b/tests/ui/impl-trait/issues/issue-88236.rs
index 36d12417354..e782a876573 100644
--- a/tests/ui/impl-trait/issues/issue-88236.rs
+++ b/tests/ui/impl-trait/issues/issue-88236.rs
@@ -13,6 +13,6 @@ impl<'a> Hrtb<'a> for &'a () {
 }
 
 fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
-//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
 
 fn main() {}
diff --git a/tests/ui/impl-trait/issues/issue-88236.stderr b/tests/ui/impl-trait/issues/issue-88236.stderr
index 6cf1a42d6a9..5dee5f88c89 100644
--- a/tests/ui/impl-trait/issues/issue-88236.stderr
+++ b/tests/ui/impl-trait/issues/issue-88236.stderr
@@ -1,4 +1,4 @@
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/issue-88236.rs:15:61
    |
 LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
@@ -12,3 +12,4 @@ LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.rs b/tests/ui/impl-trait/nested-rpit-hrtb.rs
index a3eca741daa..c10bfbfe4dc 100644
--- a/tests/ui/impl-trait/nested-rpit-hrtb.rs
+++ b/tests/ui/impl-trait/nested-rpit-hrtb.rs
@@ -23,18 +23,18 @@ impl Qux<'_> for () {}
 
 // This is not supported.
 fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {}
-//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
 
 // This is not supported.
 fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {}
-//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
 
 fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
-//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
 //~| ERROR implementation of `Bar` is not general enough
 
 fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
-//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
 //~| ERROR: the trait bound `for<'a> &'a (): Qux<'_>` is not satisfied
 
 // This should resolve.
diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.stderr b/tests/ui/impl-trait/nested-rpit-hrtb.stderr
index 0e0f76874e3..2779694a517 100644
--- a/tests/ui/impl-trait/nested-rpit-hrtb.stderr
+++ b/tests/ui/impl-trait/nested-rpit-hrtb.stderr
@@ -29,7 +29,7 @@ help: consider introducing lifetime `'b` here
 LL | fn two_htrb_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
    |                          ++++
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/nested-rpit-hrtb.rs:25:69
    |
 LL | fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {}
@@ -41,7 +41,7 @@ note: lifetime declared here
 LL | fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {}
    |                                    ^^
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/nested-rpit-hrtb.rs:29:68
    |
 LL | fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {}
@@ -53,7 +53,7 @@ note: lifetime declared here
 LL | fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {}
    |                                       ^^
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/nested-rpit-hrtb.rs:32:74
    |
 LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
@@ -65,7 +65,16 @@ note: lifetime declared here
 LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
    |                                         ^^
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error: implementation of `Bar` is not general enough
+  --> $DIR/nested-rpit-hrtb.rs:32:78
+   |
+LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
+   |                                                                              ^^ implementation of `Bar` is not general enough
+   |
+   = note: `()` must implement `Bar<'a>`
+   = note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0`
+
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/nested-rpit-hrtb.rs:36:73
    |
 LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
@@ -77,15 +86,6 @@ note: lifetime declared here
 LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
    |                                            ^^
 
-error: implementation of `Bar` is not general enough
-  --> $DIR/nested-rpit-hrtb.rs:32:78
-   |
-LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
-   |                                                                              ^^ implementation of `Bar` is not general enough
-   |
-   = note: `()` must implement `Bar<'a>`
-   = note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0`
-
 error[E0277]: the trait bound `for<'a> &'a (): Qux<'_>` is not satisfied
   --> $DIR/nested-rpit-hrtb.rs:36:64
    |
@@ -133,5 +133,5 @@ LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Si
 
 error: aborting due to 12 previous errors
 
-Some errors have detailed explanations: E0261, E0277.
+Some errors have detailed explanations: E0261, E0277, E0657.
 For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr
index fee3b86034a..4a5e4bfe94b 100644
--- a/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr
+++ b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr
@@ -1,9 +1,9 @@
 error[E0282]: type annotations needed
-  --> $DIR/recursive-coroutine-boxed.rs:10:23
+  --> $DIR/recursive-coroutine-boxed.rs:11:23
    |
 LL |         let mut gen = Box::pin(foo());
    |                       ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Box`
-...
+LL |
 LL |         let mut r = gen.as_mut().resume(());
    |                         ------ type must be known at this point
    |
@@ -13,10 +13,10 @@ LL |         let mut gen = Box::<T>::pin(foo());
    |                          +++++
 
 error[E0282]: type annotations needed
-  --> $DIR/recursive-coroutine-boxed.rs:10:32
+  --> $DIR/recursive-coroutine-boxed.rs:8:13
    |
-LL |         let mut gen = Box::pin(foo());
-   |                                ^^^^^ cannot infer type for opaque type `impl Coroutine<Yield = (), Return = ()>`
+LL | fn foo() -> impl Coroutine<Yield = (), Return = ()> {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for opaque type `impl Coroutine<Yield = (), Return = ()>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/impl-trait/recursive-coroutine-boxed.rs b/tests/ui/impl-trait/recursive-coroutine-boxed.rs
index a42ae68f28e..8f0bbb400cf 100644
--- a/tests/ui/impl-trait/recursive-coroutine-boxed.rs
+++ b/tests/ui/impl-trait/recursive-coroutine-boxed.rs
@@ -6,10 +6,10 @@
 use std::ops::{Coroutine, CoroutineState};
 
 fn foo() -> impl Coroutine<Yield = (), Return = ()> {
+    //[next]~^ ERROR type annotations needed
     || {
         let mut gen = Box::pin(foo());
         //[next]~^ ERROR type annotations needed
-        //[next]~| ERROR type annotations needed
         let mut r = gen.as_mut().resume(());
         while let CoroutineState::Yielded(v) = r {
             yield v;
diff --git a/tests/ui/impl-trait/wf-check-hidden-type.rs b/tests/ui/impl-trait/wf-check-hidden-type.rs
new file mode 100644
index 00000000000..c3b1182a98f
--- /dev/null
+++ b/tests/ui/impl-trait/wf-check-hidden-type.rs
@@ -0,0 +1,20 @@
+//! Regression test for #114728.
+
+trait Extend<'a, 'b> {
+    fn extend(self, _: &'a str) -> &'b str;
+}
+
+impl<'a, 'b> Extend<'a, 'b> for Option<&'b &'a ()> {
+    fn extend(self, s: &'a str) -> &'b str {
+        s
+    }
+}
+
+fn boom<'a, 'b>() -> impl Extend<'a, 'b> {
+    None::<&'_ &'_ ()> //~ ERROR lifetime may not live long enough
+}
+
+fn main() {
+    let y = boom().extend(&String::from("temporary"));
+    println!("{}", y);
+}
diff --git a/tests/ui/impl-trait/wf-check-hidden-type.stderr b/tests/ui/impl-trait/wf-check-hidden-type.stderr
new file mode 100644
index 00000000000..86ba7aff54a
--- /dev/null
+++ b/tests/ui/impl-trait/wf-check-hidden-type.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+  --> $DIR/wf-check-hidden-type.rs:14:5
+   |
+LL | fn boom<'a, 'b>() -> impl Extend<'a, 'b> {
+   |         --  -- lifetime `'b` defined here
+   |         |
+   |         lifetime `'a` defined here
+LL |     None::<&'_ &'_ ()>
+   |     ^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr
index c4bdd484fdb..bffe0447f8b 100644
--- a/tests/ui/impl-trait/where-allowed.stderr
+++ b/tests/ui/impl-trait/where-allowed.stderr
@@ -342,33 +342,6 @@ LL |     let _in_return_in_local_variable = || -> impl Fn() { || {} };
    |
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
-error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
-  --> $DIR/where-allowed.rs:239:7
-   |
-LL | impl <T = impl Debug> T {}
-   |       ^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
-   = note: `#[deny(invalid_type_param_default)]` on by default
-
-error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
-  --> $DIR/where-allowed.rs:246:36
-   |
-LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
-   |                                    ^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
-
-error[E0118]: no nominal type found for inherent implementation
-  --> $DIR/where-allowed.rs:239:1
-   |
-LL | impl <T = impl Debug> T {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
-   |
-   = note: either implement a trait on it or create a newtype to wrap it instead
-
 error[E0283]: type annotations needed
   --> $DIR/where-allowed.rs:46:57
    |
@@ -389,6 +362,24 @@ LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { pani
            - impl<Args, F, A> Fn<Args> for Box<F, A>
              where Args: Tuple, F: Fn<Args>, A: Allocator, F: ?Sized;
 
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/where-allowed.rs:239:7
+   |
+LL | impl <T = impl Debug> T {}
+   |       ^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+   = note: `#[deny(invalid_type_param_default)]` on by default
+
+error[E0118]: no nominal type found for inherent implementation
+  --> $DIR/where-allowed.rs:239:1
+   |
+LL | impl <T = impl Debug> T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
+   |
+   = note: either implement a trait on it or create a newtype to wrap it instead
+
 error[E0599]: no function or associated item named `into_vec` found for slice `[_]` in the current scope
   --> $DIR/where-allowed.rs:81:5
    |
@@ -428,6 +419,15 @@ LL |     type Out = impl Debug;
    |
    = note: `Out` must be used in combination with a concrete type within the same impl
 
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/where-allowed.rs:246:36
+   |
+LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
+   |                                    ^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+
 error: aborting due to 50 previous errors
 
 Some errors have detailed explanations: E0053, E0118, E0283, E0562, E0599, E0658, E0666.
diff --git a/tests/ui/impl-unused-tps.stderr b/tests/ui/impl-unused-tps.stderr
index 93215326c2f..af427cb5f3e 100644
--- a/tests/ui/impl-unused-tps.stderr
+++ b/tests/ui/impl-unused-tps.stderr
@@ -1,3 +1,25 @@
+error[E0119]: conflicting implementations of trait `Foo<_>` for type `[isize; 0]`
+  --> $DIR/impl-unused-tps.rs:27:1
+   |
+LL | impl<T> Foo<T> for [isize;0] {
+   | ---------------------------- first implementation here
+...
+LL | impl<T,U> Foo<T> for U {
+   | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[isize; 0]`
+
+error[E0275]: overflow evaluating the requirement `([isize; 0], _): Sized`
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`impl_unused_tps`)
+note: required for `([isize; 0], _)` to implement `Bar`
+  --> $DIR/impl-unused-tps.rs:31:11
+   |
+LL | impl<T,U> Bar for T {
+   |      -    ^^^     ^
+   |      |
+   |      unsatisfied trait bound introduced here
+   = note: 126 redundant requirements hidden
+   = note: required for `([isize; 0], _)` to implement `Bar`
+
 error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
   --> $DIR/impl-unused-tps.rs:15:8
    |
@@ -28,28 +50,6 @@ error[E0207]: the type parameter `V` is not constrained by the impl trait, self
 LL | impl<T,U,V> Foo<T> for T
    |          ^ unconstrained type parameter
 
-error[E0119]: conflicting implementations of trait `Foo<_>` for type `[isize; 0]`
-  --> $DIR/impl-unused-tps.rs:27:1
-   |
-LL | impl<T> Foo<T> for [isize;0] {
-   | ---------------------------- first implementation here
-...
-LL | impl<T,U> Foo<T> for U {
-   | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[isize; 0]`
-
-error[E0275]: overflow evaluating the requirement `([isize; 0], _): Sized`
-   |
-   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`impl_unused_tps`)
-note: required for `([isize; 0], _)` to implement `Bar`
-  --> $DIR/impl-unused-tps.rs:31:11
-   |
-LL | impl<T,U> Bar for T {
-   |      -    ^^^     ^
-   |      |
-   |      unsatisfied trait bound introduced here
-   = note: 126 redundant requirements hidden
-   = note: required for `([isize; 0], _)` to implement `Bar`
-
 error: aborting due to 7 previous errors
 
 Some errors have detailed explanations: E0119, E0207, E0275.
diff --git a/tests/ui/imports/append-import-suggestion.rs b/tests/ui/imports/append-import-suggestion.rs
new file mode 100644
index 00000000000..6b75804b86f
--- /dev/null
+++ b/tests/ui/imports/append-import-suggestion.rs
@@ -0,0 +1,16 @@
+// https://github.com/rust-lang/rust/issues/114884
+
+mod mod1 {
+    pub trait TraitA {}
+}
+
+mod mod2 {
+    mod sub_mod {
+       use super::super::mod1::TraitA;
+    }
+}
+
+use mod2::{sub_mod::TraitA};
+//~^ ERROR: module `sub_mod` is private
+
+fn main() {}
diff --git a/tests/ui/imports/append-import-suggestion.stderr b/tests/ui/imports/append-import-suggestion.stderr
new file mode 100644
index 00000000000..6d7b657f3d1
--- /dev/null
+++ b/tests/ui/imports/append-import-suggestion.stderr
@@ -0,0 +1,21 @@
+error[E0603]: module `sub_mod` is private
+  --> $DIR/append-import-suggestion.rs:13:12
+   |
+LL | use mod2::{sub_mod::TraitA};
+   |            ^^^^^^^ private module
+   |
+help: consider importing this trait instead:
+      mod1::TraitA
+  --> $DIR/append-import-suggestion.rs:13:12
+   |
+LL | use mod2::{sub_mod::TraitA};
+   |            ^^^^^^^^^^^^^^^
+note: the module `sub_mod` is defined here
+  --> $DIR/append-import-suggestion.rs:8:5
+   |
+LL |     mod sub_mod {
+   |     ^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/tests/ui/imports/auxiliary/aux-issue-121915.rs b/tests/ui/imports/auxiliary/aux-issue-121915.rs
new file mode 100644
index 00000000000..7f9f5bda79f
--- /dev/null
+++ b/tests/ui/imports/auxiliary/aux-issue-121915.rs
@@ -0,0 +1 @@
+pub fn item() {}
diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.rs b/tests/ui/imports/redundant-import-issue-121915-2015.rs
new file mode 100644
index 00000000000..d41d190bb58
--- /dev/null
+++ b/tests/ui/imports/redundant-import-issue-121915-2015.rs
@@ -0,0 +1,11 @@
+//@ compile-flags: --extern aux_issue_121915 --edition 2015
+//@ aux-build: aux-issue-121915.rs
+
+extern crate aux_issue_121915;
+
+#[deny(unused_imports)]
+fn main() {
+    use aux_issue_121915;
+    //~^ ERROR the item `aux_issue_121915` is imported redundantly
+    aux_issue_121915::item();
+}
diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.stderr b/tests/ui/imports/redundant-import-issue-121915-2015.stderr
new file mode 100644
index 00000000000..174ed4fb96b
--- /dev/null
+++ b/tests/ui/imports/redundant-import-issue-121915-2015.stderr
@@ -0,0 +1,17 @@
+error: the item `aux_issue_121915` is imported redundantly
+  --> $DIR/redundant-import-issue-121915-2015.rs:8:9
+   |
+LL | extern crate aux_issue_121915;
+   | ------------------------------ the item `aux_issue_121915` is already imported here
+...
+LL |     use aux_issue_121915;
+   |         ^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/redundant-import-issue-121915-2015.rs:6:8
+   |
+LL | #[deny(unused_imports)]
+   |        ^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/imports/redundant-import-issue-121915.rs b/tests/ui/imports/redundant-import-issue-121915.rs
new file mode 100644
index 00000000000..237acc4af25
--- /dev/null
+++ b/tests/ui/imports/redundant-import-issue-121915.rs
@@ -0,0 +1,9 @@
+//@ compile-flags: --extern aux_issue_121915 --edition 2018
+//@ aux-build: aux-issue-121915.rs
+
+#[deny(unused_imports)]
+fn main() {
+    use aux_issue_121915;
+    //~^ ERROR the item `aux_issue_121915` is imported redundantly
+    aux_issue_121915::item();
+}
diff --git a/tests/ui/imports/redundant-import-issue-121915.stderr b/tests/ui/imports/redundant-import-issue-121915.stderr
new file mode 100644
index 00000000000..0047d7c3420
--- /dev/null
+++ b/tests/ui/imports/redundant-import-issue-121915.stderr
@@ -0,0 +1,14 @@
+error: the item `aux_issue_121915` is imported redundantly
+  --> $DIR/redundant-import-issue-121915.rs:6:9
+   |
+LL |     use aux_issue_121915;
+   |         ^^^^^^^^^^^^^^^^ the item `aux_issue_121915` is already defined by prelude
+   |
+note: the lint level is defined here
+  --> $DIR/redundant-import-issue-121915.rs:4:8
+   |
+LL | #[deny(unused_imports)]
+   |        ^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/imports/suggest-remove-issue-121315.rs b/tests/ui/imports/suggest-remove-issue-121315.rs
new file mode 100644
index 00000000000..63533480ec1
--- /dev/null
+++ b/tests/ui/imports/suggest-remove-issue-121315.rs
@@ -0,0 +1,40 @@
+//@ compile-flags: --edition 2021
+#![deny(unused_imports)]
+#![allow(dead_code)]
+
+fn test0() {
+    // Test remove FlatUnused
+    use std::convert::TryFrom;
+    //~^ ERROR the item `TryFrom` is imported redundantly
+    let _ = u32::try_from(5i32);
+}
+
+fn test1() {
+    // FIXME(yukang) Test remove NestedFullUnused
+    use std::convert::{TryFrom, TryInto};
+    //~^ ERROR the item `TryFrom` is imported redundantly
+    //~| ERROR the item `TryInto` is imported redundantly
+
+    let _ = u32::try_from(5i32);
+    let _a: i32 = u32::try_into(5u32).unwrap();
+}
+
+fn test2() {
+    // FIXME(yukang): Test remove both redundant and unused
+    use std::convert::{AsMut, Into};
+    //~^ ERROR unused import: `AsMut`
+    //~| ERROR the item `Into` is imported redundantly
+
+    let _a: u32 = (5u8).into();
+}
+
+fn test3() {
+    // Test remove NestedPartialUnused
+    use std::convert::{From, Infallible};
+    //~^ ERROR unused import: `From`
+
+    trait MyTrait {}
+    impl MyTrait for fn() -> Infallible {}
+}
+
+fn main() {}
diff --git a/tests/ui/imports/suggest-remove-issue-121315.stderr b/tests/ui/imports/suggest-remove-issue-121315.stderr
new file mode 100644
index 00000000000..dbd742f6c78
--- /dev/null
+++ b/tests/ui/imports/suggest-remove-issue-121315.stderr
@@ -0,0 +1,56 @@
+error: the item `TryFrom` is imported redundantly
+  --> $DIR/suggest-remove-issue-121315.rs:7:9
+   |
+LL |     use std::convert::TryFrom;
+   |         ^^^^^^^^^^^^^^^^^^^^^
+  --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
+   |
+   = note: the item `TryFrom` is already defined here
+   |
+note: the lint level is defined here
+  --> $DIR/suggest-remove-issue-121315.rs:2:9
+   |
+LL | #![deny(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+error: the item `TryFrom` is imported redundantly
+  --> $DIR/suggest-remove-issue-121315.rs:14:24
+   |
+LL |     use std::convert::{TryFrom, TryInto};
+   |                        ^^^^^^^
+  --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
+   |
+   = note: the item `TryFrom` is already defined here
+
+error: the item `TryInto` is imported redundantly
+  --> $DIR/suggest-remove-issue-121315.rs:14:33
+   |
+LL |     use std::convert::{TryFrom, TryInto};
+   |                                 ^^^^^^^
+  --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
+   |
+   = note: the item `TryInto` is already defined here
+
+error: unused import: `AsMut`
+  --> $DIR/suggest-remove-issue-121315.rs:24:24
+   |
+LL |     use std::convert::{AsMut, Into};
+   |                        ^^^^^
+
+error: the item `Into` is imported redundantly
+  --> $DIR/suggest-remove-issue-121315.rs:24:31
+   |
+LL |     use std::convert::{AsMut, Into};
+   |                               ^^^^
+  --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
+   |
+   = note: the item `Into` is already defined here
+
+error: unused import: `From`
+  --> $DIR/suggest-remove-issue-121315.rs:33:24
+   |
+LL |     use std::convert::{From, Infallible};
+   |                        ^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/imports/unresolved-seg-after-ambiguous.rs b/tests/ui/imports/unresolved-seg-after-ambiguous.rs
new file mode 100644
index 00000000000..dcabc528a85
--- /dev/null
+++ b/tests/ui/imports/unresolved-seg-after-ambiguous.rs
@@ -0,0 +1,24 @@
+mod a {
+    mod b {
+        mod c {
+            pub struct E;
+        }
+
+        mod d {
+            #[derive(Debug)]
+            pub struct E;
+        }
+
+        pub use self::d::*;
+        pub use self::c::*;
+    }
+
+    pub use self::b::*;
+}
+
+use self::a::E::in_exist;
+//~^ ERROR: unresolved import `self::a::E`
+//~| WARNING: `E` is ambiguous
+//~| WARNING: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+fn main() {}
diff --git a/tests/ui/imports/unresolved-seg-after-ambiguous.stderr b/tests/ui/imports/unresolved-seg-after-ambiguous.stderr
new file mode 100644
index 00000000000..9e0efd4a75f
--- /dev/null
+++ b/tests/ui/imports/unresolved-seg-after-ambiguous.stderr
@@ -0,0 +1,32 @@
+error[E0432]: unresolved import `self::a::E`
+  --> $DIR/unresolved-seg-after-ambiguous.rs:19:14
+   |
+LL | use self::a::E::in_exist;
+   |              ^ `E` is a struct, not a module
+
+warning: `E` is ambiguous
+  --> $DIR/unresolved-seg-after-ambiguous.rs:19:14
+   |
+LL | use self::a::E::in_exist;
+   |              ^ ambiguous name
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #114095 <https://github.com/rust-lang/rust/issues/114095>
+   = note: ambiguous because of multiple glob imports of a name in the same module
+note: `E` could refer to the struct imported here
+  --> $DIR/unresolved-seg-after-ambiguous.rs:13:17
+   |
+LL |         pub use self::c::*;
+   |                 ^^^^^^^^^^
+   = help: consider adding an explicit import of `E` to disambiguate
+note: `E` could also refer to the struct imported here
+  --> $DIR/unresolved-seg-after-ambiguous.rs:12:17
+   |
+LL |         pub use self::d::*;
+   |                 ^^^^^^^^^^
+   = help: consider adding an explicit import of `E` to disambiguate
+   = note: `#[warn(ambiguous_glob_imports)]` on by default
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/infinite/infinite-trait-alias-recursion.stderr b/tests/ui/infinite/infinite-trait-alias-recursion.stderr
index 220d81031ac..b3980cb935e 100644
--- a/tests/ui/infinite/infinite-trait-alias-recursion.stderr
+++ b/tests/ui/infinite/infinite-trait-alias-recursion.stderr
@@ -16,7 +16,7 @@ LL | trait T3 = T1 + T3;
    |            ^^
    = note: ...which again requires computing the super predicates of `T1`, completing the cycle
    = note: trait aliases cannot be recursive
-note: cycle used when collecting item types in top-level module
+note: cycle used when checking that `T1` is well-formed
   --> $DIR/infinite-trait-alias-recursion.rs:3:1
    |
 LL | trait T1 = T2;
diff --git a/tests/ui/infinite/infinite-type-alias-mutual-recursion.gated.stderr b/tests/ui/infinite/infinite-type-alias-mutual-recursion.gated.stderr
index 57ca1b24d2a..ab1bcc44cb8 100644
--- a/tests/ui/infinite/infinite-type-alias-mutual-recursion.gated.stderr
+++ b/tests/ui/infinite/infinite-type-alias-mutual-recursion.gated.stderr
@@ -18,17 +18,11 @@ LL | type X3 = X1;
    = note: type aliases cannot be recursive
    = help: consider using a struct, enum, or union instead to break the cycle
    = help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
-note: cycle used when collecting item types in top-level module
-  --> $DIR/infinite-type-alias-mutual-recursion.rs:3:1
+note: cycle used when checking that `X1` is well-formed
+  --> $DIR/infinite-type-alias-mutual-recursion.rs:6:1
    |
-LL | / #![cfg_attr(feature, feature(lazy_type_alias))]
-LL | | #![allow(incomplete_features)]
-LL | |
-LL | | type X1 = X2;
-...  |
-LL | |
-LL | | fn main() {}
-   | |____________^
+LL | type X1 = X2;
+   | ^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/infinite/infinite-vec-type-recursion.gated.stderr b/tests/ui/infinite/infinite-vec-type-recursion.gated.stderr
index efafc9b75cd..43364892bb5 100644
--- a/tests/ui/infinite/infinite-vec-type-recursion.gated.stderr
+++ b/tests/ui/infinite/infinite-vec-type-recursion.gated.stderr
@@ -8,17 +8,11 @@ LL | type X = Vec<X>;
    = note: type aliases cannot be recursive
    = help: consider using a struct, enum, or union instead to break the cycle
    = help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
-note: cycle used when collecting item types in top-level module
-  --> $DIR/infinite-vec-type-recursion.rs:3:1
+note: cycle used when checking that `X` is well-formed
+  --> $DIR/infinite-vec-type-recursion.rs:6:1
    |
-LL | / #![cfg_attr(feature, feature(lazy_type_alias))]
-LL | | #![allow(incomplete_features)]
-LL | |
-LL | | type X = Vec<X>;
-...  |
-LL | | #[rustfmt::skip]
-LL | | fn main() { let b: X = Vec::new(); }
-   | |____________________________________^
+LL | type X = Vec<X>;
+   | ^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/instrument-coverage/bad-value.bad.stderr b/tests/ui/instrument-coverage/bad-value.bad.stderr
index b867d169dae..0411a1f98a3 100644
--- a/tests/ui/instrument-coverage/bad-value.bad.stderr
+++ b/tests/ui/instrument-coverage/bad-value.bad.stderr
@@ -1,2 +1,2 @@
-error: incorrect value `bad-value` for codegen option `instrument-coverage` - `all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off` was expected
+error: incorrect value `bad-value` for codegen option `instrument-coverage` - either a boolean (`yes`, `no`, `on`, `off`, etc) or (unstable) one of `branch`, `except-unused-generics`, `except-unused-functions` was expected
 
diff --git a/tests/ui/instrument-coverage/bad-value.blank.stderr b/tests/ui/instrument-coverage/bad-value.blank.stderr
index e7122fb61cd..b3a8e7cf947 100644
--- a/tests/ui/instrument-coverage/bad-value.blank.stderr
+++ b/tests/ui/instrument-coverage/bad-value.blank.stderr
@@ -1,2 +1,2 @@
-error: incorrect value `` for codegen option `instrument-coverage` - `all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off` was expected
+error: incorrect value `` for codegen option `instrument-coverage` - either a boolean (`yes`, `no`, `on`, `off`, etc) or (unstable) one of `branch`, `except-unused-generics`, `except-unused-functions` was expected
 
diff --git a/tests/ui/intrinsics/always-gets-overridden.rs b/tests/ui/intrinsics/always-gets-overridden.rs
new file mode 100644
index 00000000000..ad2c2be4daa
--- /dev/null
+++ b/tests/ui/intrinsics/always-gets-overridden.rs
@@ -0,0 +1,20 @@
+//! Check that `vtable_size` gets overridden by llvm backend even if there is no
+//! `rustc_intrinsic_must_be_overridden` attribute on this usage.
+#![feature(rustc_attrs)]
+//@run-pass
+
+#[rustc_intrinsic]
+pub unsafe fn vtable_size(_ptr: *const ()) -> usize {
+    panic!();
+}
+
+trait Trait {}
+impl Trait for () {}
+
+fn main() {
+    let x: &dyn Trait = &();
+    unsafe {
+        let (_data, vtable): (*const (), *const ()) = core::mem::transmute(x);
+        assert_eq!(vtable_size(vtable), 0);
+    }
+}
diff --git a/tests/ui/intrinsics/const-eval-select-backtrace.rs b/tests/ui/intrinsics/const-eval-select-backtrace.rs
index d6b1c865bdf..ea4374f5d32 100644
--- a/tests/ui/intrinsics/const-eval-select-backtrace.rs
+++ b/tests/ui/intrinsics/const-eval-select-backtrace.rs
@@ -12,8 +12,5 @@ fn uhoh() {
 const fn c() {}
 
 fn main() {
-    // safety: this is unsound and just used to test
-    unsafe {
-        std::intrinsics::const_eval_select((), c, uhoh);
-    }
+    std::intrinsics::const_eval_select((), c, uhoh);
 }
diff --git a/tests/ui/intrinsics/const-eval-select-backtrace.run.stderr b/tests/ui/intrinsics/const-eval-select-backtrace.run.stderr
index 3f196bd8abc..8f38d54146b 100644
--- a/tests/ui/intrinsics/const-eval-select-backtrace.run.stderr
+++ b/tests/ui/intrinsics/const-eval-select-backtrace.run.stderr
@@ -1,3 +1,3 @@
-thread 'main' panicked at $DIR/const-eval-select-backtrace.rs:17:9:
+thread 'main' panicked at $DIR/const-eval-select-backtrace.rs:15:5:
 Aaah!
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/tests/ui/intrinsics/const-eval-select-stability.rs b/tests/ui/intrinsics/const-eval-select-stability.rs
index f9554decec1..575bc0cadda 100644
--- a/tests/ui/intrinsics/const-eval-select-stability.rs
+++ b/tests/ui/intrinsics/const-eval-select-stability.rs
@@ -13,7 +13,7 @@ const fn nothing(){}
 
 #[stable(since = "1.0", feature = "hey")]
 #[rustc_const_stable(since = "1.0", feature = "const_hey")]
-pub const unsafe fn hey() {
+pub const fn hey() {
     const_eval_select((), nothing, log);
     //~^ ERROR `const_eval_select` is not yet stable as a const fn
 }
diff --git a/tests/ui/intrinsics/const-eval-select-x86_64.rs b/tests/ui/intrinsics/const-eval-select-x86_64.rs
index 5ba7a443d0b..c17be2ddaca 100644
--- a/tests/ui/intrinsics/const-eval-select-x86_64.rs
+++ b/tests/ui/intrinsics/const-eval-select-x86_64.rs
@@ -22,9 +22,7 @@ fn eq_rt(x: [i32; 4], y: [i32; 4]) -> bool {
 }
 
 const fn eq(x: [i32; 4], y: [i32; 4]) -> bool {
-    unsafe {
-        const_eval_select((x, y), eq_ct, eq_rt)
-    }
+    const_eval_select((x, y), eq_ct, eq_rt)
 }
 
 fn main() {
diff --git a/tests/ui/intrinsics/const-eval-select.rs b/tests/ui/intrinsics/const-eval-select.rs
index 353105cb0a1..66d83585fce 100644
--- a/tests/ui/intrinsics/const-eval-select.rs
+++ b/tests/ui/intrinsics/const-eval-select.rs
@@ -13,9 +13,9 @@ fn no() -> bool {
     false
 }
 
-// not a sound use case; testing only
+// not allowed on stable; testing only
 const fn is_const_eval() -> bool {
-    unsafe { const_eval_select((), yes, no) }
+    const_eval_select((), yes, no)
 }
 
 fn main() {
diff --git a/tests/ui/intrinsics/not-overridden.rs b/tests/ui/intrinsics/not-overridden.rs
new file mode 100644
index 00000000000..d6655b51905
--- /dev/null
+++ b/tests/ui/intrinsics/not-overridden.rs
@@ -0,0 +1,18 @@
+//! Check that intrinsics that do not get overridden, but are marked as such,
+//! cause an error instead of silently invoking the body.
+#![feature(rustc_attrs, effects)]
+//@ build-fail
+//@ failure-status:101
+//@ normalize-stderr-test ".*note: .*\n\n" -> ""
+//@ normalize-stderr-test "thread 'rustc' panicked.*:\n.*\n" -> ""
+//@ normalize-stderr-test "internal compiler error:.*: intrinsic const_deallocate " -> ""
+//@ rustc-env:RUST_BACKTRACE=0
+
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {}
+
+fn main() {
+    unsafe { const_deallocate(std::ptr::null_mut(), 0, 0) }
+    //~^ ERROR: must be overridden
+}
diff --git a/tests/ui/intrinsics/not-overridden.stderr b/tests/ui/intrinsics/not-overridden.stderr
new file mode 100644
index 00000000000..9b8849cea1c
--- /dev/null
+++ b/tests/ui/intrinsics/not-overridden.stderr
@@ -0,0 +1,10 @@
+error: must be overridden by codegen backend, but isn't
+  --> $DIR/not-overridden.rs:16:14
+   |
+LL |     unsafe { const_deallocate(std::ptr::null_mut(), 0, 0) }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+query stack during panic:
+end of query stack
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/issues-71798.stderr b/tests/ui/issues-71798.stderr
index 829d0a02ec9..52dd14ccb0a 100644
--- a/tests/ui/issues-71798.stderr
+++ b/tests/ui/issues-71798.stderr
@@ -14,7 +14,6 @@ LL |     *x
    |     -- return type was inferred to be `u32` here
    |
    = help: the trait `Future` is not implemented for `u32`
-   = note: u32 must be a future or must implement `IntoFuture` to be awaited
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/issues/issue-16560.rs b/tests/ui/issues/issue-16560.rs
index 37b536e644d..d9a7aa9101d 100644
--- a/tests/ui/issues/issue-16560.rs
+++ b/tests/ui/issues/issue-16560.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_variables)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 use std::mem;
diff --git a/tests/ui/issues/issue-20831-debruijn.stderr b/tests/ui/issues/issue-20831-debruijn.stderr
index 7d1e19b7e47..60721f001b7 100644
--- a/tests/ui/issues/issue-20831-debruijn.stderr
+++ b/tests/ui/issues/issue-20831-debruijn.stderr
@@ -4,11 +4,11 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d
 LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: first, the lifetime cannot outlive the anonymous lifetime defined here...
-  --> $DIR/issue-20831-debruijn.rs:28:58
+note: first, the lifetime cannot outlive the anonymous lifetime as defined here...
+  --> $DIR/issue-20831-debruijn.rs:28:18
    |
 LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-   |                                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  ^
 note: ...but the lifetime must also be valid for the lifetime `'a` as defined here...
   --> $DIR/issue-20831-debruijn.rs:26:6
    |
diff --git a/tests/ui/issues/issue-21291.rs b/tests/ui/issues/issue-21291.rs
index 357d5520028..06f50ac6996 100644
--- a/tests/ui/issues/issue-21291.rs
+++ b/tests/ui/issues/issue-21291.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 // Regression test for unwrapping the result of `join`, issue #21291
 
diff --git a/tests/ui/issues/issue-22864-2.rs b/tests/ui/issues/issue-22864-2.rs
index 1b702f4f509..d98dbeda46b 100644
--- a/tests/ui/issues/issue-22864-2.rs
+++ b/tests/ui/issues/issue-22864-2.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 pub fn main() {
     let f = || || 0;
diff --git a/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-1.stderr b/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-1.stderr
index 53131f9130d..234060ab5c8 100644
--- a/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-1.stderr
+++ b/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-1.stderr
@@ -10,15 +10,11 @@ note: ...which requires const-evaluating + checking `X::A::{constant#0}`...
 LL |     A = X::A as isize,
    |         ^^^^^^^^^^^^^
    = note: ...which again requires simplifying constant for the type system `X::A::{constant#0}`, completing the cycle
-note: cycle used when collecting item types in top-level module
+note: cycle used when checking that `X` is well-formed
   --> $DIR/issue-23302-1.rs:3:1
    |
-LL | / enum X {
-LL | |     A = X::A as isize,
-LL | | }
-LL | |
-LL | | fn main() { }
-   | |_____________^
+LL | enum X {
+   | ^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-2.stderr b/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-2.stderr
index d55d88762be..9bd95239c83 100644
--- a/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-2.stderr
+++ b/tests/ui/issues/issue-23302-enum-infinite-recursion/issue-23302-2.stderr
@@ -10,16 +10,11 @@ note: ...which requires const-evaluating + checking `Y::A::{constant#0}`...
 LL |     A = Y::B as isize,
    |         ^^^^^^^^^^^^^
    = note: ...which again requires simplifying constant for the type system `Y::A::{constant#0}`, completing the cycle
-note: cycle used when collecting item types in top-level module
+note: cycle used when checking that `Y` is well-formed
   --> $DIR/issue-23302-2.rs:3:1
    |
-LL | / enum Y {
-LL | |     A = Y::B as isize,
-LL | |     B,
-LL | | }
-LL | |
-LL | | fn main() { }
-   | |_____________^
+LL | enum Y {
+   | ^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/issues/issue-29861.rs b/tests/ui/issues/issue-29861.rs
index 58f8eb5362c..875c168185f 100644
--- a/tests/ui/issues/issue-29861.rs
+++ b/tests/ui/issues/issue-29861.rs
@@ -14,6 +14,7 @@ impl<'a, T: 'a> MakeRef2 for T {
 }
 
 fn foo() -> <String as MakeRef2>::Ref2 { &String::from("foo") }
+//~^ ERROR temporary value dropped while borrowed
 
 fn main() {
     println!("{}", foo());
diff --git a/tests/ui/issues/issue-29861.stderr b/tests/ui/issues/issue-29861.stderr
index e7860c19eaa..a25cbf0515d 100644
--- a/tests/ui/issues/issue-29861.stderr
+++ b/tests/ui/issues/issue-29861.stderr
@@ -4,6 +4,18 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
 LL | impl<'a, T: 'a> MakeRef2 for T {
    |      ^^ unconstrained lifetime parameter
 
-error: aborting due to 1 previous error
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/issue-29861.rs:16:43
+   |
+LL | fn foo() -> <String as MakeRef2>::Ref2 { &String::from("foo") }
+   |                                           ^^^^^^^^^^^^^^^^^^^ -- borrow later used here
+   |                                           |                   |
+   |                                           |                   temporary value is freed at the end of this statement
+   |                                           creates a temporary value which is freed while still in use
+   |
+   = note: consider using a `let` binding to create a longer lived value
 
-For more information about this error, try `rustc --explain E0207`.
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0207, E0716.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/issues/issue-33941.rs b/tests/ui/issues/issue-33941.rs
index 0ad7cbe8efc..7b5be30834b 100644
--- a/tests/ui/issues/issue-33941.rs
+++ b/tests/ui/issues/issue-33941.rs
@@ -5,5 +5,4 @@ use std::collections::HashMap;
 fn main() {
     for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
     //~^ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
-    //~| ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
 }
diff --git a/tests/ui/issues/issue-33941.stderr b/tests/ui/issues/issue-33941.stderr
index e7f4a4fa004..f1b6b6ba17e 100644
--- a/tests/ui/issues/issue-33941.stderr
+++ b/tests/ui/issues/issue-33941.stderr
@@ -27,16 +27,6 @@ LL |     for _ in HashMap::new().iter().cloned() {}
    = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `Iterator`
    = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `IntoIterator`
 
-error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
-  --> $DIR/issue-33941.rs:6:14
-   |
-LL |     for _ in HashMap::new().iter().cloned() {}
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(&_, &_)`, found `&_`
-   |
-   = note:  expected tuple `(&_, &_)`
-           found reference `&_`
-   = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `Iterator`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/issues/issue-34373.stderr b/tests/ui/issues/issue-34373.stderr
index 13667cd920e..784fe935bf8 100644
--- a/tests/ui/issues/issue-34373.stderr
+++ b/tests/ui/issues/issue-34373.stderr
@@ -10,17 +10,11 @@ note: ...which requires expanding type alias `DefaultFoo`...
 LL | type DefaultFoo = Foo;
    |                   ^^^
    = note: ...which again requires computing type of `Foo::T`, completing the cycle
-note: cycle used when collecting item types in top-level module
-  --> $DIR/issue-34373.rs:1:1
+note: cycle used when checking that `Foo` is well-formed
+  --> $DIR/issue-34373.rs:7:1
    |
-LL | / #![allow(warnings)]
-LL | |
-LL | | trait Trait<T> {
-LL | |     fn foo(_: T) {}
-...  |
-LL | | fn main() {
-LL | | }
-   | |_^
+LL | pub struct Foo<T = Box<Trait<DefaultFoo>>>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error[E0038]: the trait `Trait` cannot be made into an object
diff --git a/tests/ui/issues/issue-37131.stderr b/tests/ui/issues/issue-37131.stderr
index 9ecae3e7a2b..588696f3541 100644
--- a/tests/ui/issues/issue-37131.stderr
+++ b/tests/ui/issues/issue-37131.stderr
@@ -4,8 +4,6 @@ error[E0463]: can't find crate for `std`
    = help: consider downloading the target with `rustup target add thumbv6m-none-eabi`
    = help: consider building the standard library from source with `cargo build -Zbuild-std`
 
-error: requires `sized` lang_item
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0463`.
diff --git a/tests/ui/issues/issue-49851/compiler-builtins-error.rs b/tests/ui/issues/issue-49851/compiler-builtins-error.rs
index 3b62cc73f93..db45d040f79 100644
--- a/tests/ui/issues/issue-49851/compiler-builtins-error.rs
+++ b/tests/ui/issues/issue-49851/compiler-builtins-error.rs
@@ -1,5 +1,4 @@
 //~ ERROR can't find crate for `core`
-//~^ ERROR can't find crate for `compiler_builtins`
 
 //@ compile-flags: --target thumbv7em-none-eabihf
 //@ needs-llvm-components: arm
@@ -8,6 +7,5 @@
 #![no_std]
 
 extern crate cortex_m;
-//~^ ERROR can't find crate for `cortex_m`
 
 fn main() {}
diff --git a/tests/ui/issues/issue-49851/compiler-builtins-error.stderr b/tests/ui/issues/issue-49851/compiler-builtins-error.stderr
index fcfa2bf119c..1cd65a1b68c 100644
--- a/tests/ui/issues/issue-49851/compiler-builtins-error.stderr
+++ b/tests/ui/issues/issue-49851/compiler-builtins-error.stderr
@@ -4,16 +4,6 @@ error[E0463]: can't find crate for `core`
    = help: consider downloading the target with `rustup target add thumbv7em-none-eabihf`
    = help: consider building the standard library from source with `cargo build -Zbuild-std`
 
-error[E0463]: can't find crate for `compiler_builtins`
-
-error[E0463]: can't find crate for `cortex_m`
-  --> $DIR/compiler-builtins-error.rs:10:1
-   |
-LL | extern crate cortex_m;
-   | ^^^^^^^^^^^^^^^^^^^^^^ can't find crate
-
-error: requires `sized` lang_item
-
-error: aborting due to 4 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0463`.
diff --git a/tests/ui/issues/issue-59020.rs b/tests/ui/issues/issue-59020.rs
index 5692afe811e..2a34ba52b88 100644
--- a/tests/ui/issues/issue-59020.rs
+++ b/tests/ui/issues/issue-59020.rs
@@ -1,6 +1,6 @@
 //@ edition:2018
 //@ run-pass
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 use std::time::Duration;
diff --git a/tests/ui/iterators/bound.stderr b/tests/ui/iterators/bound.stderr
index e5ed19f3731..915f0496716 100644
--- a/tests/ui/iterators/bound.stderr
+++ b/tests/ui/iterators/bound.stderr
@@ -5,7 +5,6 @@ LL | struct T(S<u8>);
    |          ^^^^^ `u8` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `u8`
-   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
 note: required by a bound in `S`
   --> $DIR/bound.rs:1:13
    |
diff --git a/tests/ui/iterators/vec-on-unimplemented.fixed b/tests/ui/iterators/vec-on-unimplemented.fixed
new file mode 100644
index 00000000000..cc46bd67f9a
--- /dev/null
+++ b/tests/ui/iterators/vec-on-unimplemented.fixed
@@ -0,0 +1,5 @@
+//@ run-rustfix
+fn main() {
+    let _ = vec![true, false].into_iter().map(|v| !v).collect::<Vec<_>>();
+    //~^ ERROR no method named `map` found for struct `Vec<bool>` in the current scope
+}
diff --git a/tests/ui/iterators/vec-on-unimplemented.rs b/tests/ui/iterators/vec-on-unimplemented.rs
index 42b5d36bfad..7367fd4c9cd 100644
--- a/tests/ui/iterators/vec-on-unimplemented.rs
+++ b/tests/ui/iterators/vec-on-unimplemented.rs
@@ -1,4 +1,5 @@
+//@ run-rustfix
 fn main() {
-    vec![true, false].map(|v| !v).collect::<Vec<_>>();
-    //~^ ERROR `Vec<bool>` is not an iterator
+    let _ = vec![true, false].map(|v| !v).collect::<Vec<_>>();
+    //~^ ERROR no method named `map` found for struct `Vec<bool>` in the current scope
 }
diff --git a/tests/ui/iterators/vec-on-unimplemented.stderr b/tests/ui/iterators/vec-on-unimplemented.stderr
index 29b19d5e3b4..d6f4bfa1cde 100644
--- a/tests/ui/iterators/vec-on-unimplemented.stderr
+++ b/tests/ui/iterators/vec-on-unimplemented.stderr
@@ -1,14 +1,13 @@
-error[E0599]: `Vec<bool>` is not an iterator
-  --> $DIR/vec-on-unimplemented.rs:2:23
+error[E0599]: no method named `map` found for struct `Vec<bool>` in the current scope
+  --> $DIR/vec-on-unimplemented.rs:3:31
    |
-LL |     vec![true, false].map(|v| !v).collect::<Vec<_>>();
-   |                       ^^^ `Vec<bool>` is not an iterator; try calling `.into_iter()` or `.iter()`
+LL |     let _ = vec![true, false].map(|v| !v).collect::<Vec<_>>();
+   |                               ^^^ `Vec<bool>` is not an iterator
    |
-   = note: the following trait bounds were not satisfied:
-           `Vec<bool>: Iterator`
-           which is required by `&mut Vec<bool>: Iterator`
-           `[bool]: Iterator`
-           which is required by `&mut [bool]: Iterator`
+help: call `.into_iter()` first
+   |
+LL |     let _ = vec![true, false].into_iter().map(|v| !v).collect::<Vec<_>>();
+   |                               ++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/kindck/kindck-impl-type-params-2.rs b/tests/ui/kindck/kindck-impl-type-params-2.rs
index 8950fc51e64..8b0771985dc 100644
--- a/tests/ui/kindck/kindck-impl-type-params-2.rs
+++ b/tests/ui/kindck/kindck-impl-type-params-2.rs
@@ -11,5 +11,5 @@ fn take_param<T:Foo>(foo: &T) { }
 fn main() {
     let x: Box<_> = Box::new(3);
     take_param(&x);
-    //~^ ERROR the trait bound `Box<{integer}>: Copy` is not satisfied
+    //~^ ERROR the trait bound `Box<{integer}>: Foo` is not satisfied
 }
diff --git a/tests/ui/kindck/kindck-impl-type-params-2.stderr b/tests/ui/kindck/kindck-impl-type-params-2.stderr
index 46c0bda9535..a7d169d3ac4 100644
--- a/tests/ui/kindck/kindck-impl-type-params-2.stderr
+++ b/tests/ui/kindck/kindck-impl-type-params-2.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied
+error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
   --> $DIR/kindck-impl-type-params-2.rs:13:16
    |
 LL |     take_param(&x);
diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr
index a85815d8cc4..979525ff407 100644
--- a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr
+++ b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied
+error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
   --> $DIR/kindck-inherited-copy-bound.rs:21:16
    |
 LL |     take_param(&x);
diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
index 687660fe7ee..30f90b88160 100644
--- a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
+++ b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied
+error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
   --> $DIR/kindck-inherited-copy-bound.rs:21:16
    |
 LL |     take_param(&x);
diff --git a/tests/ui/kindck/kindck-send-object.rs b/tests/ui/kindck/kindck-send-object.rs
index 6411e688b4a..f5d44246efe 100644
--- a/tests/ui/kindck/kindck-send-object.rs
+++ b/tests/ui/kindck/kindck-send-object.rs
@@ -10,7 +10,7 @@ trait Message : Send { }
 
 fn object_ref_with_static_bound_not_ok() {
     assert_send::<&'static (dyn Dummy + 'static)>();
-    //~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277]
+    //~^ ERROR `&'static (dyn Dummy + 'static)` cannot be sent between threads safely [E0277]
 }
 
 fn box_object_with_no_bound_not_ok<'a>() {
diff --git a/tests/ui/kindck/kindck-send-object.stderr b/tests/ui/kindck/kindck-send-object.stderr
index 0fc9cb14c7d..9f1ff4f3644 100644
--- a/tests/ui/kindck/kindck-send-object.stderr
+++ b/tests/ui/kindck/kindck-send-object.stderr
@@ -1,10 +1,10 @@
-error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely
+error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
   --> $DIR/kindck-send-object.rs:12:19
    |
 LL |     assert_send::<&'static (dyn Dummy + 'static)>();
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
    |
-   = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
+   = help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
    = note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
 note: required by a bound in `assert_send`
   --> $DIR/kindck-send-object.rs:5:18
diff --git a/tests/ui/kindck/kindck-send-object1.rs b/tests/ui/kindck/kindck-send-object1.rs
index 0ce3995dccc..76a9fc6019a 100644
--- a/tests/ui/kindck/kindck-send-object1.rs
+++ b/tests/ui/kindck/kindck-send-object1.rs
@@ -8,7 +8,7 @@ trait Dummy { }
 // careful with object types, who knows what they close over...
 fn test51<'a>() {
     assert_send::<&'a dyn Dummy>();
-    //~^ ERROR `(dyn Dummy + 'a)` cannot be shared between threads safely [E0277]
+    //~^ ERROR `&'a (dyn Dummy + 'a)` cannot be sent between threads safely [E0277]
 }
 fn test52<'a>() {
     assert_send::<&'a (dyn Dummy + Sync)>();
diff --git a/tests/ui/kindck/kindck-send-object1.stderr b/tests/ui/kindck/kindck-send-object1.stderr
index 39343b9993b..f2aa814676f 100644
--- a/tests/ui/kindck/kindck-send-object1.stderr
+++ b/tests/ui/kindck/kindck-send-object1.stderr
@@ -1,10 +1,10 @@
-error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely
+error[E0277]: `&'a (dyn Dummy + 'a)` cannot be sent between threads safely
   --> $DIR/kindck-send-object1.rs:10:19
    |
 LL |     assert_send::<&'a dyn Dummy>();
-   |                   ^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely
+   |                   ^^^^^^^^^^^^^ `&'a (dyn Dummy + 'a)` cannot be sent between threads safely
    |
-   = help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send`
+   = help: the trait `Sync` is not implemented for `&'a (dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send`
    = note: required for `&'a (dyn Dummy + 'a)` to implement `Send`
 note: required by a bound in `assert_send`
   --> $DIR/kindck-send-object1.rs:5:18
diff --git a/tests/ui/kindck/kindck-send-object2.rs b/tests/ui/kindck/kindck-send-object2.rs
index b797588e446..d37074e6574 100644
--- a/tests/ui/kindck/kindck-send-object2.rs
+++ b/tests/ui/kindck/kindck-send-object2.rs
@@ -5,7 +5,7 @@ trait Dummy { }
 
 fn test50() {
     assert_send::<&'static dyn Dummy>();
-    //~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277]
+    //~^ ERROR `&'static (dyn Dummy + 'static)` cannot be sent between threads safely [E0277]
 }
 
 fn test53() {
diff --git a/tests/ui/kindck/kindck-send-object2.stderr b/tests/ui/kindck/kindck-send-object2.stderr
index 758a517e128..cd4d74360f8 100644
--- a/tests/ui/kindck/kindck-send-object2.stderr
+++ b/tests/ui/kindck/kindck-send-object2.stderr
@@ -1,10 +1,10 @@
-error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely
+error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
   --> $DIR/kindck-send-object2.rs:7:19
    |
 LL |     assert_send::<&'static dyn Dummy>();
-   |                   ^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
+   |                   ^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
    |
-   = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
+   = help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
    = note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
 note: required by a bound in `assert_send`
   --> $DIR/kindck-send-object2.rs:3:18
diff --git a/tests/ui/layout/issue-84108.rs b/tests/ui/layout/issue-84108.rs
index 44d6ac8db72..425da65b990 100644
--- a/tests/ui/layout/issue-84108.rs
+++ b/tests/ui/layout/issue-84108.rs
@@ -11,4 +11,5 @@ const BAR: (&Path, [u8], usize) = ("hello", [], 42);
 
 static BAZ: ([u8], usize) = ([], 0);
 //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
+//~| ERROR the size for values of type `[u8]` cannot be known at compilation time
 //~| ERROR mismatched types
diff --git a/tests/ui/layout/issue-84108.stderr b/tests/ui/layout/issue-84108.stderr
index 58bddb069fc..6c168cc5fa8 100644
--- a/tests/ui/layout/issue-84108.stderr
+++ b/tests/ui/layout/issue-84108.stderr
@@ -29,6 +29,16 @@ LL | static BAZ: ([u8], usize) = ([], 0);
    = help: the trait `Sized` is not implemented for `[u8]`
    = note: only the last element of a tuple may have a dynamically sized type
 
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/issue-84108.rs:12:13
+   |
+LL | static BAZ: ([u8], usize) = ([], 0);
+   |             ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: only the last element of a tuple may have a dynamically sized type
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0308]: mismatched types
   --> $DIR/issue-84108.rs:12:30
    |
@@ -38,7 +48,7 @@ LL | static BAZ: ([u8], usize) = ([], 0);
    = note: expected slice `[u8]`
               found array `[_; 0]`
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0277, E0308, E0412.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.rs b/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.rs
index eceefa719ec..7bc91ef426b 100644
--- a/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.rs
+++ b/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.rs
@@ -3,6 +3,6 @@
 
 impl<T> Loop<T> {} //~ ERROR the type parameter `T` is not constrained
 
-type Loop<T> = Loop<T>;
+type Loop<T> = Loop<T>; //~ ERROR overflow
 
 fn main() {}
diff --git a/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.stderr b/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.stderr
index b65c84226ce..bcffa02ddd4 100644
--- a/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.stderr
+++ b/tests/ui/lazy-type-alias/unconstrained-params-in-impl-due-to-overflow.stderr
@@ -4,6 +4,15 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
 LL | impl<T> Loop<T> {}
    |      ^ unconstrained type parameter
 
-error: aborting due to 1 previous error
+error[E0275]: overflow normalizing the type alias `Loop<T>`
+  --> $DIR/unconstrained-params-in-impl-due-to-overflow.rs:6:16
+   |
+LL | type Loop<T> = Loop<T>;
+   |                ^^^^^^^
+   |
+   = note: in case this is a recursive type alias, consider using a struct, enum, or union instead
 
-For more information about this error, try `rustc --explain E0207`.
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0207, E0275.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs b/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs
index 03913869503..85eeb5d4c90 100644
--- a/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs
+++ b/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs
@@ -6,6 +6,7 @@ use std::future::Future;
 async fn wrapper<F>(f: F)
 //~^ ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32`
 //~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32`
+//~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32`
 where
 F:,
 for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,
diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr
index 89ebdb57f3c..578ba149baf 100644
--- a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr
+++ b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr
@@ -4,6 +4,7 @@ error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
 LL | / async fn wrapper<F>(f: F)
 LL | |
 LL | |
+LL | |
 LL | | where
 LL | | F:,
 LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,
@@ -20,7 +21,21 @@ LL | async fn wrapper<F>(f: F)
    = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32`
 
 error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
-  --> $DIR/issue-76168-hr-outlives-3.rs:12:1
+  --> $DIR/issue-76168-hr-outlives-3.rs:6:1
+   |
+LL | / async fn wrapper<F>(f: F)
+LL | |
+LL | |
+LL | |
+LL | | where
+LL | | F:,
+LL | | for<'a> <i32 as FnOnce<(&'a mut i32,)>>::Output: Future<Output = ()> + 'a,
+   | |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32`
+   |
+   = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32`
+
+error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32`
+  --> $DIR/issue-76168-hr-outlives-3.rs:13:1
    |
 LL | / {
 LL | |
@@ -31,6 +46,6 @@ LL | | }
    |
    = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32`
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/lifetimes/issue-95023.stderr b/tests/ui/lifetimes/issue-95023.stderr
index 0c67d7328f2..c4285dbf4bd 100644
--- a/tests/ui/lifetimes/issue-95023.stderr
+++ b/tests/ui/lifetimes/issue-95023.stderr
@@ -32,12 +32,6 @@ help: parenthesized trait syntax expands to `Fn<(&isize,), Output=()>`
 LL | impl Fn(&isize) for Error {
    |      ^^^^^^^^^^
 
-error[E0220]: associated type `B` not found for `Self`
-  --> $DIR/issue-95023.rs:8:44
-   |
-LL |     fn foo<const N: usize>(&self) -> Self::B<{ N }>;
-   |                                            ^ help: `Self` has the following associated type: `Output`
-
 error[E0277]: expected a `FnMut(&isize)` closure, found `Error`
   --> $DIR/issue-95023.rs:3:21
    |
@@ -56,6 +50,12 @@ LL | impl Fn(&isize) for Error {
    |
    = help: implement the missing item: `fn call(&self, _: (&isize,)) -> <Self as FnOnce<(&isize,)>>::Output { todo!() }`
 
+error[E0220]: associated type `B` not found for `Self`
+  --> $DIR/issue-95023.rs:8:44
+   |
+LL |     fn foo<const N: usize>(&self) -> Self::B<{ N }>;
+   |                                            ^ help: `Self` has the following associated type: `Output`
+
 error[E0220]: associated type `B` not found for `Self`
   --> $DIR/issue-95023.rs:8:44
    |
diff --git a/tests/ui/lifetimes/missing-lifetime-in-alias.stderr b/tests/ui/lifetimes/missing-lifetime-in-alias.stderr
index 9183e6302ee..b868d4b15a1 100644
--- a/tests/ui/lifetimes/missing-lifetime-in-alias.stderr
+++ b/tests/ui/lifetimes/missing-lifetime-in-alias.stderr
@@ -25,22 +25,6 @@ help: consider using one of the available lifetimes here
 LL | type C<'a, 'b> = <A<'a> as Trait<'lifetime>>::Bar;
    |                                 +++++++++++
 
-error[E0107]: missing generics for associated type `Trait::Bar`
-  --> $DIR/missing-lifetime-in-alias.rs:27:36
-   |
-LL | type C<'a, 'b> = <A<'a> as Trait>::Bar;
-   |                                    ^^^ expected 1 lifetime argument
-   |
-note: associated type defined here, with 1 lifetime parameter: `'b`
-  --> $DIR/missing-lifetime-in-alias.rs:4:10
-   |
-LL |     type Bar<'b>
-   |          ^^^ --
-help: add missing lifetime argument
-   |
-LL | type C<'a, 'b> = <A<'a> as Trait>::Bar<'a>;
-   |                                       ++++
-
 error[E0477]: the type `Impl<'a>` does not fulfill the required lifetime
   --> $DIR/missing-lifetime-in-alias.rs:16:20
    |
@@ -60,6 +44,22 @@ help: copy the `where` clause predicates from the trait
 LL |     type Bar<'b> = &'b () where Self: 'b;
    |                           ++++++++++++++
 
+error[E0107]: missing generics for associated type `Trait::Bar`
+  --> $DIR/missing-lifetime-in-alias.rs:27:36
+   |
+LL | type C<'a, 'b> = <A<'a> as Trait>::Bar;
+   |                                    ^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'b`
+  --> $DIR/missing-lifetime-in-alias.rs:4:10
+   |
+LL |     type Bar<'b>
+   |          ^^^ --
+help: add missing lifetime argument
+   |
+LL | type C<'a, 'b> = <A<'a> as Trait>::Bar<'a>;
+   |                                       ++++
+
 error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0106, E0107, E0477.
diff --git a/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr b/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr
index 667bb3ec130..93015bb2bac 100644
--- a/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr
+++ b/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr
@@ -1,3 +1,3 @@
 'common' global must have a zero initializer!
 ptr @TEST
-LLVM ERROR: Broken module found, compilation aborted!
+rustc-LLVM ERROR: Broken module found, compilation aborted!
diff --git a/tests/ui/lint/lint-qualification.fixed b/tests/ui/lint/lint-qualification.fixed
index ab450f8b734..2b1f8b59175 100644
--- a/tests/ui/lint/lint-qualification.fixed
+++ b/tests/ui/lint/lint-qualification.fixed
@@ -24,6 +24,9 @@ fn main() {
     use std::fmt;
     let _: fmt::Result = Ok(()); //~ ERROR: unnecessary qualification
 
+    let _ = <bool as Default>::default(); // issue #121999
+    //~^ ERROR: unnecessary qualification
+
     macro_rules! m { ($a:ident, $b:ident) => {
         $crate::foo::bar(); // issue #37357
         ::foo::bar(); // issue #38682
diff --git a/tests/ui/lint/lint-qualification.rs b/tests/ui/lint/lint-qualification.rs
index 84a36f509eb..002fdbf7724 100644
--- a/tests/ui/lint/lint-qualification.rs
+++ b/tests/ui/lint/lint-qualification.rs
@@ -24,6 +24,9 @@ fn main() {
     use std::fmt;
     let _: std::fmt::Result = Ok(()); //~ ERROR: unnecessary qualification
 
+    let _ = <bool as ::std::default::Default>::default(); // issue #121999
+    //~^ ERROR: unnecessary qualification
+
     macro_rules! m { ($a:ident, $b:ident) => {
         $crate::foo::bar(); // issue #37357
         ::foo::bar(); // issue #38682
diff --git a/tests/ui/lint/lint-qualification.stderr b/tests/ui/lint/lint-qualification.stderr
index 45e1525f4bf..8dddcf23f75 100644
--- a/tests/ui/lint/lint-qualification.stderr
+++ b/tests/ui/lint/lint-qualification.stderr
@@ -87,5 +87,17 @@ LL -     let _: std::fmt::Result = Ok(());
 LL +     let _: fmt::Result = Ok(());
    |
 
-error: aborting due to 7 previous errors
+error: unnecessary qualification
+  --> $DIR/lint-qualification.rs:27:13
+   |
+LL |     let _ = <bool as ::std::default::Default>::default(); // issue #121999
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: remove the unnecessary path segments
+   |
+LL -     let _ = <bool as ::std::default::Default>::default(); // issue #121999
+LL +     let _ = <bool as Default>::default(); // issue #121999
+   |
+
+error: aborting due to 8 previous errors
 
diff --git a/tests/ui/lint/non_local_definitions.rs b/tests/ui/lint/non_local_definitions.rs
index c9aaa049346..bbcc8189871 100644
--- a/tests/ui/lint/non_local_definitions.rs
+++ b/tests/ui/lint/non_local_definitions.rs
@@ -4,6 +4,7 @@
 //@ rustc-env:CARGO=/usr/bin/cargo
 
 #![feature(inline_const)]
+#![warn(non_local_definitions)]
 
 extern crate non_local_macro;
 
diff --git a/tests/ui/lint/non_local_definitions.stderr b/tests/ui/lint/non_local_definitions.stderr
index f9f29ec63a8..b9583ae983f 100644
--- a/tests/ui/lint/non_local_definitions.stderr
+++ b/tests/ui/lint/non_local_definitions.stderr
@@ -1,5 +1,5 @@
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:36:5
+  --> $DIR/non_local_definitions.rs:37:5
    |
 LL | const Z: () = {
    |       - help: use a const-anon item to suppress this lint: `_`
@@ -11,10 +11,14 @@ LL |     impl Uto for &Test {}
    = note: an `impl` definition is non-local if it is nested inside an item and neither the type nor the trait are at the same nesting level as the `impl` block
    = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
-   = note: `#[warn(non_local_definitions)]` on by default
+note: the lint level is defined here
+  --> $DIR/non_local_definitions.rs:7:9
+   |
+LL | #![warn(non_local_definitions)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:46:5
+  --> $DIR/non_local_definitions.rs:47:5
    |
 LL |     impl Uto for *mut Test {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -25,7 +29,7 @@ LL |     impl Uto for *mut Test {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:54:9
+  --> $DIR/non_local_definitions.rs:55:9
    |
 LL |         impl Uto for Test {}
    |         ^^^^^^^^^^^^^^^^^^^^
@@ -36,7 +40,7 @@ LL |         impl Uto for Test {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:63:5
+  --> $DIR/non_local_definitions.rs:64:5
    |
 LL |     impl Uto2 for Test {}
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -47,7 +51,7 @@ LL |     impl Uto2 for Test {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:71:5
+  --> $DIR/non_local_definitions.rs:72:5
    |
 LL |     impl Uto3 for Test {}
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -58,7 +62,7 @@ LL |     impl Uto3 for Test {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:75:5
+  --> $DIR/non_local_definitions.rs:76:5
    |
 LL |     macro_rules! m0 { () => { } };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -69,7 +73,7 @@ LL |     macro_rules! m0 { () => { } };
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:87:5
+  --> $DIR/non_local_definitions.rs:88:5
    |
 LL |     macro_rules! m { () => { } };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -80,7 +84,7 @@ LL |     macro_rules! m { () => { } };
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:90:5
+  --> $DIR/non_local_definitions.rs:91:5
    |
 LL | /     impl Test {
 LL | |
@@ -94,7 +98,7 @@ LL | |     }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:96:9
+  --> $DIR/non_local_definitions.rs:97:9
    |
 LL | /         impl Test {
 LL | |
@@ -108,7 +112,7 @@ LL | |         }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:105:9
+  --> $DIR/non_local_definitions.rs:106:9
    |
 LL | /         impl Test {
 LL | |
@@ -122,7 +126,7 @@ LL | |         }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:114:9
+  --> $DIR/non_local_definitions.rs:115:9
    |
 LL | /         impl Test {
 LL | |
@@ -136,7 +140,7 @@ LL | |         }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:122:5
+  --> $DIR/non_local_definitions.rs:123:5
    |
 LL | /     impl Display for Test {
 LL | |
@@ -152,7 +156,7 @@ LL | |     }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:129:5
+  --> $DIR/non_local_definitions.rs:130:5
    |
 LL |     impl dyn Uto5 {}
    |     ^^^^^^^^^^^^^^^^
@@ -163,7 +167,7 @@ LL |     impl dyn Uto5 {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:132:5
+  --> $DIR/non_local_definitions.rs:133:5
    |
 LL |     impl<T: Uto5> Uto5 for Vec<T> { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -174,7 +178,7 @@ LL |     impl<T: Uto5> Uto5 for Vec<T> { }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:135:5
+  --> $DIR/non_local_definitions.rs:136:5
    |
 LL |     impl Uto5 for &dyn Uto5 {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -185,7 +189,7 @@ LL |     impl Uto5 for &dyn Uto5 {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:138:5
+  --> $DIR/non_local_definitions.rs:139:5
    |
 LL |     impl Uto5 for *mut Test {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -196,7 +200,7 @@ LL |     impl Uto5 for *mut Test {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:141:5
+  --> $DIR/non_local_definitions.rs:142:5
    |
 LL |     impl Uto5 for *mut [Test] {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -207,7 +211,7 @@ LL |     impl Uto5 for *mut [Test] {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:144:5
+  --> $DIR/non_local_definitions.rs:145:5
    |
 LL |     impl Uto5 for [Test; 8] {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -218,7 +222,7 @@ LL |     impl Uto5 for [Test; 8] {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:147:5
+  --> $DIR/non_local_definitions.rs:148:5
    |
 LL |     impl Uto5 for (Test,) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -229,7 +233,7 @@ LL |     impl Uto5 for (Test,) {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:150:5
+  --> $DIR/non_local_definitions.rs:151:5
    |
 LL |     impl Uto5 for fn(Test) -> () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -240,7 +244,7 @@ LL |     impl Uto5 for fn(Test) -> () {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:153:5
+  --> $DIR/non_local_definitions.rs:154:5
    |
 LL |     impl Uto5 for fn() -> Test {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -251,7 +255,7 @@ LL |     impl Uto5 for fn() -> Test {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:157:9
+  --> $DIR/non_local_definitions.rs:158:9
    |
 LL |         impl Uto5 for Test {}
    |         ^^^^^^^^^^^^^^^^^^^^^
@@ -262,7 +266,7 @@ LL |         impl Uto5 for Test {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:164:9
+  --> $DIR/non_local_definitions.rs:165:9
    |
 LL |         impl Uto5 for &Test {}
    |         ^^^^^^^^^^^^^^^^^^^^^^
@@ -273,7 +277,7 @@ LL |         impl Uto5 for &Test {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:171:9
+  --> $DIR/non_local_definitions.rs:172:9
    |
 LL |         impl Uto5 for &(Test,) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -284,7 +288,7 @@ LL |         impl Uto5 for &(Test,) {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:178:9
+  --> $DIR/non_local_definitions.rs:179:9
    |
 LL |         impl Uto5 for &(Test,Test) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -295,7 +299,7 @@ LL |         impl Uto5 for &(Test,Test) {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:186:5
+  --> $DIR/non_local_definitions.rs:187:5
    |
 LL |     impl Uto5 for *mut InsideMain {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -306,7 +310,7 @@ LL |     impl Uto5 for *mut InsideMain {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:188:5
+  --> $DIR/non_local_definitions.rs:189:5
    |
 LL |     impl Uto5 for *mut [InsideMain] {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -317,7 +321,7 @@ LL |     impl Uto5 for *mut [InsideMain] {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:190:5
+  --> $DIR/non_local_definitions.rs:191:5
    |
 LL |     impl Uto5 for [InsideMain; 8] {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -328,7 +332,7 @@ LL |     impl Uto5 for [InsideMain; 8] {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:192:5
+  --> $DIR/non_local_definitions.rs:193:5
    |
 LL |     impl Uto5 for (InsideMain,) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -339,7 +343,7 @@ LL |     impl Uto5 for (InsideMain,) {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:194:5
+  --> $DIR/non_local_definitions.rs:195:5
    |
 LL |     impl Uto5 for fn(InsideMain) -> () {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -350,7 +354,7 @@ LL |     impl Uto5 for fn(InsideMain) -> () {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:196:5
+  --> $DIR/non_local_definitions.rs:197:5
    |
 LL |     impl Uto5 for fn() -> InsideMain {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -361,7 +365,7 @@ LL |     impl Uto5 for fn() -> InsideMain {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:210:9
+  --> $DIR/non_local_definitions.rs:211:9
    |
 LL | /         impl Display for InsideMain {
 LL | |
@@ -377,7 +381,7 @@ LL | |         }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:217:9
+  --> $DIR/non_local_definitions.rs:218:9
    |
 LL | /         impl InsideMain {
 LL | |
@@ -394,7 +398,7 @@ LL | |         }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:221:17
+  --> $DIR/non_local_definitions.rs:222:17
    |
 LL |                 macro_rules! m2 { () => { } };
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -405,7 +409,7 @@ LL |                 macro_rules! m2 { () => { } };
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:231:5
+  --> $DIR/non_local_definitions.rs:232:5
    |
 LL |     impl<T: Uto6> Uto3 for Vec<T> { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -416,7 +420,7 @@ LL |     impl<T: Uto6> Uto3 for Vec<T> { }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:240:5
+  --> $DIR/non_local_definitions.rs:241:5
    |
 LL |     impl Uto7 for Test where Local: std::any::Any {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -427,7 +431,7 @@ LL |     impl Uto7 for Test where Local: std::any::Any {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:243:5
+  --> $DIR/non_local_definitions.rs:244:5
    |
 LL |     impl<T> Uto8 for T {}
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -438,7 +442,7 @@ LL |     impl<T> Uto8 for T {}
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:252:5
+  --> $DIR/non_local_definitions.rs:253:5
    |
 LL | /     impl Default for UwU<OwO> {
 LL | |
@@ -454,7 +458,7 @@ LL | |     }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:263:5
+  --> $DIR/non_local_definitions.rs:264:5
    |
 LL | /     impl From<Cat> for () {
 LL | |
@@ -470,7 +474,7 @@ LL | |     }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:272:5
+  --> $DIR/non_local_definitions.rs:273:5
    |
 LL | /     impl AsRef<Cat> for () {
 LL | |
@@ -484,7 +488,7 @@ LL | |     }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:283:5
+  --> $DIR/non_local_definitions.rs:284:5
    |
 LL | /     impl PartialEq<B> for G {
 LL | |
@@ -500,7 +504,7 @@ LL | |     }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:300:5
+  --> $DIR/non_local_definitions.rs:301:5
    |
 LL | /     impl PartialEq<Dog> for &Dog {
 LL | |
@@ -516,7 +520,7 @@ LL | |     }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:307:5
+  --> $DIR/non_local_definitions.rs:308:5
    |
 LL | /     impl PartialEq<()> for Dog {
 LL | |
@@ -532,7 +536,7 @@ LL | |     }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:314:5
+  --> $DIR/non_local_definitions.rs:315:5
    |
 LL | /     impl PartialEq<()> for &Dog {
 LL | |
@@ -548,7 +552,7 @@ LL | |     }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:321:5
+  --> $DIR/non_local_definitions.rs:322:5
    |
 LL | /     impl PartialEq<Dog> for () {
 LL | |
@@ -564,7 +568,7 @@ LL | |     }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:343:5
+  --> $DIR/non_local_definitions.rs:344:5
    |
 LL | /     impl From<Wrap<Wrap<Lion>>> for () {
 LL | |
@@ -580,7 +584,7 @@ LL | |     }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:350:5
+  --> $DIR/non_local_definitions.rs:351:5
    |
 LL | /     impl From<()> for Wrap<Lion> {
 LL | |
@@ -596,7 +600,7 @@ LL | |     }
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:363:13
+  --> $DIR/non_local_definitions.rs:364:13
    |
 LL |             impl MacroTrait for OutsideStruct {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -611,7 +615,7 @@ LL | m!();
    = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 warning: non-local `impl` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:373:1
+  --> $DIR/non_local_definitions.rs:374:1
    |
 LL | non_local_macro::non_local_impl!(CargoUpdate);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -624,7 +628,7 @@ LL | non_local_macro::non_local_impl!(CargoUpdate);
    = note: this warning originates in the macro `non_local_macro::non_local_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation
-  --> $DIR/non_local_definitions.rs:376:1
+  --> $DIR/non_local_definitions.rs:377:1
    |
 LL | non_local_macro::non_local_macro_rules!(my_macro);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/use-redundant/use-redundant-issue-71450.rs b/tests/ui/lint/use-redundant/use-redundant-issue-71450.rs
new file mode 100644
index 00000000000..d0fb3454d3f
--- /dev/null
+++ b/tests/ui/lint/use-redundant/use-redundant-issue-71450.rs
@@ -0,0 +1,45 @@
+//@ check-pass
+
+#![warn(unused_imports)]
+
+mod foo {
+    use std::fmt;
+
+    pub struct String;
+
+    impl String {
+        pub fn new() -> String {
+            String{}
+        }
+    }
+
+    impl fmt::Display for String {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            write!(f, "String")
+        }
+    }
+}
+
+fn main() {
+
+    {
+        use std::string::String; //~ WARNING the item `String` is imported redundantly
+        // 'String' from 'std::string::String'.
+        let s = String::new();
+        println!("{}", s);
+    }
+
+    {
+        // 'String' from 'std::string::String'.
+        let s = String::new();
+        println!("{}", s);
+    }
+
+    {
+        use foo::*;
+        // 'String' from 'foo::String'.
+        let s = String::new();
+        println!("{}", s);
+    }
+
+}
diff --git a/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr b/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr
new file mode 100644
index 00000000000..b8832a31783
--- /dev/null
+++ b/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr
@@ -0,0 +1,17 @@
+warning: the item `String` is imported redundantly
+  --> $DIR/use-redundant-issue-71450.rs:26:13
+   |
+LL |         use std::string::String;
+   |             ^^^^^^^^^^^^^^^^^^^
+  --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
+   |
+   = note: the item `String` is already defined here
+   |
+note: the lint level is defined here
+  --> $DIR/use-redundant-issue-71450.rs:3:9
+   |
+LL | #![warn(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/lint/use-redundant/use-redundant-issue-78894.rs b/tests/ui/lint/use-redundant/use-redundant-issue-78894.rs
new file mode 100644
index 00000000000..09c87bc37a6
--- /dev/null
+++ b/tests/ui/lint/use-redundant/use-redundant-issue-78894.rs
@@ -0,0 +1,48 @@
+//@ check-pass
+//@ edition:2018
+
+#![warn(unused_imports)]
+
+mod foo {
+    macro_rules! foo1 {
+        () => ();
+    }
+
+    pub(crate) use foo1;
+}
+
+fn main ()
+{
+    bar!();
+
+    macro_rules! bar {
+        () => ();
+    }
+
+    use bar;
+
+    mod m {
+        bar1!();
+
+        macro_rules! bar1 {
+            () => ();
+        }
+
+        use bar1;
+    }
+
+    {
+        foo::foo1!();
+    }
+
+    {
+        use foo::foo1;
+        foo1!();
+    }
+
+    {
+        use foo::foo1; //~ WARNING unused import: `foo::foo1`
+        foo::foo1!();
+    }
+
+}
diff --git a/tests/ui/lint/use-redundant/use-redundant-issue-78894.stderr b/tests/ui/lint/use-redundant/use-redundant-issue-78894.stderr
new file mode 100644
index 00000000000..78dfe364223
--- /dev/null
+++ b/tests/ui/lint/use-redundant/use-redundant-issue-78894.stderr
@@ -0,0 +1,14 @@
+warning: unused import: `foo::foo1`
+  --> $DIR/use-redundant-issue-78894.rs:44:13
+   |
+LL |         use foo::foo1;
+   |             ^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/use-redundant-issue-78894.rs:4:9
+   |
+LL | #![warn(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/logging-only-prints-once.rs b/tests/ui/logging-only-prints-once.rs
index 75ef0a274ee..5377d5eeae2 100644
--- a/tests/ui/logging-only-prints-once.rs
+++ b/tests/ui/logging-only-prints-once.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 //@ ignore-windows
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::cell::Cell;
 use std::fmt;
diff --git a/tests/ui/lto/lto-still-runs-thread-dtors.rs b/tests/ui/lto/lto-still-runs-thread-dtors.rs
index a93d7cf35cc..504923a93c2 100644
--- a/tests/ui/lto/lto-still-runs-thread-dtors.rs
+++ b/tests/ui/lto/lto-still-runs-thread-dtors.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 //@ compile-flags: -C lto
 //@ no-prefer-dynamic
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 
diff --git a/tests/ui/macros/macro-with-braces-in-expr-position.rs b/tests/ui/macros/macro-with-braces-in-expr-position.rs
index febfa7241f2..4607349e963 100644
--- a/tests/ui/macros/macro-with-braces-in-expr-position.rs
+++ b/tests/ui/macros/macro-with-braces-in-expr-position.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_must_use)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 
diff --git a/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr b/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr
index 92a54cff7f5..ab86df9c8a5 100644
--- a/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr
+++ b/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr
@@ -1,15 +1,3 @@
-error[E0715]: impls for marker traits cannot contain items
-  --> $DIR/override-item-on-marker-trait.rs:12:1
-   |
-LL | impl Marker for OverrideConst {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0715]: impls for marker traits cannot contain items
-  --> $DIR/override-item-on-marker-trait.rs:18:1
-   |
-LL | impl Marker for OverrideFn {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0714]: marker traits cannot have associated items
   --> $DIR/override-item-on-marker-trait.rs:5:5
    |
@@ -22,6 +10,18 @@ error[E0714]: marker traits cannot have associated items
 LL |     fn do_something() {}
    |     ^^^^^^^^^^^^^^^^^
 
+error[E0715]: impls for marker traits cannot contain items
+  --> $DIR/override-item-on-marker-trait.rs:12:1
+   |
+LL | impl Marker for OverrideConst {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0715]: impls for marker traits cannot contain items
+  --> $DIR/override-item-on-marker-trait.rs:18:1
+   |
+LL | impl Marker for OverrideFn {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0714, E0715.
diff --git a/tests/ui/match/issue-18060.rs b/tests/ui/match/issue-18060.rs
index daba393a3fa..9d480ba6b8b 100644
--- a/tests/ui/match/issue-18060.rs
+++ b/tests/ui/match/issue-18060.rs
@@ -1,6 +1,7 @@
 //@ run-pass
 // Regression test for #18060: match arms were matching in the wrong order.
 
+#[allow(non_contiguous_range_endpoints)]
 fn main() {
     assert_eq!(2, match (1, 3) { (0, 2..=5) => 1, (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 });
     assert_eq!(2, match (1, 3) {                  (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 });
diff --git a/tests/ui/meta/dir.with.dots/test.rs b/tests/ui/meta/dir.with.dots/test.rs
new file mode 100644
index 00000000000..4d663e994f5
--- /dev/null
+++ b/tests/ui/meta/dir.with.dots/test.rs
@@ -0,0 +1,7 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/121986>.
+// Check that `tests_revision_unpaired_stdout_stderr` don't accidentally get confused by
+// paths containing periods.
+
+//@ check-pass
+
+fn main() {}
diff --git a/tests/ui/methods/issues/issue-94581.fixed b/tests/ui/methods/issues/issue-94581.fixed
new file mode 100644
index 00000000000..ff2bbeba27c
--- /dev/null
+++ b/tests/ui/methods/issues/issue-94581.fixed
@@ -0,0 +1,8 @@
+//@ run-rustfix
+fn get_slice() -> &'static [i32] {
+    &[1, 2, 3, 4]
+}
+
+fn main() {
+    let _sqsum: i32 = get_slice().into_iter().map(|i| i * i).sum(); //~ ERROR [E0599]
+}
diff --git a/tests/ui/methods/issues/issue-94581.rs b/tests/ui/methods/issues/issue-94581.rs
index df393e91db0..535d3249eb9 100644
--- a/tests/ui/methods/issues/issue-94581.rs
+++ b/tests/ui/methods/issues/issue-94581.rs
@@ -1,7 +1,8 @@
+//@ run-rustfix
 fn get_slice() -> &'static [i32] {
     &[1, 2, 3, 4]
 }
 
 fn main() {
-    let sqsum = get_slice().map(|i| i * i).sum(); //~ ERROR [E0599]
+    let _sqsum: i32 = get_slice().map(|i| i * i).sum(); //~ ERROR [E0599]
 }
diff --git a/tests/ui/methods/issues/issue-94581.stderr b/tests/ui/methods/issues/issue-94581.stderr
index ae7446d4833..d04d6ca5e3c 100644
--- a/tests/ui/methods/issues/issue-94581.stderr
+++ b/tests/ui/methods/issues/issue-94581.stderr
@@ -1,14 +1,13 @@
-error[E0599]: `&'static [i32]` is not an iterator
-  --> $DIR/issue-94581.rs:6:29
+error[E0599]: no method named `map` found for reference `&'static [i32]` in the current scope
+  --> $DIR/issue-94581.rs:7:35
    |
-LL |     let sqsum = get_slice().map(|i| i * i).sum();
-   |                             ^^^ `&'static [i32]` is not an iterator; try calling `.iter()`
+LL |     let _sqsum: i32 = get_slice().map(|i| i * i).sum();
+   |                                   ^^^ `&'static [i32]` is not an iterator
    |
-   = note: the following trait bounds were not satisfied:
-           `&'static [i32]: Iterator`
-           which is required by `&mut &'static [i32]: Iterator`
-           `[i32]: Iterator`
-           which is required by `&mut [i32]: Iterator`
+help: call `.into_iter()` first
+   |
+LL |     let _sqsum: i32 = get_slice().into_iter().map(|i| i * i).sum();
+   |                                   ++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/mir/mir_match_test.rs b/tests/ui/mir/mir_match_test.rs
index 925e1e6ab3d..0da8522f218 100644
--- a/tests/ui/mir/mir_match_test.rs
+++ b/tests/ui/mir/mir_match_test.rs
@@ -1,5 +1,6 @@
 #![feature(exclusive_range_pattern)]
 #![allow(overlapping_range_endpoints)]
+#![allow(non_contiguous_range_endpoints)]
 
 //@ run-pass
 
diff --git a/tests/ui/moves/moves-based-on-type-capture-clause.rs b/tests/ui/moves/moves-based-on-type-capture-clause.rs
index baf52ffb515..46759f66468 100644
--- a/tests/ui/moves/moves-based-on-type-capture-clause.rs
+++ b/tests/ui/moves/moves-based-on-type-capture-clause.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_must_use)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 
diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr
index e7fcdbd0c9c..6beb04e5b93 100644
--- a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr
+++ b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr
@@ -1,21 +1,3 @@
-error[E0038]: the trait `Baz` cannot be made into an object
-  --> $DIR/object-safety-supertrait-mentions-Self.rs:16:31
-   |
-LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
-   |                               ^^^^^^^ `Baz` cannot be made into an object
-   |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/object-safety-supertrait-mentions-Self.rs:8:13
-   |
-LL | trait Baz : Bar<Self> {
-   |       ---   ^^^^^^^^^ ...because it uses `Self` as a type parameter
-   |       |
-   |       this trait cannot be made into an object...
-help: consider using an opaque type instead
-   |
-LL | fn make_baz<T:Baz>(t: &T) -> &impl Baz {
-   |                               ~~~~
-
 error[E0277]: the size for values of type `Self` cannot be known at compilation time
   --> $DIR/object-safety-supertrait-mentions-Self.rs:8:13
    |
@@ -36,6 +18,24 @@ help: consider relaxing the implicit `Sized` restriction
 LL | trait Bar<T: ?Sized> {
    |            ++++++++
 
+error[E0038]: the trait `Baz` cannot be made into an object
+  --> $DIR/object-safety-supertrait-mentions-Self.rs:16:31
+   |
+LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
+   |                               ^^^^^^^ `Baz` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/object-safety-supertrait-mentions-Self.rs:8:13
+   |
+LL | trait Baz : Bar<Self> {
+   |       ---   ^^^^^^^^^ ...because it uses `Self` as a type parameter
+   |       |
+   |       this trait cannot be made into an object...
+help: consider using an opaque type instead
+   |
+LL | fn make_baz<T:Baz>(t: &T) -> &impl Baz {
+   |                               ~~~~
+
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0038, E0277.
diff --git a/tests/ui/panics/default-backtrace-ice.stderr b/tests/ui/panics/default-backtrace-ice.stderr
index 9d27cb22ae9..82b61e43f44 100644
--- a/tests/ui/panics/default-backtrace-ice.stderr
+++ b/tests/ui/panics/default-backtrace-ice.stderr
@@ -21,5 +21,5 @@ error: the compiler unexpectedly panicked. this is a bug.
 
 
 query stack during panic:
-#0 [resolver_for_lowering] getting the resolver for lowering
+#0 [resolver_for_lowering_raw] getting the resolver for lowering
 end of query stack
diff --git a/tests/ui/panics/panic-handler-chain.rs b/tests/ui/panics/panic-handler-chain.rs
index eb23849f3ac..fea71ad9ec4 100644
--- a/tests/ui/panics/panic-handler-chain.rs
+++ b/tests/ui/panics/panic-handler-chain.rs
@@ -1,9 +1,8 @@
 //@ run-pass
 //@ needs-unwind
+//@ needs-threads
 #![allow(stable_features)]
 
-//@ ignore-emscripten no threads support
-
 #![feature(std_panic)]
 
 use std::sync::atomic::{AtomicUsize, Ordering};
diff --git a/tests/ui/panics/panic-task-name-none.rs b/tests/ui/panics/panic-task-name-none.rs
index 7eb974bde4c..8695771ff5e 100644
--- a/tests/ui/panics/panic-task-name-none.rs
+++ b/tests/ui/panics/panic-task-name-none.rs
@@ -1,7 +1,7 @@
 //@ run-fail
 //@ error-pattern:thread '<unnamed>' panicked
 //@ error-pattern:test
-//@ ignore-emscripten Needs threads
+//@ needs-threads
 
 use std::thread;
 
diff --git a/tests/ui/panics/panic-task-name-owned.rs b/tests/ui/panics/panic-task-name-owned.rs
index 9a680676dc0..42ae33b5d35 100644
--- a/tests/ui/panics/panic-task-name-owned.rs
+++ b/tests/ui/panics/panic-task-name-owned.rs
@@ -1,7 +1,7 @@
 //@ run-fail
 //@ error-pattern:thread 'owned name' panicked
 //@ error-pattern:test
-//@ ignore-emscripten Needs threads.
+//@ needs-threads
 
 use std::thread::Builder;
 
diff --git a/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr b/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr
index 1c71cdacd89..29b0b25a564 100644
--- a/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr
+++ b/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr
@@ -82,15 +82,6 @@ LL |     type W where Self: Eq;
    = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0592]: duplicate definitions with name `W`
-  --> $DIR/impl-item-type-no-body-semantic-fail.rs:18:5
-   |
-LL |     type W: Ord where Self: Eq;
-   |     ------ other definition for `W`
-...
-LL |     type W where Self: Eq;
-   |     ^^^^^^ duplicate definitions for `W`
-
 error[E0277]: the trait bound `X: Eq` is not satisfied
   --> $DIR/impl-item-type-no-body-semantic-fail.rs:13:23
    |
@@ -119,6 +110,15 @@ LL + #[derive(Eq)]
 LL | struct X;
    |
 
+error[E0592]: duplicate definitions with name `W`
+  --> $DIR/impl-item-type-no-body-semantic-fail.rs:18:5
+   |
+LL |     type W: Ord where Self: Eq;
+   |     ------ other definition for `W`
+...
+LL |     type W where Self: Eq;
+   |     ^^^^^^ duplicate definitions for `W`
+
 error: aborting due to 13 previous errors
 
 Some errors have detailed explanations: E0277, E0592, E0658.
diff --git a/tests/ui/parser/impls-nested-within-anon-consts-semantic.rs b/tests/ui/parser/impls-nested-within-anon-consts-semantic.rs
new file mode 100644
index 00000000000..36a7825cec8
--- /dev/null
+++ b/tests/ui/parser/impls-nested-within-anon-consts-semantic.rs
@@ -0,0 +1,35 @@
+// Regression test for issue #89342 and for part of #119924.
+//@ check-pass
+
+struct Expr<const N: u32>;
+
+trait Trait0 {
+    fn required(_: Expr<{
+        struct Type;
+
+        impl Type {
+            // This visibility qualifier used to get rejected.
+            pub fn perform() {}
+        }
+
+        0
+    }>);
+}
+
+trait Trait1 {}
+
+impl Trait1 for ()
+where
+    [(); {
+        struct Type;
+
+        impl Type {
+            // This visibility qualifier used to get rejected.
+            pub const STORE: Self = Self;
+        }
+
+        0
+    }]:
+{}
+
+fn main() {}
diff --git a/tests/ui/parser/impls-nested-within-fns-semantic-0.rs b/tests/ui/parser/impls-nested-within-fns-semantic-0.rs
new file mode 100644
index 00000000000..107380d33c7
--- /dev/null
+++ b/tests/ui/parser/impls-nested-within-fns-semantic-0.rs
@@ -0,0 +1,15 @@
+// Regression test for #121607 and for part of issue #119924.
+//@ check-pass
+
+trait Trait {
+    fn provided() {
+        pub struct Type;
+
+        impl Type {
+            // This visibility qualifier used to get rejected.
+            pub fn perform() {}
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/parser/impls-nested-within-fns-semantic-1.rs b/tests/ui/parser/impls-nested-within-fns-semantic-1.rs
new file mode 100644
index 00000000000..43530e41a66
--- /dev/null
+++ b/tests/ui/parser/impls-nested-within-fns-semantic-1.rs
@@ -0,0 +1,22 @@
+// Regression test for part of issue #119924.
+//@ check-pass
+
+#![feature(const_trait_impl, effects)]
+
+#[const_trait]
+trait Trait {
+    fn required();
+}
+
+impl const Trait for () {
+    fn required() {
+        pub struct Type;
+
+        impl Type {
+            // This visibility qualifier used to get rejected.
+            pub fn perform() {}
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs
index ed4de58cd23..521eb6a818b 100644
--- a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs
+++ b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs
@@ -1,3 +1,10 @@
+#![allow(unused)]
+
+fn test_122112() {
+    // Make sure we don't ICE if parsing in recovery fails
+    let _: std::env::temp_dir().join(&self, push: Box<usize>);  //~ ERROR expected one of
+}
+
 fn main() {
     let _: std::env::temp_dir().join("foo"); //~ ERROR expected one of
 }
diff --git a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr
index d03f3ae0283..15c27bb9451 100644
--- a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr
+++ b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr
@@ -1,5 +1,13 @@
 error: expected one of `!`, `+`, `->`, `::`, `;`, or `=`, found `.`
-  --> $DIR/recover-colon-instead-of-eq-in-local.rs:2:32
+  --> $DIR/recover-colon-instead-of-eq-in-local.rs:5:32
+   |
+LL |     let _: std::env::temp_dir().join(&self, push: Box<usize>);
+   |          -                     ^ expected one of `!`, `+`, `->`, `::`, `;`, or `=`
+   |          |
+   |          while parsing the type for `_`
+
+error: expected one of `!`, `+`, `->`, `::`, `;`, or `=`, found `.`
+  --> $DIR/recover-colon-instead-of-eq-in-local.rs:9:32
    |
 LL |     let _: std::env::temp_dir().join("foo");
    |          -                     ^ expected one of `!`, `+`, `->`, `::`, `;`, or `=`
@@ -7,5 +15,5 @@ LL |     let _: std::env::temp_dir().join("foo");
    |          while parsing the type for `_`
    |          help: use `=` if you meant to assign
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs
index 0f5f49c4ca4..07156d9a08a 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs
+++ b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.rs
@@ -1,5 +1,6 @@
 #![feature(exclusive_range_pattern)]
 #![allow(overlapping_range_endpoints)]
+#![allow(non_contiguous_range_endpoints)]
 #![deny(unreachable_patterns)]
 
 macro_rules! m {
diff --git a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr
index b585de20629..90d0fd7483a 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr
+++ b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
-  --> $DIR/exhaustiveness.rs:47:8
+  --> $DIR/exhaustiveness.rs:48:8
    |
 LL |     m!(0u8, 0..255);
    |        ^^^ pattern `u8::MAX` not covered
@@ -11,7 +11,7 @@ LL |         match $s { $($t)+ => {}, u8::MAX => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
-  --> $DIR/exhaustiveness.rs:48:8
+  --> $DIR/exhaustiveness.rs:49:8
    |
 LL |     m!(0u8, 0..=254);
    |        ^^^ pattern `u8::MAX` not covered
@@ -23,7 +23,7 @@ LL |         match $s { $($t)+ => {}, u8::MAX => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_u8` not covered
-  --> $DIR/exhaustiveness.rs:49:8
+  --> $DIR/exhaustiveness.rs:50:8
    |
 LL |     m!(0u8, 1..=255);
    |        ^^^ pattern `0_u8` not covered
@@ -35,7 +35,7 @@ LL |         match $s { $($t)+ => {}, 0_u8 => todo!() }
    |                                +++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `42_u8` not covered
-  --> $DIR/exhaustiveness.rs:50:8
+  --> $DIR/exhaustiveness.rs:51:8
    |
 LL |     m!(0u8, 0..42 | 43..=255);
    |        ^^^ pattern `42_u8` not covered
@@ -47,7 +47,7 @@ LL |         match $s { $($t)+ => {}, 42_u8 => todo!() }
    |                                ++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
-  --> $DIR/exhaustiveness.rs:51:8
+  --> $DIR/exhaustiveness.rs:52:8
    |
 LL |     m!(0i8, -128..127);
    |        ^^^ pattern `i8::MAX` not covered
@@ -59,7 +59,7 @@ LL |         match $s { $($t)+ => {}, i8::MAX => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
-  --> $DIR/exhaustiveness.rs:52:8
+  --> $DIR/exhaustiveness.rs:53:8
    |
 LL |     m!(0i8, -128..=126);
    |        ^^^ pattern `i8::MAX` not covered
@@ -71,7 +71,7 @@ LL |         match $s { $($t)+ => {}, i8::MAX => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i8::MIN` not covered
-  --> $DIR/exhaustiveness.rs:53:8
+  --> $DIR/exhaustiveness.rs:54:8
    |
 LL |     m!(0i8, -127..=127);
    |        ^^^ pattern `i8::MIN` not covered
@@ -83,7 +83,7 @@ LL |         match $s { $($t)+ => {}, i8::MIN => todo!() }
    |                                ++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_i8` not covered
-  --> $DIR/exhaustiveness.rs:54:11
+  --> $DIR/exhaustiveness.rs:55:11
    |
 LL |     match 0i8 {
    |           ^^^ pattern `0_i8` not covered
@@ -96,7 +96,7 @@ LL +         0_i8 => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
-  --> $DIR/exhaustiveness.rs:59:8
+  --> $DIR/exhaustiveness.rs:60:8
    |
 LL |     m!(0u128, 0..=ALMOST_MAX);
    |        ^^^^^ pattern `u128::MAX` not covered
@@ -108,7 +108,7 @@ LL |         match $s { $($t)+ => {}, u128::MAX => todo!() }
    |                                ++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `5_u128..=u128::MAX` not covered
-  --> $DIR/exhaustiveness.rs:60:8
+  --> $DIR/exhaustiveness.rs:61:8
    |
 LL |     m!(0u128, 0..=4);
    |        ^^^^^ pattern `5_u128..=u128::MAX` not covered
@@ -120,7 +120,7 @@ LL |         match $s { $($t)+ => {}, 5_u128..=u128::MAX => todo!() }
    |                                +++++++++++++++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `0_u128` not covered
-  --> $DIR/exhaustiveness.rs:61:8
+  --> $DIR/exhaustiveness.rs:62:8
    |
 LL |     m!(0u128, 1..=u128::MAX);
    |        ^^^^^ pattern `0_u128` not covered
@@ -132,7 +132,7 @@ LL |         match $s { $($t)+ => {}, 0_u128 => todo!() }
    |                                +++++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `(126_u8..=127_u8, false)` not covered
-  --> $DIR/exhaustiveness.rs:69:11
+  --> $DIR/exhaustiveness.rs:70:11
    |
 LL |     match (0u8, true) {
    |           ^^^^^^^^^^^ pattern `(126_u8..=127_u8, false)` not covered
diff --git a/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.rs b/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.rs
new file mode 100644
index 00000000000..78849d7e143
--- /dev/null
+++ b/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.rs
@@ -0,0 +1,117 @@
+#![feature(exclusive_range_pattern)]
+#![deny(non_contiguous_range_endpoints)]
+
+macro_rules! m {
+    ($s:expr, $t1:pat, $t2:pat) => {
+        match $s {
+            $t1 => {}
+            $t2 => {}
+            _ => {}
+        }
+    };
+}
+
+fn main() {
+    match 0u8 {
+        20..30 => {} //~ ERROR multiple ranges are one apart
+        31..=40 => {}
+        _ => {}
+    }
+    match 0u8 {
+        20..30 => {} //~ ERROR multiple ranges are one apart
+        31 => {}
+        _ => {}
+    }
+
+    m!(0u8, 20..30, 31..=40); //~ ERROR multiple ranges are one apart
+    m!(0u8, 31..=40, 20..30); //~ ERROR multiple ranges are one apart
+    m!(0u8, 20..30, 29..=40); //~ WARN multiple patterns overlap on their endpoints
+    m!(0u8, 20..30, 30..=40);
+    m!(0u8, 20..30, 31..=40); //~ ERROR multiple ranges are one apart
+    m!(0u8, 20..30, 32..=40);
+    m!(0u8, 20..30, 31..=32); //~ ERROR multiple ranges are one apart
+    // Don't lint two singletons.
+    m!(0u8, 30, 32);
+    // Don't lint on the equivalent inclusive range
+    m!(0u8, 20..=29, 31..=40);
+    // Don't lint if the lower one is a singleton.
+    m!(0u8, 30, 32..=40);
+
+    // Catch the `lo..MAX` case.
+    match 0u8 {
+        0..255 => {} //~ ERROR exclusive range missing `u8::MAX`
+        _ => {}
+    }
+    // Except for `usize`, since `0..=usize::MAX` isn't exhaustive either.
+    match 0usize {
+        0..usize::MAX => {}
+        _ => {}
+    }
+
+    // Don't lint if the gap is caught by another range.
+    match 0u8 {
+        0..10 => {}
+        11..20 => {}
+        10 => {}
+        _ => {}
+    }
+    match 0u8 {
+        0..10 => {}
+        11..20 => {}
+        5..15 => {}
+        _ => {}
+    }
+    match 0u8 {
+        0..255 => {}
+        255 => {}
+    }
+
+    // Test multiple at once
+    match 0u8 {
+        0..10 => {} //~ ERROR multiple ranges are one apart
+        11..20 => {}
+        11..30 => {}
+        _ => {}
+    }
+    match 0u8 {
+        0..10 => {}  //~ ERROR multiple ranges are one apart
+        11..20 => {} //~ ERROR multiple ranges are one apart
+        21..30 => {}
+        _ => {}
+    }
+    match 0u8 {
+        00..20 => {} //~ ERROR multiple ranges are one apart
+        10..20 => {} //~ ERROR multiple ranges are one apart
+        21..30 => {}
+        21..40 => {}
+        _ => {}
+    }
+
+    // Test nested
+    match (0u8, true) {
+        (0..10, true) => {} //~ ERROR multiple ranges are one apart
+        (11..20, true) => {}
+        _ => {}
+    }
+    match (true, 0u8) {
+        (true, 0..10) => {} //~ ERROR multiple ranges are one apart
+        (true, 11..20) => {}
+        _ => {}
+    }
+    // Asymmetry due to how exhaustiveness is computed.
+    match (0u8, true) {
+        (0..10, true) => {} //~ ERROR multiple ranges are one apart
+        (11..20, false) => {}
+        _ => {}
+    }
+    match (true, 0u8) {
+        (true, 0..10) => {}
+        (false, 11..20) => {}
+        _ => {}
+    }
+    match Some(0u8) {
+        Some(0..10) => {} //~ ERROR multiple ranges are one apart
+        Some(11..20) => {}
+        _ => {}
+    }
+}
diff --git a/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.stderr b/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.stderr
new file mode 100644
index 00000000000..e5c2d788ba4
--- /dev/null
+++ b/tests/ui/pattern/usefulness/integer-ranges/gap_between_ranges.stderr
@@ -0,0 +1,193 @@
+error: multiple ranges are one apart
+  --> $DIR/gap_between_ranges.rs:16:9
+   |
+LL |         20..30 => {}
+   |         ^^^^^^
+   |         |
+   |         this range doesn't match `30_u8` because `..` is an exclusive range
+   |         help: use an inclusive range instead: `20_u8..=30_u8`
+LL |         31..=40 => {}
+   |         ------- this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them
+   |
+note: the lint level is defined here
+  --> $DIR/gap_between_ranges.rs:2:9
+   |
+LL | #![deny(non_contiguous_range_endpoints)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: multiple ranges are one apart
+  --> $DIR/gap_between_ranges.rs:21:9
+   |
+LL |         20..30 => {}
+   |         ^^^^^^
+   |         |
+   |         this range doesn't match `30_u8` because `..` is an exclusive range
+   |         help: use an inclusive range instead: `20_u8..=30_u8`
+LL |         31 => {}
+   |         -- this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them
+
+error: multiple ranges are one apart
+  --> $DIR/gap_between_ranges.rs:26:13
+   |
+LL |     m!(0u8, 20..30, 31..=40);
+   |             ^^^^^^  ------- this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them
+   |             |
+   |             this range doesn't match `30_u8` because `..` is an exclusive range
+   |             help: use an inclusive range instead: `20_u8..=30_u8`
+
+error: multiple ranges are one apart
+  --> $DIR/gap_between_ranges.rs:27:22
+   |
+LL |     m!(0u8, 31..=40, 20..30);
+   |             -------  ^^^^^^
+   |             |        |
+   |             |        this range doesn't match `30_u8` because `..` is an exclusive range
+   |             |        help: use an inclusive range instead: `20_u8..=30_u8`
+   |             this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them
+
+warning: multiple patterns overlap on their endpoints
+  --> $DIR/gap_between_ranges.rs:28:21
+   |
+LL |     m!(0u8, 20..30, 29..=40);
+   |             ------  ^^^^^^^ ... with this range
+   |             |
+   |             this range overlaps on `29_u8`...
+   |
+   = note: you likely meant to write mutually exclusive ranges
+   = note: `#[warn(overlapping_range_endpoints)]` on by default
+
+error: multiple ranges are one apart
+  --> $DIR/gap_between_ranges.rs:30:13
+   |
+LL |     m!(0u8, 20..30, 31..=40);
+   |             ^^^^^^  ------- this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them
+   |             |
+   |             this range doesn't match `30_u8` because `..` is an exclusive range
+   |             help: use an inclusive range instead: `20_u8..=30_u8`
+
+error: multiple ranges are one apart
+  --> $DIR/gap_between_ranges.rs:32:13
+   |
+LL |     m!(0u8, 20..30, 31..=32);
+   |             ^^^^^^  ------- this could appear to continue range `20_u8..30_u8`, but `30_u8` isn't matched by either of them
+   |             |
+   |             this range doesn't match `30_u8` because `..` is an exclusive range
+   |             help: use an inclusive range instead: `20_u8..=30_u8`
+
+error: exclusive range missing `u8::MAX`
+  --> $DIR/gap_between_ranges.rs:42:9
+   |
+LL |         0..255 => {}
+   |         ^^^^^^
+   |         |
+   |         this range doesn't match `u8::MAX` because `..` is an exclusive range
+   |         help: use an inclusive range instead: `0_u8..=u8::MAX`
+
+error: multiple ranges are one apart
+  --> $DIR/gap_between_ranges.rs:71:9
+   |
+LL |         0..10 => {}
+   |         ^^^^^
+   |         |
+   |         this range doesn't match `10_u8` because `..` is an exclusive range
+   |         help: use an inclusive range instead: `0_u8..=10_u8`
+LL |         11..20 => {}
+   |         ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them
+LL |         11..30 => {}
+   |         ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them
+
+error: multiple ranges are one apart
+  --> $DIR/gap_between_ranges.rs:77:9
+   |
+LL |         0..10 => {}
+   |         ^^^^^
+   |         |
+   |         this range doesn't match `10_u8` because `..` is an exclusive range
+   |         help: use an inclusive range instead: `0_u8..=10_u8`
+LL |         11..20 => {}
+   |         ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them
+
+error: multiple ranges are one apart
+  --> $DIR/gap_between_ranges.rs:78:9
+   |
+LL |         11..20 => {}
+   |         ^^^^^^
+   |         |
+   |         this range doesn't match `20_u8` because `..` is an exclusive range
+   |         help: use an inclusive range instead: `11_u8..=20_u8`
+LL |         21..30 => {}
+   |         ------ this could appear to continue range `11_u8..20_u8`, but `20_u8` isn't matched by either of them
+
+error: multiple ranges are one apart
+  --> $DIR/gap_between_ranges.rs:83:9
+   |
+LL |         00..20 => {}
+   |         ^^^^^^
+   |         |
+   |         this range doesn't match `20_u8` because `..` is an exclusive range
+   |         help: use an inclusive range instead: `0_u8..=20_u8`
+LL |         10..20 => {}
+LL |         21..30 => {}
+   |         ------ this could appear to continue range `0_u8..20_u8`, but `20_u8` isn't matched by either of them
+LL |         21..40 => {}
+   |         ------ this could appear to continue range `0_u8..20_u8`, but `20_u8` isn't matched by either of them
+
+error: multiple ranges are one apart
+  --> $DIR/gap_between_ranges.rs:84:9
+   |
+LL |         10..20 => {}
+   |         ^^^^^^
+   |         |
+   |         this range doesn't match `20_u8` because `..` is an exclusive range
+   |         help: use an inclusive range instead: `10_u8..=20_u8`
+LL |         21..30 => {}
+   |         ------ this could appear to continue range `10_u8..20_u8`, but `20_u8` isn't matched by either of them
+LL |         21..40 => {}
+   |         ------ this could appear to continue range `10_u8..20_u8`, but `20_u8` isn't matched by either of them
+
+error: multiple ranges are one apart
+  --> $DIR/gap_between_ranges.rs:92:10
+   |
+LL |         (0..10, true) => {}
+   |          ^^^^^
+   |          |
+   |          this range doesn't match `10_u8` because `..` is an exclusive range
+   |          help: use an inclusive range instead: `0_u8..=10_u8`
+LL |         (11..20, true) => {}
+   |          ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them
+
+error: multiple ranges are one apart
+  --> $DIR/gap_between_ranges.rs:97:16
+   |
+LL |         (true, 0..10) => {}
+   |                ^^^^^
+   |                |
+   |                this range doesn't match `10_u8` because `..` is an exclusive range
+   |                help: use an inclusive range instead: `0_u8..=10_u8`
+LL |         (true, 11..20) => {}
+   |                ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them
+
+error: multiple ranges are one apart
+  --> $DIR/gap_between_ranges.rs:103:10
+   |
+LL |         (0..10, true) => {}
+   |          ^^^^^
+   |          |
+   |          this range doesn't match `10_u8` because `..` is an exclusive range
+   |          help: use an inclusive range instead: `0_u8..=10_u8`
+LL |         (11..20, false) => {}
+   |          ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them
+
+error: multiple ranges are one apart
+  --> $DIR/gap_between_ranges.rs:113:14
+   |
+LL |         Some(0..10) => {}
+   |              ^^^^^
+   |              |
+   |              this range doesn't match `10_u8` because `..` is an exclusive range
+   |              help: use an inclusive range instead: `0_u8..=10_u8`
+LL |         Some(11..20) => {}
+   |              ------ this could appear to continue range `0_u8..10_u8`, but `10_u8` isn't matched by either of them
+
+error: aborting due to 16 previous errors; 1 warning emitted
+
diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.rs b/tests/ui/pattern/usefulness/integer-ranges/reachability.rs
index 247fdd91572..13b84e2c44b 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/reachability.rs
+++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.rs
@@ -1,5 +1,6 @@
 #![feature(exclusive_range_pattern)]
 #![allow(overlapping_range_endpoints)]
+#![allow(non_contiguous_range_endpoints)]
 #![deny(unreachable_patterns)]
 
 macro_rules! m {
diff --git a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr
index c5b028d2038..0f52dfd83b9 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr
+++ b/tests/ui/pattern/usefulness/integer-ranges/reachability.stderr
@@ -1,137 +1,137 @@
 error: unreachable pattern
-  --> $DIR/reachability.rs:18:17
+  --> $DIR/reachability.rs:19:17
    |
 LL |     m!(0u8, 42, 42);
    |                 ^^
    |
 note: the lint level is defined here
-  --> $DIR/reachability.rs:3:9
+  --> $DIR/reachability.rs:4:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:22:22
+  --> $DIR/reachability.rs:23:22
    |
 LL |     m!(0u8, 20..=30, 20);
    |                      ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:23:22
+  --> $DIR/reachability.rs:24:22
    |
 LL |     m!(0u8, 20..=30, 21);
    |                      ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:24:22
+  --> $DIR/reachability.rs:25:22
    |
 LL |     m!(0u8, 20..=30, 25);
    |                      ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:25:22
+  --> $DIR/reachability.rs:26:22
    |
 LL |     m!(0u8, 20..=30, 29);
    |                      ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:26:22
+  --> $DIR/reachability.rs:27:22
    |
 LL |     m!(0u8, 20..=30, 30);
    |                      ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:29:21
+  --> $DIR/reachability.rs:30:21
    |
 LL |     m!(0u8, 20..30, 20);
    |                     ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:30:21
+  --> $DIR/reachability.rs:31:21
    |
 LL |     m!(0u8, 20..30, 21);
    |                     ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:31:21
+  --> $DIR/reachability.rs:32:21
    |
 LL |     m!(0u8, 20..30, 25);
    |                     ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:32:21
+  --> $DIR/reachability.rs:33:21
    |
 LL |     m!(0u8, 20..30, 29);
    |                     ^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:36:22
+  --> $DIR/reachability.rs:37:22
    |
 LL |     m!(0u8, 20..=30, 20..=30);
    |                      ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:37:22
+  --> $DIR/reachability.rs:38:22
    |
 LL |     m!(0u8, 20.. 30, 20.. 30);
    |                      ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:38:22
+  --> $DIR/reachability.rs:39:22
    |
 LL |     m!(0u8, 20..=30, 20.. 30);
    |                      ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:40:22
+  --> $DIR/reachability.rs:41:22
    |
 LL |     m!(0u8, 20..=30, 21..=30);
    |                      ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:41:22
+  --> $DIR/reachability.rs:42:22
    |
 LL |     m!(0u8, 20..=30, 20..=29);
    |                      ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:43:24
+  --> $DIR/reachability.rs:44:24
    |
 LL |     m!('a', 'A'..='z', 'a'..='z');
    |                        ^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:50:9
+  --> $DIR/reachability.rs:51:9
    |
 LL |         5..=8 => {},
    |         ^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:56:9
+  --> $DIR/reachability.rs:57:9
    |
 LL |         5..15 => {},
    |         ^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:63:9
+  --> $DIR/reachability.rs:64:9
    |
 LL |         5..25 => {},
    |         ^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:71:9
+  --> $DIR/reachability.rs:72:9
    |
 LL |         5..25 => {},
    |         ^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:77:9
+  --> $DIR/reachability.rs:78:9
    |
 LL |         5..15 => {},
    |         ^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:84:9
+  --> $DIR/reachability.rs:85:9
    |
 LL |         _ => {},
    |         - matches any value
@@ -139,19 +139,19 @@ LL |         '\u{D7FF}'..='\u{E000}' => {},
    |         ^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:89:9
+  --> $DIR/reachability.rs:90:9
    |
 LL |         '\u{D7FF}'..='\u{E000}' => {},
    |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:105:9
+  --> $DIR/reachability.rs:106:9
    |
 LL |         &FOO => {}
    |         ^^^^
 
 error: unreachable pattern
-  --> $DIR/reachability.rs:106:9
+  --> $DIR/reachability.rs:107:9
    |
 LL |         BAR => {}
    |         ^^^
diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs
index 8567d812e4f..29793e9f734 100644
--- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs
+++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs
@@ -14,7 +14,7 @@ struct PriorityQueueEntry<T> {
 //~^ ERROR can't compare `PriorityQueue<T>` with `PriorityQueue<T>`
 //~| ERROR the trait bound `PriorityQueue<T>: Eq` is not satisfied
 //~| ERROR can't compare `T` with `T`
-//~| ERROR `BinaryHeap<PriorityQueueEntry<T>>` is not an iterator
+//~| ERROR no method named `cmp` found for struct `BinaryHeap<PriorityQueueEntry<T>>`
 //~| ERROR no field `height` on type `&PriorityQueue<T>`
 
 struct PriorityQueue<T>(BinaryHeap<PriorityQueueEntry<T>>);
diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr
index 6fa639877d3..0fe560afcb5 100644
--- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr
+++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr
@@ -46,15 +46,12 @@ LL | struct PriorityQueue<T>(BinaryHeap<PriorityQueueEntry<T>>);
    = help: the trait `PartialOrd<_>` is not implemented for `BinaryHeap<PriorityQueueEntry<T>>`
    = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0599]: `BinaryHeap<PriorityQueueEntry<T>>` is not an iterator
+error[E0599]: no method named `cmp` found for struct `BinaryHeap<PriorityQueueEntry<T>>` in the current scope
   --> $DIR/issue-104884-trait-impl-sugg-err.rs:13:22
    |
 LL | #[derive(PartialOrd, AddImpl)]
    |                      ^^^^^^^ `BinaryHeap<PriorityQueueEntry<T>>` is not an iterator
    |
-   = note: the following trait bounds were not satisfied:
-           `BinaryHeap<PriorityQueueEntry<T>>: Iterator`
-           which is required by `&mut BinaryHeap<PriorityQueueEntry<T>>: Iterator`
    = note: this error originates in the derive macro `AddImpl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0609]: no field `height` on type `&PriorityQueue<T>`
diff --git a/tests/ui/proc-macro/nested-macro-rules.rs b/tests/ui/proc-macro/nested-macro-rules.rs
index 0dce3c408c2..2f0d85c4bbf 100644
--- a/tests/ui/proc-macro/nested-macro-rules.rs
+++ b/tests/ui/proc-macro/nested-macro-rules.rs
@@ -5,6 +5,8 @@
 //@ edition:2018
 
 #![no_std] // Don't load unnecessary hygiene information from std
+#![warn(non_local_definitions)]
+
 extern crate std;
 
 extern crate nested_macro_rules;
diff --git a/tests/ui/proc-macro/nested-macro-rules.stderr b/tests/ui/proc-macro/nested-macro-rules.stderr
index 111be882771..270e9161b03 100644
--- a/tests/ui/proc-macro/nested-macro-rules.stderr
+++ b/tests/ui/proc-macro/nested-macro-rules.stderr
@@ -12,7 +12,7 @@ LL | |             }
 LL | |         }
    | |_________^
    |
-  ::: $DIR/nested-macro-rules.rs:21:5
+  ::: $DIR/nested-macro-rules.rs:23:5
    |
 LL |       nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct);
    |       ---------------------------------------------------------------- in this macro invocation
@@ -21,7 +21,11 @@ LL |       nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct);
    = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute
    = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module
    = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
-   = note: `#[warn(non_local_definitions)]` on by default
+note: the lint level is defined here
+  --> $DIR/nested-macro-rules.rs:8:9
+   |
+LL | #![warn(non_local_definitions)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/proc-macro/nested-macro-rules.stdout b/tests/ui/proc-macro/nested-macro-rules.stdout
index 829cfdc0c33..5b678554b9e 100644
--- a/tests/ui/proc-macro/nested-macro-rules.stdout
+++ b/tests/ui/proc-macro/nested-macro-rules.stdout
@@ -25,7 +25,7 @@ PRINT-BANG INPUT (DISPLAY): SecondStruct
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "SecondStruct",
-        span: $DIR/nested-macro-rules.rs:21:38: 21:50 (#15),
+        span: $DIR/nested-macro-rules.rs:23:38: 23:50 (#15),
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct SecondAttrStruct {}
@@ -36,7 +36,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
     },
     Ident {
         ident: "SecondAttrStruct",
-        span: $DIR/nested-macro-rules.rs:21:52: 21:68 (#15),
+        span: $DIR/nested-macro-rules.rs:23:52: 23:68 (#15),
     },
     Group {
         delimiter: Brace,
diff --git a/tests/ui/process-termination/process-termination-blocking-io.rs b/tests/ui/process-termination/process-termination-blocking-io.rs
index c21edff25cf..f725a958941 100644
--- a/tests/ui/process-termination/process-termination-blocking-io.rs
+++ b/tests/ui/process-termination/process-termination-blocking-io.rs
@@ -2,7 +2,7 @@
 // https://github.com/fortanix/rust-sgx/issues/109
 
 //@ run-pass
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::{net::TcpListener, sync::mpsc, thread};
 
diff --git a/tests/ui/process-termination/process-termination-simple.rs b/tests/ui/process-termination/process-termination-simple.rs
index 63eb2c74706..8f5f185b7f9 100644
--- a/tests/ui/process-termination/process-termination-simple.rs
+++ b/tests/ui/process-termination/process-termination-simple.rs
@@ -1,7 +1,7 @@
 // program should terminate when std::process::exit is called from any thread
 
 //@ run-pass
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::{process, thread};
 
diff --git a/tests/ui/resolve/auxiliary/proc_macro_generate_packed.rs b/tests/ui/resolve/auxiliary/proc_macro_generate_packed.rs
new file mode 100644
index 00000000000..c0b24706dcb
--- /dev/null
+++ b/tests/ui/resolve/auxiliary/proc_macro_generate_packed.rs
@@ -0,0 +1,27 @@
+//@ force-host
+//@ no-prefer-dynamic
+//@ compile-flags: --crate-type proc-macro
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn proc_macro_attribute_that_generates_repr_packed(
+    _attr: TokenStream,
+    item: TokenStream,
+) -> TokenStream {
+    let repr = vec![TokenTree::Ident(Ident::new("packed", Span::call_site()))].into_iter();
+    let attr = vec![
+        TokenTree::Ident(Ident::new("repr", Span::call_site())),
+        TokenTree::Group(Group::new(Delimiter::Parenthesis, repr.collect())),
+    ]
+    .into_iter();
+    vec![
+        TokenTree::Punct(Punct::new('#', Spacing::Alone)),
+        TokenTree::Group(Group::new(Delimiter::Bracket, attr.collect())),
+    ]
+    .into_iter()
+    .chain(item)
+    .collect()
+}
diff --git a/tests/ui/resolve/multiple_definitions_attribute_merging.rs b/tests/ui/resolve/multiple_definitions_attribute_merging.rs
new file mode 100644
index 00000000000..523717861e1
--- /dev/null
+++ b/tests/ui/resolve/multiple_definitions_attribute_merging.rs
@@ -0,0 +1,19 @@
+//! This test ICEs because the `repr(packed)` attributes
+//! end up on the `Dealigned` struct's attribute list, but the
+//! derive didn't see that.
+
+//@known-bug: #120873
+//@ failure-status: 101
+//@ normalize-stderr-test "note: .*\n\n" -> ""
+//@ normalize-stderr-test "thread 'rustc' panicked.*\n" -> ""
+//@ normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
+//@ rustc-env:RUST_BACKTRACE=0
+
+#[repr(packed)]
+struct Dealigned<T>(u8, T);
+
+#[derive(PartialEq)]
+#[repr(C)]
+struct Dealigned<T>(u8, T);
+
+fn main() {}
diff --git a/tests/ui/resolve/multiple_definitions_attribute_merging.stderr b/tests/ui/resolve/multiple_definitions_attribute_merging.stderr
new file mode 100644
index 00000000000..b2d20af883a
--- /dev/null
+++ b/tests/ui/resolve/multiple_definitions_attribute_merging.stderr
@@ -0,0 +1,26 @@
+error[E0428]: the name `Dealigned` is defined multiple times
+  --> $DIR/multiple_definitions_attribute_merging.rs:17:1
+   |
+LL | struct Dealigned<T>(u8, T);
+   | --------------------------- previous definition of the type `Dealigned` here
+...
+LL | struct Dealigned<T>(u8, T);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Dealigned` redefined here
+   |
+   = error: internal compiler error: compiler/rustc_mir_transform/src/check_packed_ref.rs:LL:CC: builtin derive created an unaligned reference
+  --> $DIR/multiple_definitions_attribute_merging.rs:17:25
+   |
+LL | #[derive(PartialEq)]
+   |          --------- in this derive macro expansion
+LL | #[repr(C)]
+LL | struct Dealigned<T>(u8, T);
+   |                         ^
+   |
+   = Box<dyn Any>
+query stack during panic:
+#0 [mir_const] preparing `<impl at $DIR/multiple_definitions_attribute_merging.rs:15:10: 15:19>::eq` for borrow checking
+#1 [mir_promoted] promoting constants in MIR for `<impl at $DIR/multiple_definitions_attribute_merging.rs:15:10: 15:19>::eq`
+end of query stack
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/tests/ui/resolve/proc_macro_generated_packed.rs b/tests/ui/resolve/proc_macro_generated_packed.rs
new file mode 100644
index 00000000000..34a7e4db603
--- /dev/null
+++ b/tests/ui/resolve/proc_macro_generated_packed.rs
@@ -0,0 +1,20 @@
+//! This test ICEs because the `repr(packed)` attribute
+//! was generated by a proc macro, so `#[derive]` didn't see it.
+
+//@aux-build: proc_macro_generate_packed.rs
+//@known-bug: #120873
+//@ failure-status: 101
+//@ normalize-stderr-test "note: .*\n\n" -> ""
+//@ normalize-stderr-test "thread 'rustc' panicked.*\n" -> ""
+//@ normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
+//@ rustc-env:RUST_BACKTRACE=0
+
+extern crate proc_macro_generate_packed;
+use proc_macro_generate_packed::proc_macro_attribute_that_generates_repr_packed;
+
+#[derive(PartialEq)]
+#[repr(C)]
+#[proc_macro_attribute_that_generates_repr_packed]
+struct Dealigned<T>(u8, T);
+
+fn main() {}
diff --git a/tests/ui/resolve/proc_macro_generated_packed.stderr b/tests/ui/resolve/proc_macro_generated_packed.stderr
new file mode 100644
index 00000000000..507e5867c90
--- /dev/null
+++ b/tests/ui/resolve/proc_macro_generated_packed.stderr
@@ -0,0 +1,16 @@
+error: internal compiler error: compiler/rustc_mir_transform/src/check_packed_ref.rs:LL:CC: builtin derive created an unaligned reference
+  --> $DIR/proc_macro_generated_packed.rs:18:25
+   |
+LL | #[derive(PartialEq)]
+   |          --------- in this derive macro expansion
+...
+LL | struct Dealigned<T>(u8, T);
+   |                         ^
+   |
+   = Box<dyn Any>
+query stack during panic:
+#0 [mir_const] preparing `<impl at $DIR/proc_macro_generated_packed.rs:15:10: 15:19>::eq` for borrow checking
+#1 [mir_promoted] promoting constants in MIR for `<impl at $DIR/proc_macro_generated_packed.rs:15:10: 15:19>::eq`
+end of query stack
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/resolve/resolve-self-in-impl.stderr b/tests/ui/resolve/resolve-self-in-impl.stderr
index 183a17171f7..62cfdb4dc78 100644
--- a/tests/ui/resolve/resolve-self-in-impl.stderr
+++ b/tests/ui/resolve/resolve-self-in-impl.stderr
@@ -14,6 +14,20 @@ LL | impl Tr for S<Self> {}
    |
    = note: replace `Self` with a different type
 
+error[E0391]: cycle detected when computing trait implemented by `<impl at $DIR/resolve-self-in-impl.rs:19:1: 19:23>`
+  --> $DIR/resolve-self-in-impl.rs:19:1
+   |
+LL | impl Tr<Self::A> for S {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: ...which immediately requires computing trait implemented by `<impl at $DIR/resolve-self-in-impl.rs:19:1: 19:23>` again
+note: cycle used when building specialization graph of trait `Tr`
+  --> $DIR/resolve-self-in-impl.rs:4:1
+   |
+LL | trait Tr<T = u8> {
+   | ^^^^^^^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
 error: `Self` is not valid in the self type of an impl block
   --> $DIR/resolve-self-in-impl.rs:16:6
    |
@@ -38,26 +52,6 @@ LL | impl (Self, Self) {}
    |
    = note: replace `Self` with a different type
 
-error[E0391]: cycle detected when computing trait implemented by `<impl at $DIR/resolve-self-in-impl.rs:19:1: 19:23>`
-  --> $DIR/resolve-self-in-impl.rs:19:1
-   |
-LL | impl Tr<Self::A> for S {}
-   | ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: ...which immediately requires computing trait implemented by `<impl at $DIR/resolve-self-in-impl.rs:19:1: 19:23>` again
-note: cycle used when collecting item types in top-level module
-  --> $DIR/resolve-self-in-impl.rs:1:1
-   |
-LL | / #![feature(associated_type_defaults)]
-LL | |
-LL | | struct S<T = u8>(T);
-LL | | trait Tr<T = u8> {
-...  |
-LL | |
-LL | | fn main() {}
-   | |____________^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
 error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr
index eb0f18edd34..00efbb52f15 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr
@@ -1,12 +1,3 @@
-error: `#[target_feature(..)]` cannot be applied to safe trait method
-  --> $DIR/trait-impl.rs:22:5
-   |
-LL |     #[target_feature(enable = "sse2")]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method
-LL |
-LL |     fn foo(&self) {}
-   |     ------------- not an `unsafe` function
-
 error: `#[target_feature(..)]` cannot be applied to safe trait method
   --> $DIR/trait-impl.rs:13:5
    |
@@ -16,5 +7,14 @@ LL |
 LL |     fn foo(&self) {}
    |     ------------- not an `unsafe` function
 
+error: `#[target_feature(..)]` cannot be applied to safe trait method
+  --> $DIR/trait-impl.rs:22:5
+   |
+LL |     #[target_feature(enable = "sse2")]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method
+LL |
+LL |     fn foo(&self) {}
+   |     ------------- not an `unsafe` function
+
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs
index 5053c115b45..c9dc1c6e649 100644
--- a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs
+++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs
@@ -17,5 +17,5 @@ fn stuff<T: Bar>(_: T) {}
 
 fn main() {
     stuff(1u8);
-    //~^ the trait bound `u8: Foo` is not satisfied
+    //~^ the trait bound `u8: Bar` is not satisfied
 }
diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr
index 99d318a7933..284dacf7000 100644
--- a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr
+++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `u8: Foo` is not satisfied
+error[E0277]: the trait bound `u8: Bar` is not satisfied
   --> $DIR/feature-gate-do_not_recommend.rs:19:11
    |
 LL |     stuff(1u8);
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr
index 8f374bc4d8f..e45c1a1f46f 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr
@@ -13,6 +13,15 @@ LL | impl const Default for A {
    = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
    = note: adding a non-const method body in the future would be a breaking change
 
+error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/derive-const-use.rs:7:6
+   |
+LL | impl const Default for A {
+   |      ^^^^^ unconstrained const parameter
+   |
+   = note: expressions using a const parameter must map each value to a distinct output value
+   = note: proving the result of expressions other than the parameter are unique is not supported
+
 error: const `impl` for trait `Default` which is not marked with `#[const_trait]`
   --> $DIR/derive-const-use.rs:15:16
    |
@@ -24,20 +33,23 @@ LL | #[derive_const(Default, PartialEq)]
    = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/derive-const-use.rs:7:6
-   |
-LL | impl const Default for A {
-   |      ^^^^^ unconstrained const parameter
    |
    = note: expressions using a const parameter must map each value to a distinct output value
    = note: proving the result of expressions other than the parameter are unique is not supported
 
-error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates
+error[E0308]: mismatched types
+  --> $DIR/derive-const-use.rs:16:14
    |
-   = note: expressions using a const parameter must map each value to a distinct output value
-   = note: proving the result of expressions other than the parameter are unique is not supported
+LL | #[derive_const(Default, PartialEq)]
+   |                         --------- in this derive macro expansion
+LL | pub struct S((), A);
+   |              ^^ expected `host`, found `true`
+   |
+   = note: expected constant `host`
+              found constant `true`
+   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0207, E0635.
+Some errors have detailed explanations: E0207, E0308, E0635.
 For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs
index 5ee38078a29..1b380c989fa 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs
@@ -511,6 +511,7 @@ const fn drop<T: ~const Destruct>(_: T) {}
 
 extern "rust-intrinsic" {
     #[rustc_const_stable(feature = "const_eval_select", since = "1.0.0")]
+    #[rustc_safe_intrinsic]
     fn const_eval_select<ARG: Tuple, F, G, RET>(
         arg: ARG,
         called_in_const: F,
@@ -525,5 +526,5 @@ fn test_const_eval_select() {
     const fn const_fn() {}
     fn rt_fn() {}
 
-    unsafe { const_eval_select((), const_fn, rt_fn); }
+    const_eval_select((), const_fn, rt_fn);
 }
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs
index 97e89f96fe1..7bead45b35a 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.rs
@@ -8,6 +8,8 @@ impl const dyn T {
     //~^ ERROR inherent impls cannot be `const`
     //~| ERROR the const parameter `host` is not constrained by the impl trait, self type, or
     pub const fn new() -> std::sync::Mutex<dyn T> {}
+    //~^ ERROR mismatched types
+    //~| ERROR cannot be known at compilation time
 }
 
 fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr
index 11577d9ec1d..3ff1efb5988 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/span-bug-issue-121418.stderr
@@ -17,6 +17,29 @@ LL | impl const dyn T {
    = note: expressions using a const parameter must map each value to a distinct output value
    = note: proving the result of expressions other than the parameter are unique is not supported
 
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+  --> $DIR/span-bug-issue-121418.rs:10:27
+   |
+LL |     pub const fn new() -> std::sync::Mutex<dyn T> {}
+   |                  ---      ^^^^^^^^^^^^^^^^^^^^^^^ expected `Mutex<dyn T>`, found `()`
+   |                  |
+   |                  implicitly returns `()` as its body has no tail or `return` expression
+   |
+   = note: expected struct `Mutex<(dyn T + 'static)>`
+           found unit type `()`
 
-For more information about this error, try `rustc --explain E0207`.
+error[E0277]: the size for values of type `(dyn T + 'static)` cannot be known at compilation time
+  --> $DIR/span-bug-issue-121418.rs:10:27
+   |
+LL |     pub const fn new() -> std::sync::Mutex<dyn T> {}
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Mutex<(dyn T + 'static)>`, the trait `Sized` is not implemented for `(dyn T + 'static)`, which is required by `Mutex<(dyn T + 'static)>: Sized`
+note: required because it appears within the type `Mutex<(dyn T + 'static)>`
+  --> $SRC_DIR/std/src/sync/mutex.rs:LL:COL
+   = note: the return type of a function must have a statically known size
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0207, E0277, E0308.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr
index 2c63c0217ab..77aee6a8bb8 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr
@@ -24,12 +24,6 @@ LL | trait Bar: ~const Foo {}
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: `~const` can only be applied to `#[const_trait]` traits
-  --> $DIR/super-traits-fail-3.rs:18:24
-   |
-LL | const fn foo<T: ~const Bar>(x: &T) {
-   |                        ^^^
-
 error: `~const` can only be applied to `#[const_trait]` traits
   --> $DIR/super-traits-fail-3.rs:12:19
    |
@@ -38,5 +32,11 @@ LL | trait Bar: ~const Foo {}
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error: `~const` can only be applied to `#[const_trait]` traits
+  --> $DIR/super-traits-fail-3.rs:18:24
+   |
+LL | const fn foo<T: ~const Bar>(x: &T) {
+   |                        ^^^
+
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
index 92a9c347a07..8151b9aaa23 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
@@ -262,16 +262,6 @@ LL |     const CONSTANT<T: ~const Trait>: () = ();
    = help: add `#![feature(generic_const_items)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: inherent associated types are unstable
-  --> $DIR/tilde-const-invalid-places.rs:44:5
-   |
-LL |     type Type<T: ~const Trait> = ();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
-   = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
 error[E0392]: type parameter `T` is never used
   --> $DIR/tilde-const-invalid-places.rs:11:19
    |
@@ -304,6 +294,16 @@ note: required by a bound in `NonConstTrait::Type`
 LL |     type Type<T: ~const Trait>: ~const Trait;
    |                                 ^^^^^^^^^^^^ required by this bound in `NonConstTrait::Type`
 
+error[E0658]: inherent associated types are unstable
+  --> $DIR/tilde-const-invalid-places.rs:44:5
+   |
+LL |     type Type<T: ~const Trait> = ();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
+   = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
 error: aborting due to 30 previous errors
 
 Some errors have detailed explanations: E0275, E0392, E0658, E0740.
diff --git a/tests/ui/shell-argfiles/shell-argfiles-badquotes-windows.stderr b/tests/ui/shell-argfiles/shell-argfiles-badquotes-windows.stderr
index 14adb1f740a..dc219c153f7 100644
--- a/tests/ui/shell-argfiles/shell-argfiles-badquotes-windows.stderr
+++ b/tests/ui/shell-argfiles/shell-argfiles-badquotes-windows.stderr
@@ -1,2 +1,2 @@
-error: Failed to load argument file: Invalid shell-style arguments in $DIR/shell-argfiles-badquotes.args
+error: failed to load argument file: invalid shell-style arguments in $DIR/shell-argfiles-badquotes.args
 
diff --git a/tests/ui/shell-argfiles/shell-argfiles-badquotes.stderr b/tests/ui/shell-argfiles/shell-argfiles-badquotes.stderr
index 14adb1f740a..dc219c153f7 100644
--- a/tests/ui/shell-argfiles/shell-argfiles-badquotes.stderr
+++ b/tests/ui/shell-argfiles/shell-argfiles-badquotes.stderr
@@ -1,2 +1,2 @@
-error: Failed to load argument file: Invalid shell-style arguments in $DIR/shell-argfiles-badquotes.args
+error: failed to load argument file: invalid shell-style arguments in $DIR/shell-argfiles-badquotes.args
 
diff --git a/tests/ui/span/issue-35987.rs b/tests/ui/span/issue-35987.rs
index 3a6e6ffe249..d52a3793af9 100644
--- a/tests/ui/span/issue-35987.rs
+++ b/tests/ui/span/issue-35987.rs
@@ -7,6 +7,7 @@ impl<T: Clone, Add> Add for Foo<T> {
     type Output = usize;
 
     fn add(self, rhs: Self) -> Self::Output {
+        //~^ ERROR ambiguous associated type
         unimplemented!();
     }
 }
diff --git a/tests/ui/span/issue-35987.stderr b/tests/ui/span/issue-35987.stderr
index d3014f276fd..36c59137b31 100644
--- a/tests/ui/span/issue-35987.stderr
+++ b/tests/ui/span/issue-35987.stderr
@@ -9,6 +9,20 @@ LL | impl<T: Clone, Add> Add for Foo<T> {
    |                |
    |                found this type parameter
 
-error: aborting due to 1 previous error
+error[E0223]: ambiguous associated type
+  --> $DIR/issue-35987.rs:9:32
+   |
+LL |     fn add(self, rhs: Self) -> Self::Output {
+   |                                ^^^^^^^^^^^^
+   |
+help: use fully-qualified syntax
+   |
+LL |     fn add(self, rhs: Self) -> <Foo<T> as BitOr>::Output {
+   |                                ~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     fn add(self, rhs: Self) -> <Foo<T> as IntoFuture>::Output {
+   |                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-For more information about this error, try `rustc --explain E0404`.
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0223, E0404.
+For more information about an error, try `rustc --explain E0223`.
diff --git a/tests/ui/structs-enums/ivec-tag.rs b/tests/ui/structs-enums/ivec-tag.rs
index 9185a0cbb6e..2a0b6dd1ed4 100644
--- a/tests/ui/structs-enums/ivec-tag.rs
+++ b/tests/ui/structs-enums/ivec-tag.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_must_use)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 use std::sync::mpsc::{channel, Sender};
diff --git a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
index ec9826819c0..05e087fd9f9 100644
--- a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
+++ b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
@@ -7,7 +7,6 @@ LL |     bar(foo);
    |     required by a bound introduced by this call
    |
    = help: the trait `Future` is not implemented for fn item `fn() -> impl Future<Output = ()> {foo}`
-   = note: fn() -> impl Future<Output = ()> {foo} must be a future or must implement `IntoFuture` to be awaited
 note: required by a bound in `bar`
   --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
    |
@@ -27,7 +26,6 @@ LL |     bar(async_closure);
    |     required by a bound introduced by this call
    |
    = help: the trait `Future` is not implemented for `{async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}`
-   = note: {async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33} must be a future or must implement `IntoFuture` to be awaited
 note: required by a bound in `bar`
   --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
    |
diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
index a7d636b63bd..61a2925f582 100644
--- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
+++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
@@ -150,6 +150,14 @@ help: consider introducing a named lifetime parameter
 LL |     fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&()> { x.next() }
    |         ++++                              ++
 
+error: lifetime may not live long enough
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:19:67
+   |
+LL |     async fn i(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
+   |     -----------------------------------------------------------   ^^^^^^^^ returning this value requires that `'1` must outlive `'static`
+   |     |
+   |     return type `impl Future<Output = Option<&'static ()>>` contains a lifetime `'1`
+
 error[E0658]: anonymous lifetimes in `impl Trait` are unstable
   --> $DIR/impl-trait-missing-lifetime-gated.rs:25:35
    |
@@ -176,6 +184,14 @@ help: consider introducing a named lifetime parameter
 LL |     fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'_ ()> { x.next() }
    |         ++++                              ~~
 
+error: lifetime may not live long enough
+  --> $DIR/impl-trait-missing-lifetime-gated.rs:38:73
+   |
+LL |     async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
+   |     -----------------------------------------------------------------   ^^^^^^^^ returning this value requires that `'1` must outlive `'static`
+   |     |
+   |     return type `impl Future<Output = Option<&'static ()>>` contains a lifetime `'1`
+
 error[E0658]: anonymous lifetimes in `impl Trait` are unstable
   --> $DIR/impl-trait-missing-lifetime-gated.rs:46:18
    |
@@ -228,22 +244,6 @@ help: consider introducing a named lifetime parameter
 LL |     fn g<'a>(mut x: impl Foo<'a, ()>) -> Option<&()> { x.next() }
    |         ++++                 +++
 
-error: lifetime may not live long enough
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:19:67
-   |
-LL |     async fn i(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
-   |     -----------------------------------------------------------   ^^^^^^^^ returning this value requires that `'1` must outlive `'static`
-   |     |
-   |     return type `impl Future<Output = Option<&'static ()>>` contains a lifetime `'1`
-
-error: lifetime may not live long enough
-  --> $DIR/impl-trait-missing-lifetime-gated.rs:38:73
-   |
-LL |     async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
-   |     -----------------------------------------------------------------   ^^^^^^^^ returning this value requires that `'1` must outlive `'static`
-   |     |
-   |     return type `impl Future<Output = Option<&'static ()>>` contains a lifetime `'1`
-
 error: aborting due to 16 previous errors
 
 Some errors have detailed explanations: E0106, E0658.
diff --git a/tests/ui/suggestions/issue-104961.fixed b/tests/ui/suggestions/issue-104961.fixed
index a4047def341..5def21b506e 100644
--- a/tests/ui/suggestions/issue-104961.fixed
+++ b/tests/ui/suggestions/issue-104961.fixed
@@ -2,12 +2,12 @@
 
 fn foo(x: &str) -> bool {
     x.starts_with(&("hi".to_string() + " you"))
-    //~^ ERROR expected a `FnMut(char)` closure, found `String`
+    //~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277]
 }
 
 fn foo2(x: &str) -> bool {
     x.starts_with(&"hi".to_string())
-    //~^ ERROR expected a `FnMut(char)` closure, found `String`
+    //~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277]
 }
 
 fn main() {
diff --git a/tests/ui/suggestions/issue-104961.rs b/tests/ui/suggestions/issue-104961.rs
index 9d02f570c84..a09b8a88711 100644
--- a/tests/ui/suggestions/issue-104961.rs
+++ b/tests/ui/suggestions/issue-104961.rs
@@ -2,12 +2,12 @@
 
 fn foo(x: &str) -> bool {
     x.starts_with("hi".to_string() + " you")
-    //~^ ERROR expected a `FnMut(char)` closure, found `String`
+    //~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277]
 }
 
 fn foo2(x: &str) -> bool {
     x.starts_with("hi".to_string())
-    //~^ ERROR expected a `FnMut(char)` closure, found `String`
+    //~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277]
 }
 
 fn main() {
diff --git a/tests/ui/suggestions/issue-104961.stderr b/tests/ui/suggestions/issue-104961.stderr
index 7e795a74c90..3c5f86817f3 100644
--- a/tests/ui/suggestions/issue-104961.stderr
+++ b/tests/ui/suggestions/issue-104961.stderr
@@ -1,4 +1,4 @@
-error[E0277]: expected a `FnMut(char)` closure, found `String`
+error[E0277]: the trait bound `String: Pattern<'_>` is not satisfied
   --> $DIR/issue-104961.rs:4:19
    |
 LL |     x.starts_with("hi".to_string() + " you")
@@ -6,7 +6,6 @@ LL |     x.starts_with("hi".to_string() + " you")
    |       |
    |       required by a bound introduced by this call
    |
-   = note: the trait bound `String: Pattern<'_>` is not satisfied
    = note: required for `String` to implement `Pattern<'_>`
 note: required by a bound in `core::str::<impl str>::starts_with`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
@@ -15,7 +14,7 @@ help: consider borrowing here
 LL |     x.starts_with(&("hi".to_string() + " you"))
    |                   ++                         +
 
-error[E0277]: expected a `FnMut(char)` closure, found `String`
+error[E0277]: the trait bound `String: Pattern<'_>` is not satisfied
   --> $DIR/issue-104961.rs:9:19
    |
 LL |     x.starts_with("hi".to_string())
@@ -23,7 +22,6 @@ LL |     x.starts_with("hi".to_string())
    |       |
    |       required by a bound introduced by this call
    |
-   = note: the trait bound `String: Pattern<'_>` is not satisfied
    = note: required for `String` to implement `Pattern<'_>`
 note: required by a bound in `core::str::<impl str>::starts_with`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
diff --git a/tests/ui/suggestions/issue-62843.stderr b/tests/ui/suggestions/issue-62843.stderr
index f3a9f6b7913..84ab4a0edd3 100644
--- a/tests/ui/suggestions/issue-62843.stderr
+++ b/tests/ui/suggestions/issue-62843.stderr
@@ -1,4 +1,4 @@
-error[E0277]: expected a `FnMut(char)` closure, found `String`
+error[E0277]: the trait bound `String: Pattern<'_>` is not satisfied
   --> $DIR/issue-62843.rs:4:32
    |
 LL |     println!("{:?}", line.find(pattern));
@@ -6,7 +6,6 @@ LL |     println!("{:?}", line.find(pattern));
    |                           |
    |                           required by a bound introduced by this call
    |
-   = note: the trait bound `String: Pattern<'_>` is not satisfied
    = note: required for `String` to implement `Pattern<'_>`
 note: required by a bound in `core::str::<impl str>::find`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
diff --git a/tests/ui/suggestions/slice-issue-87994.rs b/tests/ui/suggestions/slice-issue-87994.rs
index ecb7f54ea25..5a2574fff8a 100644
--- a/tests/ui/suggestions/slice-issue-87994.rs
+++ b/tests/ui/suggestions/slice-issue-87994.rs
@@ -1,16 +1,16 @@
 fn main() {
   let v = vec![1i32, 2, 3];
   for _ in v[1..] {
-    //~^ ERROR [i32]` is not an iterator [E0277]
-    //~^^ ERROR known at compilation time
+    //~^ ERROR `[i32]` is not an iterator [E0277]
+    //~| ERROR `[i32]` is not an iterator [E0277]
   }
   struct K {
     n: i32,
   }
   let mut v2 = vec![K { n: 1 }, K { n: 1 }, K { n: 1 }];
   for i2 in v2[1..] {
-    //~^ ERROR [K]` is not an iterator [E0277]
-    //~^^ ERROR known at compilation time
+    //~^ ERROR `[K]` is not an iterator [E0277]
+    //~| ERROR `[K]` is not an iterator [E0277]
     i2.n = 2;
   }
 }
diff --git a/tests/ui/suggestions/slice-issue-87994.stderr b/tests/ui/suggestions/slice-issue-87994.stderr
index 656f71eb877..22ad5d35212 100644
--- a/tests/ui/suggestions/slice-issue-87994.stderr
+++ b/tests/ui/suggestions/slice-issue-87994.stderr
@@ -13,7 +13,7 @@ LL |   for _ in &v[1..] {
 LL |   for _ in &mut v[1..] {
    |            ++++
 
-error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+error[E0277]: `[i32]` is not an iterator
   --> $DIR/slice-issue-87994.rs:3:12
    |
 LL |   for _ in v[1..] {
@@ -21,6 +21,7 @@ LL |   for _ in v[1..] {
    |
    = note: the trait bound `[i32]: IntoIterator` is not satisfied
    = note: required for `[i32]` to implement `IntoIterator`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: consider borrowing here
    |
 LL |   for _ in &v[1..] {
@@ -43,7 +44,7 @@ LL |   for i2 in &v2[1..] {
 LL |   for i2 in &mut v2[1..] {
    |             ++++
 
-error[E0277]: the size for values of type `[K]` cannot be known at compilation time
+error[E0277]: `[K]` is not an iterator
   --> $DIR/slice-issue-87994.rs:11:13
    |
 LL |   for i2 in v2[1..] {
@@ -51,6 +52,7 @@ LL |   for i2 in v2[1..] {
    |
    = note: the trait bound `[K]: IntoIterator` is not satisfied
    = note: required for `[K]` to implement `IntoIterator`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 help: consider borrowing here
    |
 LL |   for i2 in &v2[1..] {
diff --git a/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr b/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr
index 398caa98b84..769f3bd64f3 100644
--- a/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr
+++ b/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr
@@ -1,40 +1,3 @@
-error[E0782]: trait objects must include the `dyn` keyword
-  --> $DIR/suggest-blanket-impl-local-trait.rs:13:24
-   |
-LL | impl LocalTraitTwo for LocalTraitOne {}
-   |                        ^^^^^^^^^^^^^
-   |
-help: add `dyn` keyword before this trait
-   |
-LL | impl LocalTraitTwo for dyn LocalTraitOne {}
-   |                        +++
-help: alternatively use a blanket implementation to implement `LocalTraitTwo` for all types that also implement `LocalTraitOne`
-   |
-LL | impl<T: LocalTraitOne> LocalTraitTwo for T {}
-   |     ++++++++++++++++++                   ~
-
-error[E0782]: trait objects must include the `dyn` keyword
-  --> $DIR/suggest-blanket-impl-local-trait.rs:18:23
-   |
-LL | impl fmt::Display for LocalTraitOne {
-   |                       ^^^^^^^^^^^^^
-   |
-help: add `dyn` keyword before this trait
-   |
-LL | impl fmt::Display for dyn LocalTraitOne {
-   |                       +++
-
-error[E0782]: trait objects must include the `dyn` keyword
-  --> $DIR/suggest-blanket-impl-local-trait.rs:26:23
-   |
-LL | impl fmt::Display for LocalTraitTwo + Send {
-   |                       ^^^^^^^^^^^^^^^^^^^^
-   |
-help: add `dyn` keyword before this trait
-   |
-LL | impl fmt::Display for dyn LocalTraitTwo + Send {
-   |                       +++
-
 error[E0782]: trait objects must include the `dyn` keyword
   --> $DIR/suggest-blanket-impl-local-trait.rs:34:24
    |
@@ -65,6 +28,21 @@ help: alternatively use a blanket implementation to implement `LocalTraitOne` fo
 LL | impl<T: fmt::Display + Send> LocalTraitOne for T {}
    |     ++++++++++++++++++++++++                   ~
 
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/suggest-blanket-impl-local-trait.rs:13:24
+   |
+LL | impl LocalTraitTwo for LocalTraitOne {}
+   |                        ^^^^^^^^^^^^^
+   |
+help: add `dyn` keyword before this trait
+   |
+LL | impl LocalTraitTwo for dyn LocalTraitOne {}
+   |                        +++
+help: alternatively use a blanket implementation to implement `LocalTraitTwo` for all types that also implement `LocalTraitOne`
+   |
+LL | impl<T: LocalTraitOne> LocalTraitTwo for T {}
+   |     ++++++++++++++++++                   ~
+
 error[E0782]: trait objects must include the `dyn` keyword
   --> $DIR/suggest-blanket-impl-local-trait.rs:46:29
    |
@@ -80,6 +58,28 @@ help: alternatively use a blanket implementation to implement `GenericTrait<E>`
 LL | impl<E, T: LocalTraitOne> GenericTrait<E> for T {}
    |       ++++++++++++++++++                      ~
 
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/suggest-blanket-impl-local-trait.rs:18:23
+   |
+LL | impl fmt::Display for LocalTraitOne {
+   |                       ^^^^^^^^^^^^^
+   |
+help: add `dyn` keyword before this trait
+   |
+LL | impl fmt::Display for dyn LocalTraitOne {
+   |                       +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/suggest-blanket-impl-local-trait.rs:26:23
+   |
+LL | impl fmt::Display for LocalTraitTwo + Send {
+   |                       ^^^^^^^^^^^^^^^^^^^^
+   |
+help: add `dyn` keyword before this trait
+   |
+LL | impl fmt::Display for dyn LocalTraitTwo + Send {
+   |                       +++
+
 error[E0782]: trait objects must include the `dyn` keyword
   --> $DIR/suggest-blanket-impl-local-trait.rs:53:35
    |
diff --git a/tests/ui/suggestions/suggest-remove-refs-5.stderr b/tests/ui/suggestions/suggest-remove-refs-5.stderr
index 6b2f330e1a3..3b6994b45d1 100644
--- a/tests/ui/suggestions/suggest-remove-refs-5.stderr
+++ b/tests/ui/suggestions/suggest-remove-refs-5.stderr
@@ -1,10 +1,10 @@
-error[E0277]: `Vec<i32>` is not an iterator
+error[E0277]: `&mut &mut &mut &mut Vec<i32>` is not an iterator
   --> $DIR/suggest-remove-refs-5.rs:4:14
    |
 LL |     for _ in &mut &mut v {}
-   |              ^^^^^^^^^^^ `Vec<i32>` is not an iterator; try calling `.into_iter()` or `.iter()`
+   |              ^^^^^^^^^^^ `&mut &mut &mut &mut Vec<i32>` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `Vec<i32>`, which is required by `&mut &mut &mut &mut Vec<i32>: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `&mut &mut &mut &mut Vec<i32>`, which is required by `&mut &mut &mut &mut Vec<i32>: IntoIterator`
    = note: required for `&mut Vec<i32>` to implement `Iterator`
    = note: 3 redundant requirements hidden
    = note: required for `&mut &mut &mut &mut Vec<i32>` to implement `Iterator`
@@ -15,13 +15,13 @@ LL ~     let v = &mut Vec::<i32>::new();
 LL ~     for _ in v {}
    |
 
-error[E0277]: `[u8; 1]` is not an iterator
+error[E0277]: `&mut &mut &mut [u8; 1]` is not an iterator
   --> $DIR/suggest-remove-refs-5.rs:7:14
    |
 LL |     for _ in &mut v {}
-   |              ^^^^^^ `[u8; 1]` is not an iterator; try calling `.into_iter()` or `.iter()`
+   |              ^^^^^^ `&mut &mut &mut [u8; 1]` is not an iterator
    |
-   = help: the trait `Iterator` is not implemented for `[u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator`
+   = help: the trait `Iterator` is not implemented for `&mut &mut &mut [u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator`
    = note: required for `&mut [u8; 1]` to implement `Iterator`
    = note: 2 redundant requirements hidden
    = note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator`
diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs
index c4384bce3a9..a5ab8be7f45 100644
--- a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs
+++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs
@@ -3,9 +3,12 @@
 pub trait Trait<'a, T> {}
 
 pub struct Struct<T>;
+//~^ ERROR `T` is never used
 pub enum Enum<T> {}
+//~^ ERROR `T` is never used
 
 pub union Union<T> {
+    //~^ ERROR `T` is never used
     f1: usize,
 }
 
@@ -15,8 +18,10 @@ impl<'a, T> Struct<T> for Trait<'a, T> {}
 
 impl<'a, T> Enum<T> for Trait<'a, T> {}
 //~^ ERROR expected trait, found enum `Enum`
+//~| ERROR trait objects must include the `dyn` keyword
 
 impl<'a, T> Union<T> for Trait<'a, T> {}
 //~^ ERROR expected trait, found union `Union`
+//~| ERROR trait objects must include the `dyn` keyword
 
 fn main() {}
diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr
index 87e71643620..2893370570d 100644
--- a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr
+++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr
@@ -1,5 +1,5 @@
 error[E0404]: expected trait, found struct `Struct`
-  --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:12:13
+  --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:15:13
    |
 LL | impl<'a, T> Struct<T> for Trait<'a, T> {}
    |             ^^^^^^^^^ not a trait
@@ -10,7 +10,7 @@ LL | impl<'a, T> Trait<'a, T> for Struct<T> {}
    |             ~~~~~~~~~~~~     ~~~~~~~~~
 
 error[E0404]: expected trait, found enum `Enum`
-  --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:16:13
+  --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:19:13
    |
 LL | impl<'a, T> Enum<T> for Trait<'a, T> {}
    |             ^^^^^^^ not a trait
@@ -21,7 +21,7 @@ LL | impl<'a, T> Trait<'a, T> for Enum<T> {}
    |             ~~~~~~~~~~~~     ~~~~~~~
 
 error[E0404]: expected trait, found union `Union`
-  --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:19:13
+  --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:23:13
    |
 LL | impl<'a, T> Union<T> for Trait<'a, T> {}
    |             ^^^^^^^^ not a trait
@@ -31,8 +31,35 @@ help: `impl` items mention the trait being implemented first and the type it is
 LL | impl<'a, T> Trait<'a, T> for Union<T> {}
    |             ~~~~~~~~~~~~     ~~~~~~~~
 
+error[E0392]: type parameter `T` is never used
+  --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:5:19
+   |
+LL | pub struct Struct<T>;
+   |                   ^ unused type parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+
+error[E0392]: type parameter `T` is never used
+  --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:7:15
+   |
+LL | pub enum Enum<T> {}
+   |               ^ unused type parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+
+error[E0392]: type parameter `T` is never used
+  --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:10:17
+   |
+LL | pub union Union<T> {
+   |                 ^ unused type parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+
 error[E0782]: trait objects must include the `dyn` keyword
-  --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:12:27
+  --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:15:27
    |
 LL | impl<'a, T> Struct<T> for Trait<'a, T> {}
    |                           ^^^^^^^^^^^^
@@ -42,7 +69,29 @@ help: add `dyn` keyword before this trait
 LL | impl<'a, T> Struct<T> for dyn Trait<'a, T> {}
    |                           +++
 
-error: aborting due to 4 previous errors
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:19:25
+   |
+LL | impl<'a, T> Enum<T> for Trait<'a, T> {}
+   |                         ^^^^^^^^^^^^
+   |
+help: add `dyn` keyword before this trait
+   |
+LL | impl<'a, T> Enum<T> for dyn Trait<'a, T> {}
+   |                         +++
 
-Some errors have detailed explanations: E0404, E0782.
-For more information about an error, try `rustc --explain E0404`.
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:23:26
+   |
+LL | impl<'a, T> Union<T> for Trait<'a, T> {}
+   |                          ^^^^^^^^^^^^
+   |
+help: add `dyn` keyword before this trait
+   |
+LL | impl<'a, T> Union<T> for dyn Trait<'a, T> {}
+   |                          +++
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0392, E0404, E0782.
+For more information about an error, try `rustc --explain E0392`.
diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.rs b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.rs
index 947bc2c7965..951e7313f0a 100644
--- a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.rs
+++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.rs
@@ -1,9 +1,12 @@
 pub trait Trait<'a, T> {}
 
 pub struct Struct<T>;
+//~^ ERROR `T` is never used
 pub enum Enum<T> {}
+//~^ ERROR `T` is never used
 
 pub union Union<T> {
+    //~^ ERROR `T` is never used
     f1: usize,
 }
 
@@ -14,8 +17,12 @@ impl<'a, T> Struct<T> for Trait<'a, T> {}
 
 impl<'a, T> Enum<T> for Trait<'a, T> {}
 //~^ ERROR expected trait, found enum `Enum`
+//~| WARNING trait objects without an explicit `dyn` are deprecated
+//~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
 
 impl<'a, T> Union<T> for Trait<'a, T> {}
 //~^ ERROR expected trait, found union `Union`
+//~| WARNING trait objects without an explicit `dyn` are deprecated
+//~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
 
 fn main() {}
diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr
index 0098814f81e..5d805d97a43 100644
--- a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr
+++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr
@@ -1,5 +1,5 @@
 error[E0404]: expected trait, found struct `Struct`
-  --> $DIR/suggest-swapping-self-ty-and-trait.rs:10:13
+  --> $DIR/suggest-swapping-self-ty-and-trait.rs:13:13
    |
 LL | impl<'a, T> Struct<T> for Trait<'a, T> {}
    |             ^^^^^^^^^ not a trait
@@ -10,7 +10,7 @@ LL | impl<'a, T> Trait<'a, T> for Struct<T> {}
    |             ~~~~~~~~~~~~     ~~~~~~~~~
 
 error[E0404]: expected trait, found enum `Enum`
-  --> $DIR/suggest-swapping-self-ty-and-trait.rs:15:13
+  --> $DIR/suggest-swapping-self-ty-and-trait.rs:18:13
    |
 LL | impl<'a, T> Enum<T> for Trait<'a, T> {}
    |             ^^^^^^^ not a trait
@@ -21,7 +21,7 @@ LL | impl<'a, T> Trait<'a, T> for Enum<T> {}
    |             ~~~~~~~~~~~~     ~~~~~~~
 
 error[E0404]: expected trait, found union `Union`
-  --> $DIR/suggest-swapping-self-ty-and-trait.rs:18:13
+  --> $DIR/suggest-swapping-self-ty-and-trait.rs:23:13
    |
 LL | impl<'a, T> Union<T> for Trait<'a, T> {}
    |             ^^^^^^^^ not a trait
@@ -31,8 +31,35 @@ help: `impl` items mention the trait being implemented first and the type it is
 LL | impl<'a, T> Trait<'a, T> for Union<T> {}
    |             ~~~~~~~~~~~~     ~~~~~~~~
 
+error[E0392]: type parameter `T` is never used
+  --> $DIR/suggest-swapping-self-ty-and-trait.rs:3:19
+   |
+LL | pub struct Struct<T>;
+   |                   ^ unused type parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+
+error[E0392]: type parameter `T` is never used
+  --> $DIR/suggest-swapping-self-ty-and-trait.rs:5:15
+   |
+LL | pub enum Enum<T> {}
+   |               ^ unused type parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+
+error[E0392]: type parameter `T` is never used
+  --> $DIR/suggest-swapping-self-ty-and-trait.rs:8:17
+   |
+LL | pub union Union<T> {
+   |                 ^ unused type parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+
 warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/suggest-swapping-self-ty-and-trait.rs:10:27
+  --> $DIR/suggest-swapping-self-ty-and-trait.rs:13:27
    |
 LL | impl<'a, T> Struct<T> for Trait<'a, T> {}
    |                           ^^^^^^^^^^^^
@@ -45,6 +72,33 @@ help: if this is an object-safe trait, use `dyn`
 LL | impl<'a, T> Struct<T> for dyn Trait<'a, T> {}
    |                           +++
 
-error: aborting due to 3 previous errors; 1 warning emitted
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/suggest-swapping-self-ty-and-trait.rs:18:25
+   |
+LL | impl<'a, T> Enum<T> for Trait<'a, T> {}
+   |                         ^^^^^^^^^^^^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: if this is an object-safe trait, use `dyn`
+   |
+LL | impl<'a, T> Enum<T> for dyn Trait<'a, T> {}
+   |                         +++
 
-For more information about this error, try `rustc --explain E0404`.
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/suggest-swapping-self-ty-and-trait.rs:23:26
+   |
+LL | impl<'a, T> Union<T> for Trait<'a, T> {}
+   |                          ^^^^^^^^^^^^
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+help: if this is an object-safe trait, use `dyn`
+   |
+LL | impl<'a, T> Union<T> for dyn Trait<'a, T> {}
+   |                          +++
+
+error: aborting due to 6 previous errors; 3 warnings emitted
+
+Some errors have detailed explanations: E0392, E0404.
+For more information about an error, try `rustc --explain E0392`.
diff --git a/tests/ui/tag-type-args.stderr b/tests/ui/tag-type-args.stderr
index a1136f61cc5..def13832e1a 100644
--- a/tests/ui/tag-type-args.stderr
+++ b/tests/ui/tag-type-args.stderr
@@ -1,3 +1,12 @@
+error[E0392]: type parameter `T` is never used
+  --> $DIR/tag-type-args.rs:1:11
+   |
+LL | enum Quux<T> { Bar }
+   |           ^ unused type parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+
 error[E0107]: missing generics for enum `Quux`
   --> $DIR/tag-type-args.rs:4:11
    |
@@ -14,15 +23,6 @@ help: add missing generic argument
 LL | fn foo(c: Quux<T>) { assert!((false)); }
    |               +++
 
-error[E0392]: type parameter `T` is never used
-  --> $DIR/tag-type-args.rs:1:11
-   |
-LL | enum Quux<T> { Bar }
-   |           ^ unused type parameter
-   |
-   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
-
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0107, E0392.
diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr
index 278b9ad5003..bf48911edec 100644
--- a/tests/ui/target-feature/invalid-attribute.stderr
+++ b/tests/ui/target-feature/invalid-attribute.stderr
@@ -183,6 +183,15 @@ error: cannot use `#[inline(always)]` with `#[target_feature]`
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
 
+error[E0046]: not all trait items implemented, missing: `foo`
+  --> $DIR/invalid-attribute.rs:88:1
+   |
+LL | impl Quux for u8 {}
+   | ^^^^^^^^^^^^^^^^ missing `foo` in implementation
+...
+LL |     fn foo();
+   |     --------- `foo` from trait
+
 error[E0658]: `#[target_feature(..)]` can only be applied to `unsafe` functions
   --> $DIR/invalid-attribute.rs:103:5
    |
@@ -196,15 +205,6 @@ LL |     fn foo() {}
    = help: add `#![feature(target_feature_11)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0046]: not all trait items implemented, missing: `foo`
-  --> $DIR/invalid-attribute.rs:88:1
-   |
-LL | impl Quux for u8 {}
-   | ^^^^^^^^^^^^^^^^ missing `foo` in implementation
-...
-LL |     fn foo();
-   |     --------- `foo` from trait
-
 error: aborting due to 23 previous errors
 
 Some errors have detailed explanations: E0046, E0658.
diff --git a/tests/ui/test-attrs/terse.rs b/tests/ui/test-attrs/terse.rs
new file mode 100644
index 00000000000..ab9d5cc19bd
--- /dev/null
+++ b/tests/ui/test-attrs/terse.rs
@@ -0,0 +1,125 @@
+//@ compile-flags: --test
+//@ run-fail
+//@ run-flags: --test-threads=1 --quiet
+//@ check-run-results
+//@ exec-env:RUST_BACKTRACE=0
+//@ normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+//@ ignore-emscripten no threads support
+//@ needs-unwind
+
+#[test]
+fn abc() {
+    panic!();
+}
+
+#[test]
+fn foo() {
+    panic!();
+}
+
+#[test]
+fn foo2() {
+    panic!();
+}
+
+// run a whole bunch of tests so we can see what happens when we go over 88 columns
+#[test] fn f0() {}
+#[test] fn f1() {}
+#[test] fn f2() {}
+#[test] fn f3() {}
+#[test] fn f4() {}
+#[test] fn f5() {}
+#[test] fn f6() {}
+#[test] fn f7() {}
+#[test] fn f8() {}
+#[test] fn f9() {}
+#[test] fn f10() {}
+#[test] fn f11() {}
+#[test] fn f12() {}
+#[test] fn f13() {}
+#[test] fn f14() {}
+#[test] fn f15() {}
+#[test] fn f16() {}
+#[test] fn f17() {}
+#[test] fn f18() {}
+#[test] fn f19() {}
+#[test] fn f20() {}
+#[test] fn f21() {}
+#[test] fn f22() {}
+#[test] fn f23() {}
+#[test] fn f24() {}
+#[test] fn f25() {}
+#[test] fn f26() {}
+#[test] fn f27() {}
+#[test] fn f28() {}
+#[test] fn f29() {}
+#[test] fn f30() {}
+#[test] fn f31() {}
+#[test] fn f32() {}
+#[test] fn f33() {}
+#[test] fn f34() {}
+#[test] fn f35() {}
+#[test] fn f36() {}
+#[test] fn f37() {}
+#[test] fn f38() {}
+#[test] fn f39() {}
+#[test] fn f40() {}
+#[test] fn f41() {}
+#[test] fn f42() {}
+#[test] fn f43() {}
+#[test] fn f44() {}
+#[test] fn f45() {}
+#[test] fn f46() {}
+#[test] fn f47() {}
+#[test] fn f48() {}
+#[test] fn f49() {}
+#[test] fn f50() {}
+#[test] fn f51() {}
+#[test] fn f52() {}
+#[test] fn f53() {}
+#[test] fn f54() {}
+#[test] fn f55() {}
+#[test] fn f56() {}
+#[test] fn f57() {}
+#[test] fn f58() {}
+#[test] fn f59() {}
+#[test] fn f60() {}
+#[test] fn f61() {}
+#[test] fn f62() {}
+#[test] fn f63() {}
+#[test] fn f64() {}
+#[test] fn f65() {}
+#[test] fn f66() {}
+#[test] fn f67() {}
+#[test] fn f68() {}
+#[test] fn f69() {}
+#[test] fn f70() {}
+#[test] fn f71() {}
+#[test] fn f72() {}
+#[test] fn f73() {}
+#[test] fn f74() {}
+#[test] fn f75() {}
+#[test] fn f76() {}
+#[test] fn f77() {}
+#[test] fn f78() {}
+#[test] fn f79() {}
+#[test] fn f80() {}
+#[test] fn f81() {}
+#[test] fn f82() {}
+#[test] fn f83() {}
+#[test] fn f84() {}
+#[test] fn f85() {}
+#[test] fn f86() {}
+#[test] fn f87() {}
+#[test] fn f88() {}
+#[test] fn f89() {}
+#[test] fn f90() {}
+#[test] fn f91() {}
+#[test] fn f92() {}
+#[test] fn f93() {}
+#[test] fn f94() {}
+#[test] fn f95() {}
+#[test] fn f96() {}
+#[test] fn f97() {}
+#[test] fn f98() {}
+#[test] fn f99() {}
diff --git a/tests/ui/test-attrs/terse.run.stdout b/tests/ui/test-attrs/terse.run.stdout
new file mode 100644
index 00000000000..2b361361ae8
--- /dev/null
+++ b/tests/ui/test-attrs/terse.run.stdout
@@ -0,0 +1,31 @@
+
+running 103 tests
+abc --- FAILED
+....................................................................................... 88/103
+............. 101/103
+foo --- FAILED
+foo2 --- FAILED
+
+failures:
+
+---- abc stdout ----
+thread 'abc' panicked at $DIR/terse.rs:12:5:
+explicit panic
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+
+---- foo stdout ----
+thread 'foo' panicked at $DIR/terse.rs:17:5:
+explicit panic
+
+---- foo2 stdout ----
+thread 'foo2' panicked at $DIR/terse.rs:22:5:
+explicit panic
+
+
+failures:
+    abc
+    foo
+    foo2
+
+test result: FAILED. 100 passed; 3 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/ui/test-attrs/test-filter-multiple.rs b/tests/ui/test-attrs/test-filter-multiple.rs
index 0347ce457ae..05fc022834a 100644
--- a/tests/ui/test-attrs/test-filter-multiple.rs
+++ b/tests/ui/test-attrs/test-filter-multiple.rs
@@ -3,7 +3,7 @@
 //@ run-flags: --test-threads=1 test1 test2
 //@ check-run-results
 //@ normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 #[test]
 fn test1() {}
diff --git a/tests/ui/test-attrs/test-type.rs b/tests/ui/test-attrs/test-type.rs
index 8f75ff309e0..7db7e31d01d 100644
--- a/tests/ui/test-attrs/test-type.rs
+++ b/tests/ui/test-attrs/test-type.rs
@@ -2,7 +2,7 @@
 //@ run-flags: --test-threads=1
 //@ check-run-results
 //@ normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
-//@ ignore-emscripten no threads support
+//@ needs-threads
 //@ run-pass
 
 #[test]
diff --git a/tests/ui/thread-local/tls.rs b/tests/ui/thread-local/tls.rs
index 17096319d23..fa6a722b291 100644
--- a/tests/ui/thread-local/tls.rs
+++ b/tests/ui/thread-local/tls.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no threads support
+//@ needs-threads
 //@ compile-flags: -O
 //@ ignore-nto Doesn't work without emulated TLS enabled (in LLVM)
 
diff --git a/tests/ui/threads-sendsync/child-outlives-parent.rs b/tests/ui/threads-sendsync/child-outlives-parent.rs
index 2fb4a6f637a..213fd008cd3 100644
--- a/tests/ui/threads-sendsync/child-outlives-parent.rs
+++ b/tests/ui/threads-sendsync/child-outlives-parent.rs
@@ -2,7 +2,7 @@
 // Reported as issue #126, child leaks the string.
 
 //@ pretty-expanded FIXME #23616
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 
diff --git a/tests/ui/threads-sendsync/clone-with-exterior.rs b/tests/ui/threads-sendsync/clone-with-exterior.rs
index 58529e4a788..67790367e27 100644
--- a/tests/ui/threads-sendsync/clone-with-exterior.rs
+++ b/tests/ui/threads-sendsync/clone-with-exterior.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 
 #![allow(unused_must_use)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 
diff --git a/tests/ui/threads-sendsync/comm.rs b/tests/ui/threads-sendsync/comm.rs
index 589859e60a6..0c37fda8a39 100644
--- a/tests/ui/threads-sendsync/comm.rs
+++ b/tests/ui/threads-sendsync/comm.rs
@@ -1,13 +1,13 @@
 //@ run-pass
 #![allow(unused_must_use)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 use std::sync::mpsc::{channel, Sender};
 
 pub fn main() {
     let (tx, rx) = channel();
-    let t = thread::spawn(move|| { child(&tx) });
+    let t = thread::spawn(move || { child(&tx) });
     let y = rx.recv().unwrap();
     println!("received");
     println!("{}", y);
diff --git a/tests/ui/threads-sendsync/eprint-on-tls-drop.rs b/tests/ui/threads-sendsync/eprint-on-tls-drop.rs
index 3ff9fb10f24..82abf21df3f 100644
--- a/tests/ui/threads-sendsync/eprint-on-tls-drop.rs
+++ b/tests/ui/threads-sendsync/eprint-on-tls-drop.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no processes
+//@ needs-threads
 //@ ignore-sgx no processes
 
 use std::cell::RefCell;
diff --git a/tests/ui/threads-sendsync/issue-24313.rs b/tests/ui/threads-sendsync/issue-24313.rs
index 17e027520c1..1ea862f1e7d 100644
--- a/tests/ui/threads-sendsync/issue-24313.rs
+++ b/tests/ui/threads-sendsync/issue-24313.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no threads
+//@ needs-threads
 //@ ignore-sgx no processes
 
 use std::thread;
diff --git a/tests/ui/threads-sendsync/issue-29488.rs b/tests/ui/threads-sendsync/issue-29488.rs
index c848e7b50bb..fbbd6b02a06 100644
--- a/tests/ui/threads-sendsync/issue-29488.rs
+++ b/tests/ui/threads-sendsync/issue-29488.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 
diff --git a/tests/ui/threads-sendsync/issue-43733-2.rs b/tests/ui/threads-sendsync/issue-43733-2.rs
index 5a9ee015cb9..372ebf2cff9 100644
--- a/tests/ui/threads-sendsync/issue-43733-2.rs
+++ b/tests/ui/threads-sendsync/issue-43733-2.rs
@@ -1,4 +1,4 @@
-//@ ignore-wasm32
+//@ needs-threads
 //@ dont-check-compiler-stderr
 #![feature(cfg_target_thread_local, thread_local_internals)]
 
diff --git a/tests/ui/threads-sendsync/issue-43733.rs b/tests/ui/threads-sendsync/issue-43733.rs
index 12207f4e6aa..c90f60887cf 100644
--- a/tests/ui/threads-sendsync/issue-43733.rs
+++ b/tests/ui/threads-sendsync/issue-43733.rs
@@ -1,4 +1,4 @@
-//@ ignore-wasm32
+//@ needs-threads
 #![feature(thread_local)]
 #![feature(cfg_target_thread_local, thread_local_internals)]
 
diff --git a/tests/ui/threads-sendsync/issue-4446.rs b/tests/ui/threads-sendsync/issue-4446.rs
index b5e3a20ccde..aa2de51974b 100644
--- a/tests/ui/threads-sendsync/issue-4446.rs
+++ b/tests/ui/threads-sendsync/issue-4446.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::sync::mpsc::channel;
 use std::thread;
diff --git a/tests/ui/threads-sendsync/issue-4448.rs b/tests/ui/threads-sendsync/issue-4448.rs
index 0f3bf65c441..b8324a8c43f 100644
--- a/tests/ui/threads-sendsync/issue-4448.rs
+++ b/tests/ui/threads-sendsync/issue-4448.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::sync::mpsc::channel;
 use std::thread;
diff --git a/tests/ui/threads-sendsync/issue-8827.rs b/tests/ui/threads-sendsync/issue-8827.rs
index b7deef0f34d..fa07a4ebc7d 100644
--- a/tests/ui/threads-sendsync/issue-8827.rs
+++ b/tests/ui/threads-sendsync/issue-8827.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 use std::sync::mpsc::{channel, Receiver};
diff --git a/tests/ui/threads-sendsync/issue-9396.rs b/tests/ui/threads-sendsync/issue-9396.rs
index 6228f4ba706..6b5907e5c1d 100644
--- a/tests/ui/threads-sendsync/issue-9396.rs
+++ b/tests/ui/threads-sendsync/issue-9396.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 #![allow(unused_must_use)]
 #![allow(deprecated)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::sync::mpsc::{TryRecvError, channel};
 use std::thread;
diff --git a/tests/ui/threads-sendsync/mpsc_stress.rs b/tests/ui/threads-sendsync/mpsc_stress.rs
index 68c40151281..f5354c60bfc 100644
--- a/tests/ui/threads-sendsync/mpsc_stress.rs
+++ b/tests/ui/threads-sendsync/mpsc_stress.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 //@ compile-flags:--test
-//@ ignore-emscripten
+//@ needs-threads
 
 use std::sync::mpsc::channel;
 use std::sync::mpsc::TryRecvError;
diff --git a/tests/ui/threads-sendsync/send-resource.rs b/tests/ui/threads-sendsync/send-resource.rs
index 32910c5f7d1..3e1532b3132 100644
--- a/tests/ui/threads-sendsync/send-resource.rs
+++ b/tests/ui/threads-sendsync/send-resource.rs
@@ -4,7 +4,7 @@
 #![allow(non_camel_case_types)]
 
 //@ pretty-expanded FIXME #23616
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 use std::sync::mpsc::channel;
diff --git a/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs b/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs
index 5306d69a7d2..63cf3ff4049 100644
--- a/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs
+++ b/tests/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 
diff --git a/tests/ui/threads-sendsync/spawn-fn.rs b/tests/ui/threads-sendsync/spawn-fn.rs
index 863c22f70d6..e4d83b53f3c 100644
--- a/tests/ui/threads-sendsync/spawn-fn.rs
+++ b/tests/ui/threads-sendsync/spawn-fn.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_must_use)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 
diff --git a/tests/ui/threads-sendsync/spawn-types.rs b/tests/ui/threads-sendsync/spawn-types.rs
index 9c1b6550d9b..2a7a9e2f497 100644
--- a/tests/ui/threads-sendsync/spawn-types.rs
+++ b/tests/ui/threads-sendsync/spawn-types.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 #![allow(non_camel_case_types)]
 
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 /*
   Make sure we can spawn tasks that take different types of
diff --git a/tests/ui/threads-sendsync/spawn.rs b/tests/ui/threads-sendsync/spawn.rs
index 2c06fc2837f..c7b344b9f75 100644
--- a/tests/ui/threads-sendsync/spawn.rs
+++ b/tests/ui/threads-sendsync/spawn.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 
diff --git a/tests/ui/threads-sendsync/spawn2.rs b/tests/ui/threads-sendsync/spawn2.rs
index cfe907ea6d9..8278fec1885 100644
--- a/tests/ui/threads-sendsync/spawn2.rs
+++ b/tests/ui/threads-sendsync/spawn2.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 
diff --git a/tests/ui/threads-sendsync/spawning-with-debug.rs b/tests/ui/threads-sendsync/spawning-with-debug.rs
index 58f1743527c..90a81c1e53b 100644
--- a/tests/ui/threads-sendsync/spawning-with-debug.rs
+++ b/tests/ui/threads-sendsync/spawning-with-debug.rs
@@ -3,7 +3,7 @@
 #![allow(unused_mut)]
 //@ ignore-windows
 //@ exec-env:RUST_LOG=debug
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 // regression test for issue #10405, make sure we don't call println! too soon.
 
diff --git a/tests/ui/threads-sendsync/task-comm-0.rs b/tests/ui/threads-sendsync/task-comm-0.rs
index 06ce739b8e5..50f2b591894 100644
--- a/tests/ui/threads-sendsync/task-comm-0.rs
+++ b/tests/ui/threads-sendsync/task-comm-0.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_must_use)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 use std::sync::mpsc::{channel, Sender};
diff --git a/tests/ui/threads-sendsync/task-comm-1.rs b/tests/ui/threads-sendsync/task-comm-1.rs
index 77ca940e947..41592bd916b 100644
--- a/tests/ui/threads-sendsync/task-comm-1.rs
+++ b/tests/ui/threads-sendsync/task-comm-1.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_must_use)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 
diff --git a/tests/ui/threads-sendsync/task-comm-10.rs b/tests/ui/threads-sendsync/task-comm-10.rs
index 6f043b64a09..844652c0dde 100644
--- a/tests/ui/threads-sendsync/task-comm-10.rs
+++ b/tests/ui/threads-sendsync/task-comm-10.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 #![allow(unused_must_use)]
 #![allow(unused_mut)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 use std::sync::mpsc::{channel, Sender};
diff --git a/tests/ui/threads-sendsync/task-comm-11.rs b/tests/ui/threads-sendsync/task-comm-11.rs
index 51f13434435..199082fda96 100644
--- a/tests/ui/threads-sendsync/task-comm-11.rs
+++ b/tests/ui/threads-sendsync/task-comm-11.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 #![allow(unused_must_use)]
 //@ pretty-expanded FIXME #23616
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::sync::mpsc::{channel, Sender};
 use std::thread;
diff --git a/tests/ui/threads-sendsync/task-comm-12.rs b/tests/ui/threads-sendsync/task-comm-12.rs
index cb1fb774f10..7be7ec4c988 100644
--- a/tests/ui/threads-sendsync/task-comm-12.rs
+++ b/tests/ui/threads-sendsync/task-comm-12.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 #![allow(unused_must_use)]
 #![allow(unused_mut)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 
diff --git a/tests/ui/threads-sendsync/task-comm-13.rs b/tests/ui/threads-sendsync/task-comm-13.rs
index 6b5384e3f08..414e6e0db76 100644
--- a/tests/ui/threads-sendsync/task-comm-13.rs
+++ b/tests/ui/threads-sendsync/task-comm-13.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_variables)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::sync::mpsc::{channel, Sender};
 use std::thread;
diff --git a/tests/ui/threads-sendsync/task-comm-14.rs b/tests/ui/threads-sendsync/task-comm-14.rs
index 65cc750a7c3..54deb221294 100644
--- a/tests/ui/threads-sendsync/task-comm-14.rs
+++ b/tests/ui/threads-sendsync/task-comm-14.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_parens)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::sync::mpsc::{channel, Sender};
 use std::thread;
diff --git a/tests/ui/threads-sendsync/task-comm-15.rs b/tests/ui/threads-sendsync/task-comm-15.rs
index 844a18b6158..f487bf3cc84 100644
--- a/tests/ui/threads-sendsync/task-comm-15.rs
+++ b/tests/ui/threads-sendsync/task-comm-15.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_must_use)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 //@ pretty-expanded FIXME #23616
 
 use std::sync::mpsc::{channel, Sender};
diff --git a/tests/ui/threads-sendsync/task-comm-17.rs b/tests/ui/threads-sendsync/task-comm-17.rs
index 14ef4dd3ede..687322d4dc9 100644
--- a/tests/ui/threads-sendsync/task-comm-17.rs
+++ b/tests/ui/threads-sendsync/task-comm-17.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_must_use)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 //@ pretty-expanded FIXME #23616
 
 // Issue #922
diff --git a/tests/ui/threads-sendsync/task-comm-3.rs b/tests/ui/threads-sendsync/task-comm-3.rs
index 1f2a6406d79..26f3eaf9dc6 100644
--- a/tests/ui/threads-sendsync/task-comm-3.rs
+++ b/tests/ui/threads-sendsync/task-comm-3.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_must_use)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 use std::sync::mpsc::{channel, Sender};
diff --git a/tests/ui/threads-sendsync/task-comm-7.rs b/tests/ui/threads-sendsync/task-comm-7.rs
index f6e77986e16..d9b322daa66 100644
--- a/tests/ui/threads-sendsync/task-comm-7.rs
+++ b/tests/ui/threads-sendsync/task-comm-7.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 #![allow(unused_must_use)]
 #![allow(unused_assignments)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::sync::mpsc::{channel, Sender};
 use std::thread;
diff --git a/tests/ui/threads-sendsync/task-comm-9.rs b/tests/ui/threads-sendsync/task-comm-9.rs
index f8fe680e5e0..3e617e4a40c 100644
--- a/tests/ui/threads-sendsync/task-comm-9.rs
+++ b/tests/ui/threads-sendsync/task-comm-9.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_must_use)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 use std::sync::mpsc::{channel, Sender};
diff --git a/tests/ui/threads-sendsync/task-life-0.rs b/tests/ui/threads-sendsync/task-life-0.rs
index a4652197afc..d3eca5d371f 100644
--- a/tests/ui/threads-sendsync/task-life-0.rs
+++ b/tests/ui/threads-sendsync/task-life-0.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_must_use)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 //@ pretty-expanded FIXME #23616
 
 use std::thread;
diff --git a/tests/ui/threads-sendsync/task-spawn-barefn.rs b/tests/ui/threads-sendsync/task-spawn-barefn.rs
index 2c957878c95..a97e92206e2 100644
--- a/tests/ui/threads-sendsync/task-spawn-barefn.rs
+++ b/tests/ui/threads-sendsync/task-spawn-barefn.rs
@@ -1,6 +1,6 @@
 //@ run-fail
 //@ error-pattern:Ensure that the child thread runs by panicking
-//@ ignore-emscripten Needs threads.
+//@ needs-threads
 
 use std::thread;
 
diff --git a/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs b/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs
index 442955421d8..ea1c6a9b108 100644
--- a/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs
+++ b/tests/ui/threads-sendsync/task-spawn-move-and-copy.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_must_use)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 use std::sync::mpsc::channel;
diff --git a/tests/ui/threads-sendsync/task-stderr.rs b/tests/ui/threads-sendsync/task-stderr.rs
index 0f215a2b763..cad10c7a792 100644
--- a/tests/ui/threads-sendsync/task-stderr.rs
+++ b/tests/ui/threads-sendsync/task-stderr.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no threads support
+//@ needs-threads
 //@ needs-unwind
 
 #![feature(internal_output_capture)]
diff --git a/tests/ui/threads-sendsync/tcp-stress.rs b/tests/ui/threads-sendsync/tcp-stress.rs
index 488cab40140..429a4657314 100644
--- a/tests/ui/threads-sendsync/tcp-stress.rs
+++ b/tests/ui/threads-sendsync/tcp-stress.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 //@ ignore-android needs extra network permissions
-//@ ignore-emscripten no threads or sockets support
+//@ needs-threads
 //@ ignore-netbsd system ulimit (Too many open files)
 //@ ignore-openbsd system ulimit (Too many open files)
 
diff --git a/tests/ui/threads-sendsync/test-tasks-invalid-value.rs b/tests/ui/threads-sendsync/test-tasks-invalid-value.rs
index 4b38b9ce2c9..127086743ca 100644
--- a/tests/ui/threads-sendsync/test-tasks-invalid-value.rs
+++ b/tests/ui/threads-sendsync/test-tasks-invalid-value.rs
@@ -5,7 +5,7 @@
 //@ error-pattern:should be a positive integer
 //@ compile-flags: --test
 //@ exec-env:RUST_TEST_THREADS=foo
-//@ ignore-emscripten
+//@ needs-threads
 
 #[test]
 fn do_nothing() {}
diff --git a/tests/ui/threads-sendsync/threads.rs b/tests/ui/threads-sendsync/threads.rs
index 7b7e52abab4..f3ed7890364 100644
--- a/tests/ui/threads-sendsync/threads.rs
+++ b/tests/ui/threads-sendsync/threads.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_must_use)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 
diff --git a/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs b/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs
index 66fd6169db0..84176659412 100644
--- a/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs
+++ b/tests/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 //@ no-prefer-dynamic
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 static mut HIT: bool = false;
 
diff --git a/tests/ui/threads-sendsync/tls-init-on-init.rs b/tests/ui/threads-sendsync/tls-init-on-init.rs
index ba5e4698e63..fd764669e7f 100644
--- a/tests/ui/threads-sendsync/tls-init-on-init.rs
+++ b/tests/ui/threads-sendsync/tls-init-on-init.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 #![allow(stable_features)]
 
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 #![feature(thread_local_try_with)]
 
diff --git a/tests/ui/threads-sendsync/tls-try-with.rs b/tests/ui/threads-sendsync/tls-try-with.rs
index d9af1caf741..72cee219a0a 100644
--- a/tests/ui/threads-sendsync/tls-try-with.rs
+++ b/tests/ui/threads-sendsync/tls-try-with.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 #![allow(stable_features)]
 
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 #![feature(thread_local_try_with)]
 
diff --git a/tests/ui/threads-sendsync/unwind-resource.rs b/tests/ui/threads-sendsync/unwind-resource.rs
index ea9e0c7514c..3b1ab57b46e 100644
--- a/tests/ui/threads-sendsync/unwind-resource.rs
+++ b/tests/ui/threads-sendsync/unwind-resource.rs
@@ -2,7 +2,7 @@
 //@ needs-unwind
 
 #![allow(non_camel_case_types)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::sync::mpsc::{channel, Sender};
 use std::thread;
diff --git a/tests/ui/threads-sendsync/yield.rs b/tests/ui/threads-sendsync/yield.rs
index 4d89b10af95..99d14bd92ea 100644
--- a/tests/ui/threads-sendsync/yield.rs
+++ b/tests/ui/threads-sendsync/yield.rs
@@ -2,7 +2,7 @@
 
 #![allow(unused_must_use)]
 #![allow(unused_mut)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 
diff --git a/tests/ui/threads-sendsync/yield1.rs b/tests/ui/threads-sendsync/yield1.rs
index b003a70f47e..c965d2fc303 100644
--- a/tests/ui/threads-sendsync/yield1.rs
+++ b/tests/ui/threads-sendsync/yield1.rs
@@ -2,7 +2,7 @@
 
 #![allow(unused_must_use)]
 #![allow(unused_mut)]
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::thread;
 
diff --git a/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.rs b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.rs
new file mode 100644
index 00000000000..c3a2ab82adc
--- /dev/null
+++ b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.rs
@@ -0,0 +1,16 @@
+// Regression test for #121443
+// Checks that no ICE occurs upon encountering
+// a tuple with unsized element that is not
+// the last element
+
+type Fn = dyn FnOnce() -> u8;
+
+const TEST: Fn = some_fn;
+//~^ ERROR cannot find value `some_fn` in this scope
+//~| ERROR the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time
+//~| ERROR the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time
+const TEST2: (Fn, u8) = (TEST, 0);
+//~^ ERROR the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time
+//~| ERROR the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr
new file mode 100644
index 00000000000..0e92979ccd5
--- /dev/null
+++ b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr
@@ -0,0 +1,45 @@
+error[E0425]: cannot find value `some_fn` in this scope
+  --> $DIR/ice-unsized-tuple-const-issue-121443.rs:8:18
+   |
+LL | const TEST: Fn = some_fn;
+   |                  ^^^^^^^ not found in this scope
+
+error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time
+  --> $DIR/ice-unsized-tuple-const-issue-121443.rs:8:13
+   |
+LL | const TEST: Fn = some_fn;
+   |             ^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)`
+
+error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time
+  --> $DIR/ice-unsized-tuple-const-issue-121443.rs:8:18
+   |
+LL | const TEST: Fn = some_fn;
+   |                  ^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)`
+   = note: constant expressions must have a statically known size
+
+error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time
+  --> $DIR/ice-unsized-tuple-const-issue-121443.rs:12:14
+   |
+LL | const TEST2: (Fn, u8) = (TEST, 0);
+   |              ^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)`
+   = note: only the last element of a tuple may have a dynamically sized type
+
+error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time
+  --> $DIR/ice-unsized-tuple-const-issue-121443.rs:12:25
+   |
+LL | const TEST2: (Fn, u8) = (TEST, 0);
+   |                         ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)`
+   = note: only the last element of a tuple may have a dynamically sized type
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0277, E0425.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.rs b/tests/ui/trait-bounds/super-assoc-mismatch.rs
new file mode 100644
index 00000000000..97dfec80e31
--- /dev/null
+++ b/tests/ui/trait-bounds/super-assoc-mismatch.rs
@@ -0,0 +1,60 @@
+trait Super {
+    type Assoc;
+}
+impl Super for () {
+    type Assoc = u8;
+}
+trait Sub: Super<Assoc = u16> {}
+
+trait BoundOnSelf: Sub {}
+impl BoundOnSelf for () {}
+//~^ ERROR the trait bound `(): Sub` is not satisfied
+
+trait BoundOnParam<T: Sub> {}
+impl BoundOnParam<()> for () {}
+//~^ ERROR the trait bound `(): Sub` is not satisfied
+
+trait BoundOnAssoc {
+    type Assoc: Sub;
+}
+impl BoundOnAssoc for () {
+    type Assoc = ();
+    //~^ ERROR the trait bound `(): Sub` is not satisfied
+}
+
+trait BoundOnGat where Self::Assoc<u8>: Sub {
+    type Assoc<T>;
+}
+impl BoundOnGat for u8 {
+    type Assoc<T> = ();
+    //~^ ERROR the trait bound `(): Sub` is not satisfied
+}
+
+fn trivial_bound() where (): Sub {}
+//~^ ERROR the trait bound `(): Sub` is not satisfied
+
+// The following is an edge case where the unsatisfied projection predicate
+// `<<u8 as MultiAssoc>::Assoc1<()> as SuperGeneric<u16>>::Assoc == <u8 as MultiAssoc>::Assoc2`
+// contains both associated types of `MultiAssoc`. To suppress the error about the unsatisfied
+// super projection, the error's span must be equal to the span of the unsatisfied trait error.
+trait SuperGeneric<T> {
+    type Assoc;
+}
+trait SubGeneric<T>: SuperGeneric<T, Assoc = T> {}
+trait MultiAssoc
+where
+    Self::Assoc1<()>: SubGeneric<Self::Assoc2>
+{
+    type Assoc1<T>;
+    type Assoc2;
+}
+impl SuperGeneric<u16> for () {
+    type Assoc = u8;
+}
+impl MultiAssoc for u8 {
+    type Assoc1<T> = ();
+    //~^ ERROR the trait bound `(): SubGeneric<u16>` is not satisfied
+    type Assoc2 = u16;
+}
+
+fn main() {}
diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.stderr b/tests/ui/trait-bounds/super-assoc-mismatch.stderr
new file mode 100644
index 00000000000..47535776348
--- /dev/null
+++ b/tests/ui/trait-bounds/super-assoc-mismatch.stderr
@@ -0,0 +1,105 @@
+error[E0277]: the trait bound `(): Sub` is not satisfied
+  --> $DIR/super-assoc-mismatch.rs:10:22
+   |
+LL | impl BoundOnSelf for () {}
+   |                      ^^ the trait `Sub` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/super-assoc-mismatch.rs:7:1
+   |
+LL | trait Sub: Super<Assoc = u16> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `BoundOnSelf`
+  --> $DIR/super-assoc-mismatch.rs:9:20
+   |
+LL | trait BoundOnSelf: Sub {}
+   |                    ^^^ required by this bound in `BoundOnSelf`
+
+error[E0277]: the trait bound `(): Sub` is not satisfied
+  --> $DIR/super-assoc-mismatch.rs:14:27
+   |
+LL | impl BoundOnParam<()> for () {}
+   |                           ^^ the trait `Sub` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/super-assoc-mismatch.rs:7:1
+   |
+LL | trait Sub: Super<Assoc = u16> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `BoundOnParam`
+  --> $DIR/super-assoc-mismatch.rs:13:23
+   |
+LL | trait BoundOnParam<T: Sub> {}
+   |                       ^^^ required by this bound in `BoundOnParam`
+
+error[E0277]: the trait bound `(): Sub` is not satisfied
+  --> $DIR/super-assoc-mismatch.rs:21:18
+   |
+LL |     type Assoc = ();
+   |                  ^^ the trait `Sub` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/super-assoc-mismatch.rs:7:1
+   |
+LL | trait Sub: Super<Assoc = u16> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `BoundOnAssoc::Assoc`
+  --> $DIR/super-assoc-mismatch.rs:18:17
+   |
+LL |     type Assoc: Sub;
+   |                 ^^^ required by this bound in `BoundOnAssoc::Assoc`
+
+error[E0277]: the trait bound `(): Sub` is not satisfied
+  --> $DIR/super-assoc-mismatch.rs:29:21
+   |
+LL |     type Assoc<T> = ();
+   |                     ^^ the trait `Sub` is not implemented for `()`, which is required by `<u8 as BoundOnGat>::Assoc<u8>: Sub`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/super-assoc-mismatch.rs:7:1
+   |
+LL | trait Sub: Super<Assoc = u16> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `BoundOnGat`
+  --> $DIR/super-assoc-mismatch.rs:25:41
+   |
+LL | trait BoundOnGat where Self::Assoc<u8>: Sub {
+   |                                         ^^^ required by this bound in `BoundOnGat`
+
+error[E0277]: the trait bound `(): Sub` is not satisfied
+  --> $DIR/super-assoc-mismatch.rs:33:26
+   |
+LL | fn trivial_bound() where (): Sub {}
+   |                          ^^^^^^^ the trait `Sub` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/super-assoc-mismatch.rs:7:1
+   |
+LL | trait Sub: Super<Assoc = u16> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: see issue #48214
+   = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+
+error[E0277]: the trait bound `(): SubGeneric<u16>` is not satisfied
+  --> $DIR/super-assoc-mismatch.rs:55:22
+   |
+LL |     type Assoc1<T> = ();
+   |                      ^^ the trait `SubGeneric<u16>` is not implemented for `()`, which is required by `<u8 as MultiAssoc>::Assoc1<()>: SubGeneric<<u8 as MultiAssoc>::Assoc2>`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/super-assoc-mismatch.rs:43:1
+   |
+LL | trait SubGeneric<T>: SuperGeneric<T, Assoc = T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `MultiAssoc`
+  --> $DIR/super-assoc-mismatch.rs:46:23
+   |
+LL | trait MultiAssoc
+   |       ---------- required by a bound in this trait
+LL | where
+LL |     Self::Assoc1<()>: SubGeneric<Self::Assoc2>
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `MultiAssoc`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/alias/cross-crate.rs b/tests/ui/traits/alias/cross-crate.rs
index 207216f73bf..37681948548 100644
--- a/tests/ui/traits/alias/cross-crate.rs
+++ b/tests/ui/traits/alias/cross-crate.rs
@@ -12,6 +12,6 @@ fn use_alias<T: SendSync>() {}
 fn main() {
     use_alias::<u32>();
     use_alias::<Rc<u32>>();
-    //~^ ERROR `Rc<u32>` cannot be sent between threads safely [E0277]
-    //~^^ ERROR `Rc<u32>` cannot be shared between threads safely [E0277]
+    //~^ ERROR the trait bound `Rc<u32>: SendSync` is not satisfied [E0277]
+    //~| ERROR the trait bound `Rc<u32>: SendSync` is not satisfied [E0277]
 }
diff --git a/tests/ui/traits/alias/cross-crate.stderr b/tests/ui/traits/alias/cross-crate.stderr
index fd614b4bcd5..52eb7e44f44 100644
--- a/tests/ui/traits/alias/cross-crate.stderr
+++ b/tests/ui/traits/alias/cross-crate.stderr
@@ -1,10 +1,9 @@
-error[E0277]: `Rc<u32>` cannot be sent between threads safely
+error[E0277]: the trait bound `Rc<u32>: SendSync` is not satisfied
   --> $DIR/cross-crate.rs:14:17
    |
 LL |     use_alias::<Rc<u32>>();
-   |                 ^^^^^^^ `Rc<u32>` cannot be sent between threads safely
+   |                 ^^^^^^^ the trait `Send` is not implemented for `Rc<u32>`, which is required by `Rc<u32>: SendSync`
    |
-   = help: the trait `Send` is not implemented for `Rc<u32>`, which is required by `Rc<u32>: SendSync`
    = note: required for `Rc<u32>` to implement `SendSync`
 note: required by a bound in `use_alias`
   --> $DIR/cross-crate.rs:10:17
@@ -12,13 +11,12 @@ note: required by a bound in `use_alias`
 LL | fn use_alias<T: SendSync>() {}
    |                 ^^^^^^^^ required by this bound in `use_alias`
 
-error[E0277]: `Rc<u32>` cannot be shared between threads safely
+error[E0277]: the trait bound `Rc<u32>: SendSync` is not satisfied
   --> $DIR/cross-crate.rs:14:17
    |
 LL |     use_alias::<Rc<u32>>();
-   |                 ^^^^^^^ `Rc<u32>` cannot be shared between threads safely
+   |                 ^^^^^^^ the trait `Sync` is not implemented for `Rc<u32>`, which is required by `Rc<u32>: SendSync`
    |
-   = help: the trait `Sync` is not implemented for `Rc<u32>`, which is required by `Rc<u32>: SendSync`
    = note: required for `Rc<u32>` to implement `SendSync`
 note: required by a bound in `use_alias`
   --> $DIR/cross-crate.rs:10:17
diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs
index d254c0ae3ef..bffa856bbee 100644
--- a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs
+++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs
@@ -7,5 +7,5 @@ trait IteratorAlias = Iterator;
 fn f(_: impl IteratorAlias) {}
 
 fn main() {
-    f(()) //~ `()` is not an iterator
+    f(()) //~ ERROR the trait bound `(): IteratorAlias` is not satisfied
 }
diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr
index 1e4f4cb7046..c73c2f68032 100644
--- a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr
+++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr
@@ -1,12 +1,11 @@
-error[E0277]: `()` is not an iterator
+error[E0277]: the trait bound `(): IteratorAlias` is not satisfied
   --> $DIR/issue-108072-unmet-trait-alias-bound.rs:10:7
    |
 LL |     f(())
-   |     - ^^ `()` is not an iterator
+   |     - ^^ the trait `Iterator` is not implemented for `()`, which is required by `(): IteratorAlias`
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Iterator` is not implemented for `()`, which is required by `(): IteratorAlias`
    = note: required for `()` to implement `IteratorAlias`
 note: required by a bound in `f`
   --> $DIR/issue-108072-unmet-trait-alias-bound.rs:7:14
diff --git a/tests/ui/traits/alias/only-require-assocs-from-supertraits.rs b/tests/ui/traits/alias/only-require-assocs-from-supertraits.rs
new file mode 100644
index 00000000000..35149fdfba0
--- /dev/null
+++ b/tests/ui/traits/alias/only-require-assocs-from-supertraits.rs
@@ -0,0 +1,16 @@
+//@ check-pass
+
+#![feature(trait_alias)]
+
+trait Foo<T> {}
+trait Bar { type Assoc; }
+
+trait Alias<T: Bar> = Foo<T>;
+
+// Check that an alias only requires us to specify the associated types
+// of the principal's supertraits. For example, we shouldn't require
+// specifying the type `Assoc` on trait `Bar` just because we have some
+// `T: Bar` where clause on the alias... because that makes no sense.
+fn use_alias<T: Bar>(x: &dyn Alias<T>) {}
+
+fn main() {}
diff --git a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs
index 52ecbcc9e2c..7d71fcdd158 100644
--- a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs
+++ b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs
@@ -20,6 +20,7 @@ impl<T, S> Trait<T, S> for () {}
 fn func<T: Trait<u32, String>>(t: T) -> impl Trait<(), i32> {
 //~^ ERROR trait takes 1 generic argument but 2 generic arguments were supplied
 //~| ERROR trait takes 1 generic argument but 2 generic arguments were supplied
+//~| ERROR type annotations needed
     3
 }
 
diff --git a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr
index e7ceb7372bf..f4ede4190fc 100644
--- a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr
+++ b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr
@@ -1,3 +1,9 @@
+error[E0207]: the type parameter `S` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:9:9
+   |
+LL | impl<T, S> Trait<T> for i32 {
+   |         ^ unconstrained type parameter
+
 error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
   --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:15:12
    |
@@ -10,6 +16,12 @@ note: trait defined here, with 1 generic parameter: `T`
 LL | pub trait Trait<T> {
    |           ^^^^^ -
 
+error[E0207]: the type parameter `S` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:15:9
+   |
+LL | impl<T, S> Trait<T, S> for () {}
+   |         ^ unconstrained type parameter
+
 error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
   --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:20:12
    |
@@ -42,8 +54,14 @@ help: replace the generic bound with the associated type
 LL | fn func<T: Trait<u32, String>>(t: T) -> impl Trait<(), Assoc = i32> {
    |                                                        +++++++
 
+error[E0282]: type annotations needed
+  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:20:41
+   |
+LL | fn func<T: Trait<u32, String>>(t: T) -> impl Trait<(), i32> {
+   |                                         ^^^^^^^^^^^^^^^^^^^ cannot infer type
+
 error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:26:18
+  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:27:18
    |
 LL | struct Struct<T: Trait<u32, String>> {
    |                  ^^^^^ expected 1 generic argument
@@ -59,7 +77,7 @@ LL | struct Struct<T: Trait<u32, Assoc = String>> {
    |                             +++++++
 
 error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:31:23
+  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:32:23
    |
 LL | trait AnotherTrait<T: Trait<T, i32>> {}
    |                       ^^^^^ expected 1 generic argument
@@ -75,7 +93,7 @@ LL | trait AnotherTrait<T: Trait<T, Assoc = i32>> {}
    |                                +++++++
 
 error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:34:9
+  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:35:9
    |
 LL | impl<T: Trait<u32, String>> Struct<T> {}
    |         ^^^^^ expected 1 generic argument
@@ -91,7 +109,7 @@ LL | impl<T: Trait<u32, Assoc = String>> Struct<T> {}
    |                    +++++++
 
 error[E0107]: struct takes 1 generic argument but 2 generic arguments were supplied
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:40:58
+  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:41:58
    |
 LL | impl<T: Trait<u32, Assoc=String>, U> YetAnotherTrait for Struct<T, U> {}
    |                                                          ^^^^^^    - help: remove this generic argument
@@ -99,24 +117,12 @@ LL | impl<T: Trait<u32, Assoc=String>, U> YetAnotherTrait for Struct<T, U> {}
    |                                                          expected 1 generic argument
    |
 note: struct defined here, with 1 generic parameter: `T`
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:26:8
+  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:27:8
    |
 LL | struct Struct<T: Trait<u32, String>> {
    |        ^^^^^^ -
 
-error[E0207]: the type parameter `S` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:9:9
-   |
-LL | impl<T, S> Trait<T> for i32 {
-   |         ^ unconstrained type parameter
+error: aborting due to 10 previous errors
 
-error[E0207]: the type parameter `S` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:15:9
-   |
-LL | impl<T, S> Trait<T, S> for () {}
-   |         ^ unconstrained type parameter
-
-error: aborting due to 9 previous errors
-
-Some errors have detailed explanations: E0107, E0207.
+Some errors have detailed explanations: E0107, E0207, E0282.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/traits/bound/in-arc.rs b/tests/ui/traits/bound/in-arc.rs
index 40a6115e838..2616ad84ff8 100644
--- a/tests/ui/traits/bound/in-arc.rs
+++ b/tests/ui/traits/bound/in-arc.rs
@@ -3,7 +3,7 @@
 // Tests that a heterogeneous list of existential `dyn` types can be put inside an Arc
 // and shared between threads as long as all types fulfill Send.
 
-//@ ignore-emscripten no threads support
+//@ needs-threads
 
 use std::sync::Arc;
 use std::sync::mpsc::channel;
diff --git a/tests/ui/traits/bound/on-structs-and-enums-static.rs b/tests/ui/traits/bound/on-structs-and-enums-static.rs
index 066416cb362..d734893dd7c 100644
--- a/tests/ui/traits/bound/on-structs-and-enums-static.rs
+++ b/tests/ui/traits/bound/on-structs-and-enums-static.rs
@@ -8,6 +8,7 @@ struct Foo<T:Trait> {
 
 static X: Foo<usize> = Foo {
 //~^ ERROR E0277
+//~| ERROR E0277
     x: 1, //~ ERROR: E0277
 };
 
diff --git a/tests/ui/traits/bound/on-structs-and-enums-static.stderr b/tests/ui/traits/bound/on-structs-and-enums-static.stderr
index 28bbe00c582..42ebcc07571 100644
--- a/tests/ui/traits/bound/on-structs-and-enums-static.stderr
+++ b/tests/ui/traits/bound/on-structs-and-enums-static.stderr
@@ -16,7 +16,25 @@ LL | struct Foo<T:Trait> {
    |              ^^^^^ required by this bound in `Foo`
 
 error[E0277]: the trait bound `usize: Trait` is not satisfied
-  --> $DIR/on-structs-and-enums-static.rs:11:8
+  --> $DIR/on-structs-and-enums-static.rs:9:11
+   |
+LL | static X: Foo<usize> = Foo {
+   |           ^^^^^^^^^^ the trait `Trait` is not implemented for `usize`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/on-structs-and-enums-static.rs:1:1
+   |
+LL | trait Trait {
+   | ^^^^^^^^^^^
+note: required by a bound in `Foo`
+  --> $DIR/on-structs-and-enums-static.rs:5:14
+   |
+LL | struct Foo<T:Trait> {
+   |              ^^^^^ required by this bound in `Foo`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: the trait bound `usize: Trait` is not satisfied
+  --> $DIR/on-structs-and-enums-static.rs:12:8
    |
 LL |     x: 1,
    |        ^ the trait `Trait` is not implemented for `usize`
@@ -32,6 +50,6 @@ note: required by a bound in `Foo`
 LL | struct Foo<T:Trait> {
    |              ^^^^^ required by this bound in `Foo`
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
index 629ccac49c5..17fced307ed 100644
--- a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
+++ b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
@@ -6,7 +6,7 @@ LL | auto trait Magic: Copy {}
    |            |
    |            auto traits cannot have super traits or lifetime bounds
 
-error[E0277]: the trait bound `NoClone: Copy` is not satisfied
+error[E0277]: the trait bound `NoClone: Magic` is not satisfied
   --> $DIR/supertrait-auto-trait.rs:16:23
    |
 LL |     let (a, b) = copy(NoClone);
diff --git a/tests/ui/traits/issue-105231.rs b/tests/ui/traits/issue-105231.rs
index 74c7afd6b9e..89b2da4452a 100644
--- a/tests/ui/traits/issue-105231.rs
+++ b/tests/ui/traits/issue-105231.rs
@@ -1,7 +1,9 @@
 //~ ERROR overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send`
 struct A<T>(B<T>);
 //~^ ERROR recursive types `A` and `B` have infinite size
+//~| ERROR `T` is never used
 struct B<T>(A<A<T>>);
+//~^ ERROR `T` is never used
 trait Foo {}
 impl<T> Foo for T where T: Send {}
 impl Foo for B<u8> {}
diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr
index fe20c47c57a..6467a438375 100644
--- a/tests/ui/traits/issue-105231.stderr
+++ b/tests/ui/traits/issue-105231.stderr
@@ -3,7 +3,7 @@ error[E0072]: recursive types `A` and `B` have infinite size
    |
 LL | struct A<T>(B<T>);
    | ^^^^^^^^^^^ ---- recursive without indirection
-LL |
+...
 LL | struct B<T>(A<A<T>>);
    | ^^^^^^^^^^^ ------- recursive without indirection
    |
@@ -11,19 +11,38 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
    |
 LL ~ struct A<T>(Box<B<T>>);
 LL |
+LL |
 LL ~ struct B<T>(Box<A<A<T>>>);
    |
 
+error[E0392]: type parameter `T` is never used
+  --> $DIR/issue-105231.rs:2:10
+   |
+LL | struct A<T>(B<T>);
+   |          ^ unused type parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+
+error[E0392]: type parameter `T` is never used
+  --> $DIR/issue-105231.rs:5:10
+   |
+LL | struct B<T>(A<A<T>>);
+   |          ^ unused type parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+
 error[E0275]: overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send`
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_105231`)
 note: required because it appears within the type `B<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<u8>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/issue-105231.rs:4:8
+  --> $DIR/issue-105231.rs:5:8
    |
 LL | struct B<T>(A<A<T>>);
    |        ^
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0072, E0275.
+Some errors have detailed explanations: E0072, E0275, E0392.
 For more information about an error, try `rustc --explain E0072`.
diff --git a/tests/ui/traits/issue-28576.stderr b/tests/ui/traits/issue-28576.stderr
index 653ce05d285..7e0f52bc4fe 100644
--- a/tests/ui/traits/issue-28576.stderr
+++ b/tests/ui/traits/issue-28576.stderr
@@ -1,3 +1,23 @@
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+  --> $DIR/issue-28576.rs:5:16
+   |
+LL | pub trait Bar: Foo<Assoc=()> {
+   |                ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+note: required by an implicit `Sized` bound in `Foo`
+  --> $DIR/issue-28576.rs:1:15
+   |
+LL | pub trait Foo<RHS=Self> {
+   |               ^^^^^^^^ required by the implicit `Sized` requirement on this type parameter in `Foo`
+help: consider further restricting `Self`
+   |
+LL | pub trait Bar: Foo<Assoc=()> + Sized {
+   |                              +++++++
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | pub trait Foo<RHS: ?Sized=Self> {
+   |                  ++++++++
+
 error[E0038]: the trait `Bar` cannot be made into an object
   --> $DIR/issue-28576.rs:9:12
    |
@@ -19,26 +39,6 @@ help: consider using an opaque type instead
 LL |            impl Bar
    |            ~~~~
 
-error[E0277]: the size for values of type `Self` cannot be known at compilation time
-  --> $DIR/issue-28576.rs:5:16
-   |
-LL | pub trait Bar: Foo<Assoc=()> {
-   |                ^^^^^^^^^^^^^ doesn't have a size known at compile-time
-   |
-note: required by an implicit `Sized` bound in `Foo`
-  --> $DIR/issue-28576.rs:1:15
-   |
-LL | pub trait Foo<RHS=Self> {
-   |               ^^^^^^^^ required by the implicit `Sized` requirement on this type parameter in `Foo`
-help: consider further restricting `Self`
-   |
-LL | pub trait Bar: Foo<Assoc=()> + Sized {
-   |                              +++++++
-help: consider relaxing the implicit `Sized` restriction
-   |
-LL | pub trait Foo<RHS: ?Sized=Self> {
-   |                  ++++++++
-
 error[E0277]: the size for values of type `Self` cannot be known at compilation time
   --> $DIR/issue-28576.rs:5:16
    |
diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr
index 6c019f59b09..330b23b5755 100644
--- a/tests/ui/traits/issue-50480.stderr
+++ b/tests/ui/traits/issue-50480.stderr
@@ -60,6 +60,14 @@ error[E0412]: cannot find type `NotDefined` in this scope
 LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |                     ^^^^^^^^^^ not found in this scope
 
+error[E0277]: `i32` is not an iterator
+  --> $DIR/issue-50480.rs:3:27
+   |
+LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `i32`
+
 error[E0204]: the trait `Copy` cannot be implemented for this type
   --> $DIR/issue-50480.rs:1:17
    |
@@ -86,15 +94,6 @@ LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |
    = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0277]: `i32` is not an iterator
-  --> $DIR/issue-50480.rs:3:27
-   |
-LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
-   |
-   = help: the trait `Iterator` is not implemented for `i32`
-   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-
 error[E0277]: `i32` is not an iterator
   --> $DIR/issue-50480.rs:14:33
    |
@@ -102,7 +101,6 @@ LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `i32`
-   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
 
 error[E0277]: `i32` is not an iterator
   --> $DIR/issue-50480.rs:3:28
@@ -111,7 +109,6 @@ LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |                            ^^^ `i32` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `i32`
-   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
 
 error[E0277]: `i32` is not an iterator
   --> $DIR/issue-50480.rs:11:10
@@ -120,7 +117,6 @@ LL | #[derive(Clone, Copy)]
    |          ^^^^^ `i32` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `i32`
-   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: `i32` is not an iterator
@@ -133,7 +129,6 @@ LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `i32`
-   = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 13 previous errors
diff --git a/tests/ui/traits/next-solver/assembly/param-env-alias-bound-conflict.rs b/tests/ui/traits/next-solver/assembly/param-env-alias-bound-conflict.rs
new file mode 100644
index 00000000000..ddda1a71d7e
--- /dev/null
+++ b/tests/ui/traits/next-solver/assembly/param-env-alias-bound-conflict.rs
@@ -0,0 +1,26 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+// Regression test for #119607.
+
+pub trait IntoFoo {
+    type Item;
+    type IntoIter: Foo<Item = Self::Item>;
+
+    fn into_iter(self) -> Self::IntoIter;
+}
+
+pub trait Foo {
+    type Item;
+
+    fn next(self) -> Option<Self::Item>;
+}
+
+pub fn foo<'a, Iter1, Elem1>(a: &'a Iter1)
+where
+    &'a Iter1: IntoFoo<Item = Elem1>,
+{
+    a.into_iter().next();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
index a04fa1ab8a1..39d453e8035 100644
--- a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
+++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
@@ -1,15 +1,3 @@
-error[E0119]: conflicting implementations of trait `Trait`
-  --> $DIR/trait_ref_is_knowable-norm-overflow.rs:18:1
-   |
-LL | impl<T: Copy> Trait for T {}
-   | ------------------------- first implementation here
-LL | struct LocalTy;
-LL | impl Trait for <LocalTy as Overflow>::Assoc {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
-   |
-   = note: overflow evaluating the requirement `_ == <LocalTy as Overflow>::Assoc`
-   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`trait_ref_is_knowable_norm_overflow`)
-
 error[E0275]: overflow evaluating the requirement `<T as Overflow>::Assoc: Sized`
   --> $DIR/trait_ref_is_knowable-norm-overflow.rs:10:18
    |
@@ -27,6 +15,18 @@ help: consider relaxing the implicit `Sized` restriction
 LL |     type Assoc: ?Sized;
    |               ++++++++
 
+error[E0119]: conflicting implementations of trait `Trait`
+  --> $DIR/trait_ref_is_knowable-norm-overflow.rs:18:1
+   |
+LL | impl<T: Copy> Trait for T {}
+   | ------------------------- first implementation here
+LL | struct LocalTy;
+LL | impl Trait for <LocalTy as Overflow>::Assoc {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+   |
+   = note: overflow evaluating the requirement `_ == <LocalTy as Overflow>::Assoc`
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`trait_ref_is_knowable_norm_overflow`)
+
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0119, E0275.
diff --git a/tests/ui/traits/next-solver/env-shadows-impls/param-env-impl-conflict.rs b/tests/ui/traits/next-solver/env-shadows-impls/param-env-impl-conflict.rs
new file mode 100644
index 00000000000..1b9e9866cd6
--- /dev/null
+++ b/tests/ui/traits/next-solver/env-shadows-impls/param-env-impl-conflict.rs
@@ -0,0 +1,23 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+// Regression test for #119608.
+
+pub trait Foo {}
+
+pub trait Bar {
+    type Assoc;
+}
+
+impl<T: Foo> Bar for T {
+    type Assoc = T;
+}
+
+pub fn foo<I>(_input: <I as Bar>::Assoc)
+where
+    I: Bar,
+    <I as Bar>::Assoc: Foo,
+{
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr
index 931c46c6887..45ff9f763cd 100644
--- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr
+++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr
@@ -13,6 +13,12 @@ LL | #![feature(lazy_type_alias)]
    = note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
+error: the type `<*const T as ToUnit<'a>>::Unit` is not well-formed
+  --> $DIR/issue-118950-root-region.rs:14:21
+   |
+LL | type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit;
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }
 WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }
 WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }
@@ -26,12 +32,6 @@ LL |
 LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(_)`
 
-error: the type `<*const T as ToUnit<'a>>::Unit` is not well-formed
-  --> $DIR/issue-118950-root-region.rs:14:21
-   |
-LL | type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit;
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error: aborting due to 3 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0119, E0412.
diff --git a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr
index 3a4415ed23a..6c259621466 100644
--- a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr
+++ b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr
@@ -21,6 +21,20 @@ help: consider adding an explicit lifetime bound
 LL |     for<F> F: 'a, !1_"F": 'a
    |                 ~~~~~~~~~~~~
 
-error: aborting due to 1 previous error; 1 warning emitted
+error[E0309]: the placeholder type `!2_"F"` may not live long enough
+  --> $DIR/type-match-with-late-bound.rs:11:1
+   |
+LL | async fn walk2<'a, T: 'a>(_: T)
+   |                -- the placeholder type `!2_"F"` must be valid for the lifetime `'a` as defined here...
+...
+LL | {}
+   | ^^ ...so that the type `F` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL |     for<F> F: 'a, !2_"F": 'a
+   |                 ~~~~~~~~~~~~
+
+error: aborting due to 2 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0309`.
diff --git a/tests/ui/traits/suggest-dereferences/root-obligation.fixed b/tests/ui/traits/suggest-dereferences/root-obligation.fixed
index eecd52304ff..072296c6b15 100644
--- a/tests/ui/traits/suggest-dereferences/root-obligation.fixed
+++ b/tests/ui/traits/suggest-dereferences/root-obligation.fixed
@@ -4,7 +4,7 @@ fn get_vowel_count(string: &str) -> usize {
     string
         .chars()
         .filter(|c| "aeiou".contains(*c))
-        //~^ ERROR expected a `Fn(char)` closure, found `char`
+        //~^ ERROR the trait bound `&char: Pattern<'_>` is not satisfied
         .count()
 }
 
diff --git a/tests/ui/traits/suggest-dereferences/root-obligation.rs b/tests/ui/traits/suggest-dereferences/root-obligation.rs
index d58193f1213..e7025fe0825 100644
--- a/tests/ui/traits/suggest-dereferences/root-obligation.rs
+++ b/tests/ui/traits/suggest-dereferences/root-obligation.rs
@@ -4,7 +4,7 @@ fn get_vowel_count(string: &str) -> usize {
     string
         .chars()
         .filter(|c| "aeiou".contains(c))
-        //~^ ERROR expected a `Fn(char)` closure, found `char`
+        //~^ ERROR the trait bound `&char: Pattern<'_>` is not satisfied
         .count()
 }
 
diff --git a/tests/ui/traits/suggest-dereferences/root-obligation.stderr b/tests/ui/traits/suggest-dereferences/root-obligation.stderr
index a41330373be..56f95e20715 100644
--- a/tests/ui/traits/suggest-dereferences/root-obligation.stderr
+++ b/tests/ui/traits/suggest-dereferences/root-obligation.stderr
@@ -1,12 +1,11 @@
-error[E0277]: expected a `Fn(char)` closure, found `char`
+error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
   --> $DIR/root-obligation.rs:6:38
    |
 LL |         .filter(|c| "aeiou".contains(c))
-   |                             -------- ^ expected an `Fn(char)` closure, found `char`
+   |                             -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
    |                             |
    |                             required by a bound introduced by this call
    |
-   = help: the trait `Fn<(char,)>` is not implemented for `char`, which is required by `&char: Pattern<'_>`
    = note: required for `&char` to implement `FnOnce<(char,)>`
    = note: required for `&char` to implement `Pattern<'_>`
 note: required by a bound in `core::str::<impl str>::contains`
diff --git a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs
index 511e41562b2..6211c7fac41 100644
--- a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs
+++ b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.rs
@@ -1,5 +1,6 @@
 trait A: B + A {}
 //~^ ERROR cycle detected when computing the super predicates of `A` [E0391]
+//~| ERROR cycle detected when computing the implied predicates of `A` [E0391]
 
 trait B {}
 
diff --git a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr
index 85c05bd05db..b9988e2e6d3 100644
--- a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr
+++ b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr
@@ -5,13 +5,27 @@ LL | trait A: B + A {}
    |              ^
    |
    = note: ...which immediately requires computing the super predicates of `A` again
-note: cycle used when collecting item types in top-level module
+note: cycle used when checking that `A` is well-formed
   --> $DIR/cyclic-trait-resolution.rs:1:1
    |
 LL | trait A: B + A {}
    | ^^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
-error: aborting due to 1 previous error
+error[E0391]: cycle detected when computing the implied predicates of `A`
+  --> $DIR/cyclic-trait-resolution.rs:1:14
+   |
+LL | trait A: B + A {}
+   |              ^
+   |
+   = note: ...which immediately requires computing the implied predicates of `A` again
+note: cycle used when checking that `<impl at $DIR/cyclic-trait-resolution.rs:7:1: 7:14>` is well-formed
+  --> $DIR/cyclic-trait-resolution.rs:7:1
+   |
+LL | impl A for () {}
+   | ^^^^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr b/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr
index 7f80c3cfaba..df466609a12 100644
--- a/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr
+++ b/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr
@@ -46,17 +46,11 @@ LL |     V3 = Self::V1 {} as u8 + 2,
    |          ^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires computing layout of `Alpha`...
    = note: ...which again requires simplifying constant for the type system `Alpha::V3::{constant#0}`, completing the cycle
-note: cycle used when collecting item types in top-level module
-  --> $DIR/self-in-enum-definition.rs:1:1
+note: cycle used when checking that `Alpha` is well-formed
+  --> $DIR/self-in-enum-definition.rs:2:1
    |
-LL | / #[repr(u8)]
-LL | | enum Alpha {
-LL | |     V1 = 41,
-LL | |     V2 = Self::V1 as u8 + 1,    // OK; See #50072.
-...  |
-LL | |
-LL | | fn main() {}
-   | |____________^
+LL | enum Alpha {
+   | ^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs
index 7c7c68ad60a..f62dccff58d 100644
--- a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs
+++ b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs
@@ -20,6 +20,7 @@ impl<'a, I> UnwrapItemsExt for I {
 
     fn unwrap_items(self) -> Self::Iter {
         MyStruct {}
+        //~^ ERROR expected generic lifetime parameter
     }
 }
 
diff --git a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr
index 089c3e4fd8a..e6b94c525ff 100644
--- a/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr
+++ b/tests/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr
@@ -4,6 +4,16 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
 LL | impl<'a, I> UnwrapItemsExt for I {
    |      ^^ unconstrained lifetime parameter
 
-error: aborting due to 1 previous error
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/assoc-type-lifetime-unconstrained.rs:22:9
+   |
+LL | impl<'a, I> UnwrapItemsExt for I {
+   |      -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |         MyStruct {}
+   |         ^^^^^^^^^^^
 
-For more information about this error, try `rustc --explain E0207`.
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0207, E0792.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/type-alias-impl-trait/escaping-bound-var.rs b/tests/ui/type-alias-impl-trait/escaping-bound-var.rs
index bf27e76db2b..1ff200680be 100644
--- a/tests/ui/type-alias-impl-trait/escaping-bound-var.rs
+++ b/tests/ui/type-alias-impl-trait/escaping-bound-var.rs
@@ -7,7 +7,7 @@ pub trait Trait<'a> {
 trait Test<'a> {}
 
 pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
-//~^ ERROR cannot capture late-bound lifetime in type alias impl trait
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
 
 impl Trait<'_> for () {
     type Assoc = ();
diff --git a/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr b/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr
index 7dce067d39c..09f6fba79cf 100644
--- a/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr
+++ b/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr
@@ -1,8 +1,15 @@
-error: cannot capture late-bound lifetime in type alias impl trait
-  --> $DIR/escaping-bound-var.rs:9:57
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
+  --> $DIR/escaping-bound-var.rs:9:47
    |
 LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
-   |                         -- lifetime defined here        ^^
+   |                                               ^^^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope
+   |
+note: lifetime declared here
+  --> $DIR/escaping-bound-var.rs:9:25
+   |
+LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
+   |                         ^^
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs
index 4c881dd1330..3117060cef0 100644
--- a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs
@@ -15,7 +15,7 @@ impl Trait for Bar {
     type Assoc = impl std::fmt::Debug;
     fn foo() -> Foo {
         Foo { field: () }
-        //~^ ERROR: item constrains opaque type that is not in its signature
+        //~^ ERROR: mismatched types
     }
 }
 
diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.stderr b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.stderr
index 5c53dfa3a75..4910e794e8d 100644
--- a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.stderr
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.stderr
@@ -1,11 +1,15 @@
-error: item constrains opaque type that is not in its signature
+error[E0308]: mismatched types
   --> $DIR/hidden_behind_struct_field2.rs:17:22
    |
+LL |     type Assoc = impl std::fmt::Debug;
+   |                  -------------------- the expected opaque type
+LL |     fn foo() -> Foo {
 LL |         Foo { field: () }
-   |                      ^^
+   |                      ^^ expected opaque type, found `()`
    |
-   = note: this item must mention the opaque type in its signature in order to be able to register hidden types
-note: this item must mention the opaque type in its signature in order to be able to register hidden types
+   = note: expected opaque type `<Bar as Trait>::Assoc`
+                found unit type `()`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
   --> $DIR/hidden_behind_struct_field2.rs:16:8
    |
 LL |     fn foo() -> Foo {
@@ -13,3 +17,4 @@ LL |     fn foo() -> Foo {
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs
new file mode 100644
index 00000000000..c1f13599412
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs
@@ -0,0 +1,28 @@
+//! This test demonstrates a bug where we accidentally
+//! detected opaque types in struct fields, but only if nested
+//! in projections of another opaque type.
+
+#![feature(impl_trait_in_assoc_type)]
+
+struct Bar;
+
+trait Trait: Sized {
+    type Assoc2;
+    type Assoc;
+    fn foo() -> Self::Assoc;
+}
+
+impl Trait for Bar {
+    type Assoc2 = impl std::fmt::Debug;
+    type Assoc = impl Iterator<Item = Foo>;
+    fn foo() -> Self::Assoc {
+        vec![Foo { field: () }].into_iter()
+        //~^ ERROR mismatched types
+    }
+}
+
+struct Foo {
+    field: <Bar as Trait>::Assoc2,
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr
new file mode 100644
index 00000000000..f10ccc00299
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/hidden_behind_struct_field3.rs:19:27
+   |
+LL |     type Assoc2 = impl std::fmt::Debug;
+   |                   -------------------- the expected opaque type
+...
+LL |         vec![Foo { field: () }].into_iter()
+   |                           ^^ expected opaque type, found `()`
+   |
+   = note: expected opaque type `<Bar as Trait>::Assoc2`
+                found unit type `()`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/hidden_behind_struct_field3.rs:18:8
+   |
+LL |     fn foo() -> Self::Assoc {
+   |        ^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs
index 1824ff5e2fb..fcac83500ec 100644
--- a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs
+++ b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs
@@ -12,6 +12,8 @@ impl<T> X for () {
     //~^ ERROR the type parameter `T` is not constrained
     type I = impl Sized;
     fn f() -> Self::I {}
+    //~^ ERROR type annotations needed
+    //~| ERROR type annotations needed
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr
index 137a4db81b5..bb0e11d314c 100644
--- a/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr
+++ b/tests/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr
@@ -4,6 +4,19 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
 LL | impl<T> X for () {
    |      ^ unconstrained type parameter
 
-error: aborting due to 1 previous error
+error[E0282]: type annotations needed
+  --> $DIR/impl-with-unconstrained-param.rs:14:23
+   |
+LL |     fn f() -> Self::I {}
+   |                       ^^ cannot infer type for type parameter `T`
 
-For more information about this error, try `rustc --explain E0207`.
+error[E0282]: type annotations needed
+  --> $DIR/impl-with-unconstrained-param.rs:14:15
+   |
+LL |     fn f() -> Self::I {}
+   |               ^^^^^^^ cannot infer type for type parameter `T`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0207, E0282.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/type-alias-impl-trait/issue-74244.rs b/tests/ui/type-alias-impl-trait/issue-74244.rs
index bb4104b3d25..ce8a38a3361 100644
--- a/tests/ui/type-alias-impl-trait/issue-74244.rs
+++ b/tests/ui/type-alias-impl-trait/issue-74244.rs
@@ -14,6 +14,7 @@ impl<T> Allocator for DefaultAllocator {
 type A = impl Fn(<DefaultAllocator as Allocator>::Buffer);
 
 fn foo() -> A {
+    //~^ ERROR: type annotations needed
     |_| ()
 }
 
diff --git a/tests/ui/type-alias-impl-trait/issue-74244.stderr b/tests/ui/type-alias-impl-trait/issue-74244.stderr
index f5ca56baccc..d2b50ffd86b 100644
--- a/tests/ui/type-alias-impl-trait/issue-74244.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-74244.stderr
@@ -4,6 +4,13 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
 LL | impl<T> Allocator for DefaultAllocator {
    |      ^ unconstrained type parameter
 
-error: aborting due to 1 previous error
+error[E0282]: type annotations needed
+  --> $DIR/issue-74244.rs:16:13
+   |
+LL | fn foo() -> A {
+   |             ^ cannot infer type for type parameter `T`
 
-For more information about this error, try `rustc --explain E0207`.
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0207, E0282.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/type-alias-impl-trait/issue-74761-2.rs b/tests/ui/type-alias-impl-trait/issue-74761-2.rs
index f582592e9bc..e556025adee 100644
--- a/tests/ui/type-alias-impl-trait/issue-74761-2.rs
+++ b/tests/ui/type-alias-impl-trait/issue-74761-2.rs
@@ -10,6 +10,7 @@ impl<'a, 'b> A for () {
     type B = impl core::fmt::Debug;
 
     fn f(&self) -> Self::B {}
+    //~^ ERROR expected generic lifetime parameter
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-74761-2.stderr b/tests/ui/type-alias-impl-trait/issue-74761-2.stderr
index f15d0a069ca..26babc29000 100644
--- a/tests/ui/type-alias-impl-trait/issue-74761-2.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-74761-2.stderr
@@ -10,6 +10,16 @@ error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait,
 LL | impl<'a, 'b> A for () {
    |          ^^ unconstrained lifetime parameter
 
-error: aborting due to 2 previous errors
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/issue-74761-2.rs:12:28
+   |
+LL | impl<'a, 'b> A for () {
+   |      -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     fn f(&self) -> Self::B {}
+   |                            ^^
 
-For more information about this error, try `rustc --explain E0207`.
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0207, E0792.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/type-alias-impl-trait/issue-74761.rs b/tests/ui/type-alias-impl-trait/issue-74761.rs
index f582592e9bc..e556025adee 100644
--- a/tests/ui/type-alias-impl-trait/issue-74761.rs
+++ b/tests/ui/type-alias-impl-trait/issue-74761.rs
@@ -10,6 +10,7 @@ impl<'a, 'b> A for () {
     type B = impl core::fmt::Debug;
 
     fn f(&self) -> Self::B {}
+    //~^ ERROR expected generic lifetime parameter
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-74761.stderr b/tests/ui/type-alias-impl-trait/issue-74761.stderr
index 1d016fe070f..a4826c29346 100644
--- a/tests/ui/type-alias-impl-trait/issue-74761.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-74761.stderr
@@ -10,6 +10,16 @@ error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait,
 LL | impl<'a, 'b> A for () {
    |          ^^ unconstrained lifetime parameter
 
-error: aborting due to 2 previous errors
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/issue-74761.rs:12:28
+   |
+LL | impl<'a, 'b> A for () {
+   |      -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     fn f(&self) -> Self::B {}
+   |                            ^^
 
-For more information about this error, try `rustc --explain E0207`.
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0207, E0792.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr
index 5e978e97d6b..b4b78f8175f 100644
--- a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr
@@ -2,15 +2,13 @@ error[E0277]: the trait bound `B: Bar` is not satisfied
   --> $DIR/issue-90400-2.rs:25:9
    |
 LL |         MyBaz(bar)
-   |         ^^^^^^^^^^ the trait `Bar` is not implemented for `B`, which is required by `MyBaz<B>: Baz`
+   |         ^^^^^^^^^^ the trait `Bar` is not implemented for `B`
    |
-note: required for `MyBaz<B>` to implement `Baz`
-  --> $DIR/issue-90400-2.rs:30:14
+note: required by a bound in `MyBaz`
+  --> $DIR/issue-90400-2.rs:29:17
    |
-LL | impl<B: Bar> Baz for MyBaz<B> {
-   |         ---  ^^^     ^^^^^^^^
-   |         |
-   |         unsatisfied trait bound introduced here
+LL | struct MyBaz<B: Bar>(B);
+   |                 ^^^ required by this bound in `MyBaz`
 help: consider restricting type parameter `B`
    |
 LL |     type FooFn<B: Bar> = impl Baz;
diff --git a/tests/ui/type-alias-impl-trait/self-referential.rs b/tests/ui/type-alias-impl-trait/self-referential.rs
index 3090f7733d2..2bd450e6c86 100644
--- a/tests/ui/type-alias-impl-trait/self-referential.rs
+++ b/tests/ui/type-alias-impl-trait/self-referential.rs
@@ -12,14 +12,14 @@ fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
 type Foo<'a, 'b> = (i32, impl PartialEq<Foo<'a, 'b>> + std::fmt::Debug);
 
 fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> {
-    //~^ ERROR can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0})`
+    //~^ ERROR can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0}<'a, 'b>)`
     (42, i)
 }
 
 type Moo<'a, 'b> = (i32, impl PartialEq<Moo<'b, 'a>> + std::fmt::Debug);
 
 fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> {
-    //~^ ERROR can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})`
+    //~^ ERROR can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0}<'b, 'a>)`
     (42, i)
 }
 
diff --git a/tests/ui/type-alias-impl-trait/self-referential.stderr b/tests/ui/type-alias-impl-trait/self-referential.stderr
index 27506b8d06f..396237c7898 100644
--- a/tests/ui/type-alias-impl-trait/self-referential.stderr
+++ b/tests/ui/type-alias-impl-trait/self-referential.stderr
@@ -10,28 +10,28 @@ LL |     i
    = help: the trait `PartialEq<Bar<'b, 'a>>` is not implemented for `&i32`
    = help: the trait `PartialEq` is implemented for `i32`
 
-error[E0277]: can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0})`
+error[E0277]: can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0}<'a, 'b>)`
   --> $DIR/self-referential.rs:14:31
    |
 LL | fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> {
-   |                               ^^^^^^^^^^^ no implementation for `&i32 == (i32, Foo<'a, 'b>::{opaque#0})`
+   |                               ^^^^^^^^^^^ no implementation for `&i32 == (i32, Foo<'a, 'b>::{opaque#0}<'a, 'b>)`
 LL |
 LL |     (42, i)
    |     ------- return type was inferred to be `(i32, &i32)` here
    |
-   = help: the trait `PartialEq<(i32, Foo<'a, 'b>::{opaque#0})>` is not implemented for `&i32`
+   = help: the trait `PartialEq<(i32, Foo<'a, 'b>::{opaque#0}<'a, 'b>)>` is not implemented for `&i32`
    = help: the trait `PartialEq` is implemented for `i32`
 
-error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})`
+error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0}<'b, 'a>)`
   --> $DIR/self-referential.rs:21:31
    |
 LL | fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> {
-   |                               ^^^^^^^^^^^ no implementation for `&i32 == (i32, Moo<'b, 'a>::{opaque#0})`
+   |                               ^^^^^^^^^^^ no implementation for `&i32 == (i32, Moo<'b, 'a>::{opaque#0}<'b, 'a>)`
 LL |
 LL |     (42, i)
    |     ------- return type was inferred to be `(i32, &i32)` here
    |
-   = help: the trait `PartialEq<(i32, Moo<'b, 'a>::{opaque#0})>` is not implemented for `&i32`
+   = help: the trait `PartialEq<(i32, Moo<'b, 'a>::{opaque#0}<'b, 'a>)>` is not implemented for `&i32`
    = help: the trait `PartialEq` is implemented for `i32`
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs
index 296a3f3e300..b232097fdb3 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.rs
@@ -12,6 +12,7 @@ impl<'a, I: Iterator<Item = i32>> Trait for (i32, I) {
     type Associated = (i32, impl Iterator<Item = i32>);
     fn into(self) -> Self::Associated {
         (0_i32, [0_i32].iter().copied())
+        //~^ ERROR: expected generic lifetime parameter, found `'_`
     }
 }
 
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr
index cff2695304a..5f9c56f1ca9 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-unconstrained-lifetime.stderr
@@ -4,6 +4,16 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
 LL | impl<'a, I: Iterator<Item = i32>> Trait for (i32, I) {
    |      ^^ unconstrained lifetime parameter
 
-error: aborting due to 1 previous error
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/type-alias-impl-trait-unconstrained-lifetime.rs:14:9
+   |
+LL | impl<'a, I: Iterator<Item = i32>> Trait for (i32, I) {
+   |      -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |         (0_i32, [0_i32].iter().copied())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-For more information about this error, try `rustc --explain E0207`.
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0207, E0792.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/type-alias-impl-trait/variance.rs b/tests/ui/type-alias-impl-trait/variance.rs
index e92cf2513e7..4b9fa67fd64 100644
--- a/tests/ui/type-alias-impl-trait/variance.rs
+++ b/tests/ui/type-alias-impl-trait/variance.rs
@@ -5,17 +5,22 @@
 trait Captures<'a> {}
 impl<T> Captures<'_> for T {}
 
-type NotCapturedEarly<'a> = impl Sized; //~ [o]
+type NotCapturedEarly<'a> = impl Sized; //~ [*, o]
+//~^ ERROR: unconstrained opaque type
 
-type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ [o]
+type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ [*, o]
+//~^ ERROR: unconstrained opaque type
 
-// TAIT does *not* capture `'b`
-type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; //~ [o]
+type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; //~ [*, o, o]
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
+//~| ERROR: unconstrained opaque type
 
-// TAIT does *not* capture `'b`
-type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; //~ [o]
+type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; //~ [*, o, o]
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
+//~| ERROR: unconstrained opaque type
 
-type Bar<'a, 'b: 'b, T> = impl Sized; //~ ERROR [o, o, o]
+type Bar<'a, 'b: 'b, T> = impl Sized; //~ ERROR [*, *, o, o, o]
+//~^ ERROR: unconstrained opaque type
 
 trait Foo<'i> {
     type ImplicitCapture<'a>;
@@ -26,19 +31,25 @@ trait Foo<'i> {
 }
 
 impl<'i> Foo<'i> for &'i () {
-    type ImplicitCapture<'a> = impl Sized; //~ [o, o]
+    type ImplicitCapture<'a> = impl Sized; //~ [*, *, o, o]
+    //~^ ERROR: unconstrained opaque type
 
-    type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [o, o]
+    type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [*, *, o, o]
+    //~^ ERROR: unconstrained opaque type
 
-    type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [o, o]
+    type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [*, *, o, o]
+    //~^ ERROR: unconstrained opaque type
 }
 
 impl<'i> Foo<'i> for () {
-    type ImplicitCapture<'a> = impl Sized; //~ [o, o]
+    type ImplicitCapture<'a> = impl Sized; //~ [*, *, o, o]
+    //~^ ERROR: unconstrained opaque type
 
-    type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [o, o]
+    type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ [*, *, o, o]
+    //~^ ERROR: unconstrained opaque type
 
-    type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [o, o]
+    type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ [*, *, o, o]
+    //~^ ERROR: unconstrained opaque type
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/variance.stderr b/tests/ui/type-alias-impl-trait/variance.stderr
index 1794447c89a..1aaf36223b7 100644
--- a/tests/ui/type-alias-impl-trait/variance.stderr
+++ b/tests/ui/type-alias-impl-trait/variance.stderr
@@ -1,68 +1,181 @@
-error: [o]
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
+  --> $DIR/variance.rs:14:56
+   |
+LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
+   |                                                        ^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope
+   |
+note: lifetime declared here
+  --> $DIR/variance.rs:14:36
+   |
+LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
+   |                                    ^^
+
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
+  --> $DIR/variance.rs:18:49
+   |
+LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>;
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope
+   |
+note: lifetime declared here
+  --> $DIR/variance.rs:18:29
+   |
+LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>;
+   |                             ^^
+
+error: unconstrained opaque type
+  --> $DIR/variance.rs:8:29
+   |
+LL | type NotCapturedEarly<'a> = impl Sized;
+   |                             ^^^^^^^^^^
+   |
+   = note: `NotCapturedEarly` must be used in combination with a concrete type within the same module
+
+error: unconstrained opaque type
+  --> $DIR/variance.rs:11:26
+   |
+LL | type CapturedEarly<'a> = impl Sized + Captures<'a>;
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `CapturedEarly` must be used in combination with a concrete type within the same module
+
+error: unconstrained opaque type
+  --> $DIR/variance.rs:14:56
+   |
+LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
+   |                                                        ^^^^^^^^^^
+   |
+   = note: `NotCapturedLate` must be used in combination with a concrete type within the same module
+
+error: unconstrained opaque type
+  --> $DIR/variance.rs:18:49
+   |
+LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>;
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Captured` must be used in combination with a concrete type within the same module
+
+error: unconstrained opaque type
+  --> $DIR/variance.rs:22:27
+   |
+LL | type Bar<'a, 'b: 'b, T> = impl Sized;
+   |                           ^^^^^^^^^^
+   |
+   = note: `Bar` must be used in combination with a concrete type within the same module
+
+error: unconstrained opaque type
+  --> $DIR/variance.rs:34:32
+   |
+LL |     type ImplicitCapture<'a> = impl Sized;
+   |                                ^^^^^^^^^^
+   |
+   = note: `ImplicitCapture` must be used in combination with a concrete type within the same impl
+
+error: unconstrained opaque type
+  --> $DIR/variance.rs:37:42
+   |
+LL |     type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `ExplicitCaptureFromHeader` must be used in combination with a concrete type within the same impl
+
+error: unconstrained opaque type
+  --> $DIR/variance.rs:40:39
+   |
+LL |     type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `ExplicitCaptureFromGat` must be used in combination with a concrete type within the same impl
+
+error: unconstrained opaque type
+  --> $DIR/variance.rs:45:32
+   |
+LL |     type ImplicitCapture<'a> = impl Sized;
+   |                                ^^^^^^^^^^
+   |
+   = note: `ImplicitCapture` must be used in combination with a concrete type within the same impl
+
+error: unconstrained opaque type
+  --> $DIR/variance.rs:48:42
+   |
+LL |     type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `ExplicitCaptureFromHeader` must be used in combination with a concrete type within the same impl
+
+error: unconstrained opaque type
+  --> $DIR/variance.rs:51:39
+   |
+LL |     type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `ExplicitCaptureFromGat` must be used in combination with a concrete type within the same impl
+
+error: [*, o]
   --> $DIR/variance.rs:8:29
    |
 LL | type NotCapturedEarly<'a> = impl Sized;
    |                             ^^^^^^^^^^
 
-error: [o]
-  --> $DIR/variance.rs:10:26
+error: [*, o]
+  --> $DIR/variance.rs:11:26
    |
 LL | type CapturedEarly<'a> = impl Sized + Captures<'a>;
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: [o]
-  --> $DIR/variance.rs:13:56
+error: [*, o, o]
+  --> $DIR/variance.rs:14:56
    |
 LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
    |                                                        ^^^^^^^^^^
 
-error: [o]
-  --> $DIR/variance.rs:16:49
+error: [*, o, o]
+  --> $DIR/variance.rs:18:49
    |
 LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>;
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: [o, o, o]
-  --> $DIR/variance.rs:18:27
+error: [*, *, o, o, o]
+  --> $DIR/variance.rs:22:27
    |
 LL | type Bar<'a, 'b: 'b, T> = impl Sized;
    |                           ^^^^^^^^^^
 
-error: [o, o]
-  --> $DIR/variance.rs:29:32
+error: [*, *, o, o]
+  --> $DIR/variance.rs:34:32
    |
 LL |     type ImplicitCapture<'a> = impl Sized;
    |                                ^^^^^^^^^^
 
-error: [o, o]
-  --> $DIR/variance.rs:31:42
+error: [*, *, o, o]
+  --> $DIR/variance.rs:37:42
    |
 LL |     type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: [o, o]
-  --> $DIR/variance.rs:33:39
+error: [*, *, o, o]
+  --> $DIR/variance.rs:40:39
    |
 LL |     type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: [o, o]
-  --> $DIR/variance.rs:37:32
+error: [*, *, o, o]
+  --> $DIR/variance.rs:45:32
    |
 LL |     type ImplicitCapture<'a> = impl Sized;
    |                                ^^^^^^^^^^
 
-error: [o, o]
-  --> $DIR/variance.rs:39:42
+error: [*, *, o, o]
+  --> $DIR/variance.rs:48:42
    |
 LL |     type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: [o, o]
-  --> $DIR/variance.rs:41:39
+error: [*, *, o, o]
+  --> $DIR/variance.rs:51:39
    |
 LL |     type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 11 previous errors
+error: aborting due to 24 previous errors
 
+For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/type-alias-impl-trait/wf-check-definition-site.rs b/tests/ui/type-alias-impl-trait/wf-check-definition-site.rs
new file mode 100644
index 00000000000..19dd4c17936
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/wf-check-definition-site.rs
@@ -0,0 +1,40 @@
+//@ check-pass
+
+// Regression test for #114572, We were inferring an ill-formed type:
+//
+// `Opaque<'a> = Static<&'a str>`, vs
+// `Opaque<'a> = Static<&'static str>`.
+//
+// The hidden type of the opaque ends up as `Static<'?0 str>`. When
+// computing member constraints we end up choosing `'a` for `?0` unless
+// `?0` is already required to outlive `'a`. We achieve this by checking
+// that `Static<'?0 str>` is well-formed.
+#![feature(type_alias_impl_trait)]
+
+struct Static<T: 'static>(T);
+
+type OpaqueRet<'a> = impl Sized + 'a;
+fn test_return<'a>(msg: Static<&'static u8>) -> OpaqueRet<'a> {
+    msg
+}
+
+fn test_rpit<'a>(msg: Static<&'static u8>) -> impl Sized + 'a {
+    msg
+}
+
+type OpaqueAssign<'a> = impl Sized + 'a;
+fn test_assign<'a>(msg: Static<&'static u8>) -> Option<OpaqueAssign<'a>> {
+    let _: OpaqueAssign<'a> = msg;
+    None
+}
+
+// `OpaqueRef<'a, T> = Ref<'a, T>`, vs
+// `OpaqueRef<'a, T> = Ref<'static, T>`.
+trait RefAt<'a>: 'a {}
+struct Ref<'a, T: RefAt<'a>>(&'a T);
+type OpaqueRef<'a, T: RefAt<'static>> = impl Sized + 'a;
+fn test_trait<'a, T: RefAt<'static>>(msg: Ref<'static, T>) -> OpaqueRef<'a, T> {
+    msg
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr b/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr
index 17c1f8897bf..79b726f83dd 100644
--- a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr
+++ b/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr
@@ -1,21 +1,16 @@
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/wf-nested.rs:57:27
+  --> $DIR/wf-nested.rs:64:38
    |
-LL |     type InnerOpaque<T> = impl Sized;
-   |                           ^^^^^^^^^^
-   |                           |
-   |                           the parameter type `T` must be valid for the static lifetime...
-   |                           ...so that the type `T` will meet its required lifetime bounds...
+LL |     fn define<T>() -> OuterOpaque<T> {}
+   |                                      ^^
+   |                                      |
+   |                                      the parameter type `T` must be valid for the static lifetime...
+   |                                      ...so that the type `T` will meet its required lifetime bounds
    |
-note: ...that is required by this bound
-  --> $DIR/wf-nested.rs:12:20
-   |
-LL | struct IsStatic<T: 'static>(T);
-   |                    ^^^^^^^
 help: consider adding an explicit lifetime bound
    |
-LL |     type InnerOpaque<T: 'static> = impl Sized;
-   |                       +++++++++
+LL |     fn define<T: 'static>() -> OuterOpaque<T> {}
+   |                +++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/wf-nested.pass.stderr b/tests/ui/type-alias-impl-trait/wf-nested.pass.stderr
new file mode 100644
index 00000000000..b61b69d8e40
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/wf-nested.pass.stderr
@@ -0,0 +1,31 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/wf-nested.rs:34:38
+   |
+LL |     fn define<T>() -> OuterOpaque<T> {}
+   |                                      ^^
+   |                                      |
+   |                                      the parameter type `T` must be valid for the static lifetime...
+   |                                      ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL |     fn define<T: 'static>() -> OuterOpaque<T> {}
+   |                +++++++++
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/wf-nested.rs:37:69
+   |
+LL |     fn define_rpit<T>() -> impl Trait<&'static T, Out = impl Sized> {}
+   |                                                                     ^^
+   |                                                                     |
+   |                                                                     the parameter type `T` must be valid for the static lifetime...
+   |                                                                     ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL |     fn define_rpit<T: 'static>() -> impl Trait<&'static T, Out = impl Sized> {}
+   |                     +++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr b/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr
index f5d3a218542..dbd3a1394f8 100644
--- a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr
+++ b/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr
@@ -1,5 +1,19 @@
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/wf-nested.rs:46:17
+  --> $DIR/wf-nested.rs:46:38
+   |
+LL |     fn define<T>() -> OuterOpaque<T> {}
+   |                                      ^^
+   |                                      |
+   |                                      the parameter type `T` must be valid for the static lifetime...
+   |                                      ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL |     fn define<T: 'static>() -> OuterOpaque<T> {}
+   |                +++++++++
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/wf-nested.rs:51:17
    |
 LL |         let _ = outer.get();
    |                 ^^^^^^^^^^^
@@ -13,7 +27,7 @@ LL |     fn test<T: 'static>() {
    |              +++++++++
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/wf-nested.rs:46:17
+  --> $DIR/wf-nested.rs:51:17
    |
 LL |         let _ = outer.get();
    |                 ^^^^^^^^^^^
@@ -27,6 +41,6 @@ help: consider adding an explicit lifetime bound
 LL |     fn test<T: 'static>() {
    |              +++++++++
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0310`.
diff --git a/tests/ui/type-alias-impl-trait/wf-nested.rs b/tests/ui/type-alias-impl-trait/wf-nested.rs
index 1fc93a3cd27..56c524c6db0 100644
--- a/tests/ui/type-alias-impl-trait/wf-nested.rs
+++ b/tests/ui/type-alias-impl-trait/wf-nested.rs
@@ -1,12 +1,8 @@
 // Well-formedness of nested opaque types, i.e. `impl Sized` in
-// `type Outer = impl Trait<Assoc = impl Sized>`.
-// See the comments below.
-//
-//@ revisions: pass pass_sound fail
-//@ [pass] check-pass
-//@ [pass_sound] check-fail
-//@ [fail] check-fail
-
+// `type Outer = impl Trait<Assoc = impl Sized>`. We check that
+// the nested type is well-formed, even though this would also
+// be implied by the item bounds of the opaque being
+// well-formed. See the comments below.
 #![feature(type_alias_impl_trait)]
 
 struct IsStatic<T: 'static>(T);
@@ -23,40 +19,26 @@ impl<T> Trait<&'static T> for () {
     type Out = IsStatic<T>;
 }
 
-// The hidden type for `impl Sized` is `IsStatic<T>`, which requires `T: 'static`.
-// We know it is well-formed because it can *only* be referenced as a projection:
-// <OuterOpaque<T> as Trait<&'static T>>::Out`.
-// So any instantiation of the type already requires proving `T: 'static`.
-#[cfg(pass)]
-mod pass {
-    use super::*;
-    type OuterOpaque<T> = impl Trait<&'static T, Out = impl Sized>;
-    fn define<T>() -> OuterOpaque<T> {}
-}
 
-// Test the soundness of `pass` - We should require `T: 'static` at the use site.
-#[cfg(pass_sound)]
-mod pass_sound {
-    use super::*;
-    type OuterOpaque<T> = impl Trait<&'static T, Out = impl Sized>;
-    fn define<T>() -> OuterOpaque<T> {}
+// We could theoretically allow this (and previously did), as even
+// though the nested opaque is not well-formed, it can only be
+// used by normalizing the projection
+//    <OuterOpaque1<T> as Trait<&'static T>>::Out
+// Assuming that we check that this projection is well-formed, the wf
+// of the nested opaque is implied.
+type OuterOpaque1<T> = impl Trait<&'static T, Out = impl Sized>;
+fn define<T>() -> OuterOpaque1<T> {}
+//~^ ERROR `T` may not live long enough
 
-    fn test<T>() {
-        let outer = define::<T>();
-        let _ = outer.get();
-        //[pass_sound]~^ ERROR `T` may not live long enough
-        //[pass_sound]~| ERROR `T` may not live long enough
-    }
-}
+fn define_rpit<T>() -> impl Trait<&'static T, Out = impl Sized> {}
+//~^ ERROR the parameter type `T` may not live long enough
 
-// Similar to `pass` but here `impl Sized` can be referenced directly as
-// InnerOpaque<T>, so we require an explicit bound `T: 'static`.
-#[cfg(fail)]
-mod fail {
-    use super::*;
-    type InnerOpaque<T> = impl Sized; //[fail]~ ERROR `T` may not live long enough
-    type OuterOpaque<T> = impl Trait<&'static T, Out = InnerOpaque<T>>;
-    fn define<T>() -> OuterOpaque<T> {}
-}
+// Similar to `define` but here `impl Sized` can be referenced directly as
+// InnerOpaque<T>, so the `'static` bound is definitely required for
+// soundness.
+type InnerOpaque<T> = impl Sized;
+type OuterOpaque2<T> = impl Trait<&'static T, Out = InnerOpaque<T>>;
+fn define_nested_rpit<T>() -> OuterOpaque2<T> {}
+//~^ ERROR the parameter type `T` may not live long enough
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/wf-nested.stderr b/tests/ui/type-alias-impl-trait/wf-nested.stderr
new file mode 100644
index 00000000000..6d50e11c5da
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/wf-nested.stderr
@@ -0,0 +1,45 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/wf-nested.rs:30:35
+   |
+LL | fn define<T>() -> OuterOpaque1<T> {}
+   |                                   ^^
+   |                                   |
+   |                                   the parameter type `T` must be valid for the static lifetime...
+   |                                   ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | fn define<T: 'static>() -> OuterOpaque1<T> {}
+   |            +++++++++
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/wf-nested.rs:33:65
+   |
+LL | fn define_rpit<T>() -> impl Trait<&'static T, Out = impl Sized> {}
+   |                                                                 ^^
+   |                                                                 |
+   |                                                                 the parameter type `T` must be valid for the static lifetime...
+   |                                                                 ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | fn define_rpit<T: 'static>() -> impl Trait<&'static T, Out = impl Sized> {}
+   |                 +++++++++
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/wf-nested.rs:41:47
+   |
+LL | fn define_nested_rpit<T>() -> OuterOpaque2<T> {}
+   |                                               ^^
+   |                                               |
+   |                                               the parameter type `T` must be valid for the static lifetime...
+   |                                               ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound
+   |
+LL | fn define_nested_rpit<T: 'static>() -> OuterOpaque2<T> {}
+   |                        +++++++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/tests/ui/typeck/issue-13853-5.rs b/tests/ui/typeck/issue-13853-5.rs
index 2afdf95aacf..fc97c6c67d6 100644
--- a/tests/ui/typeck/issue-13853-5.rs
+++ b/tests/ui/typeck/issue-13853-5.rs
@@ -7,6 +7,7 @@ trait Deserializable {
 impl<'a, T: Deserializable> Deserializable for &'a str {
     //~^ ERROR type parameter `T` is not constrained
     fn deserialize_token<D: Deserializer<'a>>(_x: D, _y: &'a str) -> &'a str {
+        //~^ ERROR mismatched types
     }
 }
 
diff --git a/tests/ui/typeck/issue-13853-5.stderr b/tests/ui/typeck/issue-13853-5.stderr
index 1eead956328..388d5ec746c 100644
--- a/tests/ui/typeck/issue-13853-5.stderr
+++ b/tests/ui/typeck/issue-13853-5.stderr
@@ -4,6 +4,22 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
 LL | impl<'a, T: Deserializable> Deserializable for &'a str {
    |          ^ unconstrained type parameter
 
-error: aborting due to 1 previous error
+error[E0308]: mismatched types
+  --> $DIR/issue-13853-5.rs:9:70
+   |
+LL |     fn deserialize_token<D: Deserializer<'a>>(_x: D, _y: &'a str) -> &'a str {
+   |        -----------------                                             ^^^^^^^ expected `&str`, found `()`
+   |        |
+   |        implicitly returns `()` as its body has no tail or `return` expression
+   |
+help: consider returning the local binding `_y`
+   |
+LL ~     fn deserialize_token<D: Deserializer<'a>>(_x: D, _y: &'a str) -> &'a str {
+LL +         _y
+LL ~
+   |
 
-For more information about this error, try `rustc --explain E0207`.
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0207, E0308.
+For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/typeck/type-placeholder-fn-in-const.stderr b/tests/ui/typeck/type-placeholder-fn-in-const.stderr
index 302359d2500..92b47bd4781 100644
--- a/tests/ui/typeck/type-placeholder-fn-in-const.stderr
+++ b/tests/ui/typeck/type-placeholder-fn-in-const.stderr
@@ -1,3 +1,9 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/type-placeholder-fn-in-const.rs:10:25
+   |
+LL |     const TEST: fn() -> _ = 42;
+   |                         ^ not allowed in type signatures
+
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/type-placeholder-fn-in-const.rs:4:25
    |
@@ -5,21 +11,15 @@ LL |     const TEST: fn() -> _;
    |                         ^ not allowed in type signatures
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
-  --> $DIR/type-placeholder-fn-in-const.rs:4:25
-   |
-LL |     const TEST: fn() -> _;
-   |                         ^ not allowed in type signatures
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/type-placeholder-fn-in-const.rs:10:25
    |
 LL |     const TEST: fn() -> _ = 42;
    |                         ^ not allowed in type signatures
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
-  --> $DIR/type-placeholder-fn-in-const.rs:10:25
+  --> $DIR/type-placeholder-fn-in-const.rs:4:25
    |
-LL |     const TEST: fn() -> _ = 42;
+LL |     const TEST: fn() -> _;
    |                         ^ not allowed in type signatures
 
 error: aborting due to 4 previous errors
diff --git a/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr b/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr
index 1dc1d46aa71..9a9b2a68dbe 100644
--- a/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr
+++ b/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr
@@ -24,6 +24,16 @@ LL | trait Trait: Copy<dyn Send> {}
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
+  --> $DIR/typeck-builtin-bound-type-parameters.rs:4:14
+   |
+LL | trait Trait: Copy<dyn Send> {}
+   |              ^^^^---------- help: remove these generics
+   |              |
+   |              expected 0 generic arguments
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/typeck-builtin-bound-type-parameters.rs:9:21
    |
@@ -56,16 +66,6 @@ LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
    |               |
    |               expected 0 generic arguments
 
-error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
-  --> $DIR/typeck-builtin-bound-type-parameters.rs:4:14
-   |
-LL | trait Trait: Copy<dyn Send> {}
-   |              ^^^^---------- help: remove these generics
-   |              |
-   |              expected 0 generic arguments
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
 error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr
index c102926fcf5..e8f1de1ad04 100644
--- a/tests/ui/typeck/typeck_type_placeholder_item.stderr
+++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr
@@ -169,6 +169,28 @@ LL | unsafe fn test12(x: *const usize) -> *const *const _ {
    |                                      |             not allowed in type signatures
    |                                      help: replace with the correct return type: `*const *const usize`
 
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:59:24
+   |
+LL |     fn clone(&self) -> _ { Test9 }
+   |                        ^ not allowed in type signatures
+   |
+help: try replacing `_` with the type in the corresponding trait method signature
+   |
+LL |     fn clone(&self) -> Test9 { Test9 }
+   |                        ~~~~~
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:62:37
+   |
+LL |     fn clone_from(&mut self, other: _) { *self = Test9; }
+   |                                     ^ not allowed in type signatures
+   |
+help: try replacing `_` with the type in the corresponding trait method signature
+   |
+LL |     fn clone_from(&mut self, other: &Test9) { *self = Test9; }
+   |                                     ~~~~~~
+
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
   --> $DIR/typeck_type_placeholder_item.rs:67:8
    |
@@ -294,6 +316,28 @@ help: use type parameters instead
 LL |     fn fn_test8<T>(_f: fn() -> T) { }
    |                +++             ~
 
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:115:28
+   |
+LL |         fn clone(&self) -> _ { FnTest9 }
+   |                            ^ not allowed in type signatures
+   |
+help: try replacing `_` with the type in the corresponding trait method signature
+   |
+LL |         fn clone(&self) -> FnTest9 { FnTest9 }
+   |                            ~~~~~~~
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/typeck_type_placeholder_item.rs:118:41
+   |
+LL |         fn clone_from(&mut self, other: _) { *self = FnTest9; }
+   |                                         ^ not allowed in type signatures
+   |
+help: try replacing `_` with the type in the corresponding trait method signature
+   |
+LL |         fn clone_from(&mut self, other: &FnTest9) { *self = FnTest9; }
+   |                                         ~~~~~~~~
+
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
   --> $DIR/typeck_type_placeholder_item.rs:123:12
    |
@@ -346,109 +390,6 @@ LL |     fn fn_test13(x: _) -> (i32, _) { (x, x) }
    |                           |     not allowed in type signatures
    |                           help: replace with the correct return type: `(i32, i32)`
 
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
-  --> $DIR/typeck_type_placeholder_item.rs:154:21
-   |
-LL | struct BadStruct<_>(_);
-   |                     ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL | struct BadStruct<T>(T);
-   |                  ~  ~
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for implementations
-  --> $DIR/typeck_type_placeholder_item.rs:159:15
-   |
-LL | impl BadTrait<_> for BadStruct<_> {}
-   |               ^                ^ not allowed in type signatures
-   |               |
-   |               not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL | impl<T> BadTrait<T> for BadStruct<T> {}
-   |     +++          ~                ~
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for opaque types
-  --> $DIR/typeck_type_placeholder_item.rs:162:34
-   |
-LL | fn impl_trait() -> impl BadTrait<_> {
-   |                                  ^ not allowed in type signatures
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
-  --> $DIR/typeck_type_placeholder_item.rs:167:25
-   |
-LL | struct BadStruct1<_, _>(_);
-   |                         ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL | struct BadStruct1<T, _>(T);
-   |                   ~     ~
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
-  --> $DIR/typeck_type_placeholder_item.rs:172:25
-   |
-LL | struct BadStruct2<_, T>(_, T);
-   |                         ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL | struct BadStruct2<U, T>(U, T);
-   |                   ~     ~
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases
-  --> $DIR/typeck_type_placeholder_item.rs:176:14
-   |
-LL | type X = Box<_>;
-   |              ^ not allowed in type signatures
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for opaque types
-  --> $DIR/typeck_type_placeholder_item.rs:182:21
-   |
-LL | type Y = impl Trait<_>;
-   |                     ^ not allowed in type signatures
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:217:31
-   |
-LL | fn value() -> Option<&'static _> {
-   |               ----------------^-
-   |               |               |
-   |               |               not allowed in type signatures
-   |               help: replace with the correct return type: `Option<&'static u8>`
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
-  --> $DIR/typeck_type_placeholder_item.rs:222:10
-   |
-LL | const _: Option<_> = map(value);
-   |          ^^^^^^^^^
-   |          |
-   |          not allowed in type signatures
-   |          help: replace with the correct type: `Option<u8>`
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:225:31
-   |
-LL | fn evens_squared(n: usize) -> _ {
-   |                               ^
-   |                               |
-   |                               not allowed in type signatures
-   |                               help: replace with an appropriate return type: `impl Iterator<Item = usize>`
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
-  --> $DIR/typeck_type_placeholder_item.rs:230:10
-   |
-LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
-   |          ^ not allowed in type signatures
-   |
-note: however, the inferred type `Map<Filter<Range<i32>, {closure@typeck_type_placeholder_item.rs:230:29}>, {closure@typeck_type_placeholder_item.rs:230:49}>` cannot be named
-  --> $DIR/typeck_type_placeholder_item.rs:230:14
-   |
-LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:140:31
    |
@@ -519,41 +460,69 @@ help: use type parameters instead
 LL |     fn assoc_fn_test3<T>() -> T;
    |                      +++      ~
 
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
-  --> $DIR/typeck_type_placeholder_item.rs:190:14
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
+  --> $DIR/typeck_type_placeholder_item.rs:154:21
    |
-LL |     type B = _;
+LL | struct BadStruct<_>(_);
+   |                     ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | struct BadStruct<T>(T);
+   |                  ~  ~
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for implementations
+  --> $DIR/typeck_type_placeholder_item.rs:159:15
+   |
+LL | impl BadTrait<_> for BadStruct<_> {}
+   |               ^                ^ not allowed in type signatures
+   |               |
+   |               not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | impl<T> BadTrait<T> for BadStruct<T> {}
+   |     +++          ~                ~
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for opaque types
+  --> $DIR/typeck_type_placeholder_item.rs:162:34
+   |
+LL | fn impl_trait() -> impl BadTrait<_> {
+   |                                  ^ not allowed in type signatures
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
+  --> $DIR/typeck_type_placeholder_item.rs:167:25
+   |
+LL | struct BadStruct1<_, _>(_);
+   |                         ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | struct BadStruct1<T, _>(T);
+   |                   ~     ~
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
+  --> $DIR/typeck_type_placeholder_item.rs:172:25
+   |
+LL | struct BadStruct2<_, T>(_, T);
+   |                         ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL | struct BadStruct2<U, T>(U, T);
+   |                   ~     ~
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases
+  --> $DIR/typeck_type_placeholder_item.rs:176:14
+   |
+LL | type X = Box<_>;
    |              ^ not allowed in type signatures
 
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
-  --> $DIR/typeck_type_placeholder_item.rs:192:14
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for opaque types
+  --> $DIR/typeck_type_placeholder_item.rs:182:21
    |
-LL |     const C: _;
-   |              ^ not allowed in type signatures
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
-  --> $DIR/typeck_type_placeholder_item.rs:194:14
-   |
-LL |     const D: _ = 42;
-   |              ^
-   |              |
-   |              not allowed in type signatures
-   |              help: replace with the correct type: `i32`
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
-  --> $DIR/typeck_type_placeholder_item.rs:197:26
-   |
-LL |     type F: std::ops::Fn(_);
-   |                          ^ not allowed in type signatures
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:41:24
-   |
-LL |     fn test9(&self) -> _ { () }
-   |                        ^
-   |                        |
-   |                        not allowed in type signatures
-   |                        help: replace with the correct return type: `()`
+LL | type Y = impl Trait<_>;
+   |                     ^ not allowed in type signatures
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:44:27
@@ -566,37 +535,6 @@ help: use type parameters instead
 LL |     fn test10<T>(&self, _x : T) { }
    |              +++             ~
 
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:59:24
-   |
-LL |     fn clone(&self) -> _ { Test9 }
-   |                        ^ not allowed in type signatures
-   |
-help: try replacing `_` with the type in the corresponding trait method signature
-   |
-LL |     fn clone(&self) -> Test9 { Test9 }
-   |                        ~~~~~
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:62:37
-   |
-LL |     fn clone_from(&mut self, other: _) { *self = Test9; }
-   |                                     ^ not allowed in type signatures
-   |
-help: try replacing `_` with the type in the corresponding trait method signature
-   |
-LL |     fn clone_from(&mut self, other: &Test9) { *self = Test9; }
-   |                                     ~~~~~~
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:107:31
-   |
-LL |         fn fn_test9(&self) -> _ { () }
-   |                               ^
-   |                               |
-   |                               not allowed in type signatures
-   |                               help: replace with the correct return type: `()`
-
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/typeck_type_placeholder_item.rs:110:34
    |
@@ -608,39 +546,23 @@ help: use type parameters instead
 LL |         fn fn_test10<T>(&self, _x : T) { }
    |                     +++             ~
 
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:115:28
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:217:31
    |
-LL |         fn clone(&self) -> _ { FnTest9 }
-   |                            ^ not allowed in type signatures
-   |
-help: try replacing `_` with the type in the corresponding trait method signature
-   |
-LL |         fn clone(&self) -> FnTest9 { FnTest9 }
-   |                            ~~~~~~~
+LL | fn value() -> Option<&'static _> {
+   |               ----------------^-
+   |               |               |
+   |               |               not allowed in type signatures
+   |               help: replace with the correct return type: `Option<&'static u8>`
 
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:118:41
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/typeck_type_placeholder_item.rs:222:10
    |
-LL |         fn clone_from(&mut self, other: _) { *self = FnTest9; }
-   |                                         ^ not allowed in type signatures
-   |
-help: try replacing `_` with the type in the corresponding trait method signature
-   |
-LL |         fn clone_from(&mut self, other: &FnTest9) { *self = FnTest9; }
-   |                                         ~~~~~~~~
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
-  --> $DIR/typeck_type_placeholder_item.rs:202:14
-   |
-LL |     type A = _;
-   |              ^ not allowed in type signatures
-
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
-  --> $DIR/typeck_type_placeholder_item.rs:204:14
-   |
-LL |     type B = _;
-   |              ^ not allowed in type signatures
+LL | const _: Option<_> = map(value);
+   |          ^^^^^^^^^
+   |          |
+   |          not allowed in type signatures
+   |          help: replace with the correct type: `Option<u8>`
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
   --> $DIR/typeck_type_placeholder_item.rs:206:14
@@ -657,6 +579,15 @@ LL |     const D: _ = 42;
    |              not allowed in type signatures
    |              help: replace with the correct type: `i32`
 
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
+  --> $DIR/typeck_type_placeholder_item.rs:194:14
+   |
+LL |     const D: _ = 42;
+   |              ^
+   |              |
+   |              not allowed in type signatures
+   |              help: replace with the correct type: `i32`
+
 error[E0046]: not all trait items implemented, missing: `F`
   --> $DIR/typeck_type_placeholder_item.rs:200:1
    |
@@ -666,6 +597,75 @@ LL |     type F: std::ops::Fn(_);
 LL | impl Qux for Struct {
    | ^^^^^^^^^^^^^^^^^^^ missing `F` in implementation
 
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:225:31
+   |
+LL | fn evens_squared(n: usize) -> _ {
+   |                               ^
+   |                               |
+   |                               not allowed in type signatures
+   |                               help: replace with an appropriate return type: `impl Iterator<Item = usize>`
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
+  --> $DIR/typeck_type_placeholder_item.rs:230:10
+   |
+LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
+   |          ^ not allowed in type signatures
+   |
+note: however, the inferred type `Map<Filter<Range<i32>, {closure@typeck_type_placeholder_item.rs:230:29}>, {closure@typeck_type_placeholder_item.rs:230:49}>` cannot be named
+  --> $DIR/typeck_type_placeholder_item.rs:230:14
+   |
+LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:41:24
+   |
+LL |     fn test9(&self) -> _ { () }
+   |                        ^
+   |                        |
+   |                        not allowed in type signatures
+   |                        help: replace with the correct return type: `()`
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/typeck_type_placeholder_item.rs:107:31
+   |
+LL |         fn fn_test9(&self) -> _ { () }
+   |                               ^
+   |                               |
+   |                               not allowed in type signatures
+   |                               help: replace with the correct return type: `()`
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
+  --> $DIR/typeck_type_placeholder_item.rs:202:14
+   |
+LL |     type A = _;
+   |              ^ not allowed in type signatures
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
+  --> $DIR/typeck_type_placeholder_item.rs:204:14
+   |
+LL |     type B = _;
+   |              ^ not allowed in type signatures
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
+  --> $DIR/typeck_type_placeholder_item.rs:190:14
+   |
+LL |     type B = _;
+   |              ^ not allowed in type signatures
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
+  --> $DIR/typeck_type_placeholder_item.rs:192:14
+   |
+LL |     const C: _;
+   |              ^ not allowed in type signatures
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
+  --> $DIR/typeck_type_placeholder_item.rs:197:26
+   |
+LL |     type F: std::ops::Fn(_);
+   |                          ^ not allowed in type signatures
+
 error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::filter::<{closure@$DIR/typeck_type_placeholder_item.rs:230:29: 230:32}>` in constants
   --> $DIR/typeck_type_placeholder_item.rs:230:22
    |
diff --git a/tests/ui/typeck/typeck_type_placeholder_item_help.stderr b/tests/ui/typeck/typeck_type_placeholder_item_help.stderr
index b0d4ed8272b..32585e2937b 100644
--- a/tests/ui/typeck/typeck_type_placeholder_item_help.stderr
+++ b/tests/ui/typeck/typeck_type_placeholder_item_help.stderr
@@ -38,18 +38,18 @@ LL | const TEST4: fn() -> _ = 42;
    |                      ^ not allowed in type signatures
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
-  --> $DIR/typeck_type_placeholder_item_help.rs:18:18
+  --> $DIR/typeck_type_placeholder_item_help.rs:25:18
    |
-LL |     const TEST5: _ = 42;
+LL |     const TEST6: _ = 13;
    |                  ^
    |                  |
    |                  not allowed in type signatures
    |                  help: replace with the correct type: `i32`
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
-  --> $DIR/typeck_type_placeholder_item_help.rs:25:18
+  --> $DIR/typeck_type_placeholder_item_help.rs:18:18
    |
-LL |     const TEST6: _ = 13;
+LL |     const TEST5: _ = 42;
    |                  ^
    |                  |
    |                  not allowed in type signatures
diff --git a/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.rs b/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.rs
new file mode 100644
index 00000000000..5d15ec4cffd
--- /dev/null
+++ b/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.rs
@@ -0,0 +1,25 @@
+type NodeId = u32;
+struct Type<'a>(std::marker::PhantomData::<&'a ()>);
+
+type Ast<'ast> = &'ast AstStructure<'ast>;
+
+struct AstStructure<'ast> {
+//~^ ERROR struct with unnamed fields must have `#[repr(C)]` representation
+    id: NodeId,
+    _: AstKind<'ast>
+//~^ ERROR unnamed fields are not yet fully implemented [E0658]
+//~^^ ERROR unnamed fields can only have struct or union types
+}
+
+enum AstKind<'ast> {
+    ExprInt,
+    ExprLambda(Ast<'ast>),
+}
+
+fn compute_types<'tcx,'ast>(ast: Ast<'ast>) -> Type<'tcx>
+{
+    match ast.kind {}
+//~^ ERROR no field `kind` on type `&'ast AstStructure<'ast>` [E0609]
+}
+
+fn main() {}
diff --git a/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.stderr b/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.stderr
new file mode 100644
index 00000000000..4ea910202de
--- /dev/null
+++ b/tests/ui/union/unnamed-fields/unnamed-enum-field-issue-121757.stderr
@@ -0,0 +1,45 @@
+error[E0658]: unnamed fields are not yet fully implemented
+  --> $DIR/unnamed-enum-field-issue-121757.rs:9:5
+   |
+LL |     _: AstKind<'ast>
+   |     ^
+   |
+   = note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
+   = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: struct with unnamed fields must have `#[repr(C)]` representation
+  --> $DIR/unnamed-enum-field-issue-121757.rs:6:1
+   |
+LL | struct AstStructure<'ast> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ struct `AstStructure` defined here
+   |
+note: unnamed field defined here
+  --> $DIR/unnamed-enum-field-issue-121757.rs:9:5
+   |
+LL |     _: AstKind<'ast>
+   |     ^^^^^^^^^^^^^^^^
+help: add `#[repr(C)]` to this struct
+   |
+LL + #[repr(C)]
+LL | struct AstStructure<'ast> {
+   |
+
+error: unnamed fields can only have struct or union types
+  --> $DIR/unnamed-enum-field-issue-121757.rs:9:5
+   |
+LL |     _: AstKind<'ast>
+   |     ^^^^^^^^^^^^^^^^
+
+error[E0609]: no field `kind` on type `&'ast AstStructure<'ast>`
+  --> $DIR/unnamed-enum-field-issue-121757.rs:21:15
+   |
+LL |     match ast.kind {}
+   |               ^^^^ unknown field
+   |
+   = note: available fields are: `id`, `_`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0609, E0658.
+For more information about an error, try `rustc --explain E0609`.
diff --git a/tests/ui/variance/variance-associated-consts.rs b/tests/ui/variance/variance-associated-consts.rs
index da55bc96244..6a44a94df3f 100644
--- a/tests/ui/variance/variance-associated-consts.rs
+++ b/tests/ui/variance/variance-associated-consts.rs
@@ -12,6 +12,7 @@ trait Trait {
 #[rustc_variance]
 struct Foo<T: Trait> { //~ ERROR [o]
     field: [u8; <T as Trait>::Const]
+    //~^ ERROR: unconstrained generic constant
 }
 
 fn main() { }
diff --git a/tests/ui/variance/variance-associated-consts.stderr b/tests/ui/variance/variance-associated-consts.stderr
index e25f0879add..f41574ca3a3 100644
--- a/tests/ui/variance/variance-associated-consts.stderr
+++ b/tests/ui/variance/variance-associated-consts.stderr
@@ -1,8 +1,16 @@
+error: unconstrained generic constant
+  --> $DIR/variance-associated-consts.rs:14:12
+   |
+LL |     field: [u8; <T as Trait>::Const]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); <T as Trait>::Const]:`
+
 error: [o]
   --> $DIR/variance-associated-consts.rs:13:1
    |
 LL | struct Foo<T: Trait> {
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/variance/variance-regions-direct.rs b/tests/ui/variance/variance-regions-direct.rs
index 39ea77a8aa2..f1763c403f1 100644
--- a/tests/ui/variance/variance-regions-direct.rs
+++ b/tests/ui/variance/variance-regions-direct.rs
@@ -50,6 +50,7 @@ struct Test6<'a, 'b:'a> { //~ ERROR [+, o]
 
 #[rustc_variance]
 struct Test7<'a> { //~ ERROR [*]
+    //~^ ERROR: `'a` is never used
     x: isize
 }
 
diff --git a/tests/ui/variance/variance-regions-direct.stderr b/tests/ui/variance/variance-regions-direct.stderr
index c55730296f1..edfc888f656 100644
--- a/tests/ui/variance/variance-regions-direct.stderr
+++ b/tests/ui/variance/variance-regions-direct.stderr
@@ -1,3 +1,11 @@
+error[E0392]: lifetime parameter `'a` is never used
+  --> $DIR/variance-regions-direct.rs:52:14
+   |
+LL | struct Test7<'a> {
+   |              ^^ unused lifetime parameter
+   |
+   = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
+
 error: [+, +, +]
   --> $DIR/variance-regions-direct.rs:9:1
    |
@@ -35,10 +43,11 @@ LL | struct Test7<'a> {
    | ^^^^^^^^^^^^^^^^
 
 error: [-, +, o]
-  --> $DIR/variance-regions-direct.rs:59:1
+  --> $DIR/variance-regions-direct.rs:60:1
    |
 LL | enum Test8<'a, 'b, 'c:'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
+For more information about this error, try `rustc --explain E0392`.
diff --git a/tests/ui/variance/variance-regions-indirect.rs b/tests/ui/variance/variance-regions-indirect.rs
index 0d00535fef1..31e25641d8c 100644
--- a/tests/ui/variance/variance-regions-indirect.rs
+++ b/tests/ui/variance/variance-regions-indirect.rs
@@ -6,6 +6,7 @@
 
 #[rustc_variance]
 enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [-, +, o, *]
+    //~^ ERROR: `'d` is never used
     Test8A(extern "Rust" fn(&'a isize)),
     Test8B(&'b [isize]),
     Test8C(&'b mut &'c str),
@@ -13,16 +14,19 @@ enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [-, +, o, *]
 
 #[rustc_variance]
 struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR [*, o, +, -]
+    //~^ ERROR: `'w` is never used
     f: Base<'z, 'y, 'x, 'w>
 }
 
 #[rustc_variance] // Combine - and + to yield o
 struct Derived2<'a, 'b:'a, 'c> { //~ ERROR [o, o, *]
+    //~^ ERROR: `'c` is never used
     f: Base<'a, 'a, 'b, 'c>
 }
 
 #[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here)
 struct Derived3<'a:'b, 'b, 'c> { //~ ERROR [o, +, *]
+    //~^ ERROR: `'c` is never used
     f: Base<'a, 'b, 'a, 'c>
 }
 
diff --git a/tests/ui/variance/variance-regions-indirect.stderr b/tests/ui/variance/variance-regions-indirect.stderr
index edf2626d598..901ec0c6a76 100644
--- a/tests/ui/variance/variance-regions-indirect.stderr
+++ b/tests/ui/variance/variance-regions-indirect.stderr
@@ -1,3 +1,35 @@
+error[E0392]: lifetime parameter `'d` is never used
+  --> $DIR/variance-regions-indirect.rs:8:26
+   |
+LL | enum Base<'a, 'b, 'c:'b, 'd> {
+   |                          ^^ unused lifetime parameter
+   |
+   = help: consider removing `'d`, referring to it in a field, or using a marker such as `PhantomData`
+
+error[E0392]: lifetime parameter `'w` is never used
+  --> $DIR/variance-regions-indirect.rs:16:17
+   |
+LL | struct Derived1<'w, 'x:'y, 'y, 'z> {
+   |                 ^^ unused lifetime parameter
+   |
+   = help: consider removing `'w`, referring to it in a field, or using a marker such as `PhantomData`
+
+error[E0392]: lifetime parameter `'c` is never used
+  --> $DIR/variance-regions-indirect.rs:22:28
+   |
+LL | struct Derived2<'a, 'b:'a, 'c> {
+   |                            ^^ unused lifetime parameter
+   |
+   = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData`
+
+error[E0392]: lifetime parameter `'c` is never used
+  --> $DIR/variance-regions-indirect.rs:28:28
+   |
+LL | struct Derived3<'a:'b, 'b, 'c> {
+   |                            ^^ unused lifetime parameter
+   |
+   = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData`
+
 error: [-, +, o, *]
   --> $DIR/variance-regions-indirect.rs:8:1
    |
@@ -5,28 +37,29 @@ LL | enum Base<'a, 'b, 'c:'b, 'd> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: [*, o, +, -]
-  --> $DIR/variance-regions-indirect.rs:15:1
+  --> $DIR/variance-regions-indirect.rs:16:1
    |
 LL | struct Derived1<'w, 'x:'y, 'y, 'z> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: [o, o, *]
-  --> $DIR/variance-regions-indirect.rs:20:1
+  --> $DIR/variance-regions-indirect.rs:22:1
    |
 LL | struct Derived2<'a, 'b:'a, 'c> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: [o, +, *]
-  --> $DIR/variance-regions-indirect.rs:25:1
+  --> $DIR/variance-regions-indirect.rs:28:1
    |
 LL | struct Derived3<'a:'b, 'b, 'c> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: [-, +, o]
-  --> $DIR/variance-regions-indirect.rs:30:1
+  --> $DIR/variance-regions-indirect.rs:34:1
    |
 LL | struct Derived4<'a, 'b, 'c:'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 5 previous errors
+error: aborting due to 9 previous errors
 
+For more information about this error, try `rustc --explain E0392`.
diff --git a/tests/ui/variance/variance-trait-bounds.rs b/tests/ui/variance/variance-trait-bounds.rs
index ad5334602a2..25a01b160dd 100644
--- a/tests/ui/variance/variance-trait-bounds.rs
+++ b/tests/ui/variance/variance-trait-bounds.rs
@@ -19,16 +19,19 @@ struct TestStruct<U,T:Setter<U>> { //~ ERROR [+, +]
 
 #[rustc_variance]
 enum TestEnum<U,T:Setter<U>> { //~ ERROR [*, +]
+    //~^ ERROR: `U` is never used
     Foo(T)
 }
 
 #[rustc_variance]
 struct TestContraStruct<U,T:Setter<U>> { //~ ERROR [*, +]
+    //~^ ERROR: `U` is never used
     t: T
 }
 
 #[rustc_variance]
 struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR [*, +]
+    //~^ ERROR: `U` is never used
     t: T
 }
 
diff --git a/tests/ui/variance/variance-trait-bounds.stderr b/tests/ui/variance/variance-trait-bounds.stderr
index 5a73e541c3a..95ed18c1ad2 100644
--- a/tests/ui/variance/variance-trait-bounds.stderr
+++ b/tests/ui/variance/variance-trait-bounds.stderr
@@ -1,3 +1,30 @@
+error[E0392]: type parameter `U` is never used
+  --> $DIR/variance-trait-bounds.rs:21:15
+   |
+LL | enum TestEnum<U,T:Setter<U>> {
+   |               ^ unused type parameter
+   |
+   = help: consider removing `U`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `U` to be a const parameter, use `const U: /* Type */` instead
+
+error[E0392]: type parameter `U` is never used
+  --> $DIR/variance-trait-bounds.rs:27:25
+   |
+LL | struct TestContraStruct<U,T:Setter<U>> {
+   |                         ^ unused type parameter
+   |
+   = help: consider removing `U`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `U` to be a const parameter, use `const U: /* Type */` instead
+
+error[E0392]: type parameter `U` is never used
+  --> $DIR/variance-trait-bounds.rs:33:16
+   |
+LL | struct TestBox<U,T:Getter<U>+Setter<U>> {
+   |                ^ unused type parameter
+   |
+   = help: consider removing `U`, referring to it in a field, or using a marker such as `PhantomData`
+   = help: if you intended `U` to be a const parameter, use `const U: /* Type */` instead
+
 error: [+, +]
   --> $DIR/variance-trait-bounds.rs:16:1
    |
@@ -11,16 +38,17 @@ LL | enum TestEnum<U,T:Setter<U>> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: [*, +]
-  --> $DIR/variance-trait-bounds.rs:26:1
+  --> $DIR/variance-trait-bounds.rs:27:1
    |
 LL | struct TestContraStruct<U,T:Setter<U>> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: [*, +]
-  --> $DIR/variance-trait-bounds.rs:31:1
+  --> $DIR/variance-trait-bounds.rs:33:1
    |
 LL | struct TestBox<U,T:Getter<U>+Setter<U>> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 7 previous errors
 
+For more information about this error, try `rustc --explain E0392`.
diff --git a/tests/ui/wf/wf-const-type.rs b/tests/ui/wf/wf-const-type.rs
index 64b0d9c8de7..3b770b4b916 100644
--- a/tests/ui/wf/wf-const-type.rs
+++ b/tests/ui/wf/wf-const-type.rs
@@ -10,6 +10,7 @@ struct NotCopy;
 const FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
 //~^ ERROR E0277
 //~| ERROR E0277
+//~| ERROR E0277
 
 
 fn main() { }
diff --git a/tests/ui/wf/wf-const-type.stderr b/tests/ui/wf/wf-const-type.stderr
index d5e0f7672a6..d73642729ea 100644
--- a/tests/ui/wf/wf-const-type.stderr
+++ b/tests/ui/wf/wf-const-type.stderr
@@ -16,6 +16,25 @@ LL + #[derive(Copy)]
 LL | struct NotCopy;
    |
 
+error[E0277]: the trait bound `NotCopy: Copy` is not satisfied
+  --> $DIR/wf-const-type.rs:10:12
+   |
+LL | const FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
+   |            ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option<NotCopy>: Copy`
+   |
+   = note: required for `Option<NotCopy>` to implement `Copy`
+note: required by a bound in `IsCopy`
+  --> $DIR/wf-const-type.rs:7:17
+   |
+LL | struct IsCopy<T:Copy> { t: T }
+   |                 ^^^^ required by this bound in `IsCopy`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider annotating `NotCopy` with `#[derive(Copy)]`
+   |
+LL + #[derive(Copy)]
+LL | struct NotCopy;
+   |
+
 error[E0277]: the trait bound `NotCopy: Copy` is not satisfied
   --> $DIR/wf-const-type.rs:10:50
    |
@@ -34,6 +53,6 @@ LL + #[derive(Copy)]
 LL | struct NotCopy;
    |
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/wf/wf-static-type.rs b/tests/ui/wf/wf-static-type.rs
index f454fe30e77..1980c5de40c 100644
--- a/tests/ui/wf/wf-static-type.rs
+++ b/tests/ui/wf/wf-static-type.rs
@@ -10,6 +10,7 @@ struct NotCopy;
 static FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
 //~^ ERROR E0277
 //~| ERROR E0277
+//~| ERROR E0277
 
 
 fn main() { }
diff --git a/tests/ui/wf/wf-static-type.stderr b/tests/ui/wf/wf-static-type.stderr
index 481173b8a26..36234f3fd17 100644
--- a/tests/ui/wf/wf-static-type.stderr
+++ b/tests/ui/wf/wf-static-type.stderr
@@ -16,6 +16,25 @@ LL + #[derive(Copy)]
 LL | struct NotCopy;
    |
 
+error[E0277]: the trait bound `NotCopy: Copy` is not satisfied
+  --> $DIR/wf-static-type.rs:10:13
+   |
+LL | static FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option<NotCopy>: Copy`
+   |
+   = note: required for `Option<NotCopy>` to implement `Copy`
+note: required by a bound in `IsCopy`
+  --> $DIR/wf-static-type.rs:7:17
+   |
+LL | struct IsCopy<T:Copy> { t: T }
+   |                 ^^^^ required by this bound in `IsCopy`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider annotating `NotCopy` with `#[derive(Copy)]`
+   |
+LL + #[derive(Copy)]
+LL | struct NotCopy;
+   |
+
 error[E0277]: the trait bound `NotCopy: Copy` is not satisfied
   --> $DIR/wf-static-type.rs:10:51
    |
@@ -34,6 +53,6 @@ LL + #[derive(Copy)]
 LL | struct NotCopy;
    |
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0277`.