Rollup merge of #154230 - aryannrd:issue-50411, r=Kivooeo

Moved and rename issue-50411 to tests/ui/mir/inliner-double-elaborate
diff --git a/.mailmap b/.mailmap
index c0333b4..1723208 100644
--- a/.mailmap
+++ b/.mailmap
@@ -262,6 +262,7 @@
 Guillaume Gomez <guillaume1.gomez@gmail.com> ggomez <ggomez@ggo.ifr.lan>
 Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <ggomez@ggo.ifr.lan>
 Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <guillaume.gomez@huawei.com>
+Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <contact@guillaume-gomez.fr>
 gnzlbg <gonzalobg88@gmail.com> <gnzlbg@users.noreply.github.com>
 hamidreza kalbasi <hamidrezakalbasi@protonmail.com>
 Hanna Kruppe <hanna.kruppe@gmail.com> <robin.kruppe@gmail.com>
diff --git a/Cargo.lock b/Cargo.lock
index 539f66f..85997e1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2175,9 +2175,9 @@
 
 [[package]]
 name = "libc"
-version = "0.2.177"
+version = "0.2.183"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
+checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
 
 [[package]]
 name = "libdbus-sys"
@@ -2454,11 +2454,12 @@
 
 [[package]]
 name = "mio"
-version = "1.1.0"
+version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873"
+checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
 dependencies = [
  "libc",
+ "log",
  "wasi 0.11.1+wasi-snapshot-preview1",
  "windows-sys 0.61.2",
 ]
@@ -2490,6 +2491,7 @@
  "libffi",
  "libloading 0.9.0",
  "measureme",
+ "mio",
  "nix",
  "rand 0.9.2",
  "regex",
@@ -4571,7 +4573,6 @@
  "rustc_data_structures",
  "rustc_errors",
  "rustc_hir",
- "rustc_index",
  "rustc_macros",
  "rustc_middle",
  "rustc_serialize",
diff --git a/RELEASES.md b/RELEASES.md
index f180d74..c396cd8 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,17 @@
+Version 1.94.1 (2026-03-26)
+===========================
+
+<a id="1.94.1"></a>
+
+* [Fix `std::thread::spawn` on wasm32-wasip1-threads](https://github.com/rust-lang/rust/pull/153634)
+* [Remove new methods added to `std::os::windows::fs::OpenOptionsExt`](https://github.com/rust-lang/rust/pull/153491)
+  The new methods were unstable, but the trait itself is not sealed and so
+  cannot be extended with non-default methods.
+* [Clippy: fix ICE in `match_same_arms`](https://github.com/rust-lang/rust-clippy/pull/16685)
+* [Cargo: update tar to 0.4.45](https://github.com/rust-lang/cargo/pull/16769)
+  This resolves CVE-2026-33055 and CVE-2026-33056. Users of crates.io are not affected.
+  See [blog](https://blog.rust-lang.org/2026/03/21/cve-2026-33056/) for more details.
+
 Version 1.94.0 (2026-03-05)
 ==========================
 
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 74cc1ec..024624c 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -938,7 +938,7 @@ pub enum PatKind {
     Never,
 
     /// A guard pattern (e.g., `x if guard(x)`).
-    Guard(Box<Pat>, Box<Expr>),
+    Guard(Box<Pat>, Box<Guard>),
 
     /// Parentheses in patterns used for grouping (i.e., `(PAT)`).
     Paren(Box<Pat>),
@@ -1346,7 +1346,7 @@ pub struct Arm {
     /// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }`.
     pub pat: Box<Pat>,
     /// Match arm guard, e.g. `n > 10` in `match foo { n if n > 10 => {}, _ => {} }`.
-    pub guard: Option<Box<Expr>>,
+    pub guard: Option<Box<Guard>>,
     /// Match arm body. Omitted if the pattern is a never pattern.
     pub body: Option<Box<Expr>>,
     pub span: Span,
@@ -3954,6 +3954,18 @@ impl ConstBlockItem {
     pub const IDENT: Ident = Ident { name: kw::Underscore, span: DUMMY_SP };
 }
 
+#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
+pub struct Guard {
+    pub cond: Expr,
+    pub span_with_leading_if: Span,
+}
+
+impl Guard {
+    pub fn span(&self) -> Span {
+        self.cond.span
+    }
+}
+
 // Adding a new variant? Please update `test_item` in `tests/ui/macros/stringify.rs`.
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub enum ItemKind {
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 72e7b27..369fe12 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -876,11 +876,15 @@ pub trait AttributeExt: Debug {
     /// a doc comment) will return `false`.
     fn is_doc_comment(&self) -> Option<Span>;
 
+    /// Returns true if the attribute's first *and only* path segment is equal to the passed-in
+    /// symbol.
     #[inline]
     fn has_name(&self, name: Symbol) -> bool {
         self.name().map(|x| x == name).unwrap_or(false)
     }
 
+    /// Returns true if the attribute's first *and only* path segment is any of the passed-in
+    /// symbols.
     #[inline]
     fn has_any_name(&self, names: &[Symbol]) -> bool {
         names.iter().any(|&name| self.has_name(name))
@@ -889,6 +893,7 @@ fn has_any_name(&self, names: &[Symbol]) -> bool {
     /// get the span of the entire attribute
     fn span(&self) -> Span;
 
+    /// Returns whether the attribute is a path, without any arguments.
     fn is_word(&self) -> bool;
 
     fn path(&self) -> SmallVec<[Symbol; 1]> {
@@ -911,11 +916,14 @@ fn has_any_name(&self, names: &[Symbol]) -> bool {
     /// * `#[deprecated(note = "note", ...)]` returns `Some("note")`.
     fn deprecation_note(&self) -> Option<Ident>;
 
+    /// Returns whether this attribute is any of the proc macro attributes.
+    /// i.e. `proc_macro`, `proc_macro_attribute` or `proc_macro_derive`.
     fn is_proc_macro_attr(&self) -> bool {
         [sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive]
             .iter()
             .any(|kind| self.has_name(*kind))
     }
+    /// Returns true if this attribute is `#[automatically_deived]`.
     fn is_automatically_derived_attr(&self) -> bool;
 
     /// Returns the documentation and its kind if this is a doc comment or a sugared doc comment.
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index f825130..62ec063 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -94,6 +94,7 @@ pub enum MetaVarKind {
     },
     Path,
     Vis,
+    Guard,
     TT,
 }
 
@@ -114,6 +115,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             MetaVarKind::Meta { .. } => sym::meta,
             MetaVarKind::Path => sym::path,
             MetaVarKind::Vis => sym::vis,
+            MetaVarKind::Guard => sym::guard,
             MetaVarKind::TT => sym::tt,
         };
         write!(f, "{sym}")
@@ -1124,6 +1126,7 @@ pub enum NonterminalKind {
     Meta,
     Path,
     Vis,
+    Guard,
     TT,
 }
 
@@ -1161,6 +1164,7 @@ pub fn from_symbol(
             sym::meta => NonterminalKind::Meta,
             sym::path => NonterminalKind::Path,
             sym::vis => NonterminalKind::Vis,
+            sym::guard => NonterminalKind::Guard,
             sym::tt => NonterminalKind::TT,
             _ => return None,
         })
@@ -1182,6 +1186,7 @@ fn symbol(self) -> Symbol {
             NonterminalKind::Meta => sym::meta,
             NonterminalKind::Path => sym::path,
             NonterminalKind::Vis => sym::vis,
+            NonterminalKind::Guard => sym::guard,
             NonterminalKind::TT => sym::tt,
         }
     }
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index bdf290f..6aa8d5f 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -442,6 +442,7 @@ pub fn ctxt(&self) -> Option<FnCtxt> {
             FormatArguments,
             FormatPlaceholder,
             GenericParamKind,
+            Guard,
             Impl,
             ImplPolarity,
             Inline,
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 51994c2..3a27962 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -1,5 +1,4 @@
 use std::collections::hash_map::Entry;
-use std::fmt::Write;
 
 use rustc_ast::*;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
@@ -124,13 +123,9 @@ pub(crate) fn lower_inline_asm(
                         self.dcx().emit_err(ClobberAbiNotSupported { abi_span: *abi_span });
                     }
                     Err(supported_abis) => {
-                        let mut abis = format!("`{}`", supported_abis[0]);
-                        for m in &supported_abis[1..] {
-                            let _ = write!(abis, ", `{m}`");
-                        }
                         self.dcx().emit_err(InvalidAbiClobberAbi {
                             abi_span: *abi_span,
-                            supported_abis: abis,
+                            supported_abis: supported_abis.to_vec().into(),
                         });
                     }
                 }
@@ -164,15 +159,12 @@ pub(crate) fn lower_inline_asm(
                         asm::InlineAsmRegOrRegClass::RegClass(if let Some(asm_arch) = asm_arch {
                             asm::InlineAsmRegClass::parse(asm_arch, reg_class).unwrap_or_else(
                                 |supported_register_classes| {
-                                    let mut register_classes =
-                                        format!("`{}`", supported_register_classes[0]);
-                                    for m in &supported_register_classes[1..] {
-                                        let _ = write!(register_classes, ", `{m}`");
-                                    }
                                     self.dcx().emit_err(InvalidRegisterClass {
                                         op_span: *op_sp,
                                         reg_class,
-                                        supported_register_classes: register_classes,
+                                        supported_register_classes: supported_register_classes
+                                            .to_vec()
+                                            .into(),
                                     });
                                     asm::InlineAsmRegClass::Err
                                 },
@@ -272,23 +264,20 @@ pub(crate) fn lower_inline_asm(
                         }
                         let valid_modifiers = class.valid_modifiers(asm_arch.unwrap());
                         if !valid_modifiers.contains(&modifier) {
-                            let sub = if !valid_modifiers.is_empty() {
-                                let mut mods = format!("`{}`", valid_modifiers[0]);
-                                for m in &valid_modifiers[1..] {
-                                    let _ = write!(mods, ", `{m}`");
-                                }
-                                InvalidAsmTemplateModifierRegClassSub::SupportModifier {
-                                    class_name: class.name(),
-                                    modifiers: mods,
-                                }
-                            } else {
+                            let sub = if valid_modifiers.is_empty() {
                                 InvalidAsmTemplateModifierRegClassSub::DoesNotSupportModifier {
                                     class_name: class.name(),
                                 }
+                            } else {
+                                InvalidAsmTemplateModifierRegClassSub::SupportModifier {
+                                    class_name: class.name(),
+                                    modifiers: valid_modifiers.to_vec().into(),
+                                }
                             };
                             self.dcx().emit_err(InvalidAsmTemplateModifierRegClass {
                                 placeholder_span,
                                 op_span: op_sp,
+                                modifier: modifier.to_string(),
                                 sub,
                             });
                         }
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index 0044913..022f9e3 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -146,12 +146,10 @@ pub(crate) fn lower_delegation(
 
                 let (param_count, c_variadic) = self.param_count(sig_id);
 
-                let mut generics =
-                    self.lower_delegation_generics(delegation, sig_id, item_id, span);
+                let mut generics = self.uplift_delegation_generics(delegation, sig_id, item_id);
 
                 let body_id = self.lower_delegation_body(
                     delegation,
-                    item_id,
                     is_method,
                     param_count,
                     &mut generics,
@@ -166,10 +164,8 @@ pub(crate) fn lower_delegation(
 
                 let generics = self.arena.alloc(hir::Generics {
                     has_where_clause_predicates: false,
-                    params: self.arena.alloc_from_iter(generics.all_params(item_id, span, self)),
-                    predicates: self
-                        .arena
-                        .alloc_from_iter(generics.all_predicates(item_id, span, self)),
+                    params: self.arena.alloc_from_iter(generics.all_params(span, self)),
+                    predicates: self.arena.alloc_from_iter(generics.all_predicates(span, self)),
                     span,
                     where_clause_span: span,
                 });
@@ -294,19 +290,22 @@ fn lower_delegation_decl(
         let decl_param_count = param_count - c_variadic as usize;
         let inputs = self.arena.alloc_from_iter((0..decl_param_count).map(|arg| hir::Ty {
             hir_id: self.next_id(),
-            kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Input(arg)),
+            kind: hir::TyKind::InferDelegation(hir::InferDelegation::Sig(
+                sig_id,
+                hir::InferDelegationSig::Input(arg),
+            )),
             span,
         }));
 
         let output = self.arena.alloc(hir::Ty {
             hir_id: self.next_id(),
-            kind: hir::TyKind::InferDelegation(
+            kind: hir::TyKind::InferDelegation(hir::InferDelegation::Sig(
                 sig_id,
-                hir::InferDelegationKind::Output(self.arena.alloc(hir::DelegationGenerics {
+                hir::InferDelegationSig::Output(self.arena.alloc(hir::DelegationGenerics {
                     child_args_segment_id: generics.child.args_segment_id,
                     parent_args_segment_id: generics.parent.args_segment_id,
                 })),
-            ),
+            )),
             span,
         });
 
@@ -399,7 +398,6 @@ fn generate_arg(
     fn lower_delegation_body(
         &mut self,
         delegation: &Delegation,
-        item_id: NodeId,
         is_method: bool,
         param_count: usize,
         generics: &mut GenericsGenerationResults<'hir>,
@@ -434,7 +432,18 @@ fn lower_delegation_body(
                 args.push(arg);
             }
 
-            let final_expr = this.finalize_body_lowering(delegation, item_id, args, generics, span);
+            // If we have no params in signature function but user still wrote some code in
+            // delegation body, then add this code as first arg, eventually an error will be shown,
+            // also nested delegations may need to access information about this code (#154332),
+            // so it is better to leave this code as opposed to bodies of extern functions,
+            // which are completely erased from existence.
+            if param_count == 0
+                && let Some(block) = block
+            {
+                args.push(this.lower_target_expr(&block));
+            }
+
+            let final_expr = this.finalize_body_lowering(delegation, args, generics, span);
 
             (this.arena.alloc_from_iter(parameters), final_expr)
         })
@@ -471,7 +480,6 @@ fn lower_target_expr(&mut self, block: &Block) -> hir::Expr<'hir> {
     fn finalize_body_lowering(
         &mut self,
         delegation: &Delegation,
-        item_id: NodeId,
         args: Vec<hir::Expr<'hir>>,
         generics: &mut GenericsGenerationResults<'hir>,
         span: Span,
@@ -501,7 +509,7 @@ fn finalize_body_lowering(
 
             // FIXME(fn_delegation): proper support for parent generics propagation
             // in method call scenario.
-            let segment = self.process_segment(item_id, span, &segment, &mut generics.child, false);
+            let segment = self.process_segment(span, &segment, &mut generics.child, false);
             let segment = self.arena.alloc(segment);
 
             self.arena.alloc(hir::Expr {
@@ -528,7 +536,7 @@ fn finalize_body_lowering(
                     new_path.segments = self.arena.alloc_from_iter(
                         new_path.segments.iter().enumerate().map(|(idx, segment)| {
                             let mut process_segment = |result, add_lifetimes| {
-                                self.process_segment(item_id, span, segment, result, add_lifetimes)
+                                self.process_segment(span, segment, result, add_lifetimes)
                             };
 
                             if idx + 2 == len {
@@ -544,8 +552,7 @@ fn finalize_body_lowering(
                     hir::QPath::Resolved(ty, self.arena.alloc(new_path))
                 }
                 hir::QPath::TypeRelative(ty, segment) => {
-                    let segment =
-                        self.process_segment(item_id, span, segment, &mut generics.child, false);
+                    let segment = self.process_segment(span, segment, &mut generics.child, false);
 
                     hir::QPath::TypeRelative(ty, self.arena.alloc(segment))
                 }
@@ -569,7 +576,6 @@ fn finalize_body_lowering(
 
     fn process_segment(
         &mut self,
-        item_id: NodeId,
         span: Span,
         segment: &hir::PathSegment<'hir>,
         result: &mut GenericsGenerationResult<'hir>,
@@ -577,15 +583,14 @@ fn process_segment(
     ) -> hir::PathSegment<'hir> {
         let details = result.generics.args_propagation_details();
 
-        // The first condition is needed when there is SelfAndUserSpecified case,
-        // we don't want to propagate generics params in this situation.
-        let segment = if details.should_propagate
-            && let Some(args) = result
-                .generics
-                .into_hir_generics(self, item_id, span)
-                .into_generic_args(self, add_lifetimes, span)
-        {
-            hir::PathSegment { args: Some(args), ..segment.clone() }
+        let segment = if details.should_propagate {
+            let generics = result.generics.into_hir_generics(self, span);
+            let args = generics.into_generic_args(self, add_lifetimes, span);
+
+            // Needed for better error messages (`trait-impl-wrong-args-count.rs` test).
+            let args = if args.is_empty() { None } else { Some(args) };
+
+            hir::PathSegment { args, ..segment.clone() }
         } else {
             segment.clone()
         };
diff --git a/compiler/rustc_ast_lowering/src/delegation/generics.rs b/compiler/rustc_ast_lowering/src/delegation/generics.rs
index d6d8819..4e960e3 100644
--- a/compiler/rustc_ast_lowering/src/delegation/generics.rs
+++ b/compiler/rustc_ast_lowering/src/delegation/generics.rs
@@ -5,10 +5,8 @@
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::{bug, ty};
-use rustc_span::sym::{self};
 use rustc_span::symbol::kw;
 use rustc_span::{Ident, Span};
-use thin_vec::{ThinVec, thin_vec};
 
 use crate::{LoweringContext, ResolverAstLoweringExt};
 
@@ -16,34 +14,33 @@ pub(super) enum DelegationGenerics<T> {
     /// User-specified args are present: `reuse foo::<String>;`.
     UserSpecified,
     /// The default case when no user-specified args are present: `reuse Trait::foo;`.
-    Default(Option<T>),
+    Default(T),
     /// In free-to-trait reuse, when user specified args for trait `reuse Trait::<i32>::foo;`
     /// in this case we need to both generate `Self` and process user args.
-    SelfAndUserSpecified(Option<T>),
+    SelfAndUserSpecified(T),
     /// In delegations from trait impl to other entities like free functions or trait functions,
     /// we want to generate a function whose generics matches generics of signature function
     /// in trait.
-    TraitImpl(Option<T>, bool /* Has user-specified args */),
+    TraitImpl(T, bool /* Has user-specified args */),
 }
 
-/// Used for storing either AST generics or their lowered HIR version. Firstly we obtain
-/// AST generics either from local function from AST index or from external function
-/// through `tcx`. Next, at some point of generics processing we need to lower those
-/// generics to HIR, for this purpose we use `into_hir_generics` that lowers AST generics
-/// and replaces Ast variant with Hir. Such approach is useful as we can call this method
-/// at any time knowing that lowering will occur at most only once. Then, in order to obtain generic
+/// Used for storing either ty generics or their uplifted HIR version. First we obtain
+/// ty generics. Next, at some point of generics processing we need to uplift those
+/// generics to HIR, for this purpose we use `into_hir_generics` that uplifts ty generics
+/// and replaces Ty variant with Hir. Such approach is useful as we can call this method
+/// at any time knowing that uplifting will occur at most only once. Then, in order to obtain generic
 /// params or args we use `hir_generics_or_empty` or `into_generic_args` functions.
-/// There also may be situations when we obtained AST generics but never lowered them to HIR,
+/// There also may be situations when we obtained ty generics but never uplifted them to HIR,
 /// meaning we did not propagate them and thus we do not need to generate generic params
 /// (i.e., method call scenarios), in such a case this approach helps
-/// a lot as if `into_hir_generics` will not be called then lowering will not happen.
-pub(super) enum HirOrAstGenerics<'hir> {
-    Ast(DelegationGenerics<Generics>),
+/// a lot as if `into_hir_generics` will not be called then uplifting will not happen.
+pub(super) enum HirOrTyGenerics<'hir> {
+    Ty(DelegationGenerics<&'hir [ty::GenericParamDef]>),
     Hir(DelegationGenerics<&'hir hir::Generics<'hir>>),
 }
 
 pub(super) struct GenericsGenerationResult<'hir> {
-    pub(super) generics: HirOrAstGenerics<'hir>,
+    pub(super) generics: HirOrTyGenerics<'hir>,
     pub(super) args_segment_id: Option<HirId>,
 }
 
@@ -78,35 +75,31 @@ fn args_propagation_details(&self) -> GenericArgsPropagationDetails {
     }
 }
 
-impl<'hir> HirOrAstGenerics<'hir> {
+impl<'hir> HirOrTyGenerics<'hir> {
     pub(super) fn into_hir_generics(
         &mut self,
         ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
-        item_id: NodeId,
         span: Span,
-    ) -> &mut HirOrAstGenerics<'hir> {
-        if let HirOrAstGenerics::Ast(generics) = self {
-            let process_params = |generics: &mut Generics| {
-                ctx.lower_delegation_generic_params(item_id, span, &mut generics.params)
+    ) -> &mut HirOrTyGenerics<'hir> {
+        if let HirOrTyGenerics::Ty(params) = self {
+            let mut uplift_params = |generics: &'hir [ty::GenericParamDef]| {
+                ctx.uplift_delegation_generic_params(span, generics)
             };
 
-            let hir_generics = match generics {
+            let hir_generics = match params {
                 DelegationGenerics::UserSpecified => DelegationGenerics::UserSpecified,
-                DelegationGenerics::Default(generics) => {
-                    DelegationGenerics::Default(generics.as_mut().map(process_params))
+                DelegationGenerics::Default(params) => {
+                    DelegationGenerics::Default(uplift_params(params))
                 }
-                DelegationGenerics::SelfAndUserSpecified(generics) => {
-                    DelegationGenerics::SelfAndUserSpecified(generics.as_mut().map(process_params))
+                DelegationGenerics::SelfAndUserSpecified(params) => {
+                    DelegationGenerics::SelfAndUserSpecified(uplift_params(params))
                 }
-                DelegationGenerics::TraitImpl(generics, user_specified) => {
-                    DelegationGenerics::TraitImpl(
-                        generics.as_mut().map(process_params),
-                        *user_specified,
-                    )
+                DelegationGenerics::TraitImpl(params, user_specified) => {
+                    DelegationGenerics::TraitImpl(uplift_params(params), *user_specified)
                 }
             };
 
-            *self = HirOrAstGenerics::Hir(hir_generics);
+            *self = HirOrTyGenerics::Hir(hir_generics);
         }
 
         self
@@ -114,14 +107,12 @@ pub(super) fn into_hir_generics(
 
     fn hir_generics_or_empty(&self) -> &'hir hir::Generics<'hir> {
         match self {
-            HirOrAstGenerics::Ast(_) => hir::Generics::empty(),
-            HirOrAstGenerics::Hir(hir_generics) => match hir_generics {
+            HirOrTyGenerics::Ty(_) => hir::Generics::empty(),
+            HirOrTyGenerics::Hir(hir_generics) => match hir_generics {
                 DelegationGenerics::UserSpecified => hir::Generics::empty(),
                 DelegationGenerics::Default(generics)
                 | DelegationGenerics::SelfAndUserSpecified(generics)
-                | DelegationGenerics::TraitImpl(generics, _) => {
-                    generics.unwrap_or(hir::Generics::empty())
-                }
+                | DelegationGenerics::TraitImpl(generics, _) => generics,
             },
         }
     }
@@ -131,43 +122,41 @@ pub(super) fn into_generic_args(
         ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
         add_lifetimes: bool,
         span: Span,
-    ) -> Option<&'hir hir::GenericArgs<'hir>> {
+    ) -> &'hir hir::GenericArgs<'hir> {
         match self {
-            HirOrAstGenerics::Ast(_) => {
-                bug!("Attempting to get generic args before lowering to HIR")
+            HirOrTyGenerics::Ty(_) => {
+                bug!("Attempting to get generic args before uplifting to HIR")
             }
-            HirOrAstGenerics::Hir(hir_generics) => match hir_generics {
-                DelegationGenerics::UserSpecified => None,
+            HirOrTyGenerics::Hir(hir_generics) => match hir_generics {
+                DelegationGenerics::UserSpecified => hir::GenericArgs::NONE,
                 DelegationGenerics::Default(generics)
                 | DelegationGenerics::SelfAndUserSpecified(generics)
-                | DelegationGenerics::TraitImpl(generics, _) => generics.map(|generics| {
+                | DelegationGenerics::TraitImpl(generics, _) => {
                     ctx.create_generics_args_from_params(generics.params, add_lifetimes, span)
-                }),
+                }
             },
         }
     }
 
     pub(super) fn args_propagation_details(&self) -> GenericArgsPropagationDetails {
         match self {
-            HirOrAstGenerics::Ast(ast_generics) => ast_generics.args_propagation_details(),
-            HirOrAstGenerics::Hir(hir_generics) => hir_generics.args_propagation_details(),
+            HirOrTyGenerics::Ty(ty_generics) => ty_generics.args_propagation_details(),
+            HirOrTyGenerics::Hir(hir_generics) => hir_generics.args_propagation_details(),
         }
     }
 }
 
-impl<'a> GenericsGenerationResult<'a> {
-    fn new(generics: DelegationGenerics<Generics>) -> GenericsGenerationResult<'a> {
-        GenericsGenerationResult {
-            generics: HirOrAstGenerics::Ast(generics),
-            args_segment_id: None,
-        }
+impl<'hir> GenericsGenerationResult<'hir> {
+    fn new(
+        generics: DelegationGenerics<&'hir [ty::GenericParamDef]>,
+    ) -> GenericsGenerationResult<'hir> {
+        GenericsGenerationResult { generics: HirOrTyGenerics::Ty(generics), args_segment_id: None }
     }
 }
 
 impl<'hir> GenericsGenerationResults<'hir> {
     pub(super) fn all_params(
         &mut self,
-        item_id: NodeId,
         span: Span,
         ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
     ) -> impl Iterator<Item = hir::GenericParam<'hir>> {
@@ -176,21 +165,14 @@ pub(super) fn all_params(
         // method call will be supported (if HIR generics were not obtained
         // then it means that we did not propagated them, thus we do not need
         // to generate params).
-        let parent = self
-            .parent
-            .generics
-            .into_hir_generics(ctx, item_id, span)
-            .hir_generics_or_empty()
-            .params;
+        let mut create_params = |result: &mut GenericsGenerationResult<'hir>| {
+            result.generics.into_hir_generics(ctx, span).hir_generics_or_empty().params
+        };
 
-        let child = self
-            .child
-            .generics
-            .into_hir_generics(ctx, item_id, span)
-            .hir_generics_or_empty()
-            .params;
+        let parent = create_params(&mut self.parent);
+        let child = create_params(&mut self.child);
 
-        // Order generics, firstly we have parent and child lifetimes,
+        // Order generics, first we have parent and child lifetimes,
         // then parent and child types and consts.
         // `generics_of` in `rustc_hir_analysis` will order them anyway,
         // however we want the order to be consistent in HIR too.
@@ -203,13 +185,12 @@ pub(super) fn all_params(
             .copied()
     }
 
-    /// As we add hack predicates(`'a: 'a`) for all lifetimes (see `lower_delegation_generic_params`
+    /// As we add hack predicates(`'a: 'a`) for all lifetimes (see `uplift_delegation_generic_params`
     /// and `generate_lifetime_predicate` functions) we need to add them to delegation generics.
     /// Those predicates will not affect resulting predicate inheritance and folding
     /// in `rustc_hir_analysis`, as we inherit all predicates from delegation signature.
     pub(super) fn all_predicates(
         &mut self,
-        item_id: NodeId,
         span: Span,
         ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
     ) -> impl Iterator<Item = hir::WherePredicate<'hir>> {
@@ -218,31 +199,23 @@ pub(super) fn all_predicates(
         // method call will be supported (if HIR generics were not obtained
         // then it means that we did not propagated them, thus we do not need
         // to generate predicates).
-        self.parent
-            .generics
-            .into_hir_generics(ctx, item_id, span)
-            .hir_generics_or_empty()
-            .predicates
-            .into_iter()
-            .chain(
-                self.child
-                    .generics
-                    .into_hir_generics(ctx, item_id, span)
-                    .hir_generics_or_empty()
-                    .predicates
-                    .into_iter(),
-            )
-            .copied()
+        let mut create_predicates = |result: &mut GenericsGenerationResult<'hir>| {
+            result.generics.into_hir_generics(ctx, span).hir_generics_or_empty().predicates
+        };
+
+        let parent = create_predicates(&mut self.parent);
+        let child = create_predicates(&mut self.child);
+
+        parent.into_iter().chain(child).copied()
     }
 }
 
 impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
-    pub(super) fn lower_delegation_generics(
+    pub(super) fn uplift_delegation_generics(
         &mut self,
         delegation: &Delegation,
         sig_id: DefId,
         item_id: NodeId,
-        span: Span,
     ) -> GenericsGenerationResults<'hir> {
         let delegation_parent_kind =
             self.tcx.def_kind(self.tcx.local_parent(self.local_def_id(item_id)));
@@ -251,15 +224,16 @@ pub(super) fn lower_delegation_generics(
         let len = segments.len();
         let child_user_specified = segments[len - 1].args.is_some();
 
+        let sig_params = &self.tcx.generics_of(sig_id).own_params[..];
+
         // If we are in trait impl always generate function whose generics matches
         // those that are defined in trait.
         if matches!(delegation_parent_kind, DefKind::Impl { of_trait: true }) {
             // Considering parent generics, during signature inheritance
             // we will take those args that are in trait impl header trait ref.
-            let parent = GenericsGenerationResult::new(DelegationGenerics::Default(None));
+            let parent = GenericsGenerationResult::new(DelegationGenerics::TraitImpl(&[], true));
 
-            let generics = self.get_external_generics(sig_id, false, span);
-            let child = DelegationGenerics::TraitImpl(generics, child_user_specified);
+            let child = DelegationGenerics::TraitImpl(sig_params, child_user_specified);
             let child = GenericsGenerationResult::new(child);
 
             return GenericsGenerationResults { parent, child };
@@ -268,38 +242,37 @@ pub(super) fn lower_delegation_generics(
         let delegation_in_free_ctx =
             !matches!(delegation_parent_kind, DefKind::Trait | DefKind::Impl { .. });
 
-        let root_function_in_trait =
-            matches!(self.tcx.def_kind(self.tcx.parent(sig_id)), DefKind::Trait);
-
-        let generate_self = delegation_in_free_ctx && root_function_in_trait;
-
-        let parent_generics_factory = |this: &mut Self, user_specified: bool| {
-            this.get_parent_generics(this.tcx.parent(sig_id), generate_self, user_specified, span)
-        };
+        let sig_parent = self.tcx.parent(sig_id);
+        let sig_in_trait = matches!(self.tcx.def_kind(sig_parent), DefKind::Trait);
 
         let can_add_generics_to_parent = len >= 2
             && self.get_resolution_id(segments[len - 2].id).is_some_and(|def_id| {
                 matches!(self.tcx.def_kind(def_id), DefKind::Trait | DefKind::TraitAlias)
             });
 
+        let generate_self = delegation_in_free_ctx && sig_in_trait;
         let parent_generics = if can_add_generics_to_parent {
+            let sig_parent_params = &self.tcx.generics_of(sig_parent).own_params[..];
+
             if segments[len - 2].args.is_some() {
                 if generate_self {
-                    DelegationGenerics::SelfAndUserSpecified(parent_generics_factory(self, true))
+                    // Take only first Self parameter, it is trait so Self must be present.
+                    DelegationGenerics::SelfAndUserSpecified(&sig_parent_params[..1])
                 } else {
                     DelegationGenerics::UserSpecified
                 }
             } else {
-                DelegationGenerics::Default(parent_generics_factory(self, false))
+                let skip_self = usize::from(!generate_self);
+                DelegationGenerics::Default(&sig_parent_params[skip_self..])
             }
         } else {
-            DelegationGenerics::Default(None)
+            DelegationGenerics::<&'hir [ty::GenericParamDef]>::Default(&[])
         };
 
         let child_generics = if child_user_specified {
             DelegationGenerics::UserSpecified
         } else {
-            DelegationGenerics::Default(self.get_external_generics(sig_id, false, span))
+            DelegationGenerics::Default(sig_params)
         };
 
         GenericsGenerationResults {
@@ -308,59 +281,70 @@ pub(super) fn lower_delegation_generics(
         }
     }
 
-    fn lower_delegation_generic_params(
+    fn uplift_delegation_generic_params(
         &mut self,
-        item_id: NodeId,
         span: Span,
-        params: &mut ThinVec<GenericParam>,
+        params: &'hir [ty::GenericParamDef],
     ) -> &'hir hir::Generics<'hir> {
-        for p in params.iter_mut() {
-            // We want to create completely new params, so we generate
-            // a new id, otherwise assertions will be triggered.
-            p.id = self.next_node_id();
+        let params = self.arena.alloc_from_iter(params.iter().map(|p| {
+            let def_kind = match p.kind {
+                GenericParamDefKind::Lifetime => DefKind::LifetimeParam,
+                GenericParamDefKind::Type { .. } => DefKind::TyParam,
+                GenericParamDefKind::Const { .. } => DefKind::ConstParam,
+            };
 
-            // Remove default params, as they are not supported on functions
-            // and there will duplicate DefId  when we try to lower them later.
-            match &mut p.kind {
-                GenericParamKind::Lifetime => {}
-                GenericParamKind::Type { default } => *default = None,
-                GenericParamKind::Const { default, .. } => *default = None,
+            let param_ident = Ident::new(p.name, span);
+            let def_name = Some(param_ident.name);
+            let path_data = def_kind.def_path_data(def_name);
+            let node_id = self.next_node_id();
+
+            let def_id = self.create_def(node_id, def_name, def_kind, path_data, span);
+
+            let kind = match p.kind {
+                GenericParamDefKind::Lifetime => {
+                    hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
+                }
+                GenericParamDefKind::Type { synthetic, .. } => {
+                    hir::GenericParamKind::Type { default: None, synthetic }
+                }
+                GenericParamDefKind::Const { .. } => {
+                    let hir_id = self.next_id();
+                    let kind = hir::TyKind::InferDelegation(hir::InferDelegation::DefId(p.def_id));
+
+                    hir::GenericParamKind::Const {
+                        ty: self.arena.alloc(hir::Ty { kind, hir_id, span }),
+                        default: None,
+                    }
+                }
+            };
+
+            // Important: we don't use `self.next_id()` as we want to execute
+            // `lower_node_id` routine so param's id is added to `self.children`.
+            let hir_id = self.lower_node_id(node_id);
+
+            hir::GenericParam {
+                hir_id,
+                colon_span: Some(span),
+                def_id,
+                kind,
+                name: hir::ParamName::Plain(param_ident),
+                pure_wrt_drop: p.pure_wrt_drop,
+                source: hir::GenericParamSource::Generics,
+                span,
             }
-
-            // Note that we use self.disambiguator here, if we will create new every time
-            // we will get ICE if params have the same name.
-            self.resolver.insert_new_def_id(
-                p.id,
-                self.tcx
-                    .create_def(
-                        self.local_def_id(item_id),
-                        Some(p.ident.name),
-                        match p.kind {
-                            GenericParamKind::Lifetime => DefKind::LifetimeParam,
-                            GenericParamKind::Type { .. } => DefKind::TyParam,
-                            GenericParamKind::Const { .. } => DefKind::ConstParam,
-                        },
-                        None,
-                        &mut self.disambiguator,
-                    )
-                    .def_id(),
-            );
-        }
-
-        // Fallback to default generic param lowering, we modified them in the loop above.
-        let params = self.arena.alloc_from_iter(
-            params.iter().map(|p| self.lower_generic_param(p, hir::GenericParamSource::Generics)),
-        );
+        }));
 
         // HACK: for now we generate predicates such that all lifetimes are early bound,
         // we can not not generate early-bound lifetimes, but we can't know which of them
         // are late-bound at this level of compilation.
-        // FIXME(fn_delegation): proper support for late bound lifetimes.
+        let predicates =
+            self.arena.alloc_from_iter(params.iter().filter_map(|p| {
+                p.is_lifetime().then(|| self.generate_lifetime_predicate(p, span))
+            }));
+
         self.arena.alloc(hir::Generics {
             params,
-            predicates: self.arena.alloc_from_iter(params.iter().filter_map(|p| {
-                p.is_lifetime().then(|| self.generate_lifetime_predicate(p, span))
-            })),
+            predicates,
             has_where_clause_predicates: false,
             where_clause_span: span,
             span,
@@ -376,11 +360,9 @@ fn generate_lifetime_predicate(
             this.arena.alloc(hir::Lifetime {
                 hir_id: this.next_id(),
                 ident: p.name.ident(),
-                kind: rustc_hir::LifetimeKind::Param(p.def_id),
-                source: rustc_hir::LifetimeSource::Path {
-                    angle_brackets: rustc_hir::AngleBrackets::Full,
-                },
-                syntax: rustc_hir::LifetimeSyntax::ExplicitBound,
+                kind: hir::LifetimeKind::Param(p.def_id),
+                source: hir::LifetimeSource::Path { angle_brackets: hir::AngleBrackets::Full },
+                syntax: hir::LifetimeSyntax::ExplicitBound,
             })
         };
 
@@ -408,7 +390,7 @@ fn create_generics_args_from_params(
         self.arena.alloc(hir::GenericArgs {
             args: self.arena.alloc_from_iter(params.iter().filter_map(|p| {
                 // Skip self generic arg, we do not need to propagate it.
-                if p.name.ident().name == kw::SelfUpper {
+                if p.name.ident().name == kw::SelfUpper || p.is_impl_trait() {
                     return None;
                 }
 
@@ -472,117 +454,4 @@ fn create_generics_args_from_params(
             span_ext: span,
         })
     }
-
-    fn get_external_generics(
-        &mut self,
-        id: DefId,
-        processing_parent: bool,
-        span: Span,
-    ) -> Option<Generics> {
-        let generics = self.tcx.generics_of(id);
-        if generics.own_params.is_empty() {
-            return None;
-        }
-
-        // Skip first Self parameter if we are in trait, it will be added later.
-        let to_skip = (processing_parent && generics.has_self) as usize;
-
-        Some(Generics {
-            params: generics
-                .own_params
-                .iter()
-                .skip(to_skip)
-                .map(|p| GenericParam {
-                    attrs: Default::default(),
-                    bounds: Default::default(),
-                    colon_span: None,
-                    id: self.next_node_id(),
-                    ident: Ident::new(p.name, span),
-                    is_placeholder: false,
-                    kind: match p.kind {
-                        GenericParamDefKind::Lifetime => GenericParamKind::Lifetime,
-                        GenericParamDefKind::Type { .. } => {
-                            GenericParamKind::Type { default: None }
-                        }
-                        GenericParamDefKind::Const { .. } => self.map_const_kind(p, span),
-                    },
-                })
-                .collect(),
-            where_clause: Default::default(),
-            span,
-        })
-    }
-
-    fn map_const_kind(&mut self, p: &ty::GenericParamDef, span: Span) -> GenericParamKind {
-        let const_type = self.tcx.type_of(p.def_id).instantiate_identity();
-
-        let (type_symbol, res) = match const_type.kind() {
-            ty::Bool => (sym::bool, Res::PrimTy(hir::PrimTy::Bool)),
-            ty::Uint(uint) => (uint.name(), Res::PrimTy(hir::PrimTy::Uint(*uint))),
-            ty::Int(int) => (int.name(), Res::PrimTy(hir::PrimTy::Int(*int))),
-            ty::Char => (sym::char, Res::PrimTy(hir::PrimTy::Char)),
-            _ => {
-                self.tcx
-                    .dcx()
-                    .span_delayed_bug(span, format!("Unexpected const type: {}", const_type));
-
-                (sym::dummy, Res::Err)
-            }
-        };
-
-        let node_id = self.next_node_id();
-
-        self.resolver.insert_partial_res(node_id, hir::def::PartialRes::new(res));
-
-        GenericParamKind::Const {
-            ty: Box::new(Ty {
-                id: node_id,
-                kind: TyKind::Path(
-                    None,
-                    Path {
-                        segments: thin_vec![PathSegment {
-                            ident: Ident::new(type_symbol, span),
-                            id: self.next_node_id(),
-                            args: None
-                        }],
-                        span,
-                        tokens: None,
-                    },
-                ),
-                span,
-                tokens: None,
-            }),
-            span,
-            default: None,
-        }
-    }
-
-    fn get_parent_generics(
-        &mut self,
-        id: DefId,
-        add_self: bool,
-        user_specified: bool,
-        span: Span,
-    ) -> Option<Generics> {
-        // If args are user-specified we still maybe need to add self.
-        let mut generics =
-            if user_specified { None } else { self.get_external_generics(id, true, span) };
-
-        if add_self {
-            generics.get_or_insert_default().params.insert(
-                0,
-                GenericParam {
-                    id: self.next_node_id(),
-                    ident: Ident::new(kw::SelfUpper, span),
-                    attrs: Default::default(),
-                    bounds: vec![],
-                    is_placeholder: false,
-                    kind: GenericParamKind::Type { default: None },
-                    colon_span: None,
-                },
-            );
-        }
-
-        generics
-    }
 }
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 1eb7272..95b8bb4 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -1,5 +1,5 @@
-use rustc_errors::DiagArgFromDisplay;
 use rustc_errors::codes::*;
+use rustc_errors::{DiagArgFromDisplay, DiagSymbolList};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{Ident, Span, Symbol};
 
@@ -191,10 +191,10 @@ pub(crate) struct ClobberAbiNotSupported {
 #[derive(Diagnostic)]
 #[note("the following ABIs are supported on this target: {$supported_abis}")]
 #[diag("invalid ABI for `clobber_abi`")]
-pub(crate) struct InvalidAbiClobberAbi {
+pub(crate) struct InvalidAbiClobberAbi<'a> {
     #[primary_span]
     pub abi_span: Span,
-    pub supported_abis: String,
+    pub supported_abis: DiagSymbolList<&'a str>,
 }
 
 #[derive(Diagnostic)]
@@ -215,17 +215,18 @@ pub(crate) struct InvalidRegisterClass {
     #[primary_span]
     pub op_span: Span,
     pub reg_class: Symbol,
-    pub supported_register_classes: String,
+    pub supported_register_classes: DiagSymbolList<Symbol>,
 }
 
 #[derive(Diagnostic)]
-#[diag("invalid asm template modifier for this register class")]
+#[diag("invalid asm template modifier `{$modifier}` for this register class")]
 pub(crate) struct InvalidAsmTemplateModifierRegClass {
     #[primary_span]
     #[label("template modifier")]
     pub placeholder_span: Span,
     #[label("argument")]
     pub op_span: Span,
+    pub modifier: String,
     #[subdiagnostic]
     pub sub: InvalidAsmTemplateModifierRegClassSub,
 }
@@ -235,7 +236,7 @@ pub(crate) enum InvalidAsmTemplateModifierRegClassSub {
     #[note(
         "the `{$class_name}` register class supports the following template modifiers: {$modifiers}"
     )]
-    SupportModifier { class_name: Symbol, modifiers: String },
+    SupportModifier { class_name: Symbol, modifiers: DiagSymbolList<char> },
     #[note("the `{$class_name}` register class does not support template modifiers")]
     DoesNotSupportModifier { class_name: Symbol },
 }
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 920ca8a..b6bc122 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -640,7 +640,7 @@ fn wrap_in_try_constructor(
 
     fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
         let pat = self.lower_pat(&arm.pat);
-        let guard = arm.guard.as_ref().map(|cond| self.lower_expr(cond));
+        let guard = arm.guard.as_ref().map(|guard| self.lower_expr(&guard.cond));
         let hir_id = self.next_id();
         let span = self.lower_span(arm.span);
         self.lower_attrs(hir_id, &arm.attrs, arm.span, Target::Arm);
@@ -663,7 +663,7 @@ fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
             } else if let Some(body) = &arm.body {
                 self.dcx().emit_err(NeverPatternWithBody { span: body.span });
             } else if let Some(g) = &arm.guard {
-                self.dcx().emit_err(NeverPatternWithGuard { span: g.span });
+                self.dcx().emit_err(NeverPatternWithGuard { span: g.span() });
             }
 
             // We add a fake `loop {}` arm body so that it typecks to `!`. The mir lowering of never
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index a2be51c..5fcc8f0 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -678,7 +678,7 @@ pub fn lower_delayed_owner(tcx: TyCtxt<'_>, def_id: LocalDefId) {
 
     lowerer.lower_node(def_id);
 
-    for (&child_def_id, &owner) in &map {
+    for (child_def_id, owner) in map {
         tcx.feed_delayed_owner(child_def_id, owner);
     }
 }
@@ -1265,7 +1265,7 @@ fn lower_assoc_item_constraint(
             };
             gen_args_ctor.into_generic_args(self)
         } else {
-            self.arena.alloc(hir::GenericArgs::none())
+            hir::GenericArgs::NONE
         };
         let kind = match &constraint.kind {
             AssocItemConstraintKind::Equality { term } => {
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index aece455..40d42ff 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -133,8 +133,11 @@ fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> {
                             self.lower_range_end(end, e2.is_some()),
                         );
                     }
-                    PatKind::Guard(inner, cond) => {
-                        break hir::PatKind::Guard(self.lower_pat(inner), self.lower_expr(cond));
+                    PatKind::Guard(inner, guard) => {
+                        break hir::PatKind::Guard(
+                            self.lower_pat(inner),
+                            self.lower_expr(&guard.cond),
+                        );
                     }
                     PatKind::Slice(pats) => break self.lower_pat_slice(pats),
                     PatKind::Rest => {
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 83cebed..139140a 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -1,6 +1,7 @@
 use std::sync::Arc;
 
 use rustc_ast::{self as ast, *};
+use rustc_errors::StashKey;
 use rustc_hir::def::{DefKind, PartialRes, PerNS, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, GenericArg};
@@ -298,7 +299,7 @@ pub(crate) fn lower_path_segment(
                                 sym::return_type_notation,
                             );
                         }
-                        err.emit();
+                        err.stash(path_span, StashKey::ReturnTypeNotation);
                         (
                             GenericArgsCtor {
                                 args: Default::default(),
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index bdb0981..dd14e91 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -27,10 +27,9 @@
 use rustc_ast_pretty::pprust::{self, State};
 use rustc_attr_parsing::validate_attr;
 use rustc_data_structures::fx::FxIndexMap;
-use rustc_errors::{DiagCtxtHandle, LintBuffer};
+use rustc_errors::{DiagCtxtHandle, Diagnostic, LintBuffer};
 use rustc_feature::Features;
 use rustc_session::Session;
-use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::lint::builtin::{
     DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, MISSING_UNSAFE_ON_EXTERN,
     PATTERNS_IN_FNS_WITHOUT_BODY, UNUSED_VISIBILITIES,
@@ -1424,7 +1423,7 @@ fn visit_item(&mut self, item: &'a Item) {
                         UNUSED_VISIBILITIES,
                         item.id,
                         item.vis.span,
-                        BuiltinLintDiag::UnusedVisibility(item.vis.span),
+                        errors::UnusedVisibility { span: item.vis.span },
                     )
                 }
 
@@ -1731,14 +1730,19 @@ fn visit_fn(&mut self, fk: FnKind<'a>, attrs: &AttrVec, span: Span, id: NodeId)
             Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
                 if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) {
                     if let Some(ident) = ident {
-                        self.lint_buffer.buffer_lint(
+                        let is_foreign = matches!(ctxt, FnCtxt::Foreign);
+                        self.lint_buffer.dyn_buffer_lint(
                             PATTERNS_IN_FNS_WITHOUT_BODY,
                             id,
                             span,
-                            BuiltinLintDiag::PatternsInFnsWithoutBody {
-                                span,
-                                ident,
-                                is_foreign: matches!(ctxt, FnCtxt::Foreign),
+                            move |dcx, level| {
+                                let sub = errors::PatternsInFnsWithoutBodySub { ident, span };
+                                if is_foreign {
+                                    errors::PatternsInFnsWithoutBody::Foreign { sub }
+                                } else {
+                                    errors::PatternsInFnsWithoutBody::Bodiless { sub }
+                                }
+                                .into_diag(dcx, level)
                             },
                         )
                     }
@@ -1828,11 +1832,26 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
                     Some((right, snippet))
                 }
             };
-            self.lint_buffer.buffer_lint(
+            let left_sp = err.span;
+            self.lint_buffer.dyn_buffer_lint(
                 DEPRECATED_WHERE_CLAUSE_LOCATION,
                 item.id,
                 err.span,
-                BuiltinLintDiag::DeprecatedWhereclauseLocation(err.span, sugg),
+                move |dcx, level| {
+                    let suggestion = match sugg {
+                        Some((right_sp, sugg)) => {
+                            errors::DeprecatedWhereClauseLocationSugg::MoveToEnd {
+                                left: left_sp,
+                                right: right_sp,
+                                sugg,
+                            }
+                        }
+                        None => {
+                            errors::DeprecatedWhereClauseLocationSugg::RemoveWhere { span: left_sp }
+                        }
+                    };
+                    errors::DeprecatedWhereClauseLocation { suggestion }.into_diag(dcx, level)
+                },
             );
         }
 
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 390c155..b3a22c0 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -1150,3 +1150,72 @@ pub(crate) struct RequiresRustAbi {
     #[label("not using the Rust ABI because of this")]
     pub extern_abi_span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag("visibility qualifiers have no effect on `const _` declarations")]
+#[note("`const _` does not declare a name, so there is nothing for the qualifier to apply to")]
+pub(crate) struct UnusedVisibility {
+    #[suggestion(
+        "remove the qualifier",
+        style = "short",
+        code = "",
+        applicability = "machine-applicable"
+    )]
+    pub span: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+    "remove `mut` from the parameter",
+    code = "{ident}",
+    applicability = "machine-applicable"
+)]
+pub(crate) struct PatternsInFnsWithoutBodySub {
+    #[primary_span]
+    pub span: Span,
+
+    pub ident: Ident,
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum PatternsInFnsWithoutBody {
+    #[diag("patterns aren't allowed in foreign function declarations")]
+    Foreign {
+        #[subdiagnostic]
+        sub: PatternsInFnsWithoutBodySub,
+    },
+    #[diag("patterns aren't allowed in functions without bodies")]
+    Bodiless {
+        #[subdiagnostic]
+        sub: PatternsInFnsWithoutBodySub,
+    },
+}
+
+#[derive(Diagnostic)]
+#[diag("where clause not allowed here")]
+#[note("see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information")]
+pub(crate) struct DeprecatedWhereClauseLocation {
+    #[subdiagnostic]
+    pub suggestion: DeprecatedWhereClauseLocationSugg,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum DeprecatedWhereClauseLocationSugg {
+    #[multipart_suggestion(
+        "move it to the end of the type declaration",
+        applicability = "machine-applicable"
+    )]
+    MoveToEnd {
+        #[suggestion_part(code = "")]
+        left: Span,
+        #[suggestion_part(code = "{sugg}")]
+        right: Span,
+
+        sugg: String,
+    },
+    #[suggestion("remove this `where`", code = "", applicability = "machine-applicable")]
+    RemoveWhere {
+        #[primary_span]
+        span: Span,
+    },
+}
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index a72ed84..74cbd66 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -1786,6 +1786,23 @@ fn print_qpath(&mut self, path: &ast::Path, qself: &ast::QSelf, colons_before_pa
         }
     }
 
+    /// Print a pattern, parenthesizing it if it is an or-pattern (`A | B`).
+    ///
+    /// Or-patterns have the lowest precedence among patterns, so they need
+    /// parentheses when nested inside `@` bindings, `&` references, or `box`
+    /// patterns — otherwise `x @ A | B` parses as `(x @ A) | B`, `&A | B`
+    /// parses as `(&A) | B`, etc.
+    fn print_pat_paren_if_or(&mut self, pat: &ast::Pat) {
+        let needs_paren = matches!(pat.kind, PatKind::Or(..));
+        if needs_paren {
+            self.popen();
+        }
+        self.print_pat(pat);
+        if needs_paren {
+            self.pclose();
+        }
+    }
+
     fn print_pat(&mut self, pat: &ast::Pat) {
         self.maybe_print_comment(pat.span.lo());
         self.ann.pre(self, AnnNode::Pat(pat));
@@ -1813,7 +1830,7 @@ fn print_pat(&mut self, pat: &ast::Pat) {
                 if let Some(p) = sub {
                     self.space();
                     self.word_space("@");
-                    self.print_pat(p);
+                    self.print_pat_paren_if_or(p);
                 }
             }
             PatKind::TupleStruct(qself, path, elts) => {
@@ -1885,7 +1902,7 @@ fn print_pat(&mut self, pat: &ast::Pat) {
             }
             PatKind::Box(inner) => {
                 self.word("box ");
-                self.print_pat(inner);
+                self.print_pat_paren_if_or(inner);
             }
             PatKind::Deref(inner) => {
                 self.word("deref!");
@@ -1909,7 +1926,7 @@ fn print_pat(&mut self, pat: &ast::Pat) {
                     self.print_pat(inner);
                     self.pclose();
                 } else {
-                    self.print_pat(inner);
+                    self.print_pat_paren_if_or(inner);
                 }
             }
             PatKind::Expr(e) => self.print_expr(e, FixupContext::default()),
@@ -1926,12 +1943,12 @@ fn print_pat(&mut self, pat: &ast::Pat) {
                     self.print_expr(e, FixupContext::default());
                 }
             }
-            PatKind::Guard(subpat, condition) => {
+            PatKind::Guard(subpat, guard) => {
                 self.popen();
                 self.print_pat(subpat);
                 self.space();
                 self.word_space("if");
-                self.print_expr(condition, FixupContext::default());
+                self.print_expr(&guard.cond, FixupContext::default());
                 self.pclose();
             }
             PatKind::Slice(elts) => {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 0c59287..ad602d5 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -891,9 +891,9 @@ fn print_arm(&mut self, arm: &ast::Arm) {
         self.print_outer_attributes(&arm.attrs);
         self.print_pat(&arm.pat);
         self.space();
-        if let Some(e) = &arm.guard {
+        if let Some(guard) = &arm.guard {
             self.word_space("if");
-            self.print_expr(e, FixupContext::default());
+            self.print_expr(&guard.cond, FixupContext::default());
             self.space();
         }
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/autodiff.rs b/compiler/rustc_attr_parsing/src/attributes/autodiff.rs
index 118a410..edd9d9c 100644
--- a/compiler/rustc_attr_parsing/src/attributes/autodiff.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/autodiff.rs
@@ -9,7 +9,7 @@
 use thin_vec::ThinVec;
 
 use crate::attributes::prelude::Allow;
-use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
+use crate::attributes::{OnDuplicate, SingleAttributeParser};
 use crate::context::{AcceptContext, Stage};
 use crate::parser::{ArgParser, MetaItemOrLitParser};
 use crate::target_checking::AllowedTargets;
@@ -18,12 +18,12 @@
 
 impl<S: Stage> SingleAttributeParser<S> for RustcAutodiffParser {
     const PATH: &[Symbol] = &[sym::rustc_autodiff];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
         Allow(Target::Fn),
         Allow(Target::Method(MethodKind::Inherent)),
         Allow(Target::Method(MethodKind::Trait { body: true })),
+        Allow(Target::Method(MethodKind::Trait { body: false })),
         Allow(Target::Method(MethodKind::TraitImpl)),
     ]);
     const TEMPLATE: AttributeTemplate = template!(
diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs
index d2f743f..badf696 100644
--- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs
@@ -20,7 +20,9 @@
 use thin_vec::ThinVec;
 
 use crate::context::{AcceptContext, ShouldEmit, Stage};
-use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser};
+use crate::parser::{
+    AllowExprMetavar, ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser,
+};
 use crate::session_diagnostics::{
     AttributeParseError, AttributeParseErrorReason, CfgAttrBadDelim, MetaBadDelimSugg,
     ParsedDescription,
@@ -363,6 +365,7 @@ fn parse_cfg_attr_internal<'a>(
     let meta = MetaItemOrLitParser::parse_single(
         parser,
         ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
+        AllowExprMetavar::Yes,
     )?;
     let pred_span = pred_start.with_hi(parser.token.span.hi());
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs
index 7377159..4ff2240 100644
--- a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs
@@ -2,18 +2,18 @@
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{AttrStyle, NodeId, token};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::Diagnostic;
 use rustc_feature::{AttributeTemplate, Features};
 use rustc_hir::attrs::CfgEntry;
 use rustc_hir::{AttrPath, Target};
 use rustc_parse::exp;
 use rustc_parse::parser::{Parser, Recovery};
 use rustc_session::Session;
-use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::lint::builtin::UNREACHABLE_CFG_SELECT_PREDICATES;
 use rustc_span::{ErrorGuaranteed, Span, Symbol, sym};
 
-use crate::parser::MetaItemOrLitParser;
-use crate::{AttributeParser, ParsedDescription, ShouldEmit, parse_cfg_entry};
+use crate::parser::{AllowExprMetavar, MetaItemOrLitParser};
+use crate::{AttributeParser, ParsedDescription, ShouldEmit, errors, parse_cfg_entry};
 
 #[derive(Clone)]
 pub enum CfgSelectPredicate {
@@ -94,6 +94,7 @@ pub fn parse_cfg_select(
             let meta = MetaItemOrLitParser::parse_single(
                 p,
                 ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
+                AllowExprMetavar::Yes,
             )
             .map_err(|diag| diag.emit())?;
             let cfg_span = meta.span();
@@ -152,11 +153,17 @@ fn lint_unreachable(
 
     let branch_is_unreachable = |predicate: CfgSelectPredicate, wildcard_span| {
         let span = predicate.span();
-        p.psess.buffer_lint(
+        p.psess.dyn_buffer_lint(
             UNREACHABLE_CFG_SELECT_PREDICATES,
             span,
             lint_node_id,
-            BuiltinLintDiag::UnreachableCfg { span, wildcard_span },
+            move |dcx, level| match wildcard_span {
+                Some(wildcard_span) => {
+                    errors::UnreachableCfgSelectPredicateWildcard { span, wildcard_span }
+                        .into_diag(dcx, level)
+                }
+                None => errors::UnreachableCfgSelectPredicate { span }.into_diag(dcx, level),
+            },
         );
     };
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs b/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs
index df1e569..3396976 100644
--- a/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/cfi_encoding.rs
@@ -8,7 +8,6 @@ impl<S: Stage> SingleAttributeParser<S> for CfiEncodingParser {
         Allow(Target::Enum),
         Allow(Target::Union),
     ]);
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "encoding");
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
index 652a783..dbf289e 100644
--- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
@@ -12,7 +12,6 @@
 
 impl<S: Stage> SingleAttributeParser<S> for OptimizeParser {
     const PATH: &[Symbol] = &[sym::optimize];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
         Allow(Target::Fn),
@@ -68,7 +67,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for ColdParser {
 
 impl<S: Stage> SingleAttributeParser<S> for CoverageParser {
     const PATH: &[Symbol] = &[sym::coverage];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
         Allow(Target::Fn),
@@ -119,7 +117,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
 
 impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
     const PATH: &[rustc_span::Symbol] = &[sym::export_name];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
         Allow(Target::Static),
@@ -157,7 +154,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
 
 impl<S: Stage> SingleAttributeParser<S> for RustcObjcClassParser {
     const PATH: &[rustc_span::Symbol] = &[sym::rustc_objc_class];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets =
         AllowedTargets::AllowList(&[Allow(Target::ForeignStatic)]);
@@ -189,7 +185,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
 
 impl<S: Stage> SingleAttributeParser<S> for RustcObjcSelectorParser {
     const PATH: &[rustc_span::Symbol] = &[sym::rustc_objc_selector];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets =
         AllowedTargets::AllowList(&[Allow(Target::ForeignStatic)]);
@@ -587,6 +582,7 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
         r#"kernel_address = "on|off""#,
         r#"cfi = "on|off""#,
         r#"hwaddress = "on|off""#,
+        r#"kernel_hwaddress = "on|off""#,
         r#"kcfi = "on|off""#,
         r#"memory = "on|off""#,
         r#"memtag = "on|off""#,
@@ -595,7 +591,6 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
         r#"realtime = "nonblocking|blocking|caller""#,
     ]);
 
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
@@ -654,7 +649,9 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
                 Some(sym::memtag) => apply(SanitizerSet::MEMTAG),
                 Some(sym::shadow_call_stack) => apply(SanitizerSet::SHADOWCALLSTACK),
                 Some(sym::thread) => apply(SanitizerSet::THREAD),
-                Some(sym::hwaddress) => apply(SanitizerSet::HWADDRESS),
+                Some(sym::hwaddress) | Some(sym::kernel_hwaddress) => {
+                    apply(SanitizerSet::HWADDRESS | SanitizerSet::KERNELHWADDRESS)
+                }
                 Some(sym::realtime) => match value.value_as_str() {
                     Some(sym::nonblocking) => rtsan = Some(RtsanSetting::Nonblocking),
                     Some(sym::blocking) => rtsan = Some(RtsanSetting::Blocking),
@@ -679,6 +676,7 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
                             sym::shadow_call_stack,
                             sym::thread,
                             sym::hwaddress,
+                            sym::kernel_hwaddress,
                             sym::realtime,
                         ],
                     );
@@ -724,7 +722,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcEiiForeignItemParser {
 impl<S: Stage> SingleAttributeParser<S> for PatchableFunctionEntryParser {
     const PATH: &[Symbol] = &[sym::patchable_function_entry];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
     const TEMPLATE: AttributeTemplate = template!(List: &["prefix_nops = m, entry_nops = n"]);
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
index 2d2994c..72a0945 100644
--- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
@@ -10,7 +10,6 @@
 
 impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
     const PATH: &[Symbol] = &[sym::crate_name];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
@@ -84,7 +83,6 @@ fn extend(
 
 impl<S: Stage> SingleAttributeParser<S> for RecursionLimitParser {
     const PATH: &[Symbol] = &[sym::recursion_limit];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute");
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
@@ -107,7 +105,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
 
 impl<S: Stage> SingleAttributeParser<S> for MoveSizeLimitParser {
     const PATH: &[Symbol] = &[sym::move_size_limit];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
@@ -130,7 +127,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
 
 impl<S: Stage> SingleAttributeParser<S> for TypeLengthLimitParser {
     const PATH: &[Symbol] = &[sym::type_length_limit];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
@@ -153,7 +149,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
 
 impl<S: Stage> SingleAttributeParser<S> for PatternComplexityLimitParser {
     const PATH: &[Symbol] = &[sym::pattern_complexity_limit];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
@@ -213,7 +208,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcCoherenceIsCoreParser {
 impl<S: Stage> SingleAttributeParser<S> for WindowsSubsystemParser {
     const PATH: &[Symbol] = &[sym::windows_subsystem];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: ["windows", "console"], "https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute");
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs
index a2c7e45..804b54e 100644
--- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs
@@ -34,7 +34,6 @@ fn get<S: Stage>(
 pub(crate) struct DeprecatedParser;
 impl<S: Stage> SingleAttributeParser<S> for DeprecatedParser {
     const PATH: &[Symbol] = &[sym::deprecated];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
         Allow(Target::Fn),
diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs
index 4a89cf6..9f3d1e2 100644
--- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/do_not_recommend.rs
@@ -4,7 +4,7 @@
 use rustc_session::lint::builtin::MALFORMED_DIAGNOSTIC_ATTRIBUTES;
 use rustc_span::{Symbol, sym};
 
-use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
+use crate::attributes::{OnDuplicate, SingleAttributeParser};
 use crate::context::{AcceptContext, Stage};
 use crate::parser::ArgParser;
 use crate::target_checking::{ALL_TARGETS, AllowedTargets};
@@ -12,7 +12,6 @@
 pub(crate) struct DoNotRecommendParser;
 impl<S: Stage> SingleAttributeParser<S> for DoNotRecommendParser {
     const PATH: &[Symbol] = &[sym::diagnostic, sym::do_not_recommend];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); // Checked in check_attr.
     const TEMPLATE: AttributeTemplate = template!(Word /*doesn't matter */);
diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs
index 6378067..8abcaeb 100644
--- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs
@@ -470,11 +470,12 @@ fn parse_filter(input: Symbol) -> FilterFormatString {
                 // if the integer type has been resolved, to allow targeting all integers.
                 // `"{integer}"` and `"{float}"` come from numerics that haven't been inferred yet,
                 // from the `Display` impl of `InferTy` to be precise.
+                // `"{union|enum|struct}"` is used as a special selector for ADTs.
                 //
                 // Don't try to format these later!
-                Position::ArgumentNamed(arg @ ("integer" | "integral" | "float")) => {
-                    LitOrArg::Lit(Symbol::intern(&format!("{{{arg}}}")))
-                }
+                Position::ArgumentNamed(
+                    arg @ ("integer" | "integral" | "float" | "union" | "enum" | "struct"),
+                ) => LitOrArg::Lit(Symbol::intern(&format!("{{{arg}}}"))),
 
                 Position::ArgumentNamed(arg) => LitOrArg::Arg(Symbol::intern(arg)),
                 Position::ArgumentImplicitlyIs(_) => LitOrArg::Lit(sym::empty_braces),
diff --git a/compiler/rustc_attr_parsing/src/attributes/dummy.rs b/compiler/rustc_attr_parsing/src/attributes/dummy.rs
index 71d10b2..ee5c507 100644
--- a/compiler/rustc_attr_parsing/src/attributes/dummy.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/dummy.rs
@@ -2,7 +2,7 @@
 use rustc_hir::attrs::AttributeKind;
 use rustc_span::{Symbol, sym};
 
-use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
+use crate::attributes::{OnDuplicate, SingleAttributeParser};
 use crate::context::{AcceptContext, Stage};
 use crate::parser::ArgParser;
 use crate::target_checking::{ALL_TARGETS, AllowedTargets};
@@ -10,7 +10,6 @@
 pub(crate) struct RustcDummyParser;
 impl<S: Stage> SingleAttributeParser<S> for RustcDummyParser {
     const PATH: &[Symbol] = &[sym::rustc_dummy];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
     const TEMPLATE: AttributeTemplate = template!(Word); // Anything, really
diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs
index 767200b..82cec25 100644
--- a/compiler/rustc_attr_parsing/src/attributes/inline.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs
@@ -11,7 +11,6 @@
 
 impl<S: Stage> SingleAttributeParser<S> for InlineParser {
     const PATH: &[Symbol] = &[sym::inline];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
         Allow(Target::Fn),
@@ -68,7 +67,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
 
 impl<S: Stage> SingleAttributeParser<S> for RustcForceInlineParser {
     const PATH: &[Symbol] = &[sym::rustc_force_inline];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
         Allow(Target::Fn),
diff --git a/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs b/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs
index 3be9b9d..5f61081 100644
--- a/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs
@@ -16,7 +16,6 @@ impl<S: Stage> SingleAttributeParser<S> for InstructionSetParser {
     ]);
     const TEMPLATE: AttributeTemplate = template!(List: &["set"], "https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute");
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
         const POSSIBLE_SYMBOLS: &[Symbol] = &[sym::arm_a32, sym::arm_t32];
diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
index c4a4831..52ab4ac 100644
--- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
@@ -22,7 +22,6 @@
 
 impl<S: Stage> SingleAttributeParser<S> for LinkNameParser {
     const PATH: &[Symbol] = &[sym::link_name];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
         Allow(Target::ForeignFn),
@@ -466,7 +465,6 @@ fn parse_link_import_name_type<S: Stage>(
 
 impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {
     const PATH: &[Symbol] = &[sym::link_section];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
         Allow(Target::Static),
@@ -541,7 +539,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcStdInternalSymbolParser {
 
 impl<S: Stage> SingleAttributeParser<S> for LinkOrdinalParser {
     const PATH: &[Symbol] = &[sym::link_ordinal];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
         Allow(Target::ForeignFn),
@@ -583,8 +580,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
 impl<S: Stage> SingleAttributeParser<S> for LinkageParser {
     const PATH: &[Symbol] = &[sym::linkage];
 
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
-
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
         Allow(Target::Fn),
diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
index 00d4068..86dde5b 100644
--- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
@@ -130,7 +130,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for AllowInternalUnsafeParser {
 
 impl<S: Stage> SingleAttributeParser<S> for MacroExportParser {
     const PATH: &[Symbol] = &[sym::macro_export];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
     const TEMPLATE: AttributeTemplate = template!(Word, List: &["local_inner_macros"]);
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
@@ -168,7 +167,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
 
 impl<S: Stage> SingleAttributeParser<S> for CollapseDebugInfoParser {
     const PATH: &[Symbol] = &[sym::collapse_debuginfo];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const TEMPLATE: AttributeTemplate = template!(
         List: &["no", "external", "yes"],
diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs
index 223c889..6714764 100644
--- a/compiler/rustc_attr_parsing/src/attributes/mod.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs
@@ -124,14 +124,8 @@ pub(crate) trait SingleAttributeParser<S: Stage>: 'static {
     /// If you need the parser to accept more than one path, use [`AttributeParser`] instead
     const PATH: &[Symbol];
 
-    /// Configures the precedence of attributes with the same `PATH` on a syntax node.
-    const ATTRIBUTE_ORDER: AttributeOrder;
-
     /// Configures what to do when when the same attribute is
     /// applied more than once on the same syntax node.
-    ///
-    /// [`ATTRIBUTE_ORDER`](Self::ATTRIBUTE_ORDER) specified which one is assumed to be correct,
-    /// and this specified whether to, for example, warn or error on the other one.
     const ON_DUPLICATE: OnDuplicate<S>;
 
     const ALLOWED_TARGETS: AllowedTargets;
@@ -162,21 +156,8 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
         <T as SingleAttributeParser<S>>::TEMPLATE,
         |group: &mut Single<T, S>, cx, args| {
             if let Some(pa) = T::convert(cx, args) {
-                match T::ATTRIBUTE_ORDER {
-                    // keep the first and report immediately. ignore this attribute
-                    AttributeOrder::KeepInnermost => {
-                        if let Some((_, unused)) = group.1 {
-                            T::ON_DUPLICATE.exec::<T>(cx, cx.attr_span, unused);
-                            return;
-                        }
-                    }
-                    // keep the new one and warn about the previous,
-                    // then replace
-                    AttributeOrder::KeepOutermost => {
-                        if let Some((_, used)) = group.1 {
-                            T::ON_DUPLICATE.exec::<T>(cx, used, cx.attr_span);
-                        }
-                    }
+                if let Some((_, used)) = group.1 {
+                    T::ON_DUPLICATE.exec::<T>(cx, used, cx.attr_span);
                 }
 
                 group.1 = Some((pa, cx.attr_span));
@@ -206,7 +187,7 @@ pub(crate) enum OnDuplicate<S: Stage> {
     /// Custom function called when a duplicate attribute is found.
     ///
     /// - `unused` is the span of the attribute that was unused or bad because of some
-    ///   duplicate reason (see [`AttributeOrder`])
+    ///   duplicate reason
     /// - `used` is the span of the attribute that was used in favor of the unused attribute
     Custom(fn(cx: &AcceptContext<'_, '_, S>, used: Span, unused: Span)),
 }
@@ -223,8 +204,8 @@ fn exec<P: SingleAttributeParser<S>>(
             OnDuplicate::WarnButFutureError => cx.warn_unused_duplicate_future_error(used, unused),
             OnDuplicate::Error => {
                 cx.emit_err(UnusedMultiple {
-                    this: used,
-                    other: unused,
+                    this: unused,
+                    other: used,
                     name: Symbol::intern(
                         &P::PATH.into_iter().map(|i| i.to_string()).collect::<Vec<_>>().join(".."),
                     ),
@@ -236,30 +217,6 @@ fn exec<P: SingleAttributeParser<S>>(
     }
 }
 
-pub(crate) enum AttributeOrder {
-    /// Duplicates after the innermost instance of the attribute will be an error/warning.
-    /// Only keep the lowest attribute.
-    ///
-    /// Attributes are processed from bottom to top, so this raises a warning/error on all the attributes
-    /// further above the lowest one:
-    /// ```
-    /// #[stable(since="1.0")] //~ WARNING duplicated attribute
-    /// #[stable(since="2.0")]
-    /// ```
-    KeepInnermost,
-
-    /// Duplicates before the outermost instance of the attribute will be an error/warning.
-    /// Only keep the highest attribute.
-    ///
-    /// Attributes are processed from bottom to top, so this raises a warning/error on all the attributes
-    /// below the highest one:
-    /// ```
-    /// #[path="foo.rs"]
-    /// #[path="bar.rs"] //~ WARNING duplicated attribute
-    /// ```
-    KeepOutermost,
-}
-
 /// An even simpler version of [`SingleAttributeParser`]:
 /// now automatically check that there are no arguments provided to the attribute.
 ///
@@ -284,7 +241,6 @@ fn default() -> Self {
 
 impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for WithoutArgs<T, S> {
     const PATH: &[Symbol] = T::PATH;
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE;
     const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
     const TEMPLATE: AttributeTemplate = template!(Word);
diff --git a/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs b/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs
index 8456ce7..7f37210 100644
--- a/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs
@@ -4,7 +4,6 @@
 
 impl<S: Stage> SingleAttributeParser<S> for MustNotSuspendParser {
     const PATH: &[rustc_span::Symbol] = &[sym::must_not_suspend];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
         Allow(Target::Struct),
diff --git a/compiler/rustc_attr_parsing/src/attributes/must_use.rs b/compiler/rustc_attr_parsing/src/attributes/must_use.rs
index 673e2c9..f1ce810 100644
--- a/compiler/rustc_attr_parsing/src/attributes/must_use.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/must_use.rs
@@ -4,7 +4,6 @@
 
 impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
     const PATH: &[Symbol] = &[sym::must_use];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
         Allow(Target::Fn),
diff --git a/compiler/rustc_attr_parsing/src/attributes/path.rs b/compiler/rustc_attr_parsing/src/attributes/path.rs
index b60f8e3..6b5eee7 100644
--- a/compiler/rustc_attr_parsing/src/attributes/path.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/path.rs
@@ -4,7 +4,6 @@
 
 impl<S: Stage> SingleAttributeParser<S> for PathParser {
     const PATH: &[Symbol] = &[sym::path];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
     const ALLOWED_TARGETS: AllowedTargets =
         AllowedTargets::AllowListWarnRest(&[Allow(Target::Mod), Error(Target::Crate)]);
diff --git a/compiler/rustc_attr_parsing/src/attributes/prelude.rs b/compiler/rustc_attr_parsing/src/attributes/prelude.rs
index 65c408f..53adf7e 100644
--- a/compiler/rustc_attr_parsing/src/attributes/prelude.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/prelude.rs
@@ -12,8 +12,8 @@
 
 #[doc(hidden)]
 pub(super) use crate::attributes::{
-    AcceptMapping, AttributeOrder, AttributeParser, CombineAttributeParser, ConvertFn,
-    NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
+    AcceptMapping, AttributeParser, CombineAttributeParser, ConvertFn, NoArgsAttributeParser,
+    OnDuplicate, SingleAttributeParser,
 };
 // contexts
 #[doc(hidden)]
diff --git a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs
index f9ace7e..aca0e94 100644
--- a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs
@@ -25,7 +25,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroAttributeParser {
 pub(crate) struct ProcMacroDeriveParser;
 impl<S: Stage> SingleAttributeParser<S> for ProcMacroDeriveParser {
     const PATH: &[Symbol] = &[sym::proc_macro_derive];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = PROC_MACRO_ALLOWED_TARGETS;
     const TEMPLATE: AttributeTemplate = template!(
@@ -46,7 +45,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
 pub(crate) struct RustcBuiltinMacroParser;
 impl<S: Stage> SingleAttributeParser<S> for RustcBuiltinMacroParser {
     const PATH: &[Symbol] = &[sym::rustc_builtin_macro];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]);
     const TEMPLATE: AttributeTemplate =
diff --git a/compiler/rustc_attr_parsing/src/attributes/prototype.rs b/compiler/rustc_attr_parsing/src/attributes/prototype.rs
index 8eb902b..15d9d34 100644
--- a/compiler/rustc_attr_parsing/src/attributes/prototype.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/prototype.rs
@@ -5,7 +5,7 @@
 use rustc_hir::attrs::{AttributeKind, MirDialect, MirPhase};
 use rustc_span::{Span, Symbol, sym};
 
-use super::{AttributeOrder, OnDuplicate};
+use super::OnDuplicate;
 use crate::attributes::SingleAttributeParser;
 use crate::context::{AcceptContext, Stage};
 use crate::parser::ArgParser;
@@ -18,8 +18,6 @@
 impl<S: Stage> SingleAttributeParser<S> for CustomMirParser {
     const PATH: &[rustc_span::Symbol] = &[sym::custom_mir];
 
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
-
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
 
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_allocator.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_allocator.rs
index 5782f94..e809ad9 100644
--- a/compiler/rustc_attr_parsing/src/attributes/rustc_allocator.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/rustc_allocator.rs
@@ -28,7 +28,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcAllocatorZeroedVariantParser {
     const ALLOWED_TARGETS: AllowedTargets =
         AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]);
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "function");
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
         let Some(name) = args.name_value().and_then(NameValueParser::value_as_str) else {
             cx.expected_name_value(cx.attr_span, None);
diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs
index e8b4cb3..15772d8 100644
--- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs
@@ -31,7 +31,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcMustImplementOneOfParser {
     const PATH: &[Symbol] = &[sym::rustc_must_implement_one_of];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const TEMPLATE: AttributeTemplate = template!(List: &["function1, function2, ..."]);
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
         let Some(list) = args.list() else {
@@ -105,7 +104,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcNoImplicitAutorefsParser {
 
 impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeStartParser {
     const PATH: &[Symbol] = &[sym::rustc_layout_scalar_valid_range_start];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
     const TEMPLATE: AttributeTemplate = template!(List: &["start"]);
@@ -120,7 +118,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
 
 impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeEndParser {
     const PATH: &[Symbol] = &[sym::rustc_layout_scalar_valid_range_end];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
     const TEMPLATE: AttributeTemplate = template!(List: &["end"]);
@@ -135,7 +132,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
 
 impl<S: Stage> SingleAttributeParser<S> for RustcLegacyConstGenericsParser {
     const PATH: &[Symbol] = &[sym::rustc_legacy_const_generics];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
     const TEMPLATE: AttributeTemplate = template!(List: &["N"]);
@@ -193,7 +189,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcInheritOverflowChecksParser {
 
 impl<S: Stage> SingleAttributeParser<S> for RustcLintOptDenyFieldAccessParser {
     const PATH: &[Symbol] = &[sym::rustc_lint_opt_deny_field_access];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Field)]);
     const TEMPLATE: AttributeTemplate = template!(Word);
@@ -373,7 +368,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcDeprecatedSafe2024Parser {
         Allow(Target::Method(MethodKind::Trait { body: true })),
         Allow(Target::Method(MethodKind::TraitImpl)),
     ]);
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const TEMPLATE: AttributeTemplate = template!(List: &[r#"audit_that = "...""#]);
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
@@ -441,7 +435,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcNeverTypeOptionsParser {
     const PATH: &[Symbol] = &[sym::rustc_never_type_options];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const TEMPLATE: AttributeTemplate = template!(List: &[
         r#"fallback = "unit", "never", "no""#,
         r#"diverging_block_default = "unit", "never""#,
@@ -592,7 +585,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcLintUntrackedQueryInformationPa
 
 impl<S: Stage> SingleAttributeParser<S> for RustcSimdMonomorphizeLaneLimitParser {
     const PATH: &[Symbol] = &[sym::rustc_simd_monomorphize_lane_limit];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
@@ -610,7 +602,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
 
 impl<S: Stage> SingleAttributeParser<S> for RustcScalableVectorParser {
     const PATH: &[Symbol] = &[sym::rustc_scalable_vector];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
     const TEMPLATE: AttributeTemplate = template!(Word, List: &["count"]);
@@ -636,7 +627,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
 
 impl<S: Stage> SingleAttributeParser<S> for LangParser {
     const PATH: &[Symbol] = &[sym::lang];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); // Targets are checked per lang item in `rustc_passes`
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
@@ -981,8 +971,6 @@ fn extend(
 impl<S: Stage> SingleAttributeParser<S> for RustcIfThisChangedParser {
     const PATH: &[Symbol] = &[sym::rustc_if_this_changed];
 
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
-
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
 
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
@@ -1147,7 +1135,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcEffectiveVisibilityParser {
 
 impl<S: Stage> SingleAttributeParser<S> for RustcDiagnosticItemParser {
     const PATH: &[Symbol] = &[sym::rustc_diagnostic_item];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
         Allow(Target::Trait),
@@ -1220,7 +1207,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcSymbolNameParser {
         Allow(Target::Impl { of_trait: false }),
     ]);
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const TEMPLATE: AttributeTemplate = template!(Word);
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
         if let Err(span) = args.no_args() {
@@ -1245,7 +1231,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcDefPathParser {
         Allow(Target::Impl { of_trait: false }),
     ]);
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const TEMPLATE: AttributeTemplate = template!(Word);
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
         if let Err(span) = args.no_args() {
@@ -1275,7 +1260,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcStrictCoherenceParser {
 
 impl<S: Stage> SingleAttributeParser<S> for RustcReservationImplParser {
     const PATH: &[Symbol] = &[sym::rustc_reservation_impl];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets =
         AllowedTargets::AllowList(&[Allow(Target::Impl { of_trait: true })]);
@@ -1311,7 +1295,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for PreludeImportParser {
 impl<S: Stage> SingleAttributeParser<S> for RustcDocPrimitiveParser {
     const PATH: &[Symbol] = &[sym::rustc_doc_primitive];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Mod)]);
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "primitive name");
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs
index 6ddd9f2..25b295c 100644
--- a/compiler/rustc_attr_parsing/src/attributes/stability.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs
@@ -1,6 +1,7 @@
 use std::num::NonZero;
 
 use rustc_errors::ErrorGuaranteed;
+use rustc_feature::ACCEPTED_LANG_FEATURES;
 use rustc_hir::target::GenericParamKind;
 use rustc_hir::{
     DefaultBodyStability, MethodKind, PartialConstStability, Stability, StabilityLevel,
@@ -366,7 +367,7 @@ pub(crate) fn parse_stability<S: Stage>(
     }
 }
 
-// Read the content of a `unstable`/`rustc_const_unstable`/`rustc_default_body_unstable`
+/// Read the content of a `unstable`/`rustc_const_unstable`/`rustc_default_body_unstable`
 /// attribute, and return the feature name and its stability information.
 pub(crate) fn parse_unstability<S: Stage>(
     cx: &AcceptContext<'_, '_, S>,
@@ -451,6 +452,16 @@ pub(crate) fn parse_unstability<S: Stage>(
 
     match (feature, issue) {
         (Ok(feature), Ok(_)) => {
+            // Stable *language* features shouldn't be used as unstable library features.
+            // (Not doing this for stable library features is checked by tidy.)
+            if ACCEPTED_LANG_FEATURES.iter().any(|f| f.name == feature) {
+                cx.emit_err(session_diagnostics::UnstableAttrForAlreadyStableFeature {
+                    attr_span: cx.attr_span,
+                    item_span: cx.target_span,
+                });
+                return None;
+            }
+
             let level = StabilityLevel::Unstable {
                 reason: UnstableReason::from_opt_reason(reason),
                 issue: issue_num,
diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs
index 2775eab..db0350f 100644
--- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs
@@ -7,7 +7,6 @@
 
 impl<S: Stage> SingleAttributeParser<S> for IgnoreParser {
     const PATH: &[Symbol] = &[sym::ignore];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
     const ALLOWED_TARGETS: AllowedTargets =
         AllowedTargets::AllowListWarnRest(&[Allow(Target::Fn), Error(Target::WherePredicate)]);
@@ -41,7 +40,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
 
 impl<S: Stage> SingleAttributeParser<S> for ShouldPanicParser {
     const PATH: &[Symbol] = &[sym::should_panic];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
     const ALLOWED_TARGETS: AllowedTargets =
         AllowedTargets::AllowListWarnRest(&[Allow(Target::Fn), Error(Target::WherePredicate)]);
@@ -98,7 +96,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
 impl<S: Stage> SingleAttributeParser<S> for ReexportTestHarnessMainParser {
     const PATH: &[Symbol] = &[sym::reexport_test_harness_main];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
 
@@ -126,7 +123,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcAbiParser {
     const PATH: &[Symbol] = &[sym::rustc_abi];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
     const TEMPLATE: AttributeTemplate = template!(OneOf: &[sym::debug, sym::assert_eq]);
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
         Allow(Target::TyAlias),
         Allow(Target::Fn),
@@ -197,7 +193,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcEvaluateWhereClausesParser {
 
 impl<S: Stage> SingleAttributeParser<S> for TestRunnerParser {
     const PATH: &[Symbol] = &[sym::test_runner];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
     const TEMPLATE: AttributeTemplate = template!(List: &["path"]);
@@ -226,7 +221,6 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
 
 impl<S: Stage> SingleAttributeParser<S> for RustcTestMarkerParser {
     const PATH: &[Symbol] = &[sym::rustc_test_marker];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
         Allow(Target::Const),
diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs
index c09e151..c418d1d 100644
--- a/compiler/rustc_attr_parsing/src/attributes/traits.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs
@@ -1,9 +1,7 @@
 use std::mem;
 
 use super::prelude::*;
-use crate::attributes::{
-    AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
-};
+use crate::attributes::{NoArgsAttributeParser, OnDuplicate, SingleAttributeParser};
 use crate::context::{AcceptContext, Stage};
 use crate::parser::ArgParser;
 use crate::target_checking::Policy::{Allow, Warn};
@@ -12,7 +10,6 @@
 pub(crate) struct RustcSkipDuringMethodDispatchParser;
 impl<S: Stage> SingleAttributeParser<S> for RustcSkipDuringMethodDispatchParser {
     const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/transparency.rs b/compiler/rustc_attr_parsing/src/attributes/transparency.rs
index 58b4a0b..c381740 100644
--- a/compiler/rustc_attr_parsing/src/attributes/transparency.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/transparency.rs
@@ -6,7 +6,6 @@
 
 impl<S: Stage> SingleAttributeParser<S> for RustcMacroTransparencyParser {
     const PATH: &[Symbol] = &[sym::rustc_macro_transparency];
-    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Custom(|cx, used, unused| {
         cx.dcx().span_err(vec![used, unused], "multiple macro transparency attributes");
     });
diff --git a/compiler/rustc_attr_parsing/src/errors.rs b/compiler/rustc_attr_parsing/src/errors.rs
new file mode 100644
index 0000000..d423641
--- /dev/null
+++ b/compiler/rustc_attr_parsing/src/errors.rs
@@ -0,0 +1,52 @@
+use rustc_errors::MultiSpan;
+use rustc_macros::{Diagnostic, Subdiagnostic};
+use rustc_span::{Span, Symbol};
+
+#[derive(Diagnostic)]
+#[diag("`{$name}` attribute cannot be used at crate level")]
+pub(crate) struct InvalidAttrAtCrateLevel {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(
+        "perhaps you meant to use an outer attribute",
+        code = "#[",
+        applicability = "machine-applicable",
+        style = "verbose"
+    )]
+    pub pound_to_opening_bracket: Span,
+    pub name: Symbol,
+    #[subdiagnostic]
+    pub item: Option<ItemFollowingInnerAttr>,
+}
+
+#[derive(Clone, Copy, Subdiagnostic)]
+#[label("the inner attribute doesn't annotate this item")]
+pub(crate) struct ItemFollowingInnerAttr {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag("unreachable configuration predicate")]
+pub(crate) struct UnreachableCfgSelectPredicate {
+    #[label("this configuration predicate is never reached")]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag("most attributes are not supported in `where` clauses")]
+#[help("only `#[cfg]` and `#[cfg_attr]` are supported")]
+pub(crate) struct UnsupportedAttributesInWhere {
+    #[primary_span]
+    pub span: MultiSpan,
+}
+
+#[derive(Diagnostic)]
+#[diag("unreachable configuration predicate")]
+pub(crate) struct UnreachableCfgSelectPredicateWildcard {
+    #[label("this configuration predicate is never reached")]
+    pub span: Span,
+
+    #[label("always matches")]
+    pub wildcard_span: Span,
+}
diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs
index f75f63a..7305c4b 100644
--- a/compiler/rustc_attr_parsing/src/interface.rs
+++ b/compiler/rustc_attr_parsing/src/interface.rs
@@ -14,7 +14,7 @@
 
 use crate::context::{AcceptContext, FinalizeContext, FinalizeFn, SharedContext, Stage};
 use crate::early_parsed::{EARLY_PARSED_ATTRIBUTES, EarlyParsedState};
-use crate::parser::{ArgParser, PathParser, RefPathParser};
+use crate::parser::{AllowExprMetavar, ArgParser, PathParser, RefPathParser};
 use crate::session_diagnostics::ParsedDescription;
 use crate::{Early, Late, OmitDoc, ShouldEmit};
 
@@ -139,6 +139,7 @@ pub fn parse_single<T>(
         emit_errors: ShouldEmit,
         parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser) -> Option<T>,
         template: &AttributeTemplate,
+        allow_expr_metavar: AllowExprMetavar,
     ) -> Option<T> {
         let ast::AttrKind::Normal(normal_attr) = &attr.kind else {
             panic!("parse_single called on a doc attr")
@@ -152,6 +153,7 @@ pub fn parse_single<T>(
             &parts,
             &sess.psess,
             emit_errors,
+            allow_expr_metavar,
         )?;
         Self::parse_single_args(
             sess,
@@ -267,6 +269,11 @@ pub fn parse_attribute_list(
         mut emit_lint: impl FnMut(LintId, Span, AttributeLintKind),
     ) -> Vec<Attribute> {
         let mut attributes = Vec::new();
+        // We store the attributes we intend to discard at the end of this function in order to
+        // check they are applied to the right target and error out if necessary. In practice, we
+        // end up dropping only derive attributes and derive helpers, both being fully processed
+        // at macro expansion.
+        let mut dropped_attributes = Vec::new();
         let mut attr_paths: Vec<RefPathParser<'_>> = Vec::new();
         let mut early_parsed_state = EarlyParsedState::default();
 
@@ -302,7 +309,7 @@ pub fn parse_attribute_list(
                         kind: DocFragmentKind::Sugared(*comment_kind),
                         span: attr_span,
                         comment: *symbol,
-                    }))
+                    }));
                 }
                 ast::AttrKind::Normal(n) => {
                     attr_paths.push(PathParser(&n.item.path));
@@ -333,6 +340,7 @@ pub fn parse_attribute_list(
                             &parts,
                             &self.sess.psess,
                             self.stage.should_emit(),
+                            AllowExprMetavar::No,
                         ) else {
                             continue;
                         };
@@ -390,29 +398,33 @@ pub fn parse_attribute_list(
                             Self::check_target(&accept.allowed_targets, target, &mut cx);
                         }
                     } else {
-                        // If we're here, we must be compiling a tool attribute... Or someone
-                        // forgot to parse their fancy new attribute. Let's warn them in any case.
-                        // If you are that person, and you really think your attribute should
-                        // remain unparsed, carefully read the documentation in this module and if
-                        // you still think so you can add an exception to this assertion.
-
-                        // FIXME(jdonszelmann): convert other attributes, and check with this that
-                        // we caught em all
-                        // const FIXME_TEMPORARY_ATTR_ALLOWLIST: &[Symbol] = &[sym::cfg];
-                        // assert!(
-                        //     self.tools.contains(&parts[0]) || true,
-                        //     // || FIXME_TEMPORARY_ATTR_ALLOWLIST.contains(&parts[0]),
-                        //     "attribute {path} wasn't parsed and isn't a know tool attribute",
-                        // );
-
-                        attributes.push(Attribute::Unparsed(Box::new(AttrItem {
+                        let attr = AttrItem {
                             path: attr_path.clone(),
                             args: self
                                 .lower_attr_args(n.item.args.unparsed_ref().unwrap(), lower_span),
                             id: HashIgnoredAttrId { attr_id: attr.id },
                             style: attr.style,
                             span: attr_span,
-                        })));
+                        };
+
+                        if !matches!(self.stage.should_emit(), ShouldEmit::Nothing)
+                            && target == Target::Crate
+                        {
+                            self.check_invalid_crate_level_attr_item(&attr, n.item.span());
+                        }
+
+                        let attr = Attribute::Unparsed(Box::new(attr));
+
+                        if self.tools.contains(&parts[0])
+                            // FIXME: this can be removed once #152369 has been merged.
+                            // https://github.com/rust-lang/rust/pull/152369
+                            || [sym::allow, sym::deny, sym::expect, sym::forbid, sym::warn]
+                                .contains(&parts[0])
+                        {
+                            attributes.push(attr);
+                        } else {
+                            dropped_attributes.push(attr);
+                        }
                     }
                 }
             }
@@ -428,6 +440,12 @@ pub fn parse_attribute_list(
             }
         }
 
+        if !matches!(self.stage.should_emit(), ShouldEmit::Nothing)
+            && target == Target::WherePredicate
+        {
+            self.check_invalid_where_predicate_attrs(attributes.iter().chain(&dropped_attributes));
+        }
+
         attributes
     }
 
diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs
index db09572..93eb5a0 100644
--- a/compiler/rustc_attr_parsing/src/lib.rs
+++ b/compiler/rustc_attr_parsing/src/lib.rs
@@ -79,6 +79,7 @@
 // tidy-alphabetical-start
 #![feature(decl_macro)]
 #![feature(iter_intersperse)]
+#![feature(try_blocks)]
 #![recursion_limit = "256"]
 // tidy-alphabetical-end
 
@@ -99,6 +100,7 @@
 pub mod parser;
 
 mod early_parsed;
+mod errors;
 mod safety;
 mod session_diagnostics;
 mod target_checking;
diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs
index 07f2463..6e8a500 100644
--- a/compiler/rustc_attr_parsing/src/parser.rs
+++ b/compiler/rustc_attr_parsing/src/parser.rs
@@ -109,6 +109,7 @@ pub fn from_attr_args<'sess>(
         parts: &[Symbol],
         psess: &'sess ParseSess,
         should_emit: ShouldEmit,
+        allow_expr_metavar: AllowExprMetavar,
     ) -> Option<Self> {
         Some(match value {
             AttrArgs::Empty => Self::NoArgs,
@@ -122,6 +123,7 @@ pub fn from_attr_args<'sess>(
                         args.dspan.entire(),
                         psess,
                         ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden },
+                        allow_expr_metavar,
                     ) {
                         Ok(p) => return Some(ArgParser::List(p)),
                         Err(e) => {
@@ -147,9 +149,15 @@ pub fn from_attr_args<'sess>(
                 }
 
                 Self::List(
-                    MetaItemListParser::new(&args.tokens, args.dspan.entire(), psess, should_emit)
-                        .map_err(|e| should_emit.emit_err(e))
-                        .ok()?,
+                    MetaItemListParser::new(
+                        &args.tokens,
+                        args.dspan.entire(),
+                        psess,
+                        should_emit,
+                        allow_expr_metavar,
+                    )
+                    .map_err(|e| should_emit.emit_err(e))
+                    .ok()?,
                 )
             }
             AttrArgs::Eq { eq_span, expr } => Self::NameValue(NameValueParser {
@@ -217,8 +225,9 @@ impl MetaItemOrLitParser {
     pub fn parse_single<'sess>(
         parser: &mut Parser<'sess>,
         should_emit: ShouldEmit,
+        allow_expr_metavar: AllowExprMetavar,
     ) -> PResult<'sess, MetaItemOrLitParser> {
-        let mut this = MetaItemListParserContext { parser, should_emit };
+        let mut this = MetaItemListParserContext { parser, should_emit, allow_expr_metavar };
         this.parse_meta_item_inner()
     }
 
@@ -404,9 +413,19 @@ fn expr_to_lit<'sess>(
     }
 }
 
+/// Whether expansions of `expr` metavariables from decrarative macros
+/// are permitted. Used when parsing meta items; currently, only `cfg` predicates
+/// enable this option
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum AllowExprMetavar {
+    No,
+    Yes,
+}
+
 struct MetaItemListParserContext<'a, 'sess> {
     parser: &'a mut Parser<'sess>,
     should_emit: ShouldEmit,
+    allow_expr_metavar: AllowExprMetavar,
 }
 
 impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
@@ -447,20 +466,44 @@ fn unsuffixed_meta_item_from_lit(
         Ok(lit)
     }
 
-    fn parse_attr_item(&mut self) -> PResult<'sess, MetaItemParser> {
-        if let Some(MetaVarKind::Meta { has_meta_form }) = self.parser.token.is_metavar_seq() {
-            return if has_meta_form {
-                let attr_item = self
-                    .parser
-                    .eat_metavar_seq(MetaVarKind::Meta { has_meta_form: true }, |this| {
-                        MetaItemListParserContext { parser: this, should_emit: self.should_emit }
-                            .parse_attr_item()
-                    })
-                    .unwrap();
-                Ok(attr_item)
-            } else {
-                self.parser.unexpected_any()
-            };
+    fn parse_meta_item(&mut self) -> PResult<'sess, MetaItemParser> {
+        if let Some(metavar) = self.parser.token.is_metavar_seq() {
+            match (metavar, self.allow_expr_metavar) {
+                (kind @ MetaVarKind::Expr { .. }, AllowExprMetavar::Yes) => {
+                    return self
+                        .parser
+                        .eat_metavar_seq(kind, |this| {
+                            MetaItemListParserContext {
+                                parser: this,
+                                should_emit: self.should_emit,
+                                allow_expr_metavar: AllowExprMetavar::Yes,
+                            }
+                            .parse_meta_item()
+                        })
+                        .ok_or_else(|| {
+                            self.parser.unexpected_any::<core::convert::Infallible>().unwrap_err()
+                        });
+                }
+                (MetaVarKind::Meta { has_meta_form }, _) => {
+                    return if has_meta_form {
+                        let attr_item = self
+                            .parser
+                            .eat_metavar_seq(MetaVarKind::Meta { has_meta_form: true }, |this| {
+                                MetaItemListParserContext {
+                                    parser: this,
+                                    should_emit: self.should_emit,
+                                    allow_expr_metavar: self.allow_expr_metavar,
+                                }
+                                .parse_meta_item()
+                            })
+                            .unwrap();
+                        Ok(attr_item)
+                    } else {
+                        self.parser.unexpected_any()
+                    };
+                }
+                _ => {}
+            }
         }
 
         let path = self.parser.parse_path(PathStyle::Mod)?;
@@ -469,8 +512,12 @@ fn parse_attr_item(&mut self) -> PResult<'sess, MetaItemParser> {
         let args = if self.parser.check(exp!(OpenParen)) {
             let start = self.parser.token.span;
             let (sub_parsers, _) = self.parser.parse_paren_comma_seq(|parser| {
-                MetaItemListParserContext { parser, should_emit: self.should_emit }
-                    .parse_meta_item_inner()
+                MetaItemListParserContext {
+                    parser,
+                    should_emit: self.should_emit,
+                    allow_expr_metavar: self.allow_expr_metavar,
+                }
+                .parse_meta_item_inner()
             })?;
             let end = self.parser.prev_token.span;
             ArgParser::List(MetaItemListParser { sub_parsers, span: start.with_hi(end.hi()) })
@@ -492,7 +539,7 @@ fn parse_meta_item_inner(&mut self) -> PResult<'sess, MetaItemOrLitParser> {
             Ok(MetaItemOrLitParser::Lit(self.unsuffixed_meta_item_from_lit(token_lit)?))
         } else {
             let prev_pros = self.parser.approx_token_stream_pos();
-            match self.parse_attr_item() {
+            match self.parse_meta_item() {
                 Ok(item) => Ok(MetaItemOrLitParser::MetaItemParser(item)),
                 Err(err) => {
                     // If `parse_attr_item` made any progress, it likely has a more precise error we should prefer
@@ -580,13 +627,15 @@ fn parse(
         psess: &'sess ParseSess,
         span: Span,
         should_emit: ShouldEmit,
+        allow_expr_metavar: AllowExprMetavar,
     ) -> PResult<'sess, MetaItemListParser> {
         let mut parser = Parser::new(psess, tokens, None);
         if let ShouldEmit::ErrorsAndLints { recovery } = should_emit {
             parser = parser.recovery(recovery);
         }
 
-        let mut this = MetaItemListParserContext { parser: &mut parser, should_emit };
+        let mut this =
+            MetaItemListParserContext { parser: &mut parser, should_emit, allow_expr_metavar };
 
         // Presumably, the majority of the time there will only be one attr.
         let mut sub_parsers = ThinVec::with_capacity(1);
@@ -618,8 +667,15 @@ pub(crate) fn new<'sess>(
         span: Span,
         psess: &'sess ParseSess,
         should_emit: ShouldEmit,
+        allow_expr_metavar: AllowExprMetavar,
     ) -> Result<Self, Diag<'sess>> {
-        MetaItemListParserContext::parse(tokens.clone(), psess, span, should_emit)
+        MetaItemListParserContext::parse(
+            tokens.clone(),
+            psess,
+            span,
+            should_emit,
+            allow_expr_metavar,
+        )
     }
 
     /// Lets you pick and choose as what you want to parse each element in the list
diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
index 0694889..bab8300 100644
--- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs
+++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
@@ -1046,3 +1046,14 @@ pub(crate) struct CustomMirIncompatibleDialectAndPhase {
     #[label("... is not compatible with this phase")]
     pub phase_span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag("can't mark as unstable using an already stable feature")]
+pub(crate) struct UnstableAttrForAlreadyStableFeature {
+    #[primary_span]
+    #[label("this feature is already stable")]
+    #[help("consider removing the attribute")]
+    pub attr_span: Span,
+    #[label("the stability attribute annotates this item")]
+    pub item_span: Span,
+}
diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs
index fb00547..253a089 100644
--- a/compiler/rustc_attr_parsing/src/target_checking.rs
+++ b/compiler/rustc_attr_parsing/src/target_checking.rs
@@ -1,14 +1,18 @@
 use std::borrow::Cow;
 
 use rustc_ast::AttrStyle;
-use rustc_errors::DiagArgValue;
+use rustc_errors::{DiagArgValue, MultiSpan, StashKey};
 use rustc_feature::Features;
+use rustc_hir::attrs::AttributeKind;
 use rustc_hir::lints::AttributeLintKind;
-use rustc_hir::{MethodKind, Target};
-use rustc_span::sym;
+use rustc_hir::{AttrItem, Attribute, MethodKind, Target};
+use rustc_span::{BytePos, Span, Symbol, sym};
 
 use crate::AttributeParser;
 use crate::context::{AcceptContext, Stage};
+use crate::errors::{
+    InvalidAttrAtCrateLevel, ItemFollowingInnerAttr, UnsupportedAttributesInWhere,
+};
 use crate::session_diagnostics::InvalidTarget;
 use crate::target_checking::Policy::Allow;
 
@@ -96,6 +100,25 @@ pub(crate) fn check_target(
             return;
         }
 
+        if matches!(cx.attr_path.segments.as_ref(), [sym::repr]) && target == Target::Crate {
+            // The allowed targets of `repr` depend on its arguments. They can't be checked using
+            // the `AttributeParser` code.
+            let span = cx.attr_span;
+            let item =
+                cx.cx.first_line_of_next_item(span).map(|span| ItemFollowingInnerAttr { span });
+
+            let pound_to_opening_bracket = cx.attr_span.until(cx.inner_span);
+
+            cx.dcx()
+                .create_err(InvalidAttrAtCrateLevel {
+                    span,
+                    pound_to_opening_bracket,
+                    name: sym::repr,
+                    item,
+                })
+                .emit();
+        }
+
         match allowed_targets.is_allowed(target) {
             AllowedResult::Allowed => {}
             AllowedResult::Warn => {
@@ -163,6 +186,113 @@ pub(crate) fn check_crate_level(target: Target, cx: &mut AcceptContext<'_, 'sess
 
         cx.emit_lint(rustc_session::lint::builtin::UNUSED_ATTRIBUTES, kind, attr_span);
     }
+
+    // FIXME: Fix "Cannot determine resolution" error and remove built-in macros
+    // from this check.
+    pub(crate) fn check_invalid_crate_level_attr_item(&self, attr: &AttrItem, inner_span: Span) {
+        // Check for builtin attributes at the crate level
+        // which were unsuccessfully resolved due to cannot determine
+        // resolution for the attribute macro error.
+        const ATTRS_TO_CHECK: &[Symbol] =
+            &[sym::derive, sym::test, sym::test_case, sym::global_allocator, sym::bench];
+
+        // FIXME(jdonszelmann): all attrs should be combined here cleaning this up some day.
+        if let Some(name) = ATTRS_TO_CHECK.iter().find(|attr_to_check| matches!(attr.path.segments.as_ref(), [segment] if segment == *attr_to_check)) {
+            let span = attr.span;
+            let name = *name;
+
+            let item = self.first_line_of_next_item(span).map(|span| ItemFollowingInnerAttr { span });
+
+            let err = self.dcx().create_err(InvalidAttrAtCrateLevel {
+                span,
+                pound_to_opening_bracket: span.until(inner_span),
+                name,
+                item,
+            });
+
+            self.dcx().try_steal_replace_and_emit_err(
+                attr.path.span,
+                StashKey::UndeterminedMacroResolution,
+                err,
+            );
+        }
+    }
+
+    fn first_line_of_next_item(&self, span: Span) -> Option<Span> {
+        // We can't exactly call `tcx.hir_free_items()` here because it's too early and querying
+        // this would create a circular dependency. Instead, we resort to getting the original
+        // source code that follows `span` and find the next item from here.
+
+        self.sess()
+            .source_map()
+            .span_to_source(span, |content, _, span_end| {
+                let mut source = &content[span_end..];
+                let initial_source_len = source.len();
+                let span = try {
+                    loop {
+                        let first = source.chars().next()?;
+
+                        if first.is_whitespace() {
+                            let split_idx = source.find(|c: char| !c.is_whitespace())?;
+                            source = &source[split_idx..];
+                        } else if source.starts_with("//") {
+                            let line_idx = source.find('\n')?;
+                            source = &source[line_idx + '\n'.len_utf8()..];
+                        } else if source.starts_with("/*") {
+                            // FIXME: support nested comments.
+                            let close_idx = source.find("*/")?;
+                            source = &source[close_idx + "*/".len()..];
+                        } else if first == '#' {
+                            // FIXME: properly find the end of the attributes in order to accurately
+                            // skip them. This version just consumes the source code until the next
+                            // `]`.
+                            let close_idx = source.find(']')?;
+                            source = &source[close_idx + ']'.len_utf8()..];
+                        } else {
+                            let lo = span_end + initial_source_len - source.len();
+                            let last_line = source.split('\n').next().map(|s| s.trim_end())?;
+
+                            let hi = lo + last_line.len();
+                            let lo = BytePos(lo as u32);
+                            let hi = BytePos(hi as u32);
+                            let next_item_span = Span::new(lo, hi, span.ctxt(), None);
+
+                            break next_item_span;
+                        }
+                    }
+                };
+
+                Ok(span)
+            })
+            .ok()
+            .flatten()
+    }
+
+    pub(crate) fn check_invalid_where_predicate_attrs<'attr>(
+        &self,
+        attrs: impl IntoIterator<Item = &'attr Attribute>,
+    ) {
+        // FIXME(where_clause_attrs): Currently, as the following check shows,
+        // only `#[cfg]` and `#[cfg_attr]` are allowed, but it should be removed
+        // if we allow more attributes (e.g., tool attributes and `allow/deny/warn`)
+        // in where clauses. After that, this function would become useless.
+        let spans = attrs
+            .into_iter()
+            // FIXME: We shouldn't need to special-case `doc`!
+            .filter(|attr| {
+                matches!(
+                    attr,
+                    Attribute::Parsed(AttributeKind::DocComment { .. } | AttributeKind::Doc(_))
+                        | Attribute::Unparsed(_)
+                )
+            })
+            .map(|attr| attr.span())
+            .collect::<Vec<_>>();
+        if !spans.is_empty() {
+            self.dcx()
+                .emit_err(UnsupportedAttributesInWhere { span: MultiSpan::from_spans(spans) });
+        }
+    }
 }
 
 /// Takes a list of `allowed_targets` for an attribute, and the `target` the attribute was applied to.
diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs
index 30391e7..afa393a 100644
--- a/compiler/rustc_builtin_macros/src/autodiff.rs
+++ b/compiler/rustc_builtin_macros/src/autodiff.rs
@@ -224,16 +224,18 @@ pub(crate) fn expand_with_mode(
                 }
                 _ => None,
             },
-            Annotatable::AssocItem(assoc_item, Impl { of_trait: _ }) => match &assoc_item.kind {
-                ast::AssocItemKind::Fn(box ast::Fn { sig, ident, generics, .. }) => Some((
-                    assoc_item.vis.clone(),
-                    sig.clone(),
-                    ident.clone(),
-                    generics.clone(),
-                    true,
-                )),
-                _ => None,
-            },
+            Annotatable::AssocItem(assoc_item, _ctxt @ (Impl { of_trait: _ } | Trait)) => {
+                match &assoc_item.kind {
+                    ast::AssocItemKind::Fn(box ast::Fn { sig, ident, generics, .. }) => Some((
+                        assoc_item.vis.clone(),
+                        sig.clone(),
+                        ident.clone(),
+                        generics.clone(),
+                        true,
+                    )),
+                    _ => None,
+                }
+            }
             _ => None,
         }) else {
             dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() });
@@ -393,14 +395,14 @@ fn same_attribute(attr: &ast::AttrKind, item: &ast::AttrKind) -> bool {
                 }
                 Annotatable::Item(iitem.clone())
             }
-            Annotatable::AssocItem(ref mut assoc_item, i @ Impl { .. }) => {
+            Annotatable::AssocItem(ref mut assoc_item, ctxt @ (Impl { .. } | Trait)) => {
                 if !assoc_item.attrs.iter().any(|a| same_attribute(&a.kind, &attr.kind)) {
                     assoc_item.attrs.push(attr);
                 }
                 if assoc_item.attrs.iter().any(|a| same_attribute(&a.kind, &inline_never.kind)) {
                     has_inline_never = true;
                 }
-                Annotatable::AssocItem(assoc_item.clone(), i)
+                Annotatable::AssocItem(assoc_item.clone(), ctxt)
             }
             Annotatable::Stmt(ref mut stmt) => {
                 match stmt.kind {
@@ -441,7 +443,7 @@ fn same_attribute(attr: &ast::AttrKind, item: &ast::AttrKind) -> bool {
         }
 
         let d_annotatable = match &item {
-            Annotatable::AssocItem(_, _) => {
+            Annotatable::AssocItem(_, ctxt) => {
                 let assoc_item: AssocItemKind = ast::AssocItemKind::Fn(d_fn);
                 let d_fn = Box::new(ast::AssocItem {
                     attrs: d_attrs,
@@ -451,7 +453,7 @@ fn same_attribute(attr: &ast::AttrKind, item: &ast::AttrKind) -> bool {
                     kind: assoc_item,
                     tokens: None,
                 });
-                Annotatable::AssocItem(d_fn, Impl { of_trait: false })
+                Annotatable::AssocItem(d_fn, *ctxt)
             }
             Annotatable::Item(_) => {
                 let mut d_fn = ecx.item(span, d_attrs, ItemKind::Fn(d_fn));
diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs
index 3ebde94..c4a4580 100644
--- a/compiler/rustc_builtin_macros/src/cfg.rs
+++ b/compiler/rustc_builtin_macros/src/cfg.rs
@@ -4,10 +4,9 @@
 
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{AttrStyle, token};
-use rustc_attr_parsing as attr;
-use rustc_attr_parsing::parser::MetaItemOrLitParser;
+use rustc_attr_parsing::parser::{AllowExprMetavar, MetaItemOrLitParser};
 use rustc_attr_parsing::{
-    AttributeParser, CFG_TEMPLATE, ParsedDescription, ShouldEmit, parse_cfg_entry,
+    self as attr, AttributeParser, CFG_TEMPLATE, ParsedDescription, ShouldEmit, parse_cfg_entry,
 };
 use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
 use rustc_hir::attrs::CfgEntry;
@@ -44,6 +43,7 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result<CfgEntry,
     let meta = MetaItemOrLitParser::parse_single(
         &mut parser,
         ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
+        AllowExprMetavar::Yes,
     )
     .map_err(|diag| diag.emit())?;
     let cfg = AttributeParser::parse_single_args(
diff --git a/compiler/rustc_codegen_cranelift/patches/0028-stdlib-Ensure-va_end-doesn-t-get-emitted-unless-VaList-is-a.patch b/compiler/rustc_codegen_cranelift/patches/0028-stdlib-Ensure-va_end-doesn-t-get-emitted-unless-VaList-is-a.patch
deleted file mode 100644
index 2aa9316..0000000
--- a/compiler/rustc_codegen_cranelift/patches/0028-stdlib-Ensure-va_end-doesn-t-get-emitted-unless-VaList-is-a.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 116abc64add4d617104993a7a3011f20bcf31ef2 Mon Sep 17 00:00:00 2001
-From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
-Date: Mon, 26 Jan 2026 16:20:58 +0000
-Subject: [PATCH] Ensure va_end doesn't get emitted unless VaList is actually
- used
-
----
- library/core/src/ffi/va_list.rs | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/library/core/src/ffi/va_list.rs b/library/core/src/ffi/va_list.rs
-index d0f1553..75129af 100644
---- a/library/core/src/ffi/va_list.rs
-+++ b/library/core/src/ffi/va_list.rs
-@@ -217,6 +217,7 @@ impl Clone for VaList<'_> {
-
- #[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
- impl<'f> const Drop for VaList<'f> {
-+    #[inline]
-     fn drop(&mut self) {
-         // SAFETY: this variable argument list is being dropped, so won't be read from again.
-         unsafe { va_end(self) }
--- 
-2.43.0
-
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index 82c2e91..cbbb0cc 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -46,7 +46,7 @@
 use rustc_session::Session;
 use rustc_session::config::OutputFilenames;
 use rustc_span::{Symbol, sym};
-use rustc_target::spec::{Abi, Arch, Env, Os};
+use rustc_target::spec::{Arch, CfgAbi, Env, Os};
 
 pub use crate::config::*;
 use crate::prelude::*;
@@ -178,7 +178,7 @@ fn target_config(&self, sess: &Session) -> TargetConfig {
         let has_reliable_f16_f128 = !(sess.target.arch == Arch::X86_64
             && sess.target.os == Os::Windows
             && sess.target.env == Env::Gnu
-            && sess.target.abi != Abi::Llvm);
+            && sess.target.cfg_abi != CfgAbi::Llvm);
 
         // FIXME(f128): f128 math operations need f128 math symbols, which currently aren't always
         // filled in by compiler-builtins. The only libc that provides these currently is glibc.
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index d51adb6..f300ee5 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -120,7 +120,8 @@ pub(crate) fn sanitize_attrs<'ll, 'tcx>(
     if enabled.contains(SanitizerSet::THREAD) {
         attrs.push(llvm::AttributeKind::SanitizeThread.create_attr(cx.llcx));
     }
-    if enabled.contains(SanitizerSet::HWADDRESS) {
+    if enabled.contains(SanitizerSet::HWADDRESS) || enabled.contains(SanitizerSet::KERNELHWADDRESS)
+    {
         attrs.push(llvm::AttributeKind::SanitizeHWAddress.create_attr(cx.llcx));
     }
     if enabled.contains(SanitizerSet::SHADOWCALLSTACK) {
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index ffa5827..515b571 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -36,7 +36,7 @@
 use crate::common::AsCCharPtr;
 use crate::errors::{
     CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, ParseTargetMachineConfig,
-    UnknownCompression, WithLlvmError, WriteBytecode,
+    UnsupportedCompression, WithLlvmError, WriteBytecode,
 };
 use crate::llvm::diagnostic::OptimizationDiagnosticKind::*;
 use crate::llvm::{self, DiagnosticInfo};
@@ -225,7 +225,7 @@ pub(crate) fn target_machine_factory(
     let triple = SmallCStr::new(&versioned_llvm_target(sess));
     let cpu = SmallCStr::new(llvm_util::target_cpu(sess));
     let features = CString::new(target_features.join(",")).unwrap();
-    let abi = SmallCStr::new(&sess.target.llvm_abiname);
+    let abi = SmallCStr::new(sess.target.llvm_abiname.desc());
     let trap_unreachable =
         sess.opts.unstable_opts.trap_unreachable.unwrap_or(sess.target.trap_unreachable);
     let emit_stack_size_section = sess.opts.unstable_opts.emit_stack_sizes;
@@ -248,7 +248,7 @@ pub(crate) fn target_machine_factory(
             if llvm::LLVMRustLLVMHasZlibCompression() {
                 llvm::CompressionKind::Zlib
             } else {
-                sess.dcx().emit_warn(UnknownCompression { algorithm: "zlib" });
+                sess.dcx().emit_warn(UnsupportedCompression { algorithm: "zlib" });
                 llvm::CompressionKind::None
             }
         }
@@ -256,7 +256,7 @@ pub(crate) fn target_machine_factory(
             if llvm::LLVMRustLLVMHasZstdCompression() {
                 llvm::CompressionKind::Zstd
             } else {
-                sess.dcx().emit_warn(UnknownCompression { algorithm: "zstd" });
+                sess.dcx().emit_warn(UnsupportedCompression { algorithm: "zstd" });
                 llvm::CompressionKind::None
             }
         }
@@ -644,6 +644,10 @@ pub(crate) unsafe fn llvm_optimize(
             sanitize_kernel_address_recover: config
                 .sanitizer_recover
                 .contains(SanitizerSet::KERNELADDRESS),
+            sanitize_kernel_hwaddress: config.sanitizer.contains(SanitizerSet::KERNELHWADDRESS),
+            sanitize_kernel_hwaddress_recover: config
+                .sanitizer_recover
+                .contains(SanitizerSet::KERNELHWADDRESS),
         })
     } else {
         None
diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs
index d00e706..2276809 100644
--- a/compiler/rustc_codegen_llvm/src/base.rs
+++ b/compiler/rustc_codegen_llvm/src/base.rs
@@ -210,10 +210,14 @@ pub(crate) fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility {
 }
 
 pub(crate) fn set_variable_sanitizer_attrs(llval: &Value, attrs: &CodegenFnAttrs) {
-    if attrs.sanitizers.disabled.contains(SanitizerSet::ADDRESS) {
+    if attrs.sanitizers.disabled.contains(SanitizerSet::ADDRESS)
+        || attrs.sanitizers.disabled.contains(SanitizerSet::KERNELADDRESS)
+    {
         unsafe { llvm::LLVMRustSetNoSanitizeAddress(llval) };
     }
-    if attrs.sanitizers.disabled.contains(SanitizerSet::HWADDRESS) {
+    if attrs.sanitizers.disabled.contains(SanitizerSet::HWADDRESS)
+        || attrs.sanitizers.disabled.contains(SanitizerSet::KERNELHWADDRESS)
+    {
         unsafe { llvm::LLVMRustSetNoSanitizeHWAddress(llval) };
     }
 }
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index cc4c5e2..e02c4ae 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -28,7 +28,7 @@
 use rustc_span::{DUMMY_SP, Span, Spanned, Symbol};
 use rustc_symbol_mangling::mangle_internal_symbol;
 use rustc_target::spec::{
-    Abi, Arch, Env, HasTargetSpec, Os, RelocModel, SmallDataThresholdSupport, Target, TlsModel,
+    Arch, CfgAbi, Env, HasTargetSpec, Os, RelocModel, SmallDataThresholdSupport, Target, TlsModel,
 };
 use smallvec::SmallVec;
 
@@ -344,7 +344,7 @@ pub(crate) unsafe fn create_module<'ll>(
     if sess.target.is_like_msvc
         || (sess.target.options.os == Os::Windows
             && sess.target.options.env == Env::Gnu
-            && sess.target.options.abi == Abi::Llvm)
+            && sess.target.options.cfg_abi == CfgAbi::Llvm)
     {
         match sess.opts.cg.control_flow_guard {
             CFGuard::Disabled => {}
@@ -509,14 +509,13 @@ pub(crate) unsafe fn create_module<'ll>(
     // to workaround lld as the LTO plugin not
     // correctly setting target-abi for the LTO object
     // FIXME: https://github.com/llvm/llvm-project/issues/50591
-    // If llvm_abiname is empty, emit nothing.
     let llvm_abiname = &sess.target.options.llvm_abiname;
-    if matches!(sess.target.arch, Arch::RiscV32 | Arch::RiscV64) && !llvm_abiname.is_empty() {
+    if matches!(sess.target.arch, Arch::RiscV32 | Arch::RiscV64) {
         llvm::add_module_flag_str(
             llmod,
             llvm::ModuleFlagMergeBehavior::Error,
             "target-abi",
-            llvm_abiname,
+            llvm_abiname.desc(),
         );
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index c3fa86f..a667877 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -471,7 +471,7 @@ fn dbg_scope_fn(
         // FIXME(eddyb) does this need to be separate from `loc.line` for some reason?
         let scope_line = loc.line;
 
-        let mut flags = DIFlags::FlagPrototyped;
+        let mut flags = DIFlags::FlagPrototyped | DIFlags::FlagAllCallsDescribed;
 
         if fn_abi.ret.layout.is_uninhabited() {
             flags |= DIFlags::FlagNoReturn;
@@ -494,6 +494,9 @@ fn dbg_scope_fn(
         // LLVM LTO can't unify type definitions when a child DIE is a full subprogram definition.
         // When we use this `decl` below, the subprogram definition gets created at the CU level
         // with a DW_AT_specification pointing back to the type's declaration.
+        // FlagAllCallsDescribed cannot appear on the method declaration DIE
+        // because it has no body, which LLVM's verifier rejects.
+        let decl_flags = flags & !DIFlags::FlagAllCallsDescribed;
         let decl = is_method.then(|| unsafe {
             llvm::LLVMRustDIBuilderCreateMethod(
                 DIB(self),
@@ -505,7 +508,7 @@ fn dbg_scope_fn(
                 file_metadata,
                 loc.line,
                 function_type_metadata,
-                flags,
+                decl_flags,
                 spflags & !DISPFlags::SPFlagDefinition,
                 template_parameters,
             )
diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
index 9fb4065..880abb3 100644
--- a/compiler/rustc_codegen_llvm/src/errors.rs
+++ b/compiler/rustc_codegen_llvm/src/errors.rs
@@ -182,9 +182,9 @@ pub(crate) struct CopyBitcode {
 
 #[derive(Diagnostic)]
 #[diag(
-    "unknown debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo"
+    "unsupported debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo"
 )]
-pub(crate) struct UnknownCompression {
+pub(crate) struct UnsupportedCompression {
     pub algorithm: &'static str,
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 7743847..c6c04ac 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -464,6 +464,8 @@ pub(crate) struct SanitizerOptions {
     pub sanitize_hwaddress_recover: bool,
     pub sanitize_kernel_address: bool,
     pub sanitize_kernel_address_recover: bool,
+    pub sanitize_kernel_hwaddress: bool,
+    pub sanitize_kernel_hwaddress_recover: bool,
 }
 
 /// LLVMRustRelocModel
@@ -779,6 +781,7 @@ pub(crate) struct DIFlags: u32 {
             const FlagNonTrivial          = (1 << 26);
             const FlagBigEndian           = (1 << 27);
             const FlagLittleEndian        = (1 << 28);
+            const FlagAllCallsDescribed   = (1 << 29);
         }
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 2423880..3e0a6ef 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -16,7 +16,7 @@
 use rustc_session::Session;
 use rustc_session::config::{PrintKind, PrintRequest};
 use rustc_target::spec::{
-    Abi, Arch, Env, MergeFunctions, Os, PanicStrategy, SmallDataThresholdSupport,
+    Arch, CfgAbi, Env, MergeFunctions, Os, PanicStrategy, SmallDataThresholdSupport,
 };
 use smallvec::{SmallVec, smallvec};
 
@@ -252,7 +252,10 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
             "fp16" => Some(LLVMFeature::new("fullfp16")),
             s => Some(LLVMFeature::new(s)),
         },
-
+        Arch::Bpf => match s {
+            "allows-misaligned-mem-access" if major < 22 => None,
+            s => Some(LLVMFeature::new(s)),
+        },
         // Filter out features that are not supported by the current LLVM version
         Arch::PowerPC | Arch::PowerPC64 => match s {
             "power8-crypto" => Some(LLVMFeature::new("crypto")),
@@ -362,7 +365,7 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
     let target_arch = &sess.target.arch;
     let target_os = &sess.target.options.os;
     let target_env = &sess.target.options.env;
-    let target_abi = &sess.target.options.abi;
+    let target_abi = &sess.target.options.cfg_abi;
     let target_pointer_width = sess.target.pointer_width;
     let version = get_version();
     let (major, _, _) = version;
@@ -371,7 +374,9 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
         // Unsupported <https://github.com/llvm/llvm-project/issues/94434> (fixed in llvm22)
         (Arch::Arm64EC, _) if major < 22 => false,
         // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
-        (Arch::X86_64, Os::Windows) if *target_env == Env::Gnu && *target_abi != Abi::Llvm => false,
+        (Arch::X86_64, Os::Windows) if *target_env == Env::Gnu && *target_abi != CfgAbi::Llvm => {
+            false
+        }
         // Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
         (Arch::CSky, _) if major < 22 => false, // (fixed in llvm22)
         (Arch::PowerPC | Arch::PowerPC64, _) if major < 22 => false, // (fixed in llvm22)
@@ -394,10 +399,12 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
         // ABI bugs <https://github.com/rust-lang/rust/issues/125109> et al. (full
         // list at <https://github.com/rust-lang/rust/issues/116909>)
         (Arch::PowerPC | Arch::PowerPC64, _) => false,
-        // ABI unsupported  <https://github.com/llvm/llvm-project/issues/41838>
-        (Arch::Sparc, _) => false,
+        // ABI unsupported  <https://github.com/llvm/llvm-project/issues/41838> (fixed in llvm22)
+        (Arch::Sparc, _) if major < 22 => false,
         // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
-        (Arch::X86_64, Os::Windows) if *target_env == Env::Gnu && *target_abi != Abi::Llvm => false,
+        (Arch::X86_64, Os::Windows) if *target_env == Env::Gnu && *target_abi != CfgAbi::Llvm => {
+            false
+        }
         // There are no known problems on other platforms, so the only requirement is that symbols
         // are available. `compiler-builtins` provides all symbols required for core `f128`
         // support, so this should work for everything else.
diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs
index 98d2c3f..fbe9cb8 100644
--- a/compiler/rustc_codegen_llvm/src/va_arg.rs
+++ b/compiler/rustc_codegen_llvm/src/va_arg.rs
@@ -8,7 +8,7 @@
 use rustc_middle::bug;
 use rustc_middle::ty::Ty;
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
-use rustc_target::spec::{Arch, Env, RustcAbi};
+use rustc_target::spec::{Arch, Env, LlvmAbi, RustcAbi};
 
 use crate::builder::Builder;
 use crate::llvm::{Type, Value};
@@ -1077,7 +1077,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
             AllowHigherAlign::Yes,
             ForceRightAdjust::Yes,
         ),
-        Arch::RiscV32 if target.llvm_abiname == "ilp32e" => {
+        Arch::RiscV32 if target.llvm_abiname == LlvmAbi::Ilp32e => {
             // FIXME: clang manually adjusts the alignment for this ABI. It notes:
             //
             // > To be compatible with GCC's behaviors, we force arguments with
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 7a3d5a6..2943672 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -47,7 +47,7 @@
 use rustc_span::Symbol;
 use rustc_target::spec::crt_objects::CrtObjects;
 use rustc_target::spec::{
-    Abi, BinaryFormat, Cc, Env, LinkOutputKind, LinkSelfContainedComponents,
+    BinaryFormat, Cc, CfgAbi, Env, LinkOutputKind, LinkSelfContainedComponents,
     LinkSelfContainedDefault, LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, Os, RelocModel,
     RelroLevel, SanitizerSet, SplitDebuginfo,
 };
@@ -1917,7 +1917,7 @@ fn self_contained_components(
                 LinkSelfContainedDefault::InferredForMusl => sess.crt_static(Some(crate_type)),
                 LinkSelfContainedDefault::InferredForMingw => {
                     sess.host == sess.target
-                        && sess.target.abi != Abi::Uwp
+                        && sess.target.cfg_abi != CfgAbi::Uwp
                         && detect_self_contained_mingw(sess, linker)
                 }
             }
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 3ace1a8..323fa7f 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -18,7 +18,7 @@
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
 use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
-use rustc_target::spec::{Abi, Arch, Cc, LinkOutputKind, LinkerFlavor, Lld, Os};
+use rustc_target::spec::{Arch, Cc, CfgAbi, LinkOutputKind, LinkerFlavor, Lld, Os};
 use tracing::{debug, warn};
 
 use super::command::Command;
@@ -84,7 +84,7 @@ pub(crate) fn get_linker<'a>(
     // To comply with the Windows App Certification Kit,
     // MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc).
     let t = &sess.target;
-    if matches!(flavor, LinkerFlavor::Msvc(..)) && t.abi == Abi::Uwp {
+    if matches!(flavor, LinkerFlavor::Msvc(..)) && t.cfg_abi == CfgAbi::Uwp {
         if let Some(ref tool) = msvc_tool {
             let original_path = tool.path();
             if let Some(root_lib_path) = original_path.ancestors().nth(4) {
@@ -135,7 +135,7 @@ pub(crate) fn get_linker<'a>(
 
     // FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
     // to the linker args construction.
-    assert!(cmd.get_args().is_empty() || sess.target.abi == Abi::Uwp);
+    assert!(cmd.get_args().is_empty() || sess.target.cfg_abi == CfgAbi::Uwp);
     match flavor {
         LinkerFlavor::Unix(Cc::No) if sess.target.os == Os::L4Re => {
             Box::new(L4Bender::new(cmd, sess)) as Box<dyn Linker>
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 240267c..f6544c0 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -20,7 +20,7 @@
 use rustc_middle::bug;
 use rustc_session::Session;
 use rustc_span::sym;
-use rustc_target::spec::{Abi, Os, RelocModel, Target, ef_avr_arch};
+use rustc_target::spec::{CfgAbi, LlvmAbi, Os, RelocModel, Target, ef_avr_arch};
 use tracing::debug;
 
 use super::apple;
@@ -295,10 +295,10 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
             };
 
             // Use the explicitly given ABI.
-            match sess.target.options.llvm_abiname.as_ref() {
-                "o32" if is_32bit => e_flags |= elf::EF_MIPS_ABI_O32,
-                "n32" if !is_32bit => e_flags |= elf::EF_MIPS_ABI2,
-                "n64" if !is_32bit => {}
+            match &sess.target.options.llvm_abiname {
+                LlvmAbi::O32 if is_32bit => e_flags |= elf::EF_MIPS_ABI_O32,
+                LlvmAbi::N32 if !is_32bit => e_flags |= elf::EF_MIPS_ABI2,
+                LlvmAbi::N64 if !is_32bit => {}
                 // The rest is invalid (which is already ensured by the target spec check).
                 s => bug!("invalid LLVM ABI `{}` for MIPS target", s),
             };
@@ -336,12 +336,12 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
 
             // Set the appropriate flag based on ABI
             // This needs to match LLVM `RISCVELFStreamer.cpp`
-            match &*sess.target.llvm_abiname {
-                "ilp32" | "lp64" => (),
-                "ilp32f" | "lp64f" => e_flags |= elf::EF_RISCV_FLOAT_ABI_SINGLE,
-                "ilp32d" | "lp64d" => e_flags |= elf::EF_RISCV_FLOAT_ABI_DOUBLE,
+            match &sess.target.llvm_abiname {
+                LlvmAbi::Ilp32 | LlvmAbi::Lp64 => (),
+                LlvmAbi::Ilp32f | LlvmAbi::Lp64f => e_flags |= elf::EF_RISCV_FLOAT_ABI_SINGLE,
+                LlvmAbi::Ilp32d | LlvmAbi::Lp64d => e_flags |= elf::EF_RISCV_FLOAT_ABI_DOUBLE,
                 // Note that the `lp64e` is still unstable as it's not (yet) part of the ELF psABI.
-                "ilp32e" | "lp64e" => e_flags |= elf::EF_RISCV_RVE,
+                LlvmAbi::Ilp32e | LlvmAbi::Lp64e => e_flags |= elf::EF_RISCV_RVE,
                 _ => bug!("unknown RISC-V ABI name"),
             }
 
@@ -353,10 +353,10 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
 
             // Set the appropriate flag based on ABI
             // This needs to match LLVM `LoongArchELFStreamer.cpp`
-            match &*sess.target.llvm_abiname {
-                "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,
+            match &sess.target.llvm_abiname {
+                LlvmAbi::Ilp32s | LlvmAbi::Lp64s => e_flags |= elf::EF_LARCH_ABI_SOFT_FLOAT,
+                LlvmAbi::Ilp32f | LlvmAbi::Lp64f => e_flags |= elf::EF_LARCH_ABI_SINGLE_FLOAT,
+                LlvmAbi::Ilp32d | LlvmAbi::Lp64d => e_flags |= elf::EF_LARCH_ABI_DOUBLE_FLOAT,
                 _ => bug!("unknown LoongArch ABI name"),
             }
 
@@ -372,7 +372,7 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
             }
         }
         Architecture::Csky => {
-            if matches!(sess.target.options.abi, Abi::AbiV2) {
+            if matches!(sess.target.options.cfg_abi, CfgAbi::AbiV2) {
                 elf::EF_CSKY_ABIV2
             } else {
                 elf::EF_CSKY_ABIV1
@@ -383,14 +383,14 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
             const EF_PPC64_ABI_ELF_V1: u32 = 1;
             const EF_PPC64_ABI_ELF_V2: u32 = 2;
 
-            match sess.target.options.llvm_abiname.as_ref() {
+            match sess.target.options.llvm_abiname {
                 // If the flags do not correctly indicate the ABI,
                 // linkers such as ld.lld assume that the ppc64 object files are always ELFv2
                 // which leads to broken binaries if ELFv1 is used for the object files.
-                "elfv1" => EF_PPC64_ABI_ELF_V1,
-                "elfv2" => EF_PPC64_ABI_ELF_V2,
-                "" if sess.target.options.binary_format.to_object() == BinaryFormat::Elf => {
-                    bug!("No ABI specified for this PPC64 ELF target");
+                LlvmAbi::ElfV1 => EF_PPC64_ABI_ELF_V1,
+                LlvmAbi::ElfV2 => EF_PPC64_ABI_ELF_V2,
+                _ if sess.target.options.binary_format.to_object() == BinaryFormat::Elf => {
+                    bug!("invalid ABI specified for this PPC64 ELF target");
                 }
                 // Fall back
                 _ => EF_PPC64_ABI_UNKNOWN,
diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs
index a0f46a2..fe4d1da 100644
--- a/compiler/rustc_codegen_ssa/src/common.rs
+++ b/compiler/rustc_codegen_ssa/src/common.rs
@@ -7,7 +7,7 @@
 use rustc_middle::{bug, mir, span_bug};
 use rustc_session::cstore::{DllCallingConvention, DllImport, DllImportSymbolType};
 use rustc_span::Span;
-use rustc_target::spec::{Abi, Env, Os, Target};
+use rustc_target::spec::{CfgAbi, Env, Os, Target};
 
 use crate::traits::*;
 
@@ -171,7 +171,7 @@ pub fn asm_const_to_str<'tcx>(
 }
 
 pub fn is_mingw_gnu_toolchain(target: &Target) -> bool {
-    target.os == Os::Windows && target.env == Env::Gnu && target.abi == Abi::Unspecified
+    target.os == Os::Windows && target.env == Env::Gnu && target.cfg_abi == CfgAbi::Unspecified
 }
 
 pub fn i686_decorated_name(
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 2dbf2cc..7d71536 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -88,7 +88,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
         &ret.clone().into(),
         ReturnContinuation::Stop { cleanup: false },
     )?;
-    ecx.storage_live_for_always_live_locals()?;
+    ecx.push_stack_frame_done()?;
 
     // The main interpreter loop.
     while ecx.step()? {
@@ -425,7 +425,7 @@ fn const_validate_mplace<'tcx>(
     cid: GlobalId<'tcx>,
 ) -> Result<(), ErrorHandled> {
     let alloc_id = mplace.ptr().provenance.unwrap().alloc_id();
-    let mut ref_tracking = RefTracking::new(mplace.clone());
+    let mut ref_tracking = RefTracking::new(mplace.clone(), mplace.layout.ty);
     let mut inner = false;
     while let Some((mplace, path)) = ref_tracking.next() {
         let mode = match ecx.tcx.static_mutability(cid.instance.def_id()) {
diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
index ad4c9aa..0b5065f 100644
--- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
@@ -37,7 +37,7 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Constness {
             }
         }
         Node::TraitItem(ti @ TraitItem { kind: TraitItemKind::Fn(..), .. }) => {
-            if find_attr!(tcx.hir_attrs(ti.hir_id()), RustcNonConstTraitMethod) {
+            if find_attr!(tcx, ti.hir_id(), RustcNonConstTraitMethod) {
                 Constness::NotConst
             } else {
                 tcx.trait_def(tcx.local_parent(def_id)).constness
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index 0381571..802aa9e 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -404,166 +404,158 @@ pub fn init_stack_frame(
 
         // Push the "raw" frame -- this leaves locals uninitialized.
         self.push_stack_frame_raw(instance, body, destination, cont)?;
+        let preamble_span = self.frame().loc.unwrap_right(); // the span used for preamble errors
 
-        // If an error is raised here, pop the frame again to get an accurate backtrace.
-        // To this end, we wrap it all in a `try` block.
-        let res: InterpResult<'tcx> = try {
-            trace!(
-                "caller ABI: {:#?}, args: {:#?}",
-                caller_fn_abi,
-                args.iter()
-                    .map(|arg| (
-                        arg.layout().ty,
-                        match arg {
-                            FnArg::Copy(op) => format!("copy({op:?})"),
-                            FnArg::InPlace(mplace) => format!("in-place({mplace:?})"),
-                        }
-                    ))
-                    .collect::<Vec<_>>()
-            );
-            trace!(
-                "spread_arg: {:?}, locals: {:#?}",
-                body.spread_arg,
-                body.args_iter()
-                    .map(|local| (
-                        local,
-                        self.layout_of_local(self.frame(), local, None).unwrap().ty,
-                    ))
-                    .collect::<Vec<_>>()
-            );
-
-            // In principle, we have two iterators: Where the arguments come from, and where
-            // they go to.
-
-            // The "where they come from" part is easy, we expect the caller to do any special handling
-            // that might be required here (e.g. for untupling).
-            // If `with_caller_location` is set we pretend there is an extra argument (that
-            // we will not pass; our `caller_location` intrinsic implementation walks the stack instead).
-            assert_eq!(
-                args.len() + if with_caller_location { 1 } else { 0 },
-                caller_fn_abi.args.len(),
-                "mismatch between caller ABI and caller arguments",
-            );
-            let mut caller_args = args
-                .iter()
-                .zip(caller_fn_abi.args.iter())
-                .filter(|arg_and_abi| !arg_and_abi.1.is_ignore());
-
-            // Now we have to spread them out across the callee's locals,
-            // taking into account the `spread_arg`. If we could write
-            // this is a single iterator (that handles `spread_arg`), then
-            // `pass_argument` would be the loop body. It takes care to
-            // not advance `caller_iter` for ignored arguments.
-            let mut callee_args_abis = callee_fn_abi.args.iter().enumerate();
-            // Determine whether there is a special VaList argument. This is always the
-            // last argument, and since arguments start at index 1 that's `arg_count`.
-            let va_list_arg =
-                callee_fn_abi.c_variadic.then(|| mir::Local::from_usize(body.arg_count));
-            for local in body.args_iter() {
-                // Construct the destination place for this argument. At this point all
-                // locals are still dead, so we cannot construct a `PlaceTy`.
-                let dest = mir::Place::from(local);
-                // `layout_of_local` does more than just the instantiation we need to get the
-                // type, but the result gets cached so this avoids calling the instantiation
-                // query *again* the next time this local is accessed.
-                let ty = self.layout_of_local(self.frame(), local, None)?.ty;
-                if Some(local) == va_list_arg {
-                    // This is the last callee-side argument of a variadic function.
-                    // This argument is a VaList holding the remaining caller-side arguments.
-                    self.storage_live(local)?;
-
-                    let place = self.eval_place(dest)?;
-                    let mplace = self.force_allocation(&place)?;
-
-                    // Consume the remaining arguments by putting them into the variable argument
-                    // list.
-                    let varargs = self.allocate_varargs(
-                        &mut caller_args,
-                        // "Ignored" arguments aren't actually passed, so the callee should also
-                        // ignore them. (`pass_argument` does this for regular arguments.)
-                        (&mut callee_args_abis).filter(|(_, abi)| !abi.is_ignore()),
-                    )?;
-                    // When the frame is dropped, these variable arguments are deallocated.
-                    self.frame_mut().va_list = varargs.clone();
-                    let key = self.va_list_ptr(varargs.into());
-
-                    // Zero the VaList, so it is fully initialized.
-                    self.write_bytes_ptr(
-                        mplace.ptr(),
-                        (0..mplace.layout.size.bytes()).map(|_| 0u8),
-                    )?;
-
-                    // Store the "key" pointer in the right field.
-                    let key_mplace = self.va_list_key_field(&mplace)?;
-                    self.write_pointer(key, &key_mplace)?;
-                } else if Some(local) == body.spread_arg {
-                    // Make the local live once, then fill in the value field by field.
-                    self.storage_live(local)?;
-                    // Must be a tuple
-                    let ty::Tuple(fields) = ty.kind() else {
-                        span_bug!(self.cur_span(), "non-tuple type for `spread_arg`: {ty}")
-                    };
-                    for (i, field_ty) in fields.iter().enumerate() {
-                        let dest = dest.project_deeper(
-                            &[mir::ProjectionElem::Field(FieldIdx::from_usize(i), field_ty)],
-                            *self.tcx,
-                        );
-                        let (idx, callee_abi) = callee_args_abis.next().unwrap();
-                        self.pass_argument(
-                            &mut caller_args,
-                            callee_abi,
-                            idx,
-                            &dest,
-                            field_ty,
-                            /* already_live */ true,
-                        )?;
+        trace!(
+            "caller ABI: {:#?}, args: {:#?}",
+            caller_fn_abi,
+            args.iter()
+                .map(|arg| (
+                    arg.layout().ty,
+                    match arg {
+                        FnArg::Copy(op) => format!("copy({op:?})"),
+                        FnArg::InPlace(mplace) => format!("in-place({mplace:?})"),
                     }
-                } else {
-                    // Normal argument. Cannot mark it as live yet, it might be unsized!
+                ))
+                .collect::<Vec<_>>()
+        );
+        trace!(
+            "spread_arg: {:?}, locals: {:#?}",
+            body.spread_arg,
+            body.args_iter()
+                .map(|local| (local, self.layout_of_local(self.frame(), local, None).unwrap().ty,))
+                .collect::<Vec<_>>()
+        );
+
+        // In principle, we have two iterators: Where the arguments come from, and where
+        // they go to.
+
+        // The "where they come from" part is easy, we expect the caller to do any special handling
+        // that might be required here (e.g. for untupling).
+        // If `with_caller_location` is set we pretend there is an extra argument (that
+        // we will not pass; our `caller_location` intrinsic implementation walks the stack instead).
+        assert_eq!(
+            args.len() + if with_caller_location { 1 } else { 0 },
+            caller_fn_abi.args.len(),
+            "mismatch between caller ABI and caller arguments",
+        );
+        let mut caller_args = args
+            .iter()
+            .zip(caller_fn_abi.args.iter())
+            .filter(|arg_and_abi| !arg_and_abi.1.is_ignore());
+
+        // Now we have to spread them out across the callee's locals,
+        // taking into account the `spread_arg`. If we could write
+        // this is a single iterator (that handles `spread_arg`), then
+        // `pass_argument` would be the loop body. It takes care to
+        // not advance `caller_iter` for ignored arguments.
+        let mut callee_args_abis = callee_fn_abi.args.iter().enumerate();
+        // Determine whether there is a special VaList argument. This is always the
+        // last argument, and since arguments start at index 1 that's `arg_count`.
+        let va_list_arg = callee_fn_abi.c_variadic.then(|| mir::Local::from_usize(body.arg_count));
+        for local in body.args_iter() {
+            // Update the span that we show in case of an error to point to this argument.
+            self.frame_mut().loc = Right(body.local_decls[local].source_info.span);
+            // Construct the destination place for this argument. At this point all
+            // locals are still dead, so we cannot construct a `PlaceTy`.
+            let dest = mir::Place::from(local);
+            // `layout_of_local` does more than just the instantiation we need to get the
+            // type, but the result gets cached so this avoids calling the instantiation
+            // query *again* the next time this local is accessed.
+            let ty = self.layout_of_local(self.frame(), local, None)?.ty;
+            if Some(local) == va_list_arg {
+                // This is the last callee-side argument of a variadic function.
+                // This argument is a VaList holding the remaining caller-side arguments.
+                self.storage_live(local)?;
+
+                let place = self.eval_place(dest)?;
+                let mplace = self.force_allocation(&place)?;
+
+                // Consume the remaining arguments by putting them into the variable argument
+                // list.
+                let varargs = self.allocate_varargs(
+                    &mut caller_args,
+                    // "Ignored" arguments aren't actually passed, so the callee should also
+                    // ignore them. (`pass_argument` does this for regular arguments.)
+                    (&mut callee_args_abis).filter(|(_, abi)| !abi.is_ignore()),
+                )?;
+                // When the frame is dropped, these variable arguments are deallocated.
+                self.frame_mut().va_list = varargs.clone();
+                let key = self.va_list_ptr(varargs.into());
+
+                // Zero the VaList, so it is fully initialized.
+                self.write_bytes_ptr(mplace.ptr(), (0..mplace.layout.size.bytes()).map(|_| 0u8))?;
+
+                // Store the "key" pointer in the right field.
+                let key_mplace = self.va_list_key_field(&mplace)?;
+                self.write_pointer(key, &key_mplace)?;
+            } else if Some(local) == body.spread_arg {
+                // Make the local live once, then fill in the value field by field.
+                self.storage_live(local)?;
+                // Must be a tuple
+                let ty::Tuple(fields) = ty.kind() else {
+                    span_bug!(self.cur_span(), "non-tuple type for `spread_arg`: {ty}")
+                };
+                for (i, field_ty) in fields.iter().enumerate() {
+                    let dest = dest.project_deeper(
+                        &[mir::ProjectionElem::Field(FieldIdx::from_usize(i), field_ty)],
+                        *self.tcx,
+                    );
                     let (idx, callee_abi) = callee_args_abis.next().unwrap();
                     self.pass_argument(
                         &mut caller_args,
                         callee_abi,
                         idx,
                         &dest,
-                        ty,
-                        /* already_live */ false,
+                        field_ty,
+                        /* already_live */ true,
                     )?;
                 }
+            } else {
+                // Normal argument. Cannot mark it as live yet, it might be unsized!
+                let (idx, callee_abi) = callee_args_abis.next().unwrap();
+                self.pass_argument(
+                    &mut caller_args,
+                    callee_abi,
+                    idx,
+                    &dest,
+                    ty,
+                    /* already_live */ false,
+                )?;
             }
-            // If the callee needs a caller location, pretend we consume one more argument from the ABI.
-            if instance.def.requires_caller_location(*self.tcx) {
-                callee_args_abis.next().unwrap();
-            }
-            // Now we should have no more caller args or callee arg ABIs.
-            assert!(
-                callee_args_abis.next().is_none(),
-                "mismatch between callee ABI and callee body arguments"
-            );
-            if caller_args.next().is_some() {
-                throw_ub_format!("calling a function with more arguments than it expected");
-            }
-            // Don't forget to check the return type!
-            if !self.check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret)? {
-                throw_ub!(AbiMismatchReturn {
-                    caller_ty: caller_fn_abi.ret.layout.ty,
-                    callee_ty: callee_fn_abi.ret.layout.ty
-                });
-            }
+        }
 
-            // Protect return place for in-place return value passing.
-            // We only need to protect anything if this is actually an in-memory place.
-            if let Some(mplace) = destination_mplace {
-                M::protect_in_place_function_argument(self, &mplace)?;
-            }
+        // Don't forget to check the return type!
+        self.frame_mut().loc = Right(body.local_decls[mir::RETURN_PLACE].source_info.span);
+        if !self.check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret)? {
+            throw_ub!(AbiMismatchReturn {
+                caller_ty: caller_fn_abi.ret.layout.ty,
+                callee_ty: callee_fn_abi.ret.layout.ty
+            });
+        }
+        // Protect return place for in-place return value passing.
+        // We only need to protect anything if this is actually an in-memory place.
+        if let Some(mplace) = destination_mplace {
+            M::protect_in_place_function_argument(self, &mplace)?;
+        }
 
-            // Don't forget to mark "initially live" locals as live.
-            self.storage_live_for_always_live_locals()?;
-        };
-        res.inspect_err_kind(|_| {
-            // Don't show the incomplete stack frame in the error stacktrace.
-            self.stack_mut().pop();
-        })
+        // For the final checks, use same span as preamble since it is unclear what else to do.
+        self.frame_mut().loc = Right(preamble_span);
+        // If the callee needs a caller location, pretend we consume one more argument from the ABI.
+        if instance.def.requires_caller_location(*self.tcx) {
+            callee_args_abis.next().unwrap();
+        }
+        // Now we should have no more caller args or callee arg ABIs.
+        assert!(
+            callee_args_abis.next().is_none(),
+            "mismatch between callee ABI and callee body arguments"
+        );
+        if caller_args.next().is_some() {
+            throw_ub_format!("calling a function with more arguments than it expected");
+        }
+
+        // Done!
+        self.push_stack_frame_done()
     }
 
     /// Initiate a call to this function -- pushing the stack frame and initializing the arguments.
diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs
index b0f3426..a737672 100644
--- a/compiler/rustc_const_eval/src/interpret/stack.rs
+++ b/compiler/rustc_const_eval/src/interpret/stack.rs
@@ -381,7 +381,7 @@ pub(crate) fn push_stack_frame_raw(
         let locals = IndexVec::from_elem(dead_local, &body.local_decls);
         let pre_frame = Frame {
             body,
-            loc: Right(body.span), // Span used for errors caused during preamble.
+            loc: Right(self.tcx.def_span(body.source.def_id())), // Span used for errors caused during preamble.
             return_cont,
             return_place: return_place.clone(),
             locals,
@@ -408,7 +408,6 @@ pub(crate) fn push_stack_frame_raw(
 
         // Finish things up.
         M::after_stack_push(self)?;
-        self.frame_mut().loc = Left(mir::Location::START);
         // `tracing_separate_thread` is used to instruct the tracing_chrome [tracing::Layer] in Miri
         // to put the "frame" span on a separate trace thread/line than other spans, to make the
         // visualization in <https://ui.perfetto.dev> easier to interpret. It is set to a value of
@@ -466,9 +465,11 @@ pub(super) fn cleanup_stack_frame(
         }
     }
 
-    /// In the current stack frame, mark all locals as live that are not arguments and don't have
-    /// `Storage*` annotations (this includes the return place).
-    pub(crate) fn storage_live_for_always_live_locals(&mut self) -> InterpResult<'tcx> {
+    /// Call this after `push_stack_frame_raw` and when all the other setup that needs to be done
+    /// is completed.
+    pub(crate) fn push_stack_frame_done(&mut self) -> InterpResult<'tcx> {
+        // Mark all locals as live that are not arguments and don't have `Storage*` annotations
+        // (this includes the return place, but not the arguments).
         self.storage_live(mir::RETURN_PLACE)?;
 
         let body = self.body();
@@ -478,6 +479,10 @@ pub(crate) fn storage_live_for_always_live_locals(&mut self) -> InterpResult<'tc
                 self.storage_live(local)?;
             }
         }
+
+        // Get ready to execute the first instruction in the stack frame.
+        self.frame_mut().loc = Left(mir::Location::START);
+
         interp_ok(())
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 41a4cb2..de34005 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -47,9 +47,9 @@
 macro_rules! err_validation_failure {
     ($where:expr,  $msg:expr ) => {{
         let where_ = &$where;
-        let path = if !where_.is_empty() {
+        let path = if !where_.projs.is_empty() {
             let mut path = String::new();
-            write_path(&mut path, where_);
+            write_path(&mut path, &where_.projs);
             Some(path)
         } else {
             None
@@ -59,6 +59,7 @@ macro_rules! err_validation_failure {
         use ValidationErrorKind::*;
         let msg = ValidationErrorKind::from($msg);
         err_ub!(ValidationError {
+            orig_ty: where_.orig_ty,
             path,
             ptr_bytes_warning: msg.ptr_bytes_warning(),
             msg: msg.to_string(),
@@ -128,7 +129,6 @@ enum ExpectedKind {
     Reference,
     Box,
     RawPtr,
-    InitScalar,
     Bool,
     Char,
     Float,
@@ -143,7 +143,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             ExpectedKind::Reference => "expected a reference",
             ExpectedKind::Box => "expected a box",
             ExpectedKind::RawPtr => "expected a raw pointer",
-            ExpectedKind::InitScalar => "expected initialized scalar value",
             ExpectedKind::Bool => "expected a boolean",
             ExpectedKind::Char => "expected a unicode scalar value",
             ExpectedKind::Float => "expected a floating point number",
@@ -236,7 +235,7 @@ fn fmt_range(r: WrappingRange, max_hi: u128) -> String {
 /// So we track a `Vec<PathElem>` where `PathElem` contains all the data we
 /// need to later print something for the user.
 #[derive(Copy, Clone, Debug)]
-pub enum PathElem {
+pub enum PathElem<'tcx> {
     Field(Symbol),
     Variant(Symbol),
     CoroutineState(VariantIdx),
@@ -246,10 +245,22 @@ pub enum PathElem {
     Deref,
     EnumTag,
     CoroutineTag,
-    DynDowncast,
+    DynDowncast(Ty<'tcx>),
     Vtable,
 }
 
+#[derive(Clone, Debug)]
+pub struct Path<'tcx> {
+    orig_ty: Ty<'tcx>,
+    projs: Vec<PathElem<'tcx>>,
+}
+
+impl<'tcx> Path<'tcx> {
+    fn new(ty: Ty<'tcx>) -> Self {
+        Self { orig_ty: ty, projs: vec![] }
+    }
+}
+
 /// Extra things to check for during validation of CTFE results.
 #[derive(Copy, Clone)]
 pub enum CtfeValidationMode {
@@ -282,16 +293,10 @@ pub struct RefTracking<T, PATH = ()> {
     todo: Vec<(T, PATH)>,
 }
 
-impl<T: Clone + Eq + Hash + std::fmt::Debug, PATH: Default> RefTracking<T, PATH> {
+impl<T: Clone + Eq + Hash + std::fmt::Debug, PATH> RefTracking<T, PATH> {
     pub fn empty() -> Self {
         RefTracking { seen: FxHashSet::default(), todo: vec![] }
     }
-    pub fn new(val: T) -> Self {
-        let mut ref_tracking_for_consts =
-            RefTracking { seen: FxHashSet::default(), todo: vec![(val.clone(), PATH::default())] };
-        ref_tracking_for_consts.seen.insert(val);
-        ref_tracking_for_consts
-    }
     pub fn next(&mut self) -> Option<(T, PATH)> {
         self.todo.pop()
     }
@@ -306,8 +311,17 @@ fn track(&mut self, val: T, path: impl FnOnce() -> PATH) {
     }
 }
 
+impl<'tcx, T: Clone + Eq + Hash + std::fmt::Debug> RefTracking<T, Path<'tcx>> {
+    pub fn new(val: T, ty: Ty<'tcx>) -> Self {
+        let mut ref_tracking_for_consts =
+            RefTracking { seen: FxHashSet::default(), todo: vec![(val.clone(), Path::new(ty))] };
+        ref_tracking_for_consts.seen.insert(val);
+        ref_tracking_for_consts
+    }
+}
+
 /// Format a path
-fn write_path(out: &mut String, path: &[PathElem]) {
+fn write_path(out: &mut String, path: &[PathElem<'_>]) {
     use self::PathElem::*;
 
     for elem in path.iter() {
@@ -325,7 +339,7 @@ fn write_path(out: &mut String, path: &[PathElem]) {
             // even use the usual syntax because we are just showing the projections,
             // not the root.
             Deref => write!(out, ".<deref>"),
-            DynDowncast => write!(out, ".<dyn-downcast>"),
+            DynDowncast(ty) => write!(out, ".<dyn-downcast({ty})>"),
             Vtable => write!(out, ".<vtable>"),
         }
         .unwrap()
@@ -384,10 +398,9 @@ fn add_range(&mut self, offset: Size, size: Size) {
 
 struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> {
     /// The `path` may be pushed to, but the part that is present when a function
-    /// starts must not be changed!  `visit_fields` and `visit_array` rely on
-    /// this stack discipline.
-    path: Vec<PathElem>,
-    ref_tracking: Option<&'rt mut RefTracking<MPlaceTy<'tcx, M::Provenance>, Vec<PathElem>>>,
+    /// starts must not be changed!  `with_elem` relies on this stack discipline.
+    path: Path<'tcx>,
+    ref_tracking: Option<&'rt mut RefTracking<MPlaceTy<'tcx, M::Provenance>, Path<'tcx>>>,
     /// `None` indicates this is not validating for CTFE (but for runtime).
     ctfe_mode: Option<CtfeValidationMode>,
     ecx: &'rt mut InterpCx<'tcx, M>,
@@ -406,7 +419,12 @@ struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> {
 }
 
 impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
-    fn aggregate_field_path_elem(&mut self, layout: TyAndLayout<'tcx>, field: usize) -> PathElem {
+    fn aggregate_field_path_elem(
+        &mut self,
+        layout: TyAndLayout<'tcx>,
+        field: usize,
+        field_ty: Ty<'tcx>,
+    ) -> PathElem<'tcx> {
         // First, check if we are projecting to a variant.
         match layout.variants {
             Variants::Multiple { tag_field, .. } => {
@@ -476,7 +494,7 @@ fn aggregate_field_path_elem(&mut self, layout: TyAndLayout<'tcx>, field: usize)
             // dyn traits
             ty::Dynamic(..) => {
                 assert_eq!(field, 0);
-                PathElem::DynDowncast
+                PathElem::DynDowncast(field_ty)
             }
 
             // nothing else has an aggregate layout
@@ -486,17 +504,17 @@ fn aggregate_field_path_elem(&mut self, layout: TyAndLayout<'tcx>, field: usize)
 
     fn with_elem<R>(
         &mut self,
-        elem: PathElem,
+        elem: PathElem<'tcx>,
         f: impl FnOnce(&mut Self) -> InterpResult<'tcx, R>,
     ) -> InterpResult<'tcx, R> {
         // Remember the old state
-        let path_len = self.path.len();
+        let path_len = self.path.projs.len();
         // Record new element
-        self.path.push(elem);
+        self.path.projs.push(elem);
         // Perform operation
         let r = f(self)?;
         // Undo changes
-        self.path.truncate(path_len);
+        self.path.projs.truncate(path_len);
         // Done
         interp_ok(r)
     }
@@ -680,8 +698,11 @@ fn check_safe_pointer(
                 format!("encountered a {ptr_kind} pointing to uninhabited type {ty}")
             )
         }
-        // Recursive checking
-        if let Some(ref_tracking) = self.ref_tracking.as_deref_mut() {
+
+        // Recursive checking (but not inside `MaybeDangling` of course).
+        if let Some(ref_tracking) = self.ref_tracking.as_deref_mut()
+            && !self.may_dangle
+        {
             // Proceed recursively even for ZST, no reason to skip them!
             // `!` is a ZST and we want to validate it.
             if let Some(ctfe_mode) = self.ctfe_mode {
@@ -795,10 +816,10 @@ fn check_safe_pointer(
             ref_tracking.track(place, || {
                 // We need to clone the path anyway, make sure it gets created
                 // with enough space for the additional `Deref`.
-                let mut new_path = Vec::with_capacity(path.len() + 1);
-                new_path.extend(path);
-                new_path.push(PathElem::Deref);
-                new_path
+                let mut new_projs = Vec::with_capacity(path.projs.len() + 1);
+                new_projs.extend(&path.projs);
+                new_projs.push(PathElem::Deref);
+                Path { projs: new_projs, orig_ty: path.orig_ty }
             });
         }
         interp_ok(())
@@ -1219,7 +1240,7 @@ fn visit_field(
         field: usize,
         new_val: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
-        let elem = self.aggregate_field_path_elem(old_val.layout, field);
+        let elem = self.aggregate_field_path_elem(old_val.layout, field, new_val.layout.ty);
         self.with_elem(elem, move |this| this.visit_value(new_val))
     }
 
@@ -1384,7 +1405,7 @@ fn visit_value(&mut self, val: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'t
                                 access.bad.start.bytes() / layout.size.bytes(),
                             )
                             .unwrap();
-                            self.path.push(PathElem::ArrayElem(i));
+                            self.path.projs.push(PathElem::ArrayElem(i));
 
                             if matches!(kind, Ub(InvalidUninitBytes(_))) {
                                 err_validation_failure!(self.path, Uninit { expected })
@@ -1478,7 +1499,9 @@ fn visit_value(&mut self, val: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'t
             BackendRepr::Scalar(scalar_layout) => {
                 if !scalar_layout.is_uninit_valid() {
                     // There is something to check here.
-                    let scalar = self.read_scalar(val, ExpectedKind::InitScalar)?;
+                    // We read directly via `ecx` since the read cannot fail -- we already read
+                    // this field above when recursing into the field.
+                    let scalar = self.ecx.read_scalar(val)?;
                     self.visit_scalar(scalar, scalar_layout)?;
                 }
             }
@@ -1487,8 +1510,9 @@ fn visit_value(&mut self, val: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'t
                 // FIXME: find a way to also check ScalarPair when one side can be uninit but
                 // the other must be init.
                 if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() {
-                    let (a, b) =
-                        self.read_immediate(val, ExpectedKind::InitScalar)?.to_scalar_pair();
+                    // We read directly via `ecx` since the read cannot fail -- we already read
+                    // this field above when recursing into the field.
+                    let (a, b) = self.ecx.read_immediate(val)?.to_scalar_pair();
                     self.visit_scalar(a, a_layout)?;
                     self.visit_scalar(b, b_layout)?;
                 }
@@ -1508,13 +1532,15 @@ fn visit_value(&mut self, val: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'t
 }
 
 impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
+    /// The internal core entry point for all validation operations.
     fn validate_operand_internal(
         &mut self,
         val: &PlaceTy<'tcx, M::Provenance>,
-        path: Vec<PathElem>,
-        ref_tracking: Option<&mut RefTracking<MPlaceTy<'tcx, M::Provenance>, Vec<PathElem>>>,
+        path: Path<'tcx>,
+        ref_tracking: Option<&mut RefTracking<MPlaceTy<'tcx, M::Provenance>, Path<'tcx>>>,
         ctfe_mode: Option<CtfeValidationMode>,
         reset_provenance_and_padding: bool,
+        start_in_may_dangle: bool,
     ) -> InterpResult<'tcx> {
         trace!("validate_operand_internal: {:?}, {:?}", *val, val.layout.ty);
 
@@ -1532,7 +1558,7 @@ fn validate_operand_internal(
                 ecx,
                 reset_provenance_and_padding,
                 data_bytes: reset_padding.then_some(RangeSet(Vec::new())),
-                may_dangle: false,
+                may_dangle: start_in_may_dangle,
             };
             v.visit_value(val)?;
             v.reset_padding(val)?;
@@ -1565,8 +1591,8 @@ fn validate_operand_internal(
     pub(crate) fn const_validate_operand(
         &mut self,
         val: &PlaceTy<'tcx, M::Provenance>,
-        path: Vec<PathElem>,
-        ref_tracking: &mut RefTracking<MPlaceTy<'tcx, M::Provenance>, Vec<PathElem>>,
+        path: Path<'tcx>,
+        ref_tracking: &mut RefTracking<MPlaceTy<'tcx, M::Provenance>, Path<'tcx>>,
         ctfe_mode: CtfeValidationMode,
     ) -> InterpResult<'tcx> {
         self.validate_operand_internal(
@@ -1575,6 +1601,7 @@ pub(crate) fn const_validate_operand(
             Some(ref_tracking),
             Some(ctfe_mode),
             /*reset_provenance*/ false,
+            /*start_in_may_dangle*/ false,
         )
     }
 
@@ -1595,36 +1622,40 @@ pub fn validate_operand(
             reset_provenance_and_padding,
             ?val,
         );
-
         // Note that we *could* actually be in CTFE here with `-Zextra-const-ub-checks`, but it's
         // still correct to not use `ctfe_mode`: that mode is for validation of the final constant
         // value, it rules out things like `UnsafeCell` in awkward places.
         if !recursive {
             return self.validate_operand_internal(
                 val,
-                vec![],
+                Path::new(val.layout.ty),
                 None,
                 None,
                 reset_provenance_and_padding,
+                /*start_in_may_dangle*/ false,
             );
         }
         // Do a recursive check.
         let mut ref_tracking = RefTracking::empty();
         self.validate_operand_internal(
             val,
-            vec![],
+            Path::new(val.layout.ty),
             Some(&mut ref_tracking),
             None,
             reset_provenance_and_padding,
+            /*start_in_may_dangle*/ false,
         )?;
         while let Some((mplace, path)) = ref_tracking.todo.pop() {
-            // Things behind reference do *not* have the provenance reset.
+            // Things behind reference do *not* have the provenance reset. In fact
+            // we treat the entire thing as being inside MaybeDangling, i.e., references
+            // do not have to be dereferenceable.
             self.validate_operand_internal(
                 &mplace.into(),
                 path,
-                Some(&mut ref_tracking),
+                None, // no further recursion
                 None,
                 /*reset_provenance_and_padding*/ false,
+                /*start_in_may_dangle*/ true,
             )?;
         }
         interp_ok(())
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index a9fff6d..33da1c5 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -5,7 +5,6 @@
 #![feature(never_type)]
 #![feature(slice_ptr_get)]
 #![feature(trait_alias)]
-#![feature(try_blocks)]
 #![feature(unqualified_local_imports)]
 #![feature(yeet_expr)]
 #![warn(unqualified_local_imports)]
diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs
index c7c0d0a..06ab95d 100644
--- a/compiler/rustc_data_structures/src/fingerprint.rs
+++ b/compiler/rustc_data_structures/src/fingerprint.rs
@@ -181,22 +181,24 @@ fn decode(d: &mut D) -> Self {
     }
 }
 
-// `PackedFingerprint` wraps a `Fingerprint`. Its purpose is to, on certain
-// architectures, behave like a `Fingerprint` without alignment requirements.
-// This behavior is only enabled on x86 and x86_64, where the impact of
-// unaligned accesses is tolerable in small doses.
-//
-// This may be preferable to use in large collections of structs containing
-// fingerprints, as it can reduce memory consumption by preventing the padding
-// that the more strictly-aligned `Fingerprint` can introduce. An application of
-// this is in the query dependency graph, which contains a large collection of
-// `DepNode`s. As of this writing, the size of a `DepNode` decreases by ~30%
-// (from 24 bytes to 17) by using the packed representation here, which
-// noticeably decreases total memory usage when compiling large crates.
-//
-// The wrapped `Fingerprint` is private to reduce the chance of a client
-// invoking undefined behavior by taking a reference to the packed field.
-#[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), repr(packed))]
+/// `PackedFingerprint` wraps a `Fingerprint`.
+/// Its purpose is to behave like a `Fingerprint` without alignment requirements.
+///
+/// This may be preferable to use in large collections of structs containing
+/// fingerprints, as it can reduce memory consumption by preventing the padding
+/// that the more strictly-aligned `Fingerprint` can introduce. An application of
+/// this is in the query dependency graph, which contains a large collection of
+/// `DepNode`s. As of this writing, the size of a `DepNode` decreases by 25%
+/// (from 24 bytes to 18) by using the packed representation here, which
+/// noticeably decreases total memory usage when compiling large crates.
+///
+/// (Unalignment was previously restricted to `x86` and `x86_64` hosts, but is
+/// now enabled by default for all host architectures, in the hope that the
+/// memory and cache savings should outweigh any unaligned access penalty.)
+///
+/// The wrapped `Fingerprint` is private to reduce the chance of a client
+/// invoking undefined behavior by taking a reference to the packed field.
+#[repr(packed)]
 #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy, Hash)]
 pub struct PackedFingerprint(Fingerprint);
 
diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs
index cbf88ef..b112ecc 100644
--- a/compiler/rustc_data_structures/src/sync/parallel.rs
+++ b/compiler/rustc_data_structures/src/sync/parallel.rs
@@ -129,12 +129,28 @@ fn par_slice<I: DynSend>(
     for_each: impl Fn(&mut I) + DynSync + DynSend,
     proof: FromDyn<()>,
 ) {
+    match items {
+        [] => return,
+        [item] => {
+            guard.run(|| for_each(item));
+            return;
+        }
+        _ => (),
+    }
+
     let for_each = proof.derive(for_each);
     let mut items = for_each.derive(items);
     rustc_thread_pool::scope(|s| {
         let proof = items.derive(());
-        let group_size = std::cmp::max(items.len() / 128, 1);
-        for group in items.chunks_mut(group_size) {
+
+        const MAX_GROUP_COUNT: usize = 128;
+        let group_size = items.len().div_ceil(MAX_GROUP_COUNT);
+        let groups = items.chunks_mut(group_size);
+
+        // Reverse the order of the later functions since Rayon executes them in reverse
+        // order when using a single thread. This ensures the execution order matches
+        // that of a single threaded rustc.
+        for group in groups.rev() {
             let group = proof.derive(group);
             s.spawn(|_| {
                 let mut group = group;
diff --git a/compiler/rustc_data_structures/src/vec_cache.rs b/compiler/rustc_data_structures/src/vec_cache.rs
index aea5924..6d026bb 100644
--- a/compiler/rustc_data_structures/src/vec_cache.rs
+++ b/compiler/rustc_data_structures/src/vec_cache.rs
@@ -6,12 +6,16 @@
 //!
 //! This is currently used for query caching.
 
-use std::fmt::Debug;
+use std::fmt::{self, Debug};
 use std::marker::PhantomData;
+use std::ops::{Index, IndexMut};
 use std::sync::atomic::{AtomicPtr, AtomicU32, AtomicUsize, Ordering};
 
 use rustc_index::Idx;
 
+#[cfg(test)]
+mod tests;
+
 struct Slot<V> {
     // We never construct &Slot<V> so it's fine for this to not be in an UnsafeCell.
     value: V,
@@ -28,7 +32,7 @@ struct Slot<V> {
 #[derive(Copy, Clone, Debug)]
 struct SlotIndex {
     // the index of the bucket in VecCache (0 to 20)
-    bucket_idx: usize,
+    bucket_idx: BucketIndex,
     // the index of the slot within the bucket
     index_in_bucket: usize,
 }
@@ -42,7 +46,7 @@ struct SlotIndex {
     let mut key = 0;
     loop {
         let si = SlotIndex::from_index(key);
-        entries[si.bucket_idx] = si.entries();
+        entries[si.bucket_idx.to_usize()] = si.bucket_idx.capacity();
         if key == 0 {
             key = 1;
         } else if key == (1 << 31) {
@@ -57,48 +61,24 @@ struct SlotIndex {
 const BUCKETS: usize = 21;
 
 impl SlotIndex {
-    /// The total possible number of entries in the bucket
-    const fn entries(&self) -> usize {
-        if self.bucket_idx == 0 { 1 << 12 } else { 1 << (self.bucket_idx + 11) }
-    }
-
-    // This unpacks a flat u32 index into identifying which bucket it belongs to and the offset
-    // within that bucket. As noted in the VecCache docs, buckets double in size with each index.
-    // Typically that would mean 31 buckets (2^0 + 2^1 ... + 2^31 = u32::MAX - 1), but to reduce
-    // the size of the VecCache struct and avoid uselessly small allocations, we instead have the
-    // first bucket have 2**12 entries. To simplify the math, the second bucket also 2**12 entries,
-    // and buckets double from there.
-    //
-    // We assert that [0, 2**32 - 1] uniquely map through this function to individual, consecutive
-    // slots (see `slot_index_exhaustive` in tests).
+    /// Unpacks a flat 32-bit index into a [`BucketIndex`] and a slot offset within that bucket.
     #[inline]
     const fn from_index(idx: u32) -> Self {
-        const FIRST_BUCKET_SHIFT: usize = 12;
-        if idx < (1 << FIRST_BUCKET_SHIFT) {
-            return SlotIndex { bucket_idx: 0, index_in_bucket: idx as usize };
-        }
-        // We already ruled out idx 0, so this `ilog2` never panics (and the check optimizes away)
-        let bucket = idx.ilog2() as usize;
-        let entries = 1 << bucket;
-        SlotIndex {
-            bucket_idx: bucket - FIRST_BUCKET_SHIFT + 1,
-            index_in_bucket: idx as usize - entries,
-        }
+        let (bucket_idx, index_in_bucket) = BucketIndex::from_flat_index(idx as usize);
+        SlotIndex { bucket_idx, index_in_bucket }
     }
 
     // SAFETY: Buckets must be managed solely by functions here (i.e., get/put on SlotIndex) and
     // `self` comes from SlotIndex::from_index
     #[inline]
     unsafe fn get<V: Copy>(&self, buckets: &[AtomicPtr<Slot<V>>; 21]) -> Option<(V, u32)> {
-        // SAFETY: `bucket_idx` is ilog2(u32).saturating_sub(11), which is at most 21, i.e.,
-        // in-bounds of buckets. See `from_index` for computation.
-        let bucket = unsafe { buckets.get_unchecked(self.bucket_idx) };
+        let bucket = &buckets[self.bucket_idx];
         let ptr = bucket.load(Ordering::Acquire);
         // Bucket is not yet initialized: then we obviously won't find this entry in that bucket.
         if ptr.is_null() {
             return None;
         }
-        debug_assert!(self.index_in_bucket < self.entries());
+        debug_assert!(self.index_in_bucket < self.bucket_idx.capacity());
         // SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this
         // must be inbounds.
         let slot = unsafe { ptr.add(self.index_in_bucket) };
@@ -131,7 +111,7 @@ fn bucket_ptr<V>(&self, bucket: &AtomicPtr<Slot<V>>) -> *mut Slot<V> {
 
     #[cold]
     #[inline(never)]
-    fn initialize_bucket<V>(bucket: &AtomicPtr<Slot<V>>, bucket_idx: usize) -> *mut Slot<V> {
+    fn initialize_bucket<V>(bucket: &AtomicPtr<Slot<V>>, bucket_idx: BucketIndex) -> *mut Slot<V> {
         static LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
 
         // If we are initializing the bucket, then acquire a global lock.
@@ -145,8 +125,8 @@ fn initialize_bucket<V>(bucket: &AtomicPtr<Slot<V>>, bucket_idx: usize) -> *mut
         // OK, now under the allocator lock, if we're still null then it's definitely us that will
         // initialize this bucket.
         if ptr.is_null() {
-            let bucket_len = SlotIndex { bucket_idx, index_in_bucket: 0 }.entries();
-            let bucket_layout = std::alloc::Layout::array::<Slot<V>>(bucket_len).unwrap();
+            let bucket_layout =
+                std::alloc::Layout::array::<Slot<V>>(bucket_idx.capacity()).unwrap();
             // This is more of a sanity check -- this code is very cold, so it's safe to pay a
             // little extra cost here.
             assert!(bucket_layout.size() > 0);
@@ -167,12 +147,10 @@ fn initialize_bucket<V>(bucket: &AtomicPtr<Slot<V>>, bucket_idx: usize) -> *mut
     /// Returns true if this successfully put into the map.
     #[inline]
     fn put<V>(&self, buckets: &[AtomicPtr<Slot<V>>; 21], value: V, extra: u32) -> bool {
-        // SAFETY: `bucket_idx` is ilog2(u32).saturating_sub(11), which is at most 21, i.e.,
-        // in-bounds of buckets.
-        let bucket = unsafe { buckets.get_unchecked(self.bucket_idx) };
+        let bucket = &buckets[self.bucket_idx];
         let ptr = self.bucket_ptr(bucket);
 
-        debug_assert!(self.index_in_bucket < self.entries());
+        debug_assert!(self.index_in_bucket < self.bucket_idx.capacity());
         // SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this
         // must be inbounds.
         let slot = unsafe { ptr.add(self.index_in_bucket) };
@@ -209,12 +187,10 @@ fn initialize_bucket<V>(bucket: &AtomicPtr<Slot<V>>, bucket_idx: usize) -> *mut
     /// Inserts into the map, given that the slot is unique, so it won't race with other threads.
     #[inline]
     unsafe fn put_unique<V>(&self, buckets: &[AtomicPtr<Slot<V>>; 21], value: V, extra: u32) {
-        // SAFETY: `bucket_idx` is ilog2(u32).saturating_sub(11), which is at most 21, i.e.,
-        // in-bounds of buckets.
-        let bucket = unsafe { buckets.get_unchecked(self.bucket_idx) };
+        let bucket = &buckets[self.bucket_idx];
         let ptr = self.bucket_ptr(bucket);
 
-        debug_assert!(self.index_in_bucket < self.entries());
+        debug_assert!(self.index_in_bucket < self.bucket_idx.capacity());
         // SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this
         // must be inbounds.
         let slot = unsafe { ptr.add(self.index_in_bucket) };
@@ -254,7 +230,7 @@ pub struct VecCache<K: Idx, V, I> {
     // ...
     // Bucket 19: 1073741824
     // Bucket 20: 2147483648
-    // The total number of entries if all buckets are initialized is u32::MAX-1.
+    // The total number of entries if all buckets are initialized is 2^32.
     buckets: [AtomicPtr<Slot<V>>; BUCKETS],
 
     // In the compiler's current usage these are only *read* during incremental and self-profiling.
@@ -289,7 +265,7 @@ fn drop(&mut self) {
         assert!(!std::mem::needs_drop::<K>());
         assert!(!std::mem::needs_drop::<V>());
 
-        for (idx, bucket) in self.buckets.iter().enumerate() {
+        for (idx, bucket) in BucketIndex::enumerate_buckets(&self.buckets) {
             let bucket = bucket.load(Ordering::Acquire);
             if !bucket.is_null() {
                 let layout = std::alloc::Layout::array::<Slot<V>>(ENTRIES_BY_BUCKET[idx]).unwrap();
@@ -299,7 +275,7 @@ fn drop(&mut self) {
             }
         }
 
-        for (idx, bucket) in self.present.iter().enumerate() {
+        for (idx, bucket) in BucketIndex::enumerate_buckets(&self.present) {
             let bucket = bucket.load(Ordering::Acquire);
             if !bucket.is_null() {
                 let layout = std::alloc::Layout::array::<Slot<()>>(ENTRIES_BY_BUCKET[idx]).unwrap();
@@ -365,5 +341,164 @@ pub fn len(&self) -> usize {
     }
 }
 
-#[cfg(test)]
-mod tests;
+/// Index into an array of buckets.
+///
+/// Using an enum lets us tell the compiler that values range from 0 to 20,
+/// allowing array bounds checks to be optimized away,
+/// without having to resort to pattern types or other unstable features.
+#[derive(Clone, Copy, PartialEq, Eq)]
+#[repr(usize)]
+enum BucketIndex {
+    // tidy-alphabetical-start
+    Bucket00,
+    Bucket01,
+    Bucket02,
+    Bucket03,
+    Bucket04,
+    Bucket05,
+    Bucket06,
+    Bucket07,
+    Bucket08,
+    Bucket09,
+    Bucket10,
+    Bucket11,
+    Bucket12,
+    Bucket13,
+    Bucket14,
+    Bucket15,
+    Bucket16,
+    Bucket17,
+    Bucket18,
+    Bucket19,
+    Bucket20,
+    // tidy-alphabetical-end
+}
+
+impl Debug for BucketIndex {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        Debug::fmt(&self.to_usize(), f)
+    }
+}
+
+impl BucketIndex {
+    /// Capacity of bucket 0 (and also of bucket 1).
+    const BUCKET_0_CAPACITY: usize = 1 << (Self::NONZERO_BUCKET_SHIFT_ADJUST + 1);
+    /// Adjustment factor from the highest-set-bit-position of a flat index,
+    /// to its corresponding bucket number.
+    ///
+    /// For example, the first flat-index in bucket 2 is 8192.
+    /// Its highest-set-bit-position is `(8192).ilog2() == 13`, and subtracting
+    /// the adjustment factor of 11 gives the bucket number of 2.
+    const NONZERO_BUCKET_SHIFT_ADJUST: usize = 11;
+
+    #[inline(always)]
+    const fn to_usize(self) -> usize {
+        self as usize
+    }
+
+    #[inline(always)]
+    const fn from_raw(raw: usize) -> Self {
+        match raw {
+            // tidy-alphabetical-start
+            00 => Self::Bucket00,
+            01 => Self::Bucket01,
+            02 => Self::Bucket02,
+            03 => Self::Bucket03,
+            04 => Self::Bucket04,
+            05 => Self::Bucket05,
+            06 => Self::Bucket06,
+            07 => Self::Bucket07,
+            08 => Self::Bucket08,
+            09 => Self::Bucket09,
+            10 => Self::Bucket10,
+            11 => Self::Bucket11,
+            12 => Self::Bucket12,
+            13 => Self::Bucket13,
+            14 => Self::Bucket14,
+            15 => Self::Bucket15,
+            16 => Self::Bucket16,
+            17 => Self::Bucket17,
+            18 => Self::Bucket18,
+            19 => Self::Bucket19,
+            20 => Self::Bucket20,
+            // tidy-alphabetical-end
+            _ => panic!("bucket index out of range"),
+        }
+    }
+
+    /// Total number of slots in this bucket.
+    #[inline(always)]
+    const fn capacity(self) -> usize {
+        match self {
+            Self::Bucket00 => Self::BUCKET_0_CAPACITY,
+            // Bucket 1 has a capacity of `1 << (1 + 11) == pow(2, 12) == 4096`.
+            // Bucket 2 has a capacity of `1 << (2 + 11) == pow(2, 13) == 8192`.
+            _ => 1 << (self.to_usize() + Self::NONZERO_BUCKET_SHIFT_ADJUST),
+        }
+    }
+
+    /// Converts a flat index in the range `0..=u32::MAX` into a bucket index,
+    /// and a slot offset within that bucket.
+    ///
+    /// Panics if `flat > u32::MAX`.
+    #[inline(always)]
+    const fn from_flat_index(flat: usize) -> (Self, usize) {
+        if flat > u32::MAX as usize {
+            panic!();
+        }
+
+        // If the index is in bucket 0, the conversion is trivial.
+        // This also avoids calling `ilog2` when `flat == 0`.
+        if flat < Self::BUCKET_0_CAPACITY {
+            return (Self::Bucket00, flat);
+        }
+
+        // General-case conversion for a non-zero bucket index.
+        //
+        //              | bucket |   slot
+        // flat | ilog2 |  index | offset
+        // ------------------------------
+        // 4096 |    12 |      1 |      0
+        // 4097 |    12 |      1 |      1
+        // ...
+        // 8191 |    12 |      1 |   4095
+        // 8192 |    13 |      2 |      0
+        let highest_bit_pos = flat.ilog2() as usize;
+        let bucket_index =
+            BucketIndex::from_raw(highest_bit_pos - Self::NONZERO_BUCKET_SHIFT_ADJUST);
+
+        // Clear the highest-set bit (which selects the bucket) to get the
+        // slot offset within this bucket.
+        let slot_offset = flat - (1 << highest_bit_pos);
+
+        (bucket_index, slot_offset)
+    }
+
+    #[inline(always)]
+    fn iter_all() -> impl ExactSizeIterator<Item = Self> {
+        (0usize..BUCKETS).map(BucketIndex::from_raw)
+    }
+
+    #[inline(always)]
+    fn enumerate_buckets<T>(buckets: &[T; BUCKETS]) -> impl ExactSizeIterator<Item = (Self, &T)> {
+        BucketIndex::iter_all().zip(buckets)
+    }
+}
+
+impl<T> Index<BucketIndex> for [T; BUCKETS] {
+    type Output = T;
+
+    #[inline(always)]
+    fn index(&self, index: BucketIndex) -> &Self::Output {
+        // The optimizer should be able to see that see that a bucket index is
+        // always in-bounds, and omit the runtime bounds check.
+        &self[index.to_usize()]
+    }
+}
+
+impl<T> IndexMut<BucketIndex> for [T; BUCKETS] {
+    #[inline(always)]
+    fn index_mut(&mut self, index: BucketIndex) -> &mut Self::Output {
+        &mut self[index.to_usize()]
+    }
+}
diff --git a/compiler/rustc_data_structures/src/vec_cache/tests.rs b/compiler/rustc_data_structures/src/vec_cache/tests.rs
index f588442..f12937a 100644
--- a/compiler/rustc_data_structures/src/vec_cache/tests.rs
+++ b/compiler/rustc_data_structures/src/vec_cache/tests.rs
@@ -1,10 +1,46 @@
 use super::*;
 
 #[test]
+#[should_panic(expected = "bucket index out of range")]
+fn bucket_index_n_buckets() {
+    BucketIndex::from_raw(BUCKETS);
+}
+
+#[test]
+fn bucket_index_round_trip() {
+    for i in 0..BUCKETS {
+        assert_eq!(BucketIndex::from_raw(i).to_usize(), i);
+    }
+}
+
+#[test]
+fn bucket_index_iter_all_len() {
+    let len = BucketIndex::iter_all().len();
+    assert_eq!(len, BUCKETS);
+
+    let len = BucketIndex::iter_all().collect::<Vec<_>>().len();
+    assert_eq!(len, BUCKETS);
+
+    let len = BucketIndex::enumerate_buckets(&[(); BUCKETS]).len();
+    assert_eq!(len, BUCKETS);
+}
+
+#[test]
+fn bucket_index_capacity() {
+    // Check that the combined capacity of all buckets is 2^32 slots.
+    // That's 1 larger than `u32::MAX`, so store the total as a `u64`.
+    let mut total = 0u64;
+    for i in BucketIndex::iter_all() {
+        total += u64::try_from(i.capacity()).unwrap();
+    }
+    assert_eq!(total, 1 << 32);
+}
+
+#[test]
 #[cfg(not(miri))]
-fn vec_cache_empty() {
+fn vec_cache_empty_exhaustive() {
     let cache: VecCache<u32, u32, u32> = VecCache::default();
-    for key in 0..u32::MAX {
+    for key in 0..=u32::MAX {
         assert!(cache.lookup(&key).is_none());
     }
 }
@@ -70,8 +106,8 @@ fn slot_entries_table() {
 
 #[test]
 fn bucket_entries_matches() {
-    for i in 0..BUCKETS {
-        assert_eq!(SlotIndex { bucket_idx: i, index_in_bucket: 0 }.entries(), ENTRIES_BY_BUCKET[i]);
+    for i in BucketIndex::iter_all() {
+        assert_eq!(i.capacity(), ENTRIES_BY_BUCKET[i]);
     }
 }
 
@@ -84,13 +120,13 @@ fn slot_index_exhaustive() {
     }
     let slot_idx = SlotIndex::from_index(0);
     assert_eq!(slot_idx.index_in_bucket, 0);
-    assert_eq!(slot_idx.bucket_idx, 0);
+    assert_eq!(slot_idx.bucket_idx, BucketIndex::Bucket00);
     let mut prev = slot_idx;
     for idx in 1..=u32::MAX {
         let slot_idx = SlotIndex::from_index(idx);
 
         // SAFETY: Ensure indices don't go out of bounds of buckets.
-        assert!(slot_idx.index_in_bucket < slot_idx.entries());
+        assert!(slot_idx.index_in_bucket < slot_idx.bucket_idx.capacity());
 
         if prev.bucket_idx == slot_idx.bucket_idx {
             assert_eq!(prev.index_in_bucket + 1, slot_idx.index_in_bucket);
@@ -98,8 +134,8 @@ fn slot_index_exhaustive() {
             assert_eq!(slot_idx.index_in_bucket, 0);
         }
 
-        assert_eq!(buckets[slot_idx.bucket_idx], slot_idx.entries() as u32);
-        assert_eq!(ENTRIES_BY_BUCKET[slot_idx.bucket_idx], slot_idx.entries(), "{}", idx);
+        assert_eq!(buckets[slot_idx.bucket_idx], slot_idx.bucket_idx.capacity() as u32);
+        assert_eq!(ENTRIES_BY_BUCKET[slot_idx.bucket_idx], slot_idx.bucket_idx.capacity(), "{idx}",);
 
         prev = slot_idx;
     }
diff --git a/compiler/rustc_errors/src/decorate_diag.rs b/compiler/rustc_errors/src/decorate_diag.rs
index a11082e..c7e0d50 100644
--- a/compiler/rustc_errors/src/decorate_diag.rs
+++ b/compiler/rustc_errors/src/decorate_diag.rs
@@ -81,4 +81,21 @@ pub fn buffer_lint(
             diagnostic: decorate.into(),
         });
     }
+
+    pub fn dyn_buffer_lint<
+        F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSend + 'static,
+    >(
+        &mut self,
+        lint: &'static Lint,
+        node_id: NodeId,
+        span: impl Into<MultiSpan>,
+        callback: F,
+    ) {
+        self.add_early_lint(BufferedEarlyLint {
+            lint_id: LintId::of(lint),
+            node_id,
+            span: Some(span.into()),
+            diagnostic: DecorateDiagCompat::Dynamic(Box::new(callback)),
+        });
+    }
 }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 8c57544..d17a4d6 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -386,6 +386,7 @@ pub enum StashKey {
     /// it's a method call without parens. If later on in `hir_typeck` we find out that this is
     /// the case we suppress this message and we give a better suggestion.
     GenericInFieldExpr,
+    ReturnTypeNotation,
 }
 
 fn default_track_diagnostic<R>(diag: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 225906d..44f148f 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -149,14 +149,14 @@ pub fn expect_item(self) -> Box<ast::Item> {
     pub fn expect_trait_item(self) -> Box<ast::AssocItem> {
         match self {
             Annotatable::AssocItem(i, AssocCtxt::Trait) => i,
-            _ => panic!("expected Item"),
+            _ => panic!("expected trait item"),
         }
     }
 
     pub fn expect_impl_item(self) -> Box<ast::AssocItem> {
         match self {
             Annotatable::AssocItem(i, AssocCtxt::Impl { .. }) => i,
-            _ => panic!("expected Item"),
+            _ => panic!("expected impl item"),
         }
     }
 
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 8e4039b..ec5951e 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -10,9 +10,10 @@
     self as ast, AttrItemKind, AttrKind, AttrStyle, Attribute, DUMMY_NODE_ID, EarlyParsedAttribute,
     HasAttrs, HasTokens, MetaItem, MetaItemInner, NodeId, NormalAttr,
 };
-use rustc_attr_parsing as attr;
+use rustc_attr_parsing::parser::AllowExprMetavar;
 use rustc_attr_parsing::{
-    AttributeParser, CFG_TEMPLATE, EvalConfigResult, ShouldEmit, eval_config_entry, parse_cfg,
+    self as attr, AttributeParser, CFG_TEMPLATE, EvalConfigResult, ShouldEmit, eval_config_entry,
+    parse_cfg,
 };
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
 use rustc_errors::msg;
@@ -402,6 +403,7 @@ pub(crate) fn cfg_true(&self, attr: &Attribute, emit_errors: ShouldEmit) -> Eval
             emit_errors,
             parse_cfg,
             &CFG_TEMPLATE,
+            AllowExprMetavar::Yes,
         ) else {
             // Cfg attribute was not parsable, give up
             return EvalConfigResult::True;
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 76a9a6f9..640d074 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -13,6 +13,7 @@
     TyKind, token,
 };
 use rustc_ast_pretty::pprust;
+use rustc_attr_parsing::parser::AllowExprMetavar;
 use rustc_attr_parsing::{
     AttributeParser, CFG_TEMPLATE, Early, EvalConfigResult, ShouldEmit, eval_config_entry,
     parse_cfg, validate_attr,
@@ -2224,6 +2225,7 @@ fn expand_cfg_true(
             ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
             parse_cfg,
             &CFG_TEMPLATE,
+            AllowExprMetavar::Yes,
         ) else {
             // Cfg attribute was not parsable, give up
             return EvalConfigResult::True;
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 7ff49e0..82d941a 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -724,7 +724,7 @@ pub fn compile_declarative_macro(
             let args = p.parse_token_tree();
             check_args_parens(sess, sym::attr, &args);
             let args = parse_one_tt(args, RulePart::Pattern, sess, node_id, features, edition);
-            check_emission(check_lhs(sess, node_id, &args));
+            check_emission(check_lhs(sess, features, node_id, &args));
             if let Some(guar) = check_no_eof(sess, &p, "expected macro attr body") {
                 return dummy_syn_ext(guar);
             }
@@ -773,7 +773,7 @@ pub fn compile_declarative_macro(
         };
         let lhs_tt = p.parse_token_tree();
         let lhs_tt = parse_one_tt(lhs_tt, RulePart::Pattern, sess, node_id, features, edition);
-        check_emission(check_lhs(sess, node_id, &lhs_tt));
+        check_emission(check_lhs(sess, features, node_id, &lhs_tt));
         if let Err(e) = p.expect(exp!(FatArrow)) {
             return dummy_syn_ext(e.emit());
         }
@@ -870,21 +870,27 @@ fn check_args_empty(sess: &Session, args: &tokenstream::TokenTree) -> Result<(),
     }
 }
 
-fn check_lhs(sess: &Session, node_id: NodeId, lhs: &mbe::TokenTree) -> Result<(), ErrorGuaranteed> {
-    let e1 = check_lhs_nt_follows(sess, node_id, lhs);
+fn check_lhs(
+    sess: &Session,
+    features: &Features,
+    node_id: NodeId,
+    lhs: &mbe::TokenTree,
+) -> Result<(), ErrorGuaranteed> {
+    let e1 = check_lhs_nt_follows(sess, features, node_id, lhs);
     let e2 = check_lhs_no_empty_seq(sess, slice::from_ref(lhs));
     e1.and(e2)
 }
 
 fn check_lhs_nt_follows(
     sess: &Session,
+    features: &Features,
     node_id: NodeId,
     lhs: &mbe::TokenTree,
 ) -> Result<(), ErrorGuaranteed> {
     // lhs is going to be like TokenTree::Delimited(...), where the
     // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
     if let mbe::TokenTree::Delimited(.., delimited) = lhs {
-        check_matcher(sess, node_id, &delimited.tts)
+        check_matcher(sess, features, node_id, &delimited.tts)
     } else {
         let msg = "invalid macro matcher; matchers must be contained in balanced delimiters";
         Err(sess.dcx().span_err(lhs.span(), msg))
@@ -989,12 +995,13 @@ fn check_rhs(sess: &Session, rhs: &mbe::TokenTree) -> Result<(), ErrorGuaranteed
 
 fn check_matcher(
     sess: &Session,
+    features: &Features,
     node_id: NodeId,
     matcher: &[mbe::TokenTree],
 ) -> Result<(), ErrorGuaranteed> {
     let first_sets = FirstSets::new(matcher);
     let empty_suffix = TokenSet::empty();
-    check_matcher_core(sess, node_id, &first_sets, matcher, &empty_suffix)?;
+    check_matcher_core(sess, features, node_id, &first_sets, matcher, &empty_suffix)?;
     Ok(())
 }
 
@@ -1331,6 +1338,7 @@ fn add_all(&mut self, other: &Self) {
 // see `FirstSets::new`.
 fn check_matcher_core<'tt>(
     sess: &Session,
+    features: &Features,
     node_id: NodeId,
     first_sets: &FirstSets<'tt>,
     matcher: &'tt [mbe::TokenTree],
@@ -1369,6 +1377,17 @@ fn check_matcher_core<'tt>(
             | TokenTree::MetaVar(..)
             | TokenTree::MetaVarDecl { .. }
             | TokenTree::MetaVarExpr(..) => {
+                if let TokenTree::MetaVarDecl { kind: NonterminalKind::Guard, .. } = token
+                    && !features.macro_guard_matcher()
+                {
+                    feature_err(
+                        sess,
+                        sym::macro_guard_matcher,
+                        token.span(),
+                        "`guard` fragments in macro are unstable",
+                    )
+                    .emit();
+                }
                 if token_can_be_followed_by_any(token) {
                     // don't need to track tokens that work with any,
                     last.replace_with_irrelevant();
@@ -1385,7 +1404,7 @@ fn check_matcher_core<'tt>(
                     d.delim.as_close_token_kind(),
                     span.close,
                 ));
-                check_matcher_core(sess, node_id, first_sets, &d.tts, &my_suffix)?;
+                check_matcher_core(sess, features, node_id, first_sets, &d.tts, &my_suffix)?;
                 // don't track non NT tokens
                 last.replace_with_irrelevant();
 
@@ -1417,7 +1436,14 @@ fn check_matcher_core<'tt>(
                 // At this point, `suffix_first` is built, and
                 // `my_suffix` is some TokenSet that we can use
                 // for checking the interior of `seq_rep`.
-                let next = check_matcher_core(sess, node_id, first_sets, &seq_rep.tts, my_suffix)?;
+                let next = check_matcher_core(
+                    sess,
+                    features,
+                    node_id,
+                    first_sets,
+                    &seq_rep.tts,
+                    my_suffix,
+                )?;
                 if next.maybe_empty {
                     last.add_all(&next);
                 } else {
@@ -1609,7 +1635,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
                 }
             }
             NonterminalKind::Pat(PatParam { .. }) => {
-                const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"];
+                const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`if let`", "`in`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
                         FatArrow | Comma | Eq | Or => IsInFollow::Yes,
@@ -1618,11 +1644,12 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
                         }
                         _ => IsInFollow::No(TOKENS),
                     },
+                    TokenTree::MetaVarDecl { kind: NonterminalKind::Guard, .. } => IsInFollow::Yes,
                     _ => IsInFollow::No(TOKENS),
                 }
             }
             NonterminalKind::Pat(PatWithOr) => {
-                const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`if`", "`in`"];
+                const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`if`", "`if let`", "`in`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
                         FatArrow | Comma | Eq => IsInFollow::Yes,
@@ -1631,6 +1658,17 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
                         }
                         _ => IsInFollow::No(TOKENS),
                     },
+                    TokenTree::MetaVarDecl { kind: NonterminalKind::Guard, .. } => IsInFollow::Yes,
+                    _ => IsInFollow::No(TOKENS),
+                }
+            }
+            NonterminalKind::Guard => {
+                const TOKENS: &[&str] = &["`=>`", "`,`", "`{`"];
+                match tok {
+                    TokenTree::Token(token) => match token.kind {
+                        FatArrow | Comma | OpenBrace => IsInFollow::Yes,
+                        _ => IsInFollow::No(TOKENS),
+                    },
                     _ => IsInFollow::No(TOKENS),
                 }
             }
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 09f006c..dcf2cd1 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -12,7 +12,8 @@
 use rustc_session::parse::ParseSess;
 use rustc_span::hygiene::{LocalExpnId, Transparency};
 use rustc_span::{
-    Ident, MacroRulesNormalizedIdent, Span, Symbol, SyntaxContext, sym, with_metavar_spans,
+    BytePos, Ident, MacroRulesNormalizedIdent, Span, Symbol, SyntaxContext, kw, sym,
+    with_metavar_spans,
 };
 use smallvec::{SmallVec, smallvec};
 
@@ -556,6 +557,19 @@ fn transcribe_pnr<'tx>(
         ParseNtResult::Vis(vis) => {
             mk_delimited(vis.span, MetaVarKind::Vis, TokenStream::from_ast(vis))
         }
+        ParseNtResult::Guard(guard) => {
+            // FIXME(macro_guard_matcher):
+            // Perhaps it would be better to treat the leading `if` as part of `ast::Guard` during parsing?
+            // Currently they are separate, but in macros we match and emit the leading `if` for `:guard` matchers, which creates some inconsistency.
+
+            let leading_if_span =
+                guard.span_with_leading_if.with_hi(guard.span_with_leading_if.lo() + BytePos(2));
+            let mut ts =
+                TokenStream::token_alone(token::Ident(kw::If, IdentIsRaw::No), leading_if_span);
+            ts.push_stream(TokenStream::from_ast(&guard.cond));
+
+            mk_delimited(guard.span_with_leading_if, MetaVarKind::Guard, ts)
+        }
     };
 
     tscx.result.push(tt);
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index d74450e..acbcba9 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -773,7 +773,7 @@ pub struct BuiltinAttribute {
         DuplicatesOk, EncodeCrossCrate::No, effective_target_features, experimental!(force_target_feature)
     ),
     gated!(
-        sanitize, Normal, template!(List: &[r#"address = "on|off""#, r#"kernel_address = "on|off""#, r#"cfi = "on|off""#, r#"hwaddress = "on|off""#, r#"kcfi = "on|off""#, r#"memory = "on|off""#, r#"memtag = "on|off""#, r#"shadow_call_stack = "on|off""#, r#"thread = "on|off""#]), ErrorPreceding,
+        sanitize, Normal, template!(List: &[r#"address = "on|off""#, r#"kernel_address = "on|off""#, r#"cfi = "on|off""#, r#"hwaddress = "on|off""#, r#"kernel_hwaddress = "on|off""#, r#"kcfi = "on|off""#, r#"memory = "on|off""#, r#"memtag = "on|off""#, r#"shadow_call_stack = "on|off""#, r#"thread = "on|off""#]), ErrorPreceding,
         EncodeCrossCrate::No, sanitize, experimental!(sanitize),
     ),
     gated!(
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index e8ca20d..5298510 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -473,7 +473,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
     /// Allows giving non-const impls custom diagnostic messages if attempted to be used as const
     (unstable, diagnostic_on_const, "1.93.0", Some(143874)),
     /// Allows giving on-move borrowck custom diagnostic messages for a type
-    (unstable, diagnostic_on_move, "CURRENT_RUSTC_VERSION", Some(150935)),
+    (unstable, diagnostic_on_move, "CURRENT_RUSTC_VERSION", Some(154181)),
     /// Allows `#[doc(cfg(...))]`.
     (unstable, doc_cfg, "1.21.0", Some(43781)),
     /// Allows `#[doc(masked)]`.
@@ -569,6 +569,8 @@ pub fn internal(&self, feature: Symbol) -> bool {
     (unstable, macro_attr, "1.91.0", Some(143547)),
     /// Allow `macro_rules!` derive rules
     (unstable, macro_derive, "1.91.0", Some(143549)),
+    /// Allow `$x:guard` matcher in macros
+    (unstable, macro_guard_matcher, "CURRENT_RUSTC_VERSION", Some(153104)),
     /// Give access to additional metadata about declarative macro meta-variables.
     (unstable, macro_metavar_expr, "1.61.0", Some(83527)),
     /// Provides a way to concatenate identifiers using metavariable expressions.
diff --git a/compiler/rustc_hir/src/attrs/mod.rs b/compiler/rustc_hir/src/attrs/mod.rs
index 09fa144..b3c1dea 100644
--- a/compiler/rustc_hir/src/attrs/mod.rs
+++ b/compiler/rustc_hir/src/attrs/mod.rs
@@ -13,6 +13,15 @@
 mod encode_cross_crate;
 mod pretty_printing;
 
+/// A trait for types that can provide a list of attributes given a `TyCtxt`.
+///
+/// It allows `find_attr!` to accept either a `DefId`, `LocalDefId`, `OwnerId`, or `HirId`.
+/// It is defined here with a generic `Tcx` because `rustc_hir` can't depend on `rustc_middle`.
+/// The concrete implementations are in `rustc_middle`.
+pub trait HasAttrs<'tcx, Tcx> {
+    fn get_attrs(self, tcx: &Tcx) -> &'tcx [crate::Attribute];
+}
+
 /// Finds attributes in sequences of attributes by pattern matching.
 ///
 /// A little like `matches` but for attributes.
@@ -34,10 +43,12 @@
 ///
 /// As a convenience, this macro can do that for you!
 ///
-/// Instead of providing an attribute list, provide the `tcx` and a `DefId`.
+/// Instead of providing an attribute list, provide the `tcx` and an id
+/// (a `DefId`, `LocalDefId`, `OwnerId` or `HirId`).
 ///
 /// ```rust,ignore (illustrative)
 /// find_attr!(tcx, def_id, <pattern>)
+/// find_attr!(tcx, hir_id, <pattern>)
 /// ```
 ///
 /// Another common case is finding attributes applied to the root of the current crate.
@@ -55,13 +66,14 @@ macro_rules! find_attr {
         $crate::find_attr!($tcx.hir_krate_attrs(), $pattern $(if $guard)? => $e)
     };
 
-    ($tcx: expr, $def_id: expr, $pattern: pat $(if $guard: expr)?) => {
-        $crate::find_attr!($tcx, $def_id, $pattern $(if $guard)? => ()).is_some()
+    ($tcx: expr, $id: expr, $pattern: pat $(if $guard: expr)?) => {
+        $crate::find_attr!($tcx, $id, $pattern $(if $guard)? => ()).is_some()
     };
-    ($tcx: expr, $def_id: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{
-        #[allow(deprecated)] {
-            $crate::find_attr!($tcx.get_all_attrs($def_id), $pattern $(if $guard)? => $e)
-        }
+    ($tcx: expr, $id: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{
+        $crate::find_attr!(
+            $crate::attrs::HasAttrs::get_attrs($id, &$tcx),
+            $pattern $(if $guard)? => $e
+        )
     }};
 
 
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 21abb55..2156c98 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -590,6 +590,13 @@ pub enum Res<Id = hir::HirId> {
     /// **Belongs to the type namespace.**
     ToolMod,
 
+    /// The resolution for an open module in a namespaced crate. E.g. `my_api`
+    /// in the namespaced crate `my_api::utils` when `my_api` isn't part of the
+    /// extern prelude.
+    ///
+    /// **Belongs to the type namespace.**
+    OpenMod(Symbol),
+
     // Macro namespace
     /// An attribute that is *not* implemented via macro.
     /// E.g., `#[inline]` and `#[rustfmt::skip]`, which are essentially directives,
@@ -838,6 +845,7 @@ pub fn opt_def_id(&self) -> Option<DefId> {
             | Res::SelfTyAlias { .. }
             | Res::SelfCtor(..)
             | Res::ToolMod
+            | Res::OpenMod(..)
             | Res::NonMacroAttr(..)
             | Res::Err => None,
         }
@@ -869,6 +877,7 @@ pub fn descr(&self) -> &'static str {
             Res::Local(..) => "local variable",
             Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => "self type",
             Res::ToolMod => "tool module",
+            Res::OpenMod(..) => "namespaced crate",
             Res::NonMacroAttr(attr_kind) => attr_kind.descr(),
             Res::Err => "unresolved item",
         }
@@ -895,6 +904,7 @@ pub fn map_id<R>(self, mut map: impl FnMut(Id) -> R) -> Res<R> {
                 Res::SelfTyAlias { alias_to, is_trait_impl }
             }
             Res::ToolMod => Res::ToolMod,
+            Res::OpenMod(sym) => Res::OpenMod(sym),
             Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
             Res::Err => Res::Err,
         }
@@ -911,6 +921,7 @@ pub fn apply_id<R, E>(self, mut map: impl FnMut(Id) -> Result<R, E>) -> Result<R
                 Res::SelfTyAlias { alias_to, is_trait_impl }
             }
             Res::ToolMod => Res::ToolMod,
+            Res::OpenMod(sym) => Res::OpenMod(sym),
             Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
             Res::Err => Res::Err,
         })
@@ -936,9 +947,11 @@ pub fn macro_kinds(self) -> Option<MacroKinds> {
     pub fn ns(&self) -> Option<Namespace> {
         match self {
             Res::Def(kind, ..) => kind.ns(),
-            Res::PrimTy(..) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::ToolMod => {
-                Some(Namespace::TypeNS)
-            }
+            Res::PrimTy(..)
+            | Res::SelfTyParam { .. }
+            | Res::SelfTyAlias { .. }
+            | Res::ToolMod
+            | Res::OpenMod(..) => Some(Namespace::TypeNS),
             Res::SelfCtor(..) | Res::Local(..) => Some(Namespace::ValueNS),
             Res::NonMacroAttr(..) => Some(Namespace::MacroNS),
             Res::Err => None,
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 9526143..57cf42c 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -397,12 +397,7 @@ pub fn invalid() -> Self {
     }
 
     pub fn args(&self) -> &GenericArgs<'hir> {
-        if let Some(ref args) = self.args {
-            args
-        } else {
-            const DUMMY: &GenericArgs<'_> = &GenericArgs::none();
-            DUMMY
-        }
+        if let Some(ref args) = self.args { args } else { GenericArgs::NONE }
     }
 }
 
@@ -643,14 +638,12 @@ pub struct GenericArgs<'hir> {
 }
 
 impl<'hir> GenericArgs<'hir> {
-    pub const fn none() -> Self {
-        Self {
-            args: &[],
-            constraints: &[],
-            parenthesized: GenericArgsParentheses::No,
-            span_ext: DUMMY_SP,
-        }
-    }
+    pub const NONE: &'hir GenericArgs<'hir> = &GenericArgs {
+        args: &[],
+        constraints: &[],
+        parenthesized: GenericArgsParentheses::No,
+        span_ext: DUMMY_SP,
+    };
 
     /// Obtain the list of input types and the output type if the generic arguments are parenthesized.
     ///
@@ -1264,6 +1257,8 @@ pub struct HashIgnoredAttrId {
     pub attr_id: AttrId,
 }
 
+/// Many functions on this type have their documentation in the [`AttributeExt`] trait,
+/// since they defer their implementation directly to that trait.
 #[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)]
 pub enum Attribute {
     /// A parsed built-in attribute.
@@ -3765,12 +3760,21 @@ pub struct DelegationGenerics {
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)]
-pub enum InferDelegationKind<'hir> {
+pub enum InferDelegationSig<'hir> {
     Input(usize),
     // Place generics info here, as we always specify output type for delegations.
     Output(&'hir DelegationGenerics),
 }
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)]
+pub enum InferDelegation<'hir> {
+    /// Infer the type of this `DefId` through `tcx.type_of(def_id).instantiate_identity()`,
+    /// used for const types propagation.
+    DefId(DefId),
+    /// Used during signature inheritance, `DefId` corresponds to the signature function.
+    Sig(DefId, InferDelegationSig<'hir>),
+}
+
 /// The various kinds of types recognized by the compiler.
 ///
 /// For an explanation of the `Unambig` generic parameter see the dev-guide:
@@ -3780,7 +3784,7 @@ pub enum InferDelegationKind<'hir> {
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub enum TyKind<'hir, Unambig = ()> {
     /// Actual type should be inherited from `DefId` signature
-    InferDelegation(DefId, InferDelegationKind<'hir>),
+    InferDelegation(InferDelegation<'hir>),
     /// A variable length slice (i.e., `[T]`).
     Slice(&'hir Ty<'hir>),
     /// A fixed length array (i.e., `[T; n]`).
@@ -3931,7 +3935,7 @@ pub struct FnDecl<'hir> {
 impl<'hir> FnDecl<'hir> {
     pub fn opt_delegation_sig_id(&self) -> Option<DefId> {
         if let FnRetTy::Return(ty) = self.output
-            && let TyKind::InferDelegation(sig_id, _) = ty.kind
+            && let TyKind::InferDelegation(InferDelegation::Sig(sig_id, _)) = ty.kind
         {
             return Some(sig_id);
         }
@@ -3940,8 +3944,8 @@ pub fn opt_delegation_sig_id(&self) -> Option<DefId> {
 
     pub fn opt_delegation_generics(&self) -> Option<&'hir DelegationGenerics> {
         if let FnRetTy::Return(ty) = self.output
-            && let TyKind::InferDelegation(_, kind) = ty.kind
-            && let InferDelegationKind::Output(generics) = kind
+            && let TyKind::InferDelegation(InferDelegation::Sig(_, kind)) = ty.kind
+            && let InferDelegationSig::Output(generics) = kind
         {
             return Some(generics);
         }
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 32cfa30..06ccf61 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -952,10 +952,10 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
             tcx.ensure_ok().type_of(def_id);
             tcx.ensure_ok().predicates_of(def_id);
             check_type_alias_type_params_are_used(tcx, def_id);
+            let ty = tcx.type_of(def_id).instantiate_identity();
+            let span = tcx.def_span(def_id);
             if tcx.type_alias_is_lazy(def_id) {
                 res = res.and(enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
-                    let ty = tcx.type_of(def_id).instantiate_identity();
-                    let span = tcx.def_span(def_id);
                     let item_ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty);
                     wfcx.register_wf_obligation(
                         span,
@@ -966,6 +966,30 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
                     Ok(())
                 }));
                 check_variances_for_type_defn(tcx, def_id);
+            } else {
+                res = res.and(enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
+                    // HACK: We sometimes incidentally check that const arguments have the correct
+                    // type as a side effect of the anon const desugaring. To make this "consistent"
+                    // for users we explicitly check `ConstArgHasType` clauses so that const args
+                    // that don't go through an anon const still have their types checked.
+                    //
+                    // We use the unnormalized type as this mirrors the behaviour that we previously
+                    // would have had when all const arguments were anon consts.
+                    //
+                    // Changing this to normalized obligations is a breaking change:
+                    // `type Bar = [(); panic!()];` would become an error
+                    if let Some(unnormalized_obligations) = wfcx.unnormalized_obligations(span, ty)
+                    {
+                        let filtered_obligations =
+                            unnormalized_obligations.into_iter().filter(|o| {
+                                matches!(o.predicate.kind().skip_binder(),
+                                    ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _))
+                                    if matches!(ct.kind(), ty::ConstKind::Param(..)))
+                            });
+                        wfcx.ocx.register_obligations(filtered_obligations)
+                    }
+                    Ok(())
+                }));
             }
 
             // Only `Node::Item` and `Node::ForeignItem` still have HIR based
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 5656c45..96d0a56 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -15,6 +15,7 @@
 use rustc_hir::{AmbigArg, ItemKind, find_attr};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{self, InferCtxt, SubregionOrigin, TyCtxtInferExt};
+use rustc_infer::traits::PredicateObligations;
 use rustc_lint_defs::builtin::SHADOWING_SUPERTRAIT_ITEMS;
 use rustc_macros::Diagnostic;
 use rustc_middle::mir::interpret::ErrorHandled;
@@ -124,6 +125,20 @@ pub(super) fn register_wf_obligation(
             ty::ClauseKind::WellFormed(term),
         ));
     }
+
+    pub(super) fn unnormalized_obligations(
+        &self,
+        span: Span,
+        ty: Ty<'tcx>,
+    ) -> Option<PredicateObligations<'tcx>> {
+        traits::wf::unnormalized_obligations(
+            self.ocx.infcx,
+            self.param_env,
+            ty.into(),
+            span,
+            self.body_def_id,
+        )
+    }
 }
 
 pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
@@ -140,7 +155,12 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
 
     let mut wfcx = WfCheckingCtxt { ocx, body_def_id, param_env };
 
-    if !tcx.features().trivial_bounds() {
+    // As of now, bounds are only checked on lazy type aliases, they're ignored for most type
+    // aliases. So, only check for false global bounds if we're not ignoring bounds altogether.
+    let ignore_bounds =
+        tcx.def_kind(body_def_id) == DefKind::TyAlias && !tcx.type_alias_is_lazy(body_def_id);
+
+    if !ignore_bounds && !tcx.features().trivial_bounds() {
         wfcx.check_false_global_bounds()
     }
     f(&mut wfcx)?;
@@ -998,7 +1018,7 @@ fn check_type_defn<'tcx>(
     item: &hir::Item<'tcx>,
     all_sized: bool,
 ) -> Result<(), ErrorGuaranteed> {
-    let _ = tcx.check_representability(item.owner_id.def_id);
+    tcx.ensure_ok().check_representability(item.owner_id.def_id);
     let adt_def = tcx.adt_def(item.owner_id);
 
     enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| {
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 18244d6..5bb4166 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -925,7 +925,7 @@ fn visit_fn(
             hir::FnRetTy::Return(ty) => Some(ty),
         };
         if let Some(ty) = output
-            && let hir::TyKind::InferDelegation(sig_id, _) = ty.kind
+            && let hir::TyKind::InferDelegation(hir::InferDelegation::Sig(sig_id, _)) = ty.kind
         {
             let bound_vars: Vec<_> =
                 self.tcx.fn_sig(sig_id).skip_binder().bound_vars().iter().collect();
diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs
index 0b142c0..7302885 100644
--- a/compiler/rustc_hir_analysis/src/delegation.rs
+++ b/compiler/rustc_hir_analysis/src/delegation.rs
@@ -138,7 +138,6 @@ fn create_mapping<'tcx>(
     tcx: TyCtxt<'tcx>,
     sig_id: DefId,
     def_id: LocalDefId,
-    args: &[ty::GenericArg<'tcx>],
 ) -> FxHashMap<u32, u32> {
     let mut mapping: FxHashMap<u32, u32> = Default::default();
 
@@ -176,13 +175,6 @@ fn create_mapping<'tcx>(
         }
     }
 
-    // If there are still unmapped lifetimes left and we are to map types and maybe self
-    // then skip them, now it is the case when we generated more lifetimes then needed.
-    // FIXME(fn_delegation): proper support for late bound lifetimes.
-    while args_index < args.len() && args[args_index].as_region().is_some() {
-        args_index += 1;
-    }
-
     // If self after lifetimes insert mapping, relying that self is at 0 in sig parent.
     if matches!(self_pos_kind, SelfPositionKind::AfterLifetimes) {
         mapping.insert(0, args_index as u32);
@@ -511,7 +503,7 @@ fn create_folder_and_args<'tcx>(
     child_args: &'tcx [ty::GenericArg<'tcx>],
 ) -> (ParamIndexRemapper<'tcx>, Vec<ty::GenericArg<'tcx>>) {
     let args = create_generic_args(tcx, sig_id, def_id, parent_args, child_args);
-    let remap_table = create_mapping(tcx, sig_id, def_id, &args);
+    let remap_table = create_mapping(tcx, sig_id, def_id);
 
     (ParamIndexRemapper { tcx, remap_table }, args)
 }
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 1c999f1..fcd4cb9 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1807,6 +1807,13 @@ pub(crate) struct CmseImplTrait {
 pub(crate) struct BadReturnTypeNotation {
     #[primary_span]
     pub span: Span,
+    #[suggestion(
+        "furthermore, argument types not allowed with return type notation",
+        applicability = "maybe-incorrect",
+        code = "(..)",
+        style = "verbose"
+    )]
+    pub suggestion: Option<Span>,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 9396bf6..91660fc 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -26,7 +26,7 @@
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_errors::codes::*;
 use rustc_errors::{
-    Applicability, Diag, DiagCtxtHandle, Diagnostic, ErrorGuaranteed, FatalError, Level,
+    Applicability, Diag, DiagCtxtHandle, Diagnostic, ErrorGuaranteed, FatalError, Level, StashKey,
     struct_span_code_err,
 };
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
@@ -2830,6 +2830,7 @@ fn lower_resolved_const_path(
             | Res::SelfCtor(_)
             | Res::Local(_)
             | Res::ToolMod
+            | Res::OpenMod(..)
             | Res::NonMacroAttr(_)
             | Res::Err) => Const::new_error_with_message(
                 tcx,
@@ -2946,7 +2947,7 @@ fn require_type_const_attribute(
             );
             if def_id.is_local() {
                 let name = tcx.def_path_str(def_id);
-                err.span_suggestion(
+                err.span_suggestion_verbose(
                     tcx.def_span(def_id).shrink_to_lo(),
                     format!("add `type` before `const` for `{name}`"),
                     format!("type "),
@@ -2959,12 +2960,19 @@ fn require_type_const_attribute(
         }
     }
 
-    fn lower_delegation_ty(&self, idx: hir::InferDelegationKind<'tcx>) -> Ty<'tcx> {
-        let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id());
+    fn lower_delegation_ty(&self, infer: hir::InferDelegation<'tcx>) -> Ty<'tcx> {
+        match infer {
+            hir::InferDelegation::DefId(def_id) => {
+                self.tcx().type_of(def_id).instantiate_identity()
+            }
+            rustc_hir::InferDelegation::Sig(_, idx) => {
+                let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id());
 
-        match idx {
-            hir::InferDelegationKind::Input(idx) => delegation_sig[idx],
-            hir::InferDelegationKind::Output { .. } => *delegation_sig.last().unwrap(),
+                match idx {
+                    hir::InferDelegationSig::Input(idx) => delegation_sig[idx],
+                    hir::InferDelegationSig::Output { .. } => *delegation_sig.last().unwrap(),
+                }
+            }
         }
     }
 
@@ -2974,7 +2982,7 @@ pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
         let tcx = self.tcx();
 
         let result_ty = match &hir_ty.kind {
-            hir::TyKind::InferDelegation(_, idx) => self.lower_delegation_ty(*idx),
+            hir::TyKind::InferDelegation(infer) => self.lower_delegation_ty(*infer),
             hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.lower_ty(ty)),
             hir::TyKind::Ptr(mt) => Ty::new_ptr(tcx, self.lower_ty(mt.ty), mt.mutbl),
             hir::TyKind::Ref(region, mt) => {
@@ -3015,7 +3023,9 @@ pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
                     matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
                 }) =>
             {
-                let guar = self.dcx().emit_err(BadReturnTypeNotation { span: hir_ty.span });
+                let guar = self
+                    .dcx()
+                    .emit_err(BadReturnTypeNotation { span: hir_ty.span, suggestion: None });
                 Ty::new_error(tcx, guar)
             }
             hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
@@ -3077,12 +3087,95 @@ pub fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
             // If we encounter a type relative path with RTN generics, then it must have
             // *not* gone through `lower_ty_maybe_return_type_notation`, and therefore
             // it's certainly in an illegal position.
-            hir::TyKind::Path(hir::QPath::TypeRelative(_, segment))
+            hir::TyKind::Path(hir::QPath::TypeRelative(hir_self_ty, segment))
                 if segment.args.is_some_and(|args| {
                     matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
                 }) =>
             {
-                let guar = self.dcx().emit_err(BadReturnTypeNotation { span: hir_ty.span });
+                let guar = if let hir::Node::LetStmt(stmt) = tcx.parent_hir_node(hir_ty.hir_id)
+                    && let None = stmt.init
+                    && let hir::TyKind::Path(hir::QPath::Resolved(_, self_ty_path)) =
+                        hir_self_ty.kind
+                    && let Res::Def(DefKind::Enum | DefKind::Struct | DefKind::Union, def_id) =
+                        self_ty_path.res
+                    && let Some(_) = tcx
+                        .inherent_impls(def_id)
+                        .iter()
+                        .flat_map(|imp| {
+                            tcx.associated_items(*imp).filter_by_name_unhygienic(segment.ident.name)
+                        })
+                        .filter(|assoc| {
+                            matches!(assoc.kind, ty::AssocKind::Fn { has_self: false, .. })
+                        })
+                        .next()
+                {
+                    // `let x: S::new(valid_in_ty_ctxt);` -> `let x = S::new(valid_in_ty_ctxt);`
+                    let err = tcx
+                        .dcx()
+                        .struct_span_err(
+                            hir_ty.span,
+                            "expected type, found associated function call",
+                        )
+                        .with_span_suggestion_verbose(
+                            stmt.pat.span.between(hir_ty.span),
+                            "use `=` if you meant to assign",
+                            " = ".to_string(),
+                            Applicability::MaybeIncorrect,
+                        );
+                    self.dcx().try_steal_replace_and_emit_err(
+                        hir_ty.span,
+                        StashKey::ReturnTypeNotation,
+                        err,
+                    )
+                } else if let hir::Node::LetStmt(stmt) = tcx.parent_hir_node(hir_ty.hir_id)
+                    && let None = stmt.init
+                    && let hir::TyKind::Path(hir::QPath::Resolved(_, self_ty_path)) =
+                        hir_self_ty.kind
+                    && let Res::PrimTy(_) = self_ty_path.res
+                    && self.dcx().has_stashed_diagnostic(hir_ty.span, StashKey::ReturnTypeNotation)
+                {
+                    // `let x: i32::something(valid_in_ty_ctxt);` -> `let x = i32::something(valid_in_ty_ctxt);`
+                    // FIXME: Check that `something` is a valid function in `i32`.
+                    let err = tcx
+                        .dcx()
+                        .struct_span_err(
+                            hir_ty.span,
+                            "expected type, found associated function call",
+                        )
+                        .with_span_suggestion_verbose(
+                            stmt.pat.span.between(hir_ty.span),
+                            "use `=` if you meant to assign",
+                            " = ".to_string(),
+                            Applicability::MaybeIncorrect,
+                        );
+                    self.dcx().try_steal_replace_and_emit_err(
+                        hir_ty.span,
+                        StashKey::ReturnTypeNotation,
+                        err,
+                    )
+                } else {
+                    let suggestion = if self
+                        .dcx()
+                        .has_stashed_diagnostic(hir_ty.span, StashKey::ReturnTypeNotation)
+                    {
+                        // We already created a diagnostic complaining that `foo(bar)` is wrong and
+                        // should have been `foo(..)`. Instead, emit only the current error and
+                        // include that prior suggestion. Changes are that the problems go further,
+                        // but keep the suggestion just in case. Either way, we want a single error
+                        // instead of two.
+                        Some(segment.ident.span.shrink_to_hi().with_hi(hir_ty.span.hi()))
+                    } else {
+                        None
+                    };
+                    let err = self
+                        .dcx()
+                        .create_err(BadReturnTypeNotation { span: hir_ty.span, suggestion });
+                    self.dcx().try_steal_replace_and_emit_err(
+                        hir_ty.span,
+                        StashKey::ReturnTypeNotation,
+                        err,
+                    )
+                };
                 Ty::new_error(tcx, guar)
             }
             hir::TyKind::Path(hir::QPath::TypeRelative(hir_self_ty, segment)) => {
diff --git a/compiler/rustc_hir_typeck/src/loops.rs b/compiler/rustc_hir_typeck/src/loops.rs
index e77c936..21b40806 100644
--- a/compiler/rustc_hir_typeck/src/loops.rs
+++ b/compiler/rustc_hir_typeck/src/loops.rs
@@ -207,7 +207,7 @@ fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
                 };
 
                 // A `#[const_continue]` must break to a block in a `#[loop_match]`.
-                if find_attr!(self.tcx.hir_attrs(e.hir_id), ConstContinue(_)) {
+                if find_attr!(self.tcx, e.hir_id, ConstContinue(_)) {
                     let Some(label) = break_destination.label else {
                         let span = e.span;
                         self.tcx.dcx().emit_fatal(ConstContinueBadLabel { span });
@@ -420,7 +420,7 @@ fn is_loop_match(
         e: &'hir hir::Expr<'hir>,
         body: &'hir hir::Block<'hir>,
     ) -> Option<Destination> {
-        if !find_attr!(self.tcx.hir_attrs(e.hir_id), LoopMatch(_)) {
+        if !find_attr!(self.tcx, e.hir_id, LoopMatch(_)) {
             return None;
         }
 
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 9d496c6..3198bbe 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -2291,8 +2291,11 @@ pub(crate) fn confusable_method_name(
                             fn_sig,
                         );
                         let name = inherent_method.name();
+                        let inputs = fn_sig.inputs();
+                        let expected_inputs =
+                            if inherent_method.is_method() { &inputs[1..] } else { inputs };
                         if let Some(ref args) = call_args
-                            && fn_sig.inputs()[1..]
+                            && expected_inputs
                                 .iter()
                                 .eq_by(args, |expected, found| self.may_coerce(*expected, *found))
                         {
@@ -3460,13 +3463,13 @@ fn consider_suggesting_derives_for_ty(
         let diagnostic_name = self.tcx.get_diagnostic_name(trait_pred.def_id())?;
 
         let can_derive = match diagnostic_name {
+            sym::Copy | sym::Clone => true,
+            _ if adt.is_union() => false,
             sym::Default
             | sym::Eq
             | sym::PartialEq
             | sym::Ord
             | sym::PartialOrd
-            | sym::Clone
-            | sym::Copy
             | sym::Hash
             | sym::Debug => true,
             _ => false,
diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs
index 1de64bb..dc14a8c 100644
--- a/compiler/rustc_incremental/src/persist/save.rs
+++ b/compiler/rustc_incremental/src/persist/save.rs
@@ -6,6 +6,7 @@
 use rustc_middle::dep_graph::{
     DepGraph, SerializedDepGraph, WorkProduct, WorkProductId, WorkProductMap,
 };
+use rustc_middle::query::on_disk_cache;
 use rustc_middle::ty::TyCtxt;
 use rustc_serialize::Encodable as RustcEncodable;
 use rustc_serialize::opaque::FileEncoder;
@@ -82,7 +83,7 @@ pub(crate) fn save_dep_graph(tcx: TyCtxt<'_>) {
 
                     file_format::save_in(sess, query_cache_path, "query cache", |encoder| {
                         tcx.sess.time("incr_comp_serialize_result_cache", || {
-                            on_disk_cache.serialize(tcx, encoder)
+                            on_disk_cache::OnDiskCache::serialize(tcx, encoder)
                         })
                     });
                 });
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index f833acf..a2ab99f 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -1323,6 +1323,12 @@ pub fn insert(&mut self, elem: T) -> bool {
         self.bit_set.insert(elem)
     }
 
+    #[inline]
+    pub fn insert_range(&mut self, elems: Range<T>) {
+        self.ensure(elems.end.index());
+        self.bit_set.insert_range(elems);
+    }
+
     /// Returns `true` if the set has changed.
     #[inline]
     pub fn remove(&mut self, elem: T) -> bool {
@@ -1331,6 +1337,16 @@ pub fn remove(&mut self, elem: T) -> bool {
     }
 
     #[inline]
+    pub fn clear(&mut self) {
+        self.bit_set.clear();
+    }
+
+    #[inline]
+    pub fn count(&self) -> usize {
+        self.bit_set.count()
+    }
+
+    #[inline]
     pub fn is_empty(&self) -> bool {
         self.bit_set.is_empty()
     }
@@ -1342,6 +1358,14 @@ pub fn contains(&self, elem: T) -> bool {
     }
 
     #[inline]
+    pub fn contains_any(&self, elems: Range<T>) -> bool {
+        elems.start.index() < self.bit_set.domain_size
+            && self
+                .bit_set
+                .contains_any(elems.start..T::new(elems.end.index().min(self.bit_set.domain_size)))
+    }
+
+    #[inline]
     pub fn iter(&self) -> BitIter<'_, T> {
         self.bit_set.iter()
     }
diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs
index 63fed51..eb60c61 100644
--- a/compiler/rustc_interface/src/proc_macro_decls.rs
+++ b/compiler/rustc_interface/src/proc_macro_decls.rs
@@ -7,7 +7,7 @@ fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> {
     let mut decls = None;
 
     for id in tcx.hir_free_items() {
-        if find_attr!(tcx.hir_attrs(id.hir_id()), RustcProcMacroDecls) {
+        if find_attr!(tcx, id.hir_id(), RustcProcMacroDecls) {
             decls = Some(id.owner_id.def_id);
         }
     }
diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs
index c282eb3..1cb0f90 100644
--- a/compiler/rustc_lint/src/early/diagnostics.rs
+++ b/compiler/rustc_lint/src/early/diagnostics.rs
@@ -1,16 +1,13 @@
 use std::borrow::Cow;
 
-use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
 use rustc_errors::{
     Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, Level,
     elided_lifetime_in_path_suggestion,
 };
 use rustc_hir::lints::{AttributeLintKind, FormatWarning};
-use rustc_middle::middle::stability;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
 use rustc_session::lint::BuiltinLintDiag;
-use rustc_span::BytePos;
 use tracing::debug;
 
 use crate::lints;
@@ -28,32 +25,6 @@ pub struct DecorateBuiltinLint<'sess, 'tcx> {
 impl<'a> Diagnostic<'a, ()> for DecorateBuiltinLint<'_, '_> {
     fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
         match self.diagnostic {
-            BuiltinLintDiag::UnicodeTextFlow(comment_span, content) => {
-                let spans: Vec<_> = content
-                    .char_indices()
-                    .filter_map(|(i, c)| {
-                        TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| {
-                            let lo = comment_span.lo() + BytePos(2 + i as u32);
-                            (c, comment_span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32)))
-                        })
-                    })
-                    .collect();
-                let characters = spans
-                    .iter()
-                    .map(|&(c, span)| lints::UnicodeCharNoteSub { span, c_debug: format!("{c:?}") })
-                    .collect();
-                let suggestions = (!spans.is_empty()).then_some(lints::UnicodeTextFlowSuggestion {
-                    spans: spans.iter().map(|(_c, span)| *span).collect(),
-                });
-
-                lints::UnicodeTextFlow {
-                    comment_span,
-                    characters,
-                    suggestions,
-                    num_codepoints: spans.len(),
-                }
-                .into_diag(dcx, level)
-            }
             BuiltinLintDiag::AbsPathWithModule(mod_span) => {
                 let (replacement, applicability) =
                     match self.sess.source_map().span_to_snippet(mod_span) {
@@ -116,87 +87,16 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
                 }
                 .into_diag(dcx, level)
             }
-            BuiltinLintDiag::RedundantImport(spans, ident) => {
-                let subs = spans
-                    .into_iter()
-                    .map(|(span, is_imported)| match (span.is_dummy(), is_imported) {
-                        (false, true) => lints::RedundantImportSub::ImportedHere { span, ident },
-                        (false, false) => lints::RedundantImportSub::DefinedHere { span, ident },
-                        (true, true) => lints::RedundantImportSub::ImportedPrelude { span, ident },
-                        (true, false) => lints::RedundantImportSub::DefinedPrelude { span, ident },
-                    })
-                    .collect();
-                lints::RedundantImport { subs, ident }.into_diag(dcx, level)
-            }
-            BuiltinLintDiag::DeprecatedMacro {
-                suggestion,
-                suggestion_span,
-                note,
-                path,
-                since_kind,
-            } => {
-                let sub = suggestion.map(|suggestion| stability::DeprecationSuggestion {
-                    span: suggestion_span,
-                    kind: "macro".to_owned(),
-                    suggestion,
-                });
-
-                stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind }
-                    .into_diag(dcx, level)
-            }
-            BuiltinLintDiag::PatternsInFnsWithoutBody { span: remove_span, ident, is_foreign } => {
-                let sub = lints::PatternsInFnsWithoutBodySub { ident, span: remove_span };
-                if is_foreign {
-                    lints::PatternsInFnsWithoutBody::Foreign { sub }
-                } else {
-                    lints::PatternsInFnsWithoutBody::Bodiless { sub }
-                }
-                .into_diag(dcx, level)
-            }
-            BuiltinLintDiag::ReservedPrefix(label_span, prefix) => lints::ReservedPrefix {
-                label: label_span,
-                suggestion: label_span.shrink_to_hi(),
-                prefix,
-            }
-            .into_diag(dcx, level),
-            BuiltinLintDiag::RawPrefix(label_span) => {
-                lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() }
-                    .into_diag(dcx, level)
-            }
-            BuiltinLintDiag::ReservedString { is_string, suggestion } => {
-                if is_string {
-                    lints::ReservedString { suggestion }.into_diag(dcx, level)
-                } else {
-                    lints::ReservedMultihash { suggestion }.into_diag(dcx, level)
-                }
-            }
-            BuiltinLintDiag::BreakWithLabelAndLoop(sugg_span) => lints::BreakWithLabelAndLoop {
-                sub: lints::BreakWithLabelAndLoopSub {
-                    left: sugg_span.shrink_to_lo(),
-                    right: sugg_span.shrink_to_hi(),
-                },
-            }
-            .into_diag(dcx, level),
-            BuiltinLintDiag::DeprecatedWhereclauseLocation(left_sp, sugg) => {
-                let suggestion = match sugg {
-                    Some((right_sp, sugg)) => lints::DeprecatedWhereClauseLocationSugg::MoveToEnd {
-                        left: left_sp,
-                        right: right_sp,
-                        sugg,
-                    },
-                    None => lints::DeprecatedWhereClauseLocationSugg::RemoveWhere { span: left_sp },
-                };
-                lints::DeprecatedWhereClauseLocation { suggestion }.into_diag(dcx, level)
-            }
             BuiltinLintDiag::SingleUseLifetime {
                 param_span,
-                use_span: Some((use_span, elide)),
+                use_span,
+                elidable,
                 deletion_span,
                 ident,
             } => {
                 debug!(?param_span, ?use_span, ?deletion_span);
                 let suggestion = if let Some(deletion_span) = deletion_span {
-                    let (use_span, replace_lt) = if elide {
+                    let (use_span, replace_lt) = if elidable {
                         let use_span =
                             self.sess.source_map().span_extend_while_whitespace(use_span);
                         (use_span, String::new())
@@ -217,9 +117,6 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
                 lints::SingleUseLifetime { suggestion, param_span, use_span, ident }
                     .into_diag(dcx, level)
             }
-            BuiltinLintDiag::SingleUseLifetime { use_span: None, deletion_span, ident, .. } => {
-                lints::UnusedLifetime { deletion_span, ident }.into_diag(dcx, level)
-            }
             BuiltinLintDiag::NamedArgumentUsedPositionally {
                 position_sp_to_replace,
                 position_sp_for_msg,
@@ -255,63 +152,7 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
                 }
                 .into_diag(dcx, level)
             }
-            BuiltinLintDiag::AmbiguousGlobReexports {
-                name,
-                namespace,
-                first_reexport_span,
-                duplicate_reexport_span,
-            } => lints::AmbiguousGlobReexports {
-                first_reexport: first_reexport_span,
-                duplicate_reexport: duplicate_reexport_span,
-                name,
-                namespace,
-            }
-            .into_diag(dcx, level),
-            BuiltinLintDiag::HiddenGlobReexports {
-                name,
-                namespace,
-                glob_reexport_span,
-                private_item_span,
-            } => lints::HiddenGlobReexports {
-                glob_reexport: glob_reexport_span,
-                private_item: private_item_span,
 
-                name,
-                namespace,
-            }
-            .into_diag(dcx, level),
-            BuiltinLintDiag::UnusedQualifications { removal_span } => {
-                lints::UnusedQualifications { removal_span }.into_diag(dcx, level)
-            }
-            BuiltinLintDiag::AssociatedConstElidedLifetime {
-                elided,
-                span: lt_span,
-                lifetimes_in_scope,
-            } => {
-                let lt_span = if elided { lt_span.shrink_to_hi() } else { lt_span };
-                let code = if elided { "'static " } else { "'static" };
-                lints::AssociatedConstElidedLifetime {
-                    span: lt_span,
-                    code,
-                    elided,
-                    lifetimes_in_scope,
-                }
-                .into_diag(dcx, level)
-            }
-            BuiltinLintDiag::UnreachableCfg { span, wildcard_span } => match wildcard_span {
-                Some(wildcard_span) => {
-                    lints::UnreachableCfgSelectPredicateWildcard { span, wildcard_span }
-                        .into_diag(dcx, level)
-                }
-                None => lints::UnreachableCfgSelectPredicate { span }.into_diag(dcx, level),
-            },
-
-            BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => {
-                lints::UnusedCrateDependency { extern_crate, local_crate }.into_diag(dcx, level)
-            }
-            BuiltinLintDiag::UnusedVisibility(span) => {
-                lints::UnusedVisibility { span }.into_diag(dcx, level)
-            }
             BuiltinLintDiag::AttributeLint(kind) => {
                 DecorateAttrLint { sess: self.sess, tcx: self.tcx, diagnostic: &kind }
                     .into_diag(dcx, level)
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 0244803..f111f81 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -6,8 +6,7 @@
 use rustc_errors::formatting::DiagMessageAddArg;
 use rustc_errors::{
     Applicability, Diag, DiagArgValue, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic,
-    ElidedLifetimeInPathSubdiag, EmissionGuarantee, Level, MultiSpan, Subdiagnostic,
-    SuggestionStyle, msg,
+    ElidedLifetimeInPathSubdiag, EmissionGuarantee, Level, Subdiagnostic, SuggestionStyle, msg,
 };
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -2995,14 +2994,6 @@ pub(crate) enum CargoHelp {
     }
 }
 
-#[derive(Diagnostic)]
-#[diag("extern crate `{$extern_crate}` is unused in crate `{$local_crate}`")]
-#[help("remove the dependency or add `use {$extern_crate} as _;` to the crate root")]
-pub(crate) struct UnusedCrateDependency {
-    pub extern_crate: Symbol,
-    pub local_crate: Symbol,
-}
-
 // FIXME(jdonszelmann): duplicated in rustc_attr_parsing, should be moved there completely.
 #[derive(Diagnostic)]
 #[diag(
@@ -3020,46 +3011,6 @@ pub(crate) struct IllFormedAttributeInput {
 }
 
 #[derive(Diagnostic)]
-#[diag("unicode codepoint changing visible direction of text present in comment")]
-#[note(
-    "these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen"
-)]
-pub(crate) struct UnicodeTextFlow {
-    #[label(
-        "{$num_codepoints ->
-            [1] this comment contains an invisible unicode text flow control codepoint
-            *[other] this comment contains invisible unicode text flow control codepoints
-        }"
-    )]
-    pub comment_span: Span,
-    #[subdiagnostic]
-    pub characters: Vec<UnicodeCharNoteSub>,
-    #[subdiagnostic]
-    pub suggestions: Option<UnicodeTextFlowSuggestion>,
-
-    pub num_codepoints: usize,
-}
-
-#[derive(Subdiagnostic)]
-#[label("{$c_debug}")]
-pub(crate) struct UnicodeCharNoteSub {
-    #[primary_span]
-    pub span: Span,
-    pub c_debug: String,
-}
-
-#[derive(Subdiagnostic)]
-#[multipart_suggestion(
-    "if their presence wasn't intentional, you can remove them",
-    applicability = "machine-applicable",
-    style = "hidden"
-)]
-pub(crate) struct UnicodeTextFlowSuggestion {
-    #[suggestion_part(code = "")]
-    pub spans: Vec<Span>,
-}
-
-#[derive(Diagnostic)]
 #[diag(
     "absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition"
 )]
@@ -3130,144 +3081,6 @@ pub(crate) enum UnusedImportsSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag("the item `{$ident}` is imported redundantly")]
-pub(crate) struct RedundantImport {
-    #[subdiagnostic]
-    pub subs: Vec<RedundantImportSub>,
-    pub ident: Ident,
-}
-
-#[derive(Subdiagnostic)]
-pub(crate) enum RedundantImportSub {
-    #[label("the item `{$ident}` is already imported here")]
-    ImportedHere {
-        #[primary_span]
-        span: Span,
-        ident: Ident,
-    },
-    #[label("the item `{$ident}` is already defined here")]
-    DefinedHere {
-        #[primary_span]
-        span: Span,
-        ident: Ident,
-    },
-    #[label("the item `{$ident}` is already imported by the extern prelude")]
-    ImportedPrelude {
-        #[primary_span]
-        span: Span,
-        ident: Ident,
-    },
-    #[label("the item `{$ident}` is already defined by the extern prelude")]
-    DefinedPrelude {
-        #[primary_span]
-        span: Span,
-        ident: Ident,
-    },
-}
-
-#[derive(Diagnostic)]
-pub(crate) enum PatternsInFnsWithoutBody {
-    #[diag("patterns aren't allowed in foreign function declarations")]
-    Foreign {
-        #[subdiagnostic]
-        sub: PatternsInFnsWithoutBodySub,
-    },
-    #[diag("patterns aren't allowed in functions without bodies")]
-    Bodiless {
-        #[subdiagnostic]
-        sub: PatternsInFnsWithoutBodySub,
-    },
-}
-
-#[derive(Subdiagnostic)]
-#[suggestion(
-    "remove `mut` from the parameter",
-    code = "{ident}",
-    applicability = "machine-applicable"
-)]
-pub(crate) struct PatternsInFnsWithoutBodySub {
-    #[primary_span]
-    pub span: Span,
-
-    pub ident: Ident,
-}
-
-#[derive(Diagnostic)]
-#[diag("prefix `{$prefix}` is unknown")]
-pub(crate) struct ReservedPrefix {
-    #[label("unknown prefix")]
-    pub label: Span,
-    #[suggestion(
-        "insert whitespace here to avoid this being parsed as a prefix in Rust 2021",
-        code = " ",
-        applicability = "machine-applicable"
-    )]
-    pub suggestion: Span,
-
-    pub prefix: String,
-}
-
-#[derive(Diagnostic)]
-#[diag("prefix `'r` is reserved")]
-pub(crate) struct RawPrefix {
-    #[label("reserved prefix")]
-    pub label: Span,
-    #[suggestion(
-        "insert whitespace here to avoid this being parsed as a prefix in Rust 2021",
-        code = " ",
-        applicability = "machine-applicable"
-    )]
-    pub suggestion: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(
-    "this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression"
-)]
-pub(crate) struct BreakWithLabelAndLoop {
-    #[subdiagnostic]
-    pub sub: BreakWithLabelAndLoopSub,
-}
-
-#[derive(Subdiagnostic)]
-#[multipart_suggestion("wrap this expression in parentheses", applicability = "machine-applicable")]
-pub(crate) struct BreakWithLabelAndLoopSub {
-    #[suggestion_part(code = "(")]
-    pub left: Span,
-    #[suggestion_part(code = ")")]
-    pub right: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag("where clause not allowed here")]
-#[note("see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information")]
-pub(crate) struct DeprecatedWhereClauseLocation {
-    #[subdiagnostic]
-    pub suggestion: DeprecatedWhereClauseLocationSugg,
-}
-
-#[derive(Subdiagnostic)]
-pub(crate) enum DeprecatedWhereClauseLocationSugg {
-    #[multipart_suggestion(
-        "move it to the end of the type declaration",
-        applicability = "machine-applicable"
-    )]
-    MoveToEnd {
-        #[suggestion_part(code = "")]
-        left: Span,
-        #[suggestion_part(code = "{sugg}")]
-        right: Span,
-
-        sugg: String,
-    },
-    #[suggestion("remove this `where`", code = "", applicability = "machine-applicable")]
-    RemoveWhere {
-        #[primary_span]
-        span: Span,
-    },
-}
-
-#[derive(Diagnostic)]
 #[diag("lifetime parameter `{$ident}` only used once")]
 pub(crate) struct SingleUseLifetime {
     #[label("this lifetime...")]
@@ -3292,15 +3105,6 @@ pub(crate) struct SingleUseLifetimeSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag("lifetime parameter `{$ident}` never used")]
-pub(crate) struct UnusedLifetime {
-    #[suggestion("elide the unused lifetime", code = "", applicability = "machine-applicable")]
-    pub deletion_span: Option<Span>,
-
-    pub ident: Ident,
-}
-
-#[derive(Diagnostic)]
 #[diag("named argument `{$named_arg_name}` is not used by name")]
 pub(crate) struct NamedArgumentUsedPositionally {
     #[label("this named argument is referred to by position in formatting string")]
@@ -3320,66 +3124,6 @@ pub(crate) struct NamedArgumentUsedPositionally {
 }
 
 #[derive(Diagnostic)]
-#[diag("ambiguous glob re-exports")]
-pub(crate) struct AmbiguousGlobReexports {
-    #[label("the name `{$name}` in the {$namespace} namespace is first re-exported here")]
-    pub first_reexport: Span,
-    #[label("but the name `{$name}` in the {$namespace} namespace is also re-exported here")]
-    pub duplicate_reexport: Span,
-
-    pub name: String,
-    pub namespace: String,
-}
-
-#[derive(Diagnostic)]
-#[diag("private item shadows public glob re-export")]
-pub(crate) struct HiddenGlobReexports {
-    #[note(
-        "the name `{$name}` in the {$namespace} namespace is supposed to be publicly re-exported here"
-    )]
-    pub glob_reexport: Span,
-    #[note("but the private item here shadows it")]
-    pub private_item: Span,
-
-    pub name: String,
-    pub namespace: String,
-}
-
-#[derive(Diagnostic)]
-#[diag("unnecessary qualification")]
-pub(crate) struct UnusedQualifications {
-    #[suggestion(
-        "remove the unnecessary path segments",
-        style = "verbose",
-        code = "",
-        applicability = "machine-applicable"
-    )]
-    pub removal_span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(
-    "{$elided ->
-        [true] `&` without an explicit lifetime name cannot be used here
-        *[false] `'_` cannot be used here
-    }"
-)]
-pub(crate) struct AssociatedConstElidedLifetime {
-    #[suggestion(
-        "use the `'static` lifetime",
-        style = "verbose",
-        code = "{code}",
-        applicability = "machine-applicable"
-    )]
-    pub span: Span,
-
-    pub code: &'static str,
-    pub elided: bool,
-    #[note("cannot automatically infer `'static` because of other lifetimes in scope")]
-    pub lifetimes_in_scope: MultiSpan,
-}
-
-#[derive(Diagnostic)]
 #[diag("creating a {$shared_label}reference to mutable static")]
 pub(crate) struct RefOfMutStatic<'a> {
     #[label("{$shared_label}reference to mutable static")]
@@ -3424,28 +3168,6 @@ pub(crate) enum MutRefSugg {
 pub(crate) struct UnqualifiedLocalImportsDiag;
 
 #[derive(Diagnostic)]
-#[diag("will be parsed as a guarded string in Rust 2024")]
-pub(crate) struct ReservedString {
-    #[suggestion(
-        "insert whitespace here to avoid this being parsed as a guarded string in Rust 2024",
-        code = " ",
-        applicability = "machine-applicable"
-    )]
-    pub suggestion: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag("reserved token in Rust 2024")]
-pub(crate) struct ReservedMultihash {
-    #[suggestion(
-        "insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024",
-        code = " ",
-        applicability = "machine-applicable"
-    )]
-    pub suggestion: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag("direct cast of function item into an integer")]
 pub(crate) struct FunctionCastsAsIntegerDiag<'tcx> {
     #[subdiagnostic]
@@ -3753,19 +3475,6 @@ pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion {
 }
 
 #[derive(Diagnostic)]
-#[diag("visibility qualifiers have no effect on `const _` declarations")]
-#[note("`const _` does not declare a name, so there is nothing for the qualifier to apply to")]
-pub(crate) struct UnusedVisibility {
-    #[suggestion(
-        "remove the qualifier",
-        style = "short",
-        code = "",
-        applicability = "machine-applicable"
-    )]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag("doc alias is duplicated")]
 pub(crate) struct DocAliasDuplicated {
     #[label("first defined here")]
@@ -3896,23 +3605,6 @@ pub(crate) struct UnknownCrateTypesSuggestion {
 }
 
 #[derive(Diagnostic)]
-#[diag("unreachable configuration predicate")]
-pub(crate) struct UnreachableCfgSelectPredicate {
-    #[label("this configuration predicate is never reached")]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag("unreachable configuration predicate")]
-pub(crate) struct UnreachableCfgSelectPredicateWildcard {
-    #[label("this configuration predicate is never reached")]
-    pub span: Span,
-
-    #[label("always matches")]
-    pub wildcard_span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag("positional format arguments are not allowed here")]
 #[help(
     "only named format arguments with the name of one of the generic types are allowed in this context"
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index ef7067b..0528a0d 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -7,7 +7,7 @@
 use rustc_data_structures::stable_hasher::{
     HashStable, StableCompare, StableHasher, ToStableHashKey,
 };
-use rustc_error_messages::{DiagArgValue, IntoDiagArg, MultiSpan};
+use rustc_error_messages::{DiagArgValue, IntoDiagArg};
 use rustc_hir_id::{HashStableContext, HirId, ItemLocalId};
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_span::def_id::DefPathHash;
@@ -665,30 +665,6 @@ pub enum BuiltinLintDiag {
         test_module_span: Option<Span>,
         span_snippets: Vec<String>,
     },
-    RedundantImport(Vec<(Span, bool)>, Ident),
-    DeprecatedMacro {
-        suggestion: Option<Symbol>,
-        suggestion_span: Span,
-        note: Option<Symbol>,
-        path: String,
-        since_kind: DeprecatedSinceKind,
-    },
-    PatternsInFnsWithoutBody {
-        span: Span,
-        ident: Ident,
-        is_foreign: bool,
-    },
-    ReservedPrefix(Span, String),
-    /// `'r#` in edition < 2021.
-    RawPrefix(Span),
-    /// `##` or `#"` in edition < 2024.
-    ReservedString {
-        is_string: bool,
-        suggestion: Span,
-    },
-    BreakWithLabelAndLoop(Span),
-    UnicodeTextFlow(Span, String),
-    DeprecatedWhereclauseLocation(Span, Option<(Span, String)>),
     SingleUseLifetime {
         /// Span of the parameter which declares this lifetime.
         param_span: Span,
@@ -697,7 +673,8 @@ pub enum BuiltinLintDiag {
         deletion_span: Option<Span>,
         /// Span of the single use, or None if the lifetime is never used.
         /// If true, the lifetime will be fully elided.
-        use_span: Option<(Span, bool)>,
+        use_span: Span,
+        elidable: bool,
         ident: Ident,
     },
     NamedArgumentUsedPositionally {
@@ -713,45 +690,7 @@ pub enum BuiltinLintDiag {
         /// Indicates if the named argument is used as a width/precision for formatting
         is_formatting_arg: bool,
     },
-    AmbiguousGlobReexports {
-        /// The name for which collision(s) have occurred.
-        name: String,
-        /// The name space for which the collision(s) occurred in.
-        namespace: String,
-        /// Span where the name is first re-exported.
-        first_reexport_span: Span,
-        /// Span where the same name is also re-exported.
-        duplicate_reexport_span: Span,
-    },
-    HiddenGlobReexports {
-        /// The name of the local binding which shadows the glob re-export.
-        name: String,
-        /// The namespace for which the shadowing occurred in.
-        namespace: String,
-        /// The glob reexport that is shadowed by the local binding.
-        glob_reexport_span: Span,
-        /// The local binding that shadows the glob reexport.
-        private_item_span: Span,
-    },
-    UnusedQualifications {
-        /// The span of the unnecessarily-qualified path to remove.
-        removal_span: Span,
-    },
-    AssociatedConstElidedLifetime {
-        elided: bool,
-        span: Span,
-        lifetimes_in_scope: MultiSpan,
-    },
-    UnusedCrateDependency {
-        extern_crate: Symbol,
-        local_crate: Symbol,
-    },
-    UnusedVisibility(Span),
     AttributeLint(AttributeLintKind),
-    UnreachableCfg {
-        span: Span,
-        wildcard_span: Option<Span>,
-    },
 }
 
 #[derive(Debug, HashStable_Generic)]
diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
index 38c16fb..66b3e26 100644
--- a/compiler/rustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -402,6 +402,16 @@ fn main() {
             continue;
         }
 
+        // On apple-darwin, llvm-config reports the versioned shared library name such as LLVM-22-..., but
+        // the distributed toolchain ships libLLVM.dylib. Normalize the link name here.
+        let name =
+            if target.contains("apple-darwin") && llvm_kind == "dylib" && name.starts_with("LLVM-")
+            {
+                "LLVM"
+            } else {
+                name
+            };
+
         let kind = if name.starts_with("LLVM") {
             llvm_kind
         } else if is_static {
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 00d03f0..b4f6bb4 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -540,6 +540,8 @@
   bool SanitizeHWAddressRecover;
   bool SanitizeKernelAddress;
   bool SanitizeKernelAddressRecover;
+  bool SanitizeKernelHWAddress;
+  bool SanitizeKernelHWAddressRecover;
 };
 
 extern "C" typedef void (*registerEnzymeAndPassPipelineFn)(
@@ -767,13 +769,15 @@
                                  !TM->getTargetTriple().isOSWindows()));
       });
     }
-    if (SanitizerOptions->SanitizeHWAddress) {
+    if (SanitizerOptions->SanitizeHWAddress ||
+        SanitizerOptions->SanitizeKernelHWAddress) {
       OptimizerLastEPCallbacks.push_back(
           [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level,
                              ThinOrFullLTOPhase phase) {
             HWAddressSanitizerOptions opts(
-                /*CompileKernel=*/false,
-                SanitizerOptions->SanitizeHWAddressRecover,
+                SanitizerOptions->SanitizeKernelHWAddress,
+                SanitizerOptions->SanitizeHWAddressRecover ||
+                    SanitizerOptions->SanitizeKernelHWAddressRecover,
                 /*DisableOptimization=*/false);
             MPM.addPass(HWAddressSanitizerPass(opts));
           });
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 63ff0b2..392cd06 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -779,6 +779,7 @@
 ASSERT_DIFLAG_VALUE(FlagNonTrivial, 1 << 26);
 ASSERT_DIFLAG_VALUE(FlagBigEndian, 1 << 27);
 ASSERT_DIFLAG_VALUE(FlagLittleEndian, 1 << 28);
+static_assert(DINode::DIFlags::FlagAllCallsDescribed == (1 << 29));
 ASSERT_DIFLAG_VALUE(FlagIndirectVirtualBase, (1 << 2) | (1 << 5));
 #undef ASSERT_DIFLAG_VALUE
 
@@ -791,7 +792,7 @@
 // to copying each bit/subvalue.
 static DINode::DIFlags fromRust(LLVMDIFlags Flags) {
   // Check that all set bits are covered by the static assertions above.
-  const unsigned UNKNOWN_BITS = (1 << 31) | (1 << 30) | (1 << 29) | (1 << 21);
+  const unsigned UNKNOWN_BITS = (1 << 31) | (1 << 30) | (1 << 21);
   if (Flags & UNKNOWN_BITS) {
     report_fatal_error("bad LLVMDIFlags");
   }
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index a803d86..b75236b 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -140,13 +140,13 @@ struct CacheOnDiskIf {
 /// See `rustc_middle::query::modifiers` for documentation of each query modifier.
 struct QueryModifiers {
     // tidy-alphabetical-start
-    anon: Option<Ident>,
     arena_cache: Option<Ident>,
     cache_on_disk_if: Option<CacheOnDiskIf>,
     depth_limit: Option<Ident>,
     desc: Desc,
     eval_always: Option<Ident>,
     feedable: Option<Ident>,
+    no_force: Option<Ident>,
     no_hash: Option<Ident>,
     separate_provide_extern: Option<Ident>,
     // tidy-alphabetical-end
@@ -156,8 +156,8 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
     let mut arena_cache = None;
     let mut cache_on_disk_if = None;
     let mut desc = None;
+    let mut no_force = None;
     let mut no_hash = None;
-    let mut anon = None;
     let mut eval_always = None;
     let mut depth_limit = None;
     let mut separate_provide_extern = None;
@@ -189,10 +189,10 @@ macro_rules! try_insert {
             try_insert!(cache_on_disk_if = CacheOnDiskIf { modifier, block });
         } else if modifier == "arena_cache" {
             try_insert!(arena_cache = modifier);
+        } else if modifier == "no_force" {
+            try_insert!(no_force = modifier);
         } else if modifier == "no_hash" {
             try_insert!(no_hash = modifier);
-        } else if modifier == "anon" {
-            try_insert!(anon = modifier);
         } else if modifier == "eval_always" {
             try_insert!(eval_always = modifier);
         } else if modifier == "depth_limit" {
@@ -212,8 +212,8 @@ macro_rules! try_insert {
         arena_cache,
         cache_on_disk_if,
         desc,
+        no_force,
         no_hash,
-        anon,
         eval_always,
         depth_limit,
         separate_provide_extern,
@@ -243,24 +243,24 @@ fn returns_error_guaranteed(ret_ty: &ReturnType) -> bool {
 fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream {
     let QueryModifiers {
         // tidy-alphabetical-start
-        anon,
         arena_cache,
         cache_on_disk_if,
         depth_limit,
         desc: _,
         eval_always,
         feedable,
+        no_force,
         no_hash,
         separate_provide_extern,
         // tidy-alphabetical-end
     } = &query.modifiers;
 
-    let anon = anon.is_some();
     let arena_cache = arena_cache.is_some();
     let cache_on_disk = cache_on_disk_if.is_some();
     let depth_limit = depth_limit.is_some();
     let eval_always = eval_always.is_some();
     let feedable = feedable.is_some();
+    let no_force = no_force.is_some();
     let no_hash = no_hash.is_some();
     let returns_error_guaranteed = returns_error_guaranteed(&query.return_ty);
     let separate_provide_extern = separate_provide_extern.is_some();
@@ -273,12 +273,12 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream {
         query_name_span =>
         // Search for (QMODLIST) to find all occurrences of this query modifier list.
         // tidy-alphabetical-start
-        anon: #anon,
         arena_cache: #arena_cache,
         cache_on_disk: #cache_on_disk,
         depth_limit: #depth_limit,
         eval_always: #eval_always,
         feedable: #feedable,
+        no_force: #no_force,
         no_hash: #no_hash,
         returns_error_guaranteed: #returns_error_guaranteed,
         separate_provide_extern: #separate_provide_extern,
@@ -387,13 +387,15 @@ macro_rules! doc_link {
     }
 
     doc_link!(
+        // tidy-alphabetical-start
         arena_cache,
-        no_hash,
-        anon,
-        eval_always,
         depth_limit,
-        separate_provide_extern,
+        eval_always,
         feedable,
+        no_force,
+        no_hash,
+        separate_provide_extern,
+        // tidy-alphabetical-end
     );
 
     let name = &query.name;
@@ -477,11 +479,6 @@ fn #name(#key_ty) #return_ty
 
         if let Some(feedable) = &modifiers.feedable {
             assert!(
-                modifiers.anon.is_none(),
-                feedable.span(),
-                "Query {name} cannot be both `feedable` and `anon`."
-            );
-            assert!(
                 modifiers.eval_always.is_none(),
                 feedable.span(),
                 "Query {name} cannot be both `feedable` and `eval_always`."
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 4000f12..345ee18 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -23,15 +23,14 @@
 use rustc_middle::ty::data_structures::IndexSet;
 use rustc_middle::ty::{TyCtxt, TyCtxtFeed};
 use rustc_proc_macro::bridge::client::ProcMacro;
-use rustc_session::Session;
 use rustc_session::config::{
     CrateType, ExtendedTargetModifierInfo, ExternLocation, Externs, OptionsTargetModifiers,
     TargetModifier,
 };
 use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate, ExternCrateSource};
-use rustc_session::lint::{self, BuiltinLintDiag};
 use rustc_session::output::validate_crate_name;
 use rustc_session::search_paths::PathKind;
+use rustc_session::{Session, lint};
 use rustc_span::def_id::DefId;
 use rustc_span::edition::Edition;
 use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym};
@@ -1211,7 +1210,7 @@ fn report_unused_deps_in_crate(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) {
                 lint::builtin::UNUSED_CRATE_DEPENDENCIES,
                 span,
                 ast::CRATE_NODE_ID,
-                BuiltinLintDiag::UnusedCrateDependency {
+                errors::UnusedCrateDependency {
                     extern_crate: name_interned,
                     local_crate: tcx.crate_name(LOCAL_CRATE),
                 },
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index d4c6144..8b2895d 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -688,3 +688,11 @@ pub struct RawDylibMalformed {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag("extern crate `{$extern_crate}` is unused in crate `{$local_crate}`")]
+#[help("remove the dependency or add `use {$extern_crate} as _;` to the crate root")]
+pub(crate) struct UnusedCrateDependency {
+    pub extern_crate: Symbol,
+    pub local_crate: Symbol,
+}
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 17b16b3..06755a0c 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -19,7 +19,7 @@
 use rustc_session::search_paths::PathKind;
 use rustc_span::Symbol;
 use rustc_span::def_id::{DefId, LOCAL_CRATE};
-use rustc_target::spec::{Abi, Arch, BinaryFormat, Env, LinkSelfContainedComponents, Os};
+use rustc_target::spec::{Arch, BinaryFormat, CfgAbi, Env, LinkSelfContainedComponents, Os};
 
 use crate::errors;
 
@@ -62,25 +62,29 @@ pub fn walk_native_lib_search_dirs<R>(
         f(&sess.target_tlib_path.dir.join("self-contained"), false)?;
     }
 
+    let has_shared_llvm_apple_darwin =
+        sess.target.is_like_darwin && sess.target_tlib_path.dir.join("libLLVM.dylib").exists();
+
     // Toolchains for some targets may ship `libunwind.a`, but place it into the main sysroot
     // library directory instead of the self-contained directories.
     // Sanitizer libraries have the same issue and are also linked by name on Apple targets.
     // The targets here should be in sync with `copy_third_party_objects` in bootstrap.
-    // Finally there is shared LLVM library, which unlike compiler libraries, is linked by the name,
-    // therefore requiring the search path for the linker.
+    // On Apple targets, shared LLVM is linked by name, so when `libLLVM.dylib` is
+    // present in the target libdir, add that directory to the linker search path.
     // FIXME: implement `-Clink-self-contained=+/-unwind,+/-sanitizers`, move the shipped libunwind
     // and sanitizers to self-contained directory, and stop adding this search path.
     // FIXME: On AIX this also has the side-effect of making the list of library search paths
     // non-empty, which is needed or the linker may decide to record the LIBPATH env, if
     // defined, as the search path instead of appending the default search paths.
-    if sess.target.abi == Abi::Fortanix
+    if sess.target.cfg_abi == CfgAbi::Fortanix
         || sess.target.os == Os::Linux
         || sess.target.os == Os::Fuchsia
         || sess.target.is_like_aix
-        || sess.target.is_like_darwin && !sess.sanitizers().is_empty()
+        || sess.target.is_like_darwin
+            && (!sess.sanitizers().is_empty() || has_shared_llvm_apple_darwin)
         || sess.target.os == Os::Windows
             && sess.target.env == Env::Gnu
-            && sess.target.abi == Abi::Llvm
+            && sess.target.cfg_abi == CfgAbi::Llvm
     {
         f(&sess.target_tlib_path.dir, false)?;
     }
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index 49ad6bb..b5f0692 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -94,10 +94,14 @@ pub const fn as_usize(&self) -> usize {
 pub struct DepNode {
     pub kind: DepKind,
 
-    /// This is _typically_ a hash of the query key, but sometimes not.
+    /// If `kind` is a query method, then its "key fingerprint" is always a
+    /// stable hash of the query key.
     ///
-    /// For example, `anon` nodes have a fingerprint that is derived from their
-    /// dependencies instead of a key.
+    /// For non-query nodes, the content of this field varies:
+    /// - Some dep kinds always use a dummy `ZERO` fingerprint.
+    /// - Some dep kinds use the stable hash of some relevant key-like value.
+    /// - Some dep kinds use the `with_anon_task` mechanism, and set their key
+    ///   fingerprint to a hash derived from the task's dependencies.
     ///
     /// In some cases the key value can be reconstructed from this fingerprint;
     /// see [`KeyFingerprintStyle`].
@@ -408,9 +412,6 @@ mod size_asserts {
     use super::*;
     // tidy-alphabetical-start
     static_assert_size!(DepKind, 2);
-    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
     static_assert_size!(DepNode, 18);
-    #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
-    static_assert_size!(DepNode, 24);
     // tidy-alphabetical-end
 }
diff --git a/compiler/rustc_middle/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs
index d410d9a..444d025 100644
--- a/compiler/rustc_middle/src/dep_graph/graph.rs
+++ b/compiler/rustc_middle/src/dep_graph/graph.rs
@@ -164,9 +164,10 @@ pub fn new(
         );
         assert_eq!(red_node_index, DepNodeIndex::FOREVER_RED_NODE);
         if prev_graph_node_count > 0 {
-            colors.insert_red(SerializedDepNodeIndex::from_u32(
-                DepNodeIndex::FOREVER_RED_NODE.as_u32(),
-            ));
+            let prev_index =
+                const { SerializedDepNodeIndex::from_u32(DepNodeIndex::FOREVER_RED_NODE.as_u32()) };
+            let result = colors.try_set_color(prev_index, DesiredColor::Red);
+            assert_matches!(result, TrySetColorResult::Success);
         }
 
         DepGraph {
@@ -375,9 +376,8 @@ pub fn with_task<'tcx, A: Debug, R>(
     /// incorrectly marked green.
     ///
     /// FIXME: This could perhaps return a `WithDepNode` to ensure that the
-    /// user of this function actually performs the read; we'll have to see
-    /// how to make that work with `anon` in `execute_job_incr`, though.
-    pub fn with_anon_task_inner<'tcx, OP, R>(
+    /// user of this function actually performs the read.
+    fn with_anon_task_inner<'tcx, OP, R>(
         &self,
         tcx: TyCtxt<'tcx>,
         dep_kind: DepKind,
@@ -709,7 +709,7 @@ fn encode_side_effect<'tcx>(
             // side effect.
             std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(),
         );
-        tcx.store_side_effect(dep_node_index, side_effect);
+        tcx.query_system.side_effects.borrow_mut().insert(dep_node_index, side_effect);
         dep_node_index
     }
 
@@ -718,7 +718,13 @@ fn encode_side_effect<'tcx>(
     #[inline]
     fn force_side_effect<'tcx>(&self, tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) {
         with_deps(TaskDepsRef::Ignore, || {
-            let side_effect = tcx.load_side_effect(prev_index).unwrap();
+            let side_effect = tcx
+                .query_system
+                .on_disk_cache
+                .as_ref()
+                .unwrap()
+                .load_side_effect(tcx, prev_index)
+                .unwrap();
 
             // Use `send_and_color` as `promote_node_and_deps_to_current` expects all
             // green dependencies. `send_and_color` will also prevent multiple nodes
@@ -745,7 +751,7 @@ fn force_side_effect<'tcx>(&self, tcx: TyCtxt<'tcx>, prev_index: SerializedDepNo
             }
 
             // This will just overwrite the same value for concurrent calls.
-            tcx.store_side_effect(dep_node_index, side_effect);
+            tcx.query_system.side_effects.borrow_mut().insert(dep_node_index, side_effect);
         })
     }
 
@@ -1416,28 +1422,29 @@ pub(super) fn current(&self, index: SerializedDepNodeIndex) -> Option<DepNodeInd
         if value <= DepNodeIndex::MAX_AS_U32 { Some(DepNodeIndex::from_u32(value)) } else { None }
     }
 
-    /// This tries to atomically mark a node green and assign `index` as the new
-    /// index if `green` is true, otherwise it will try to atomicaly mark it red.
+    /// Atomically sets the color of a previous-session dep node to either green
+    /// or red, if it has not already been colored.
     ///
-    /// This returns `Ok` if `index` gets assigned or the node is marked red, otherwise it returns
-    /// the already allocated index in `Err` if it is green already. If it was already
-    /// red, `Err(None)` is returned.
+    /// If the node already has a color, the new color is ignored, and the
+    /// return value indicates the existing color.
     #[inline(always)]
-    pub(super) fn try_mark(
+    pub(super) fn try_set_color(
         &self,
         prev_index: SerializedDepNodeIndex,
-        index: DepNodeIndex,
-        green: bool,
-    ) -> Result<(), Option<DepNodeIndex>> {
-        let value = &self.values[prev_index];
-        match value.compare_exchange(
+        color: DesiredColor,
+    ) -> TrySetColorResult {
+        match self.values[prev_index].compare_exchange(
             COMPRESSED_UNKNOWN,
-            if green { index.as_u32() } else { COMPRESSED_RED },
+            match color {
+                DesiredColor::Red => COMPRESSED_RED,
+                DesiredColor::Green { index } => index.as_u32(),
+            },
             Ordering::Relaxed,
             Ordering::Relaxed,
         ) {
-            Ok(_) => Ok(()),
-            Err(v) => Err(if v == COMPRESSED_RED { None } else { Some(DepNodeIndex::from_u32(v)) }),
+            Ok(_) => TrySetColorResult::Success,
+            Err(COMPRESSED_RED) => TrySetColorResult::AlreadyRed,
+            Err(index) => TrySetColorResult::AlreadyGreen { index: DepNodeIndex::from_u32(index) },
         }
     }
 
@@ -1455,13 +1462,28 @@ pub(super) fn get(&self, index: SerializedDepNodeIndex) -> DepNodeColor {
             DepNodeColor::Unknown
         }
     }
+}
 
-    #[inline]
-    pub(super) fn insert_red(&self, index: SerializedDepNodeIndex) {
-        let value = self.values[index].swap(COMPRESSED_RED, Ordering::Release);
-        // Sanity check for duplicate nodes
-        assert_eq!(value, COMPRESSED_UNKNOWN, "tried to color an already colored node as red");
-    }
+/// The color that [`DepNodeColorMap::try_set_color`] should try to apply to a node.
+#[derive(Clone, Copy, Debug)]
+pub(super) enum DesiredColor {
+    /// Try to mark the node red.
+    Red,
+    /// Try to mark the node green, associating it with a current-session node index.
+    Green { index: DepNodeIndex },
+}
+
+/// Return value of [`DepNodeColorMap::try_set_color`], indicating success or failure,
+/// and (on failure) what the existing color is.
+#[derive(Clone, Copy, Debug)]
+pub(super) enum TrySetColorResult {
+    /// The [`DesiredColor`] was freshly applied to the node.
+    Success,
+    /// Coloring failed because the node was already marked red.
+    AlreadyRed,
+    /// Coloring failed because the node was already marked green,
+    /// and corresponds to node `index` in the current-session dep graph.
+    AlreadyGreen { index: DepNodeIndex },
 }
 
 #[inline(never)]
@@ -1533,23 +1555,4 @@ impl<'tcx> TyCtxt<'tcx> {
     fn is_eval_always(self, kind: DepKind) -> bool {
         self.dep_kind_vtable(kind).is_eval_always
     }
-
-    // Interactions with on_disk_cache
-    fn load_side_effect(
-        self,
-        prev_dep_node_index: SerializedDepNodeIndex,
-    ) -> Option<QuerySideEffect> {
-        self.query_system
-            .on_disk_cache
-            .as_ref()
-            .and_then(|c| c.load_side_effect(self, prev_dep_node_index))
-    }
-
-    #[inline(never)]
-    #[cold]
-    fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) {
-        if let Some(c) = self.query_system.on_disk_cache.as_ref() {
-            c.store_side_effect(dep_node_index, side_effect)
-        }
-    }
 }
diff --git a/compiler/rustc_middle/src/dep_graph/serialized.rs b/compiler/rustc_middle/src/dep_graph/serialized.rs
index 8a4ac4b..ef5e3d9 100644
--- a/compiler/rustc_middle/src/dep_graph/serialized.rs
+++ b/compiler/rustc_middle/src/dep_graph/serialized.rs
@@ -43,7 +43,7 @@
 use std::cmp::max;
 use std::sync::Arc;
 use std::sync::atomic::Ordering;
-use std::{iter, mem, u64};
+use std::{iter, mem};
 
 use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint};
 use rustc_data_structures::fx::FxHashMap;
@@ -58,7 +58,7 @@
 use rustc_session::Session;
 use tracing::{debug, instrument};
 
-use super::graph::{CurrentDepGraph, DepNodeColorMap};
+use super::graph::{CurrentDepGraph, DepNodeColorMap, DesiredColor, TrySetColorResult};
 use super::retained::RetainedDepGraph;
 use super::{DepKind, DepNode, DepNodeIndex};
 use crate::dep_graph::edges::EdgesVec;
@@ -72,6 +72,15 @@
     pub struct SerializedDepNodeIndex {}
 }
 
+impl SerializedDepNodeIndex {
+    /// Converts a current-session dep node index to a "serialized" index,
+    /// for the purpose of serializing data to be loaded by future sessions.
+    #[inline(always)]
+    pub fn from_curr_for_serialization(index: DepNodeIndex) -> Self {
+        SerializedDepNodeIndex::from_u32(index.as_u32())
+    }
+}
+
 const DEP_NODE_SIZE: usize = size_of::<SerializedDepNodeIndex>();
 /// Amount of padding we need to add to the edge list data so that we can retrieve every
 /// SerializedDepNodeIndex with a fixed-size read then mask.
@@ -905,13 +914,14 @@ pub(crate) fn send_and_color(
         let mut local = self.status.local.borrow_mut();
 
         let index = self.status.next_index(&mut *local);
+        let color = if is_green { DesiredColor::Green { index } } else { DesiredColor::Red };
 
-        // Use `try_mark` to avoid racing when `send_promoted` is called concurrently
+        // Use `try_set_color` to avoid racing when `send_promoted` is called concurrently
         // on the same index.
-        match colors.try_mark(prev_index, index, is_green) {
-            Ok(()) => (),
-            Err(None) => panic!("dep node {:?} is unexpectedly red", prev_index),
-            Err(Some(dep_node_index)) => return dep_node_index,
+        match colors.try_set_color(prev_index, color) {
+            TrySetColorResult::Success => {}
+            TrySetColorResult::AlreadyRed => panic!("dep node {prev_index:?} is unexpectedly red"),
+            TrySetColorResult::AlreadyGreen { index } => return index,
         }
 
         self.status.bump_index(&mut *local);
@@ -923,7 +933,8 @@ pub(crate) fn send_and_color(
     /// from the previous dep graph and expects all edges to already have a new dep node index
     /// assigned.
     ///
-    /// This will also ensure the dep node is marked green if `Some` is returned.
+    /// Tries to mark the dep node green, and returns Some if it is now green,
+    /// or None if had already been concurrently marked red.
     #[inline]
     pub(crate) fn send_promoted(
         &self,
@@ -935,10 +946,10 @@ pub(crate) fn send_promoted(
         let mut local = self.status.local.borrow_mut();
         let index = self.status.next_index(&mut *local);
 
-        // Use `try_mark_green` to avoid racing when `send_promoted` or `send_and_color`
+        // Use `try_set_color` to avoid racing when `send_promoted` or `send_and_color`
         // is called concurrently on the same index.
-        match colors.try_mark(prev_index, index, true) {
-            Ok(()) => {
+        match colors.try_set_color(prev_index, DesiredColor::Green { index }) {
+            TrySetColorResult::Success => {
                 self.status.bump_index(&mut *local);
                 self.status.encode_promoted_node(
                     index,
@@ -949,7 +960,8 @@ pub(crate) fn send_promoted(
                 );
                 Some(index)
             }
-            Err(dep_node_index) => dep_node_index,
+            TrySetColorResult::AlreadyRed => None,
+            TrySetColorResult::AlreadyGreen { index } => Some(index),
         }
     }
 
diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs
index 60327be..c70ceef 100644
--- a/compiler/rustc_middle/src/hooks/mod.rs
+++ b/compiler/rustc_middle/src/hooks/mod.rs
@@ -9,7 +9,7 @@
 use rustc_span::{ExpnHash, ExpnId};
 
 use crate::mir;
-use crate::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex};
+use crate::query::on_disk_cache::CacheEncoder;
 use crate::ty::{Ty, TyCtxt};
 
 macro_rules! declare_hooks {
@@ -35,8 +35,10 @@ pub struct Providers {
 
         impl Default for Providers {
             fn default() -> Self {
+                #[allow(unused)]
                 Providers {
-                    $($name: |_, $($arg,)*| default_hook(stringify!($name), &($($arg,)*))),*
+                    $($name:
+                        |_, $($arg,)*| default_hook(stringify!($name))),*
                 }
             }
         }
@@ -109,15 +111,11 @@ fn clone(&self) -> Self { *self }
     /// Creates the MIR for a given `DefId`, including unreachable code.
     hook build_mir_inner_impl(def: LocalDefId) -> mir::Body<'tcx>;
 
-    hook encode_query_values(
-        encoder: &mut CacheEncoder<'_, 'tcx>,
-        query_result_index: &mut EncodedDepNodeIndex
-    ) -> ();
+    /// Serializes all eligible query return values into the on-disk cache.
+    hook encode_query_values(encoder: &mut CacheEncoder<'_, 'tcx>) -> ();
 }
 
 #[cold]
-fn default_hook(name: &str, args: &dyn std::fmt::Debug) -> ! {
-    bug!(
-        "`tcx.{name}{args:?}` cannot be called as `{name}` was never assigned to a provider function"
-    )
+fn default_hook(name: &str) -> ! {
+    bug!("`tcx.{name}` cannot be called as `{name}` was never assigned to a provider function")
 }
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index e76c9a8..f9821c9 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -4,7 +4,7 @@
 use std::num::NonZero;
 
 use rustc_ast::NodeId;
-use rustc_errors::{Applicability, Diag, EmissionGuarantee, LintBuffer, msg};
+use rustc_errors::{Applicability, Diag, Diagnostic, EmissionGuarantee, LintBuffer, msg};
 use rustc_feature::GateIssue;
 use rustc_hir::attrs::{DeprecatedSince, Deprecation};
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -12,7 +12,7 @@
 use rustc_macros::{Decodable, Encodable, HashStable, Subdiagnostic};
 use rustc_session::Session;
 use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE};
-use rustc_session::lint::{BuiltinLintDiag, DeprecatedSinceKind, Level, Lint};
+use rustc_session::lint::{DeprecatedSinceKind, Level, Lint};
 use rustc_session::parse::feature_err_issue;
 use rustc_span::{Span, Symbol, sym};
 use tracing::debug;
@@ -187,23 +187,33 @@ fn deprecated_since_kind(is_in_effect: bool, since: DeprecatedSince) -> Deprecat
 pub fn early_report_macro_deprecation(
     lint_buffer: &mut LintBuffer,
     depr: &Deprecation,
-    span: Span,
+    suggestion_span: Span,
     node_id: NodeId,
     path: String,
 ) {
-    if span.in_derive_expansion() {
+    if suggestion_span.in_derive_expansion() {
         return;
     }
 
     let is_in_effect = depr.is_in_effect();
-    let diag = BuiltinLintDiag::DeprecatedMacro {
-        suggestion: depr.suggestion,
-        suggestion_span: span,
-        note: depr.note.map(|ident| ident.name),
-        path,
-        since_kind: deprecated_since_kind(is_in_effect, depr.since),
-    };
-    lint_buffer.buffer_lint(deprecation_lint(is_in_effect), node_id, span, diag);
+    let suggestion = depr.suggestion;
+    let note = depr.note.map(|ident| ident.name);
+    let since_kind = deprecated_since_kind(is_in_effect, depr.since);
+    lint_buffer.dyn_buffer_lint(
+        deprecation_lint(is_in_effect),
+        node_id,
+        suggestion_span,
+        move |dcx, level| {
+            let sub = suggestion.map(|suggestion| DeprecationSuggestion {
+                span: suggestion_span,
+                kind: "macro".to_owned(),
+                suggestion,
+            });
+
+            Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind }
+                .into_diag(dcx, level)
+        },
+    );
 }
 
 fn late_report_deprecation(
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 2c3d114..6c7505a 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -318,7 +318,12 @@ pub enum UndefinedBehaviorInfo<'tcx> {
     /// Free-form case. Only for errors that are never caught! Used by miri
     Ub(String),
     /// Validation error.
-    ValidationError { path: Option<String>, msg: String, ptr_bytes_warning: bool },
+    ValidationError {
+        orig_ty: Ty<'tcx>,
+        path: Option<String>,
+        msg: String,
+        ptr_bytes_warning: bool,
+    },
 
     /// Unreachable code was executed.
     Unreachable,
@@ -457,11 +462,11 @@ fn fmt_in_alloc_attempt(
         match self {
             Ub(msg) => write!(f, "{msg}"),
 
-            ValidationError { path: None, msg, .. } => {
-                write!(f, "constructing invalid value: {msg}")
+            ValidationError { orig_ty, path: None, msg, .. } => {
+                write!(f, "constructing invalid value of type {orig_ty}: {msg}")
             }
-            ValidationError { path: Some(path), msg, .. } => {
-                write!(f, "constructing invalid value at {path}: {msg}")
+            ValidationError { orig_ty, path: Some(path), msg, .. } => {
+                write!(f, "constructing invalid value of type {orig_ty}: at {path}, {msg}")
             }
 
             Unreachable => write!(f, "entering unreachable code"),
diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs
index d5185a0..ff96f50 100644
--- a/compiler/rustc_middle/src/queries.rs
+++ b/compiler/rustc_middle/src/queries.rs
@@ -131,10 +131,10 @@
 // `Providers` that the driver creates (using several `rustc_*` crates).
 //
 // The result type of each query must implement `Clone`. Additionally
-// `ty::query::from_cycle_error::FromCycleError` can be implemented which produces an appropriate
+// `QueryVTable::handle_cycle_error_fn` can be used to produce an appropriate
 // placeholder (error) value if the query resulted in a query cycle.
-// Queries without a `FromCycleError` implementation will raise a fatal error on query
-// cycles instead.
+// Queries without a custom `handle_cycle_error_fn` implementation will raise a
+// fatal error on query cycles instead.
 rustc_queries! {
     /// Caches the expansion of a derive proc macro, e.g. `#[derive(Serialize)]`.
     /// The key is:
@@ -577,7 +577,7 @@
 
     /// Checks whether a type is representable or infinitely sized
     //
-    // Infinitely sized types will cause a cycle. The `value_from_cycle_error` impl will print
+    // Infinitely sized types will cause a cycle. The query's `handle_cycle_error_fn` will print
     // a custom error about the infinite size and then abort compilation. (In the past we
     // recovered and continued, but in practice that leads to confusing subsequent error
     // messages about cycles that then abort.)
@@ -585,16 +585,15 @@
         desc { "checking if `{}` is representable", tcx.def_path_str(key) }
         // We don't want recursive representability calls to be forced with
         // incremental compilation because, if a cycle occurs, we need the
-        // entire cycle to be in memory for diagnostics. This means we can't
-        // use `ensure_ok()` with this query.
-        anon
+        // entire cycle to be in memory for diagnostics.
+        no_force
     }
 
     /// An implementation detail for the `check_representability` query. See that query for more
     /// details, particularly on the modifiers.
     query check_representability_adt_ty(key: Ty<'tcx>) {
         desc { "checking if `{}` is representable", key }
-        anon
+        no_force
     }
 
     /// Set of param indexes for type params that are in the type's representation
@@ -768,14 +767,10 @@
     /// Normally you would just use `tcx.erase_and_anonymize_regions(value)`,
     /// however, which uses this query as a kind of cache.
     query erase_and_anonymize_regions_ty(ty: Ty<'tcx>) -> Ty<'tcx> {
-        // This query is not expected to have input -- as a result, it
-        // is not a good candidates for "replay" because it is essentially a
-        // pure function of its input (and hence the expectation is that
-        // no caller would be green **apart** from just these
-        // queries). Making it anonymous avoids hashing the result, which
-        // may save a bit of time.
-        anon
         desc { "erasing regions from `{}`", ty }
+        // Not hashing the return value appears to give marginally better perf for this query,
+        // which should always be marked green for having no dependencies anyway.
+        no_hash
     }
 
     query wasm_import_module_map(_: CrateNum) -> &'tcx DefIdMap<String> {
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 036aa2e..53ec058 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -10,13 +10,12 @@
 use std::mem::MaybeUninit;
 
 use rustc_ast::tokenstream::TokenStream;
+use rustc_data_structures::steal::Steal;
 use rustc_span::{ErrorGuaranteed, Spanned};
 
-use crate::mir::interpret::EvalToValTreeResult;
 use crate::mir::mono::{MonoItem, NormalizationErrorInMono};
-use crate::traits::solve;
 use crate::ty::{self, Ty, TyCtxt};
-use crate::{mir, traits};
+use crate::{mir, thir, traits};
 
 /// Internal implementation detail of [`Erased`].
 #[derive(Copy, Clone)]
@@ -101,192 +100,42 @@ pub fn restore_val<T: Erasable>(erased_value: Erased<T>) -> T {
 // FIXME(#151565): Using `T: ?Sized` here should let us remove the separate
 // impls for fat reference types.
 impl<T> Erasable for &'_ T {
-    type Storage = [u8; size_of::<&'static ()>()];
+    type Storage = [u8; size_of::<&'_ ()>()];
 }
 
 impl<T> Erasable for &'_ [T] {
-    type Storage = [u8; size_of::<&'static [()]>()];
-}
-
-impl Erasable for &'_ OsStr {
-    type Storage = [u8; size_of::<&'static OsStr>()];
+    type Storage = [u8; size_of::<&'_ [()]>()];
 }
 
 impl<T> Erasable for &'_ ty::List<T> {
-    type Storage = [u8; size_of::<&'static ty::List<()>>()];
+    type Storage = [u8; size_of::<&'_ ty::List<()>>()];
 }
 
 impl<T> Erasable for &'_ ty::ListWithCachedTypeInfo<T> {
-    type Storage = [u8; size_of::<&'static ty::ListWithCachedTypeInfo<()>>()];
-}
-
-impl<I: rustc_index::Idx, T> Erasable for &'_ rustc_index::IndexSlice<I, T> {
-    type Storage = [u8; size_of::<&'static rustc_index::IndexSlice<u32, ()>>()];
+    type Storage = [u8; size_of::<&'_ ty::ListWithCachedTypeInfo<()>>()];
 }
 
 impl<T> Erasable for Result<&'_ T, traits::query::NoSolution> {
-    type Storage = [u8; size_of::<Result<&'static (), traits::query::NoSolution>>()];
+    type Storage = [u8; size_of::<Result<&'_ (), traits::query::NoSolution>>()];
 }
 
-impl<T> Erasable for Result<&'_ [T], traits::query::NoSolution> {
-    type Storage = [u8; size_of::<Result<&'static [()], traits::query::NoSolution>>()];
-}
-
-impl<T> Erasable for Result<&'_ T, rustc_errors::ErrorGuaranteed> {
-    type Storage = [u8; size_of::<Result<&'static (), rustc_errors::ErrorGuaranteed>>()];
-}
-
-impl<T> Erasable for Result<&'_ [T], rustc_errors::ErrorGuaranteed> {
-    type Storage = [u8; size_of::<Result<&'static [()], rustc_errors::ErrorGuaranteed>>()];
-}
-
-impl<T> Erasable for Result<&'_ T, traits::CodegenObligationError> {
-    type Storage = [u8; size_of::<Result<&'static (), traits::CodegenObligationError>>()];
-}
-
-impl<T> Erasable for Result<&'_ T, &'_ ty::layout::FnAbiError<'_>> {
-    type Storage = [u8; size_of::<Result<&'static (), &'static ty::layout::FnAbiError<'static>>>()];
-}
-
-impl<T> Erasable for Result<(&'_ T, crate::thir::ExprId), rustc_errors::ErrorGuaranteed> {
-    type Storage = [u8; size_of::<
-        Result<(&'static (), crate::thir::ExprId), rustc_errors::ErrorGuaranteed>,
-    >()];
-}
-
-impl Erasable for Result<Option<ty::Instance<'_>>, rustc_errors::ErrorGuaranteed> {
-    type Storage =
-        [u8; size_of::<Result<Option<ty::Instance<'static>>, rustc_errors::ErrorGuaranteed>>()];
-}
-
-impl Erasable
-    for Result<Option<ty::EarlyBinder<'_, ty::Const<'_>>>, rustc_errors::ErrorGuaranteed>
-{
-    type Storage = [u8; size_of::<
-        Result<Option<ty::EarlyBinder<'static, ty::Const<'static>>>, rustc_errors::ErrorGuaranteed>,
-    >()];
-}
-
-impl Erasable for Result<ty::GenericArg<'_>, traits::query::NoSolution> {
-    type Storage = [u8; size_of::<Result<ty::GenericArg<'static>, traits::query::NoSolution>>()];
-}
-
-impl Erasable for Result<bool, &ty::layout::LayoutError<'_>> {
-    type Storage = [u8; size_of::<Result<bool, &'static ty::layout::LayoutError<'static>>>()];
-}
-
-impl Erasable for Result<rustc_abi::TyAndLayout<'_, Ty<'_>>, &ty::layout::LayoutError<'_>> {
-    type Storage = [u8; size_of::<
-        Result<
-            rustc_abi::TyAndLayout<'static, Ty<'static>>,
-            &'static ty::layout::LayoutError<'static>,
-        >,
-    >()];
-}
-
-impl Erasable for Result<mir::ConstAlloc<'_>, mir::interpret::ErrorHandled> {
-    type Storage =
-        [u8; size_of::<Result<mir::ConstAlloc<'static>, mir::interpret::ErrorHandled>>()];
-}
-
-impl Erasable for Option<(mir::ConstValue, Ty<'_>)> {
-    type Storage = [u8; size_of::<Option<(mir::ConstValue, Ty<'_>)>>()];
-}
-
-impl Erasable for EvalToValTreeResult<'_> {
-    type Storage = [u8; size_of::<EvalToValTreeResult<'static>>()];
-}
-
-impl Erasable for Result<&'_ ty::List<Ty<'_>>, ty::util::AlwaysRequiresDrop> {
-    type Storage =
-        [u8; size_of::<Result<&'static ty::List<Ty<'static>>, ty::util::AlwaysRequiresDrop>>()];
-}
-
-impl Erasable
-    for Result<(&'_ [Spanned<MonoItem<'_>>], &'_ [Spanned<MonoItem<'_>>]), NormalizationErrorInMono>
-{
-    type Storage = [u8; size_of::<
-        Result<
-            (&'static [Spanned<MonoItem<'static>>], &'static [Spanned<MonoItem<'static>>]),
-            NormalizationErrorInMono,
-        >,
-    >()];
-}
-
-impl Erasable for Result<&'_ TokenStream, ()> {
-    type Storage = [u8; size_of::<Result<&'static TokenStream, ()>>()];
+impl<T> Erasable for Result<&'_ T, ErrorGuaranteed> {
+    type Storage = [u8; size_of::<Result<&'_ (), ErrorGuaranteed>>()];
 }
 
 impl<T> Erasable for Option<&'_ T> {
-    type Storage = [u8; size_of::<Option<&'static ()>>()];
-}
-
-impl<T> Erasable for Option<&'_ [T]> {
-    type Storage = [u8; size_of::<Option<&'static [()]>>()];
-}
-
-impl Erasable for Option<&'_ OsStr> {
-    type Storage = [u8; size_of::<Option<&'static OsStr>>()];
-}
-
-impl Erasable for Option<mir::DestructuredConstant<'_>> {
-    type Storage = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()];
-}
-
-impl Erasable for ty::ImplTraitHeader<'_> {
-    type Storage = [u8; size_of::<ty::ImplTraitHeader<'static>>()];
-}
-
-impl Erasable for Option<ty::EarlyBinder<'_, Ty<'_>>> {
-    type Storage = [u8; size_of::<Option<ty::EarlyBinder<'static, Ty<'static>>>>()];
-}
-
-impl Erasable for Option<ty::Value<'_>> {
-    type Storage = [u8; size_of::<Option<ty::Value<'static>>>()];
-}
-
-impl Erasable for rustc_hir::MaybeOwner<'_> {
-    type Storage = [u8; size_of::<rustc_hir::MaybeOwner<'static>>()];
+    type Storage = [u8; size_of::<Option<&'_ ()>>()];
 }
 
 impl<T: Erasable> Erasable for ty::EarlyBinder<'_, T> {
     type Storage = T::Storage;
 }
 
-impl Erasable for ty::Binder<'_, ty::FnSig<'_>> {
-    type Storage = [u8; size_of::<ty::Binder<'static, ty::FnSig<'static>>>()];
-}
-
-impl Erasable for ty::Binder<'_, ty::CoroutineWitnessTypes<TyCtxt<'_>>> {
-    type Storage =
-        [u8; size_of::<ty::Binder<'static, ty::CoroutineWitnessTypes<TyCtxt<'static>>>>()];
-}
-
-impl Erasable for ty::Binder<'_, &'_ ty::List<Ty<'_>>> {
-    type Storage = [u8; size_of::<ty::Binder<'static, &'static ty::List<Ty<'static>>>>()];
-}
-
 impl<T0, T1> Erasable for (&'_ T0, &'_ T1) {
-    type Storage = [u8; size_of::<(&'static (), &'static ())>()];
+    type Storage = [u8; size_of::<(&'_ (), &'_ ())>()];
 }
 
-impl<T0> Erasable for (solve::QueryResult<'_>, &'_ T0) {
-    type Storage = [u8; size_of::<(solve::QueryResult<'static>, &'static ())>()];
-}
-
-impl<T0, T1> Erasable for (&'_ T0, &'_ [T1]) {
-    type Storage = [u8; size_of::<(&'static (), &'static [()])>()];
-}
-
-impl<T0, T1> Erasable for (&'_ [T0], &'_ [T1]) {
-    type Storage = [u8; size_of::<(&'static [()], &'static [()])>()];
-}
-
-impl<T0> Erasable for (&'_ T0, Result<(), ErrorGuaranteed>) {
-    type Storage = [u8; size_of::<(&'static (), Result<(), ErrorGuaranteed>)>()];
-}
-
-macro_rules! impl_erasable_for_simple_types {
+macro_rules! impl_erasable_for_types_with_no_type_params {
     ($($ty:ty),+ $(,)?) => {
         $(
             impl Erasable for $ty {
@@ -296,171 +145,96 @@ impl Erasable for $ty {
     }
 }
 
-// For concrete types with no lifetimes, the erased storage for `Foo` is
-// `[u8; size_of::<Foo>()]`.
-impl_erasable_for_simple_types! {
-    // FIXME(#151565): Add `tidy-alphabetical-{start,end}` and sort this.
+// For types with no type parameters the erased storage for `Foo` is
+// `[u8; size_of::<Foo>()]`. ('_ lifetimes are allowed.)
+impl_erasable_for_types_with_no_type_params! {
+    // tidy-alphabetical-start
+    (&'_ ty::CrateInherentImpls, Result<(), ErrorGuaranteed>),
     (),
-    bool,
+    (traits::solve::QueryResult<'_>, &'_ traits::solve::inspect::Probe<TyCtxt<'_>>),
+    Option<&'_ OsStr>,
+    Option<&'_ [rustc_hir::PreciseCapturingArgKind<rustc_span::Symbol, rustc_span::Symbol>]>,
+    Option<(mir::ConstValue, Ty<'_>)>,
     Option<(rustc_span::def_id::DefId, rustc_session::config::EntryFnType)>,
+    Option<rustc_abi::Align>,
     Option<rustc_ast::expand::allocator::AllocatorKind>,
+    Option<rustc_data_structures::svh::Svh>,
     Option<rustc_hir::ConstStability>,
+    Option<rustc_hir::CoroutineKind>,
     Option<rustc_hir::DefaultBodyStability>,
     Option<rustc_hir::Stability>,
-    Option<rustc_data_structures::svh::Svh>,
-    Option<rustc_hir::def::DefKind>,
-    Option<rustc_hir::CoroutineKind>,
-    Option<rustc_hir::HirId>,
     Option<rustc_middle::middle::stability::DeprecationEntry>,
     Option<rustc_middle::ty::AsyncDestructor>,
     Option<rustc_middle::ty::Destructor>,
-    Option<rustc_middle::ty::ImplTraitInTraitData>,
+    Option<rustc_middle::ty::IntrinsicDef>,
     Option<rustc_middle::ty::ScalarInt>,
+    Option<rustc_span::Span>,
     Option<rustc_span::def_id::CrateNum>,
     Option<rustc_span::def_id::DefId>,
     Option<rustc_span::def_id::LocalDefId>,
-    Option<rustc_span::Span>,
-    Option<rustc_abi::FieldIdx>,
     Option<rustc_target::spec::PanicStrategy>,
+    Option<ty::EarlyBinder<'_, Ty<'_>>>,
+    Option<ty::Value<'_>>,
     Option<usize>,
-    Option<rustc_middle::ty::IntrinsicDef>,
-    Option<rustc_abi::Align>,
-    Result<(), rustc_errors::ErrorGuaranteed>,
-    Result<(), rustc_middle::traits::query::NoSolution>,
-    Result<rustc_middle::traits::EvaluationResult, rustc_middle::traits::OverflowError>,
-    Result<rustc_middle::ty::adjustment::CoerceUnsizedInfo, rustc_errors::ErrorGuaranteed>,
+    Result<&'_ TokenStream, ()>,
+    Result<&'_ rustc_target::callconv::FnAbi<'_, Ty<'_>>, &'_ ty::layout::FnAbiError<'_>>,
+    Result<&'_ traits::ImplSource<'_, ()>, traits::CodegenObligationError>,
+    Result<&'_ ty::List<Ty<'_>>, ty::util::AlwaysRequiresDrop>,
+    Result<(&'_ Steal<thir::Thir<'_>>, thir::ExprId), ErrorGuaranteed>,
+    Result<(&'_ [Spanned<MonoItem<'_>>], &'_ [Spanned<MonoItem<'_>>]), NormalizationErrorInMono>,
+    Result<(), ErrorGuaranteed>,
+    Result<Option<ty::EarlyBinder<'_, ty::Const<'_>>>, ErrorGuaranteed>,
+    Result<Option<ty::Instance<'_>>, ErrorGuaranteed>,
+    Result<bool, &ty::layout::LayoutError<'_>>,
+    Result<mir::ConstAlloc<'_>, mir::interpret::ErrorHandled>,
     Result<mir::ConstValue, mir::interpret::ErrorHandled>,
-    rustc_abi::ReprOptions,
-    rustc_ast::expand::allocator::AllocatorKind,
-    rustc_hir::DefaultBodyStability,
-    rustc_hir::attrs::Deprecation,
-    rustc_hir::attrs::EiiDecl,
-    rustc_hir::attrs::EiiImpl,
+    Result<rustc_abi::TyAndLayout<'_, Ty<'_>>, &ty::layout::LayoutError<'_>>,
+    Result<rustc_middle::traits::EvaluationResult, rustc_middle::traits::OverflowError>,
+    Result<rustc_middle::ty::adjustment::CoerceUnsizedInfo, ErrorGuaranteed>,
+    Result<ty::GenericArg<'_>, traits::query::NoSolution>,
+    Ty<'_>,
+    bool,
     rustc_data_structures::svh::Svh,
-    rustc_errors::ErrorGuaranteed,
     rustc_hir::Constness,
-    rustc_hir::ConstStability,
-    rustc_hir::def_id::DefId,
-    rustc_hir::def_id::DefIndex,
-    rustc_hir::def_id::LocalDefId,
-    rustc_hir::def_id::LocalModDefId,
-    rustc_hir::def::DefKind,
     rustc_hir::Defaultness,
-    rustc_hir::definitions::DefKey,
-    rustc_hir::CoroutineKind,
     rustc_hir::HirId,
-    rustc_hir::IsAsync,
-    rustc_hir::ItemLocalId,
-    rustc_hir::LangItem,
+    rustc_hir::MaybeOwner<'_>,
     rustc_hir::OpaqueTyOrigin<rustc_hir::def_id::DefId>,
-    rustc_hir::OwnerId,
-    rustc_hir::Stability,
-    rustc_hir::Upvar,
-    rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs,
-    rustc_middle::middle::dependency_format::Linkage,
-    rustc_middle::middle::exported_symbols::SymbolExportInfo,
+    rustc_hir::def::DefKind,
+    rustc_hir::def_id::DefId,
+    rustc_middle::middle::codegen_fn_attrs::SanitizerFnAttrs,
     rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault,
-    rustc_middle::middle::resolve_bound_vars::ResolvedArg,
-    rustc_middle::middle::stability::DeprecationEntry,
     rustc_middle::mir::ConstQualifs,
     rustc_middle::mir::ConstValue,
     rustc_middle::mir::interpret::AllocId,
-    rustc_middle::mir::interpret::CtfeProvenance,
-    rustc_middle::mir::interpret::ErrorHandled,
-    rustc_middle::thir::ExprId,
-    rustc_middle::traits::CodegenObligationError,
-    rustc_middle::traits::EvaluationResult,
-    rustc_middle::traits::OverflowError,
-    rustc_middle::traits::query::NoSolution,
-    rustc_middle::traits::WellFormedLoc,
-    rustc_middle::ty::adjustment::CoerceUnsizedInfo,
-    rustc_middle::ty::AssocItem,
-    rustc_middle::ty::AssocContainer,
-    rustc_middle::ty::Asyncness,
-    rustc_middle::ty::AsyncDestructor,
+    rustc_middle::mir::interpret::EvalStaticInitializerRawResult<'_>,
+    rustc_middle::mir::interpret::EvalToValTreeResult<'_>,
+    rustc_middle::mir::mono::MonoItemPartitions<'_>,
+    rustc_middle::traits::query::MethodAutoderefStepsResult<'_>,
+    rustc_middle::ty::AdtDef<'_>,
     rustc_middle::ty::AnonConstKind,
-    rustc_middle::ty::Destructor,
-    rustc_middle::ty::fast_reject::SimplifiedType,
-    rustc_middle::ty::ImplPolarity,
-    rustc_middle::ty::util::AlwaysRequiresDrop,
+    rustc_middle::ty::AssocItem,
+    rustc_middle::ty::Asyncness,
+    rustc_middle::ty::Binder<'_, ty::CoroutineWitnessTypes<TyCtxt<'_>>>,
+    rustc_middle::ty::Binder<'_, ty::FnSig<'_>>,
+    rustc_middle::ty::ClosureTypeInfo<'_>,
+    rustc_middle::ty::Const<'_>,
+    rustc_middle::ty::ConstConditions<'_>,
+    rustc_middle::ty::GenericPredicates<'_>,
+    rustc_middle::ty::ImplTraitHeader<'_>,
+    rustc_middle::ty::ParamEnv<'_>,
+    rustc_middle::ty::SymbolName<'_>,
+    rustc_middle::ty::TypingEnv<'_>,
     rustc_middle::ty::Visibility<rustc_span::def_id::DefId>,
-    rustc_middle::middle::codegen_fn_attrs::SanitizerFnAttrs,
-    rustc_session::config::CrateType,
-    rustc_session::config::EntryFnType,
+    rustc_middle::ty::inhabitedness::InhabitedPredicate<'_>,
+    rustc_session::Limits,
     rustc_session::config::OptLevel,
     rustc_session::config::SymbolManglingVersion,
     rustc_session::cstore::CrateDepKind,
-    rustc_session::cstore::ExternCrate,
-    rustc_session::cstore::LinkagePreference,
-    rustc_session::Limits,
-    rustc_session::lint::LintExpectationId,
-    rustc_span::def_id::CrateNum,
-    rustc_span::def_id::DefPathHash,
-    rustc_span::ExpnHash,
     rustc_span::ExpnId,
     rustc_span::Span,
     rustc_span::Symbol,
-    rustc_span::Ident,
     rustc_target::spec::PanicStrategy,
-    rustc_type_ir::Variance,
-    u32,
     usize,
-}
-
-macro_rules! impl_erasable_for_single_lifetime_types {
-    ($($($fake_path:ident)::+),+ $(,)?) => {
-        $(
-            impl<'tcx> Erasable for $($fake_path)::+<'tcx> {
-                type Storage = [u8; size_of::<$($fake_path)::+<'static>>()];
-            }
-        )*
-    }
-}
-
-// For types containing a single lifetime and no other generics, e.g.
-// `Foo<'tcx>`, the erased storage is `[u8; size_of::<Foo<'static>>()]`.
-//
-// FIXME(#151565): Some of the hand-written impls above that only use one
-// lifetime can probably be migrated here.
-impl_erasable_for_single_lifetime_types! {
-    // FIXME(#151565): Add `tidy-alphabetical-{start,end}` and sort this.
-    rustc_middle::middle::exported_symbols::ExportedSymbol,
-    rustc_middle::mir::Const,
-    rustc_middle::mir::DestructuredConstant,
-    rustc_middle::mir::ConstAlloc,
-    rustc_middle::mir::interpret::GlobalId,
-    rustc_middle::mir::interpret::EvalStaticInitializerRawResult,
-    rustc_middle::mir::mono::MonoItemPartitions,
-    rustc_middle::traits::query::MethodAutoderefStepsResult,
-    rustc_middle::traits::query::type_op::AscribeUserType,
-    rustc_middle::traits::query::type_op::Eq,
-    rustc_middle::traits::query::type_op::ProvePredicate,
-    rustc_middle::traits::query::type_op::Subtype,
-    rustc_middle::ty::AdtDef,
-    rustc_middle::ty::AliasTy,
-    rustc_middle::ty::ClauseKind,
-    rustc_middle::ty::ClosureTypeInfo,
-    rustc_middle::ty::Const,
-    rustc_middle::ty::DestructuredAdtConst,
-    rustc_middle::ty::ExistentialTraitRef,
-    rustc_middle::ty::FnSig,
-    rustc_middle::ty::GenericArg,
-    rustc_middle::ty::GenericPredicates,
-    rustc_middle::ty::ConstConditions,
-    rustc_middle::ty::inhabitedness::InhabitedPredicate,
-    rustc_middle::ty::Instance,
-    rustc_middle::ty::BoundVariableKind,
-    rustc_middle::ty::InstanceKind,
-    rustc_middle::ty::layout::FnAbiError,
-    rustc_middle::ty::layout::LayoutError,
-    rustc_middle::ty::LitToConstInput,
-    rustc_middle::ty::ParamEnv,
-    rustc_middle::ty::TypingEnv,
-    rustc_middle::ty::Predicate,
-    rustc_middle::ty::SymbolName,
-    rustc_middle::ty::TraitRef,
-    rustc_middle::ty::Ty,
-    rustc_middle::ty::UnevaluatedConst,
-    rustc_middle::ty::ValTree,
-    rustc_middle::ty::VtblEntry,
+    // tidy-alphabetical-end
 }
diff --git a/compiler/rustc_middle/src/query/job.rs b/compiler/rustc_middle/src/query/job.rs
index 3bf37a7..24c4daf 100644
--- a/compiler/rustc_middle/src/query/job.rs
+++ b/compiler/rustc_middle/src/query/job.rs
@@ -6,7 +6,7 @@
 use parking_lot::{Condvar, Mutex};
 use rustc_span::Span;
 
-use crate::query::CycleError;
+use crate::query::Cycle;
 use crate::ty::TyCtxt;
 
 /// A value uniquely identifying an active query job.
@@ -59,7 +59,7 @@ pub struct QueryWaiter<'tcx> {
     pub parent: Option<QueryJobId>,
     pub condvar: Condvar,
     pub span: Span,
-    pub cycle: Mutex<Option<CycleError<'tcx>>>,
+    pub cycle: Mutex<Option<Cycle<'tcx>>>,
 }
 
 #[derive(Clone, Debug)]
@@ -79,7 +79,7 @@ pub fn wait_on(
         tcx: TyCtxt<'tcx>,
         query: Option<QueryJobId>,
         span: Span,
-    ) -> Result<(), CycleError<'tcx>> {
+    ) -> Result<(), Cycle<'tcx>> {
         let mut waiters_guard = self.waiters.lock();
         let Some(waiters) = &mut *waiters_guard else {
             return Ok(()); // already complete
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 9c012f2..b7e5e9b 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -5,8 +5,8 @@
 pub use self::job::{QueryJob, QueryJobId, QueryLatch, QueryWaiter};
 pub use self::keys::{AsLocalQueryKey, LocalCrate, QueryKey};
 pub use self::plumbing::{
-    ActiveKeyStatus, CycleError, EnsureMode, QueryMode, QueryState, QuerySystem, QueryVTable,
-    TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk, TyCtxtEnsureResult,
+    ActiveKeyStatus, Cycle, EnsureMode, QueryMode, QueryState, QuerySystem, QueryVTable, TyCtxtAt,
+    TyCtxtEnsureDone, TyCtxtEnsureOk, TyCtxtEnsureResult,
 };
 pub use self::stack::QueryStackFrame;
 pub use crate::queries::Providers;
diff --git a/compiler/rustc_middle/src/query/modifiers.rs b/compiler/rustc_middle/src/query/modifiers.rs
index ad9b9de..50c9136 100644
--- a/compiler/rustc_middle/src/query/modifiers.rs
+++ b/compiler/rustc_middle/src/query/modifiers.rs
@@ -7,11 +7,6 @@
 
 // tidy-alphabetical-start
 //
-/// # `anon` query modifier
-///
-/// Generate a dep node based not on the query key, but on the query's dependencies.
-pub(crate) struct anon;
-
 /// # `arena_cache` query modifier
 ///
 /// Query return values must impl `Copy` and be small, but some queries must return values that
@@ -59,6 +54,16 @@
 /// Generate a `feed` method to set the query's value from another query.
 pub(crate) struct feedable;
 
+/// # `no_force` query modifier
+///
+/// Dep nodes of queries with this modifier will never be "forced" when trying
+/// to mark their dependents green, even if their key is recoverable from the
+/// key fingerprint.
+///
+/// Used by some queries with custom cycle-handlers to ensure that if a cycle
+/// occurs, all of the relevant query calls will be on the query stack.
+pub(crate) struct no_force;
+
 /// # `no_hash` query modifier
 ///
 /// Do not hash the query's return value for incremental compilation. If the value needs to be
diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs
index 607891d..b6fd306 100644
--- a/compiler/rustc_middle/src/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/query/on_disk_cache.rs
@@ -2,14 +2,14 @@
 use std::sync::Arc;
 use std::{fmt, mem};
 
-use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
+use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::sync::{HashMapExt, Lock, RwLock};
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId, StableCrateId};
 use rustc_hir::definitions::DefPathHash;
-use rustc_index::{Idx, IndexVec};
+use rustc_index::IndexVec;
 use rustc_macros::{Decodable, Encodable};
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
@@ -53,22 +53,18 @@ pub struct OnDiskCache {
     // The complete cache data in serialized form.
     serialized_data: RwLock<Option<Mmap>>,
 
-    // Collects all `QuerySideEffect` created during the current compilation
-    // session.
-    current_side_effects: Lock<FxIndexMap<DepNodeIndex, QuerySideEffect>>,
-
     file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>,
 
     // Caches that are populated lazily during decoding.
     file_index_to_file: Lock<FxHashMap<SourceFileIndex, Arc<SourceFile>>>,
 
-    // A map from dep-node to the position of the cached query result in
-    // `serialized_data`.
-    query_result_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
+    /// For query dep nodes that have a disk-cached return value, maps the node
+    /// index to the position of its serialized value in `serialized_data`.
+    query_values_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
 
-    // A map from dep-node to the position of any associated `QuerySideEffect` in
-    // `serialized_data`.
-    prev_side_effects_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
+    /// For `DepKind::SideEffect` dep nodes, maps the node index to the position
+    /// of its serialized [`QuerySideEffect`] in `serialized_data`.
+    side_effects_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
 
     alloc_decoding_state: AllocDecodingState,
 
@@ -101,8 +97,8 @@ pub struct OnDiskCache {
 #[derive(Encodable, Decodable)]
 struct Footer {
     file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>,
-    query_result_index: EncodedDepNodeIndex,
-    side_effects_index: EncodedDepNodeIndex,
+    query_values_index: Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>,
+    side_effects_index: Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>,
     // The location of all allocations.
     // Most uses only need values up to u32::MAX, but benchmarking indicates that we can use a u64
     // without measurable overhead. This permits larger const allocations without ICEing.
@@ -114,8 +110,6 @@ struct Footer {
     foreign_expn_data: UnhashMap<ExpnHash, u32>,
 }
 
-pub type EncodedDepNodeIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
-
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable)]
 struct SourceFileIndex(u32);
 
@@ -174,9 +168,8 @@ pub fn new(sess: &Session, data: Mmap, start_pos: usize) -> Result<Self, ()> {
             serialized_data: RwLock::new(Some(data)),
             file_index_to_stable_id: footer.file_index_to_stable_id,
             file_index_to_file: Default::default(),
-            current_side_effects: Default::default(),
-            query_result_index: footer.query_result_index.into_iter().collect(),
-            prev_side_effects_index: footer.side_effects_index.into_iter().collect(),
+            query_values_index: footer.query_values_index.into_iter().collect(),
+            side_effects_index: footer.side_effects_index.into_iter().collect(),
             alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index),
             syntax_contexts: footer.syntax_contexts,
             expn_data: footer.expn_data,
@@ -190,9 +183,8 @@ pub fn new_empty() -> Self {
             serialized_data: RwLock::new(None),
             file_index_to_stable_id: Default::default(),
             file_index_to_file: Default::default(),
-            current_side_effects: Default::default(),
-            query_result_index: Default::default(),
-            prev_side_effects_index: Default::default(),
+            query_values_index: Default::default(),
+            side_effects_index: Default::default(),
             alloc_decoding_state: AllocDecodingState::new(Vec::new()),
             syntax_contexts: FxHashMap::default(),
             expn_data: UnhashMap::default(),
@@ -207,7 +199,9 @@ pub fn close_serialized_data_mmap(&self) {
         *self.serialized_data.write() = None;
     }
 
-    pub fn serialize(&self, tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResult {
+    /// Serialize the current-session data that will be loaded by [`OnDiskCache`]
+    /// in a subsequent incremental compilation session.
+    pub fn serialize(tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResult {
         // Serializing the `DepGraph` should not modify it.
         tcx.dep_graph.with_ignore(|| {
             // Allocate `SourceFileIndex`es.
@@ -241,30 +235,19 @@ pub fn serialize(&self, tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResu
                 file_to_file_index,
                 hygiene_context: &hygiene_encode_context,
                 symbol_index_table: Default::default(),
+                query_values_index: Default::default(),
+                side_effects_index: Default::default(),
             };
 
-            // Encode query results.
-            let mut query_result_index = EncodedDepNodeIndex::new();
-
+            // Encode query return values.
             tcx.sess.time("encode_query_values", || {
-                let enc = &mut encoder;
-                let qri = &mut query_result_index;
-                tcx.encode_query_values(enc, qri);
+                tcx.encode_query_values(&mut encoder);
             });
 
             // Encode side effects.
-            let side_effects_index: EncodedDepNodeIndex = self
-                .current_side_effects
-                .borrow()
-                .iter()
-                .map(|(dep_node_index, side_effect)| {
-                    let pos = AbsoluteBytePos::new(encoder.position());
-                    let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
-                    encoder.encode_tagged(dep_node_index, side_effect);
-
-                    (dep_node_index, pos)
-                })
-                .collect();
+            for (&dep_node_index, side_effect) in tcx.query_system.side_effects.borrow().iter() {
+                encoder.encode_side_effect(dep_node_index, side_effect);
+            }
 
             let interpret_alloc_index = {
                 let mut interpret_alloc_index = Vec::new();
@@ -315,11 +298,13 @@ pub fn serialize(&self, tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResu
 
             // Encode the file footer.
             let footer_pos = encoder.position() as u64;
+            let query_values_index = mem::take(&mut encoder.query_values_index);
+            let side_effects_index = mem::take(&mut encoder.side_effects_index);
             encoder.encode_tagged(
                 TAG_FILE_FOOTER,
                 &Footer {
                     file_index_to_stable_id,
-                    query_result_index,
+                    query_values_index,
                     side_effects_index,
                     interpret_alloc_index,
                     syntax_contexts,
@@ -340,35 +325,25 @@ pub fn serialize(&self, tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResu
     }
 
     /// Loads a `QuerySideEffect` created during the previous compilation session.
-    pub fn load_side_effect(
+    pub(crate) fn load_side_effect(
         &self,
         tcx: TyCtxt<'_>,
         dep_node_index: SerializedDepNodeIndex,
     ) -> Option<QuerySideEffect> {
         let side_effect: Option<QuerySideEffect> =
-            self.load_indexed(tcx, dep_node_index, &self.prev_side_effects_index);
+            self.load_indexed(tcx, dep_node_index, &self.side_effects_index);
         side_effect
     }
 
-    /// Stores a `QuerySideEffect` emitted during the current compilation session.
-    /// Anything stored like this will be available via `load_side_effect` in
-    /// the next compilation session.
-    pub fn store_side_effect(&self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) {
-        let mut current_side_effects = self.current_side_effects.borrow_mut();
-        let prev = current_side_effects.insert(dep_node_index, side_effect);
-        debug_assert!(prev.is_none());
-    }
-
-    /// Return whether the cached query result can be decoded.
+    /// Returns true if there is a disk-cached query return value for the given node.
     #[inline]
     pub fn loadable_from_disk(&self, dep_node_index: SerializedDepNodeIndex) -> bool {
-        self.query_result_index.contains_key(&dep_node_index)
+        self.query_values_index.contains_key(&dep_node_index)
         // with_decoder is infallible, so we can stop here
     }
 
-    /// Returns the cached query result if there is something in the cache for
-    /// the given `SerializedDepNodeIndex`; otherwise returns `None`.
-    pub fn try_load_query_result<'tcx, T>(
+    /// Returns the disk-cached query return value for the given node, if there is one.
+    pub fn try_load_query_value<'tcx, T>(
         &self,
         tcx: TyCtxt<'tcx>,
         dep_node_index: SerializedDepNodeIndex,
@@ -376,9 +351,7 @@ pub fn try_load_query_result<'tcx, T>(
     where
         T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
     {
-        let opt_value = self.load_indexed(tcx, dep_node_index, &self.query_result_index);
-        debug_assert_eq!(opt_value.is_some(), self.loadable_from_disk(dep_node_index));
-        opt_value
+        self.load_indexed(tcx, dep_node_index, &self.query_values_index)
     }
 
     fn load_indexed<'tcx, T>(
@@ -815,6 +788,9 @@ pub struct CacheEncoder<'a, 'tcx> {
     hygiene_context: &'a HygieneEncodeContext,
     // Used for both `Symbol`s and `ByteSymbol`s.
     symbol_index_table: FxHashMap<u32, usize>,
+
+    query_values_index: Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>,
+    side_effects_index: Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>,
 }
 
 impl<'a, 'tcx> fmt::Debug for CacheEncoder<'a, 'tcx> {
@@ -835,7 +811,7 @@ fn source_file_index(&mut self, source_file: Arc<SourceFile>) -> SourceFileIndex
     /// encode the specified tag, then the given value, then the number of
     /// bytes taken up by tag and value. On decoding, we can then verify that
     /// we get the expected tag and read the expected number of bytes.
-    pub fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>(&mut self, tag: T, value: &V) {
+    fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>(&mut self, tag: T, value: &V) {
         let start_pos = self.position();
 
         tag.encode(self);
@@ -845,6 +821,20 @@ pub fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>(&mut self, tag: T,
         ((end_pos - start_pos) as u64).encode(self);
     }
 
+    pub fn encode_query_value<V: Encodable<Self>>(&mut self, index: DepNodeIndex, value: &V) {
+        let index = SerializedDepNodeIndex::from_curr_for_serialization(index);
+
+        self.query_values_index.push((index, AbsoluteBytePos::new(self.position())));
+        self.encode_tagged(index, value);
+    }
+
+    fn encode_side_effect(&mut self, index: DepNodeIndex, side_effect: &QuerySideEffect) {
+        let index = SerializedDepNodeIndex::from_curr_for_serialization(index);
+
+        self.side_effects_index.push((index, AbsoluteBytePos::new(self.position())));
+        self.encode_tagged(index, side_effect);
+    }
+
     // copy&paste impl from rustc_metadata
     fn encode_symbol_or_byte_symbol(
         &mut self,
diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs
index 4ef1b0a..ef6259b 100644
--- a/compiler/rustc_middle/src/query/plumbing.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -2,13 +2,14 @@
 use std::ops::Deref;
 
 use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::hash_table::HashTable;
 use rustc_data_structures::sharded::Sharded;
-use rustc_data_structures::sync::{AtomicU64, WorkerLocal};
+use rustc_data_structures::sync::{AtomicU64, Lock, WorkerLocal};
 use rustc_errors::Diag;
 use rustc_span::Span;
 
-use crate::dep_graph::{DepKind, DepNodeIndex, SerializedDepNodeIndex};
+use crate::dep_graph::{DepKind, DepNodeIndex, QuerySideEffect, SerializedDepNodeIndex};
 use crate::ich::StableHashingContext;
 use crate::queries::{ExternProviders, Providers, QueryArenas, QueryVTables, TaggedQueryKey};
 use crate::query::on_disk_cache::OnDiskCache;
@@ -47,12 +48,12 @@ pub enum ActiveKeyStatus<'tcx> {
 }
 
 #[derive(Debug)]
-pub struct CycleError<'tcx> {
+pub struct Cycle<'tcx> {
     /// The query and related span that uses the cycle.
     pub usage: Option<QueryStackFrame<'tcx>>,
 
     /// The span here corresponds to the reason for which this query was required.
-    pub cycle: Vec<QueryStackFrame<'tcx>>,
+    pub frames: Vec<QueryStackFrame<'tcx>>,
 }
 
 #[derive(Debug)]
@@ -77,8 +78,6 @@ pub enum EnsureMode {
 pub struct QueryVTable<'tcx, C: QueryCache> {
     pub name: &'static str,
 
-    /// True if this query has the `anon` modifier.
-    pub anon: bool,
     /// True if this query has the `eval_always` modifier.
     pub eval_always: bool,
     /// True if this query has the `depth_limit` modifier.
@@ -106,9 +105,6 @@ pub struct QueryVTable<'tcx, C: QueryCache> {
         index: DepNodeIndex,
     ) -> Option<C::Value>,
 
-    pub is_loadable_from_disk_fn:
-        fn(tcx: TyCtxt<'tcx>, key: C::Key, index: SerializedDepNodeIndex) -> bool,
-
     /// Function pointer that hashes this query's result values.
     ///
     /// For `no_hash` queries, this function pointer is None.
@@ -116,13 +112,10 @@ pub struct QueryVTable<'tcx, C: QueryCache> {
 
     /// Function pointer that handles a cycle error. `error` must be consumed, e.g. with `emit` (if
     /// it should be emitted) or `delay_as_bug` (if it need not be emitted because an alternative
-    /// error is created and emitted).
-    pub value_from_cycle_error: fn(
-        tcx: TyCtxt<'tcx>,
-        key: C::Key,
-        cycle_error: CycleError<'tcx>,
-        error: Diag<'_>,
-    ) -> C::Value,
+    /// error is created and emitted). A value may be returned, or (more commonly) the function may
+    /// just abort after emitting the error.
+    pub handle_cycle_error_fn:
+        fn(tcx: TyCtxt<'tcx>, key: C::Key, cycle: Cycle<'tcx>, error: Diag<'_>) -> C::Value,
 
     pub format_value: fn(&C::Value) -> String,
 
@@ -156,6 +149,13 @@ pub struct QuerySystem<'tcx> {
     pub arenas: WorkerLocal<QueryArenas<'tcx>>,
     pub query_vtables: QueryVTables<'tcx>,
 
+    /// Side-effect associated with each [`DepKind::SideEffect`] node in the
+    /// current incremental-compilation session. Side effects will be written
+    /// to disk, and loaded by [`OnDiskCache`] in the next session.
+    ///
+    /// Always empty if incremental compilation is off.
+    pub side_effects: Lock<FxIndexMap<DepNodeIndex, QuerySideEffect>>,
+
     /// This provides access to the incremental compilation on-disk cache for query results.
     /// Do not access this directly. It is only meant to be used by
     /// `DepGraph::try_mark_green()` and the query infrastructure.
@@ -283,12 +283,12 @@ macro_rules! define_callbacks {
                 fn $name:ident($($K:tt)*) -> $V:ty
                 {
                     // Search for (QMODLIST) to find all occurrences of this query modifier list.
-                    anon: $anon:literal,
                     arena_cache: $arena_cache:literal,
                     cache_on_disk: $cache_on_disk:literal,
                     depth_limit: $depth_limit:literal,
                     eval_always: $eval_always:literal,
                     feedable: $feedable:literal,
+                    no_force: $no_force:literal,
                     no_hash: $no_hash:literal,
                     returns_error_guaranteed: $returns_error_guaranteed:literal,
                     separate_provide_extern: $separate_provide_extern:literal,
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 8811657..51f33691 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -866,6 +866,13 @@ pub enum PatKind<'tcx> {
         pats: Box<[Pat<'tcx>]>,
     },
 
+    /// A guard pattern, e.g. `x if guard(x)`
+    Guard {
+        subpattern: Box<Pat<'tcx>>,
+        #[type_visitable(ignore)]
+        condition: ExprId,
+    },
+
     /// A never pattern `!`.
     Never,
 
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
index c17e155..aa1b6b1 100644
--- a/compiler/rustc_middle/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -247,6 +247,12 @@ pub fn walk_pat<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
     visitor: &mut V,
     pat: &'thir Pat<'tcx>,
 ) {
+    if let PatKind::Guard { subpattern, condition } = &pat.kind {
+        visitor.visit_pat(subpattern);
+        visitor.visit_expr(&visitor.thir()[*condition]);
+        return;
+    };
+
     for_each_immediate_subpat(pat, |p| visitor.visit_pat(p));
 }
 
@@ -287,5 +293,9 @@ pub(crate) fn for_each_immediate_subpat<'a, 'tcx>(
                 callback(pat);
             }
         }
+
+        PatKind::Guard { subpattern, .. } => {
+            callback(subpattern);
+        }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index b454689..5bb11c9 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -61,7 +61,7 @@ pub(crate) fn provide(providers: &mut Providers) {
 /// requires calling [`InhabitedPredicate::instantiate`]
 fn inhabited_predicate_adt(tcx: TyCtxt<'_>, def_id: DefId) -> InhabitedPredicate<'_> {
     if let Some(def_id) = def_id.as_local() {
-        let _ = tcx.check_representability(def_id);
+        tcx.ensure_ok().check_representability(def_id);
     }
 
     let adt = tcx.adt_def(def_id);
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index f072b26..674799c 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -2172,6 +2172,36 @@ pub fn fn_abi_of_instance(
     }
 }
 
+// `HasAttrs` impls: allow `find_attr!(tcx, id, ...)` to work with both DefId-like types and HirId.
+
+impl<'tcx> hir::attrs::HasAttrs<'tcx, TyCtxt<'tcx>> for DefId {
+    fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [hir::Attribute] {
+        if let Some(did) = self.as_local() {
+            tcx.hir_attrs(tcx.local_def_id_to_hir_id(did))
+        } else {
+            tcx.attrs_for_def(self)
+        }
+    }
+}
+
+impl<'tcx> hir::attrs::HasAttrs<'tcx, TyCtxt<'tcx>> for LocalDefId {
+    fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [hir::Attribute] {
+        tcx.hir_attrs(tcx.local_def_id_to_hir_id(self))
+    }
+}
+
+impl<'tcx> hir::attrs::HasAttrs<'tcx, TyCtxt<'tcx>> for hir::OwnerId {
+    fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [hir::Attribute] {
+        hir::attrs::HasAttrs::get_attrs(self.def_id, tcx)
+    }
+}
+
+impl<'tcx> hir::attrs::HasAttrs<'tcx, TyCtxt<'tcx>> for hir::HirId {
+    fn get_attrs(self, tcx: &TyCtxt<'tcx>) -> &'tcx [hir::Attribute] {
+        tcx.hir_attrs(self)
+    }
+}
+
 pub fn provide(providers: &mut Providers) {
     closure::provide(providers);
     context::provide(providers);
diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
index 7698af4..cbe31fd 100644
--- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
@@ -360,6 +360,11 @@ pub(super) fn for_pattern(
                 Some(TestableCase::Deref { temp, mutability })
             }
 
+            PatKind::Guard { .. } => {
+                // FIXME(guard_patterns)
+                None
+            }
+
             PatKind::Never => Some(TestableCase::Never),
         };
 
diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs
index d7edf82..d4f5fe8 100644
--- a/compiler/rustc_mir_build/src/builder/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs
@@ -944,6 +944,9 @@ fn visit_primary_bindings_special(
                     visit_subpat(self, subpattern, user_tys, f);
                 }
             }
+            PatKind::Guard { ref subpattern, .. } => {
+                visit_subpat(self, subpattern, user_tys, f);
+            }
         }
     }
 }
diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs
index bcac451..01c1e2e 100644
--- a/compiler/rustc_mir_build/src/builder/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/mod.rs
@@ -491,7 +491,7 @@ fn construct_fn<'tcx>(
     };
 
     if let Some((dialect, phase)) =
-        find_attr!(tcx.hir_attrs(fn_id), CustomMir(dialect, phase, _) => (dialect, phase))
+        find_attr!(tcx, fn_id, CustomMir(dialect, phase, _) => (dialect, phase))
     {
         return custom::build_custom_mir(
             tcx,
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index ee35539..aed0c6e 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -315,6 +315,7 @@ fn visit_pat(&mut self, pat: &'a Pat<'tcx>) {
                 | PatKind::Range { .. }
                 | PatKind::Slice { .. }
                 | PatKind::Array { .. }
+                | PatKind::Guard { .. }
                 // Never constitutes a witness of uninhabitedness.
                 | PatKind::Never => {
                     self.requires_unsafe(pat.span, AccessToUnionField);
diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs
index b108dff..ea27252 100644
--- a/compiler/rustc_mir_build/src/thir/cx/block.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/block.rs
@@ -83,6 +83,7 @@ fn mirror_stmts(
                             }
                             Some(_) | None => local.span,
                         };
+                        let initializer = local.init.map(|init| self.mirror_expr(init));
                         let stmt = Stmt {
                             kind: StmtKind::Let {
                                 remainder_scope,
@@ -91,7 +92,7 @@ fn mirror_stmts(
                                     data: region::ScopeData::Node,
                                 },
                                 pattern,
-                                initializer: local.init.map(|init| self.mirror_expr(init)),
+                                initializer,
                                 else_block,
                                 hir_id: local.hir_id,
                                 span,
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index c646b0f..4256ee4 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -876,7 +876,7 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
                     };
 
                 let indices = self.typeck_results.offset_of_data().get(expr.hir_id).unwrap();
-                let mut expr = None::<ExprKind<'tcx>>;
+                let mut expr = None::<ExprKind<'_>>;
 
                 for &(container, variant, field) in indices.iter() {
                     let next = mk_call(&mut self.thir, container, variant, field);
@@ -917,7 +917,7 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
             hir::ExprKind::Ret(v) => ExprKind::Return { value: v.map(|v| self.mirror_expr(v)) },
             hir::ExprKind::Become(call) => ExprKind::Become { value: self.mirror_expr(call) },
             hir::ExprKind::Break(dest, ref value) => {
-                if find_attr!(self.tcx.hir_attrs(expr.hir_id), ConstContinue(_)) {
+                if find_attr!(self.tcx, expr.hir_id, ConstContinue(_)) {
                     match dest.target_id {
                         Ok(target_id) => {
                             let (Some(value), Some(_)) = (value, dest.label) else {
@@ -982,7 +982,7 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
                 match_source,
             },
             hir::ExprKind::Loop(body, ..) => {
-                if find_attr!(self.tcx.hir_attrs(expr.hir_id), LoopMatch(_)) {
+                if find_attr!(self.tcx, expr.hir_id, LoopMatch(_)) {
                     let dcx = self.tcx.dcx();
 
                     // Accept either `state = expr` or `state = expr;`.
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 60cb509..f22ff92 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -13,14 +13,14 @@
 use rustc_middle::ty::{self, TyCtxt};
 
 /// Query implementation for [`TyCtxt::thir_body`].
-pub(crate) fn thir_body(
-    tcx: TyCtxt<'_>,
+pub(crate) fn thir_body<'tcx>(
+    tcx: TyCtxt<'tcx>,
     owner_def: LocalDefId,
-) -> Result<(&Steal<Thir<'_>>, ExprId), ErrorGuaranteed> {
+) -> Result<(&'tcx Steal<Thir<'tcx>>, ExprId), ErrorGuaranteed> {
     debug_assert!(!tcx.is_type_const(owner_def.to_def_id()), "thir_body queried for type_const");
 
     let body = tcx.hir_body_owned_by(owner_def);
-    let mut cx = ThirBuildCx::new(tcx, owner_def);
+    let mut cx: ThirBuildCx<'tcx> = ThirBuildCx::new(tcx, owner_def);
     if let Some(reported) = cx.typeck_results.tainted_by_errors {
         return Err(reported);
     }
@@ -50,7 +50,7 @@ pub(crate) fn thir_body(
 }
 
 /// Context for lowering HIR to THIR for a single function body (or other kind of body).
-struct ThirBuildCx<'tcx> {
+pub(crate) struct ThirBuildCx<'tcx> {
     tcx: TyCtxt<'tcx>,
     /// The THIR data that this context is building.
     thir: Thir<'tcx>,
@@ -104,7 +104,7 @@ fn new(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
             typing_env: ty::TypingEnv::non_body_analysis(tcx, def),
             typeck_results,
             body_owner: def.to_def_id(),
-            apply_adjustments: !find_attr!(tcx.hir_attrs(hir_id), CustomMir(..) => ()).is_some(),
+            apply_adjustments: !find_attr!(tcx, hir_id, CustomMir(..)),
         }
     }
 
@@ -118,6 +118,7 @@ fn pattern_from_hir_with_annotation(
         let_stmt_type: Option<&hir::Ty<'tcx>>,
     ) -> Box<Pat<'tcx>> {
         crate::thir::pattern::pat_from_hir(
+            self,
             self.tcx,
             self.typing_env,
             self.typeck_results,
@@ -201,7 +202,7 @@ fn explicit_params(
                 fn_sig.inputs()[index]
             };
 
-            let pat = self.pattern_from_hir(param.pat);
+            let pat: Box<Pat<'tcx>> = self.pattern_from_hir(param.pat);
             Param { pat: Some(pat), ty, ty_span, self_kind, hir_id: Some(param.hir_id) }
         })
     }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index ff9d456..ff4778d 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -25,7 +25,7 @@
     PointerPattern, TypeNotPartialEq, TypeNotStructural, UnionPattern, UnsizedPattern,
 };
 
-impl<'tcx> PatCtxt<'tcx> {
+impl<'tcx, 'ptcx> PatCtxt<'tcx, 'ptcx> {
     /// Converts a constant to a pattern (if possible).
     /// This means aggregate values (like structs and enums) are converted
     /// to a pattern that matches the value (as if you'd compared via structural equality).
@@ -61,7 +61,7 @@ struct ConstToPat<'tcx> {
 }
 
 impl<'tcx> ConstToPat<'tcx> {
-    fn new(pat_ctxt: &PatCtxt<'tcx>, id: hir::HirId, span: Span, c: ty::Const<'tcx>) -> Self {
+    fn new(pat_ctxt: &PatCtxt<'tcx, '_>, id: hir::HirId, span: Span, c: ty::Const<'tcx>) -> Self {
         trace!(?pat_ctxt.typeck_results.hir_owner);
         ConstToPat { tcx: pat_ctxt.tcx, typing_env: pat_ctxt.typing_env, span, id, c }
     }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index fec2fb9..7d4e25c 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -30,9 +30,11 @@
 pub(crate) use self::check_match::check_match;
 use self::migration::PatMigration;
 use crate::errors::*;
+use crate::thir::cx::ThirBuildCx;
 
 /// Context for lowering HIR patterns to THIR patterns.
-struct PatCtxt<'tcx> {
+struct PatCtxt<'tcx, 'ptcx> {
+    upper: &'ptcx mut ThirBuildCx<'tcx>,
     tcx: TyCtxt<'tcx>,
     typing_env: ty::TypingEnv<'tcx>,
     typeck_results: &'tcx ty::TypeckResults<'tcx>,
@@ -41,8 +43,9 @@ struct PatCtxt<'tcx> {
     rust_2024_migration: Option<PatMigration<'tcx>>,
 }
 
-#[instrument(level = "debug", skip(tcx, typing_env, typeck_results), ret)]
-pub(super) fn pat_from_hir<'tcx>(
+#[instrument(level = "debug", skip(upper, tcx, typing_env, typeck_results), ret)]
+pub(super) fn pat_from_hir<'tcx, 'ptcx>(
+    upper: &'ptcx mut ThirBuildCx<'tcx>,
     tcx: TyCtxt<'tcx>,
     typing_env: ty::TypingEnv<'tcx>,
     typeck_results: &'tcx ty::TypeckResults<'tcx>,
@@ -51,6 +54,7 @@ pub(super) fn pat_from_hir<'tcx>(
     let_stmt_type: Option<&hir::Ty<'tcx>>,
 ) -> Box<Pat<'tcx>> {
     let mut pcx = PatCtxt {
+        upper,
         tcx,
         typing_env,
         typeck_results,
@@ -87,7 +91,7 @@ pub(super) fn pat_from_hir<'tcx>(
     thir_pat
 }
 
-impl<'tcx> PatCtxt<'tcx> {
+impl<'tcx, 'ptcx> PatCtxt<'tcx, 'ptcx> {
     fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
         let adjustments: &[PatAdjustment<'tcx>] =
             self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
@@ -443,8 +447,10 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tc
 
             hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) },
 
-            // FIXME(guard_patterns): implement guard pattern lowering
-            hir::PatKind::Guard(pat, _) => self.lower_pattern(pat).kind,
+            hir::PatKind::Guard(pat, condition) => PatKind::Guard {
+                subpattern: self.lower_pattern(pat),
+                condition: self.upper.mirror_expr(condition),
+            },
 
             hir::PatKind::Err(guar) => PatKind::Error(guar),
         };
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index 27dec99..ea34e5f 100644
--- a/compiler/rustc_mir_build/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -844,6 +844,14 @@ fn print_pat_kind(&mut self, pat_kind: &PatKind<'tcx>, depth_lvl: usize) {
                 print_indented!(self, "]", depth_lvl + 2);
                 print_indented!(self, "}", depth_lvl + 1);
             }
+            PatKind::Guard { subpattern, condition } => {
+                print_indented!(self, "Guard pattern: {", depth_lvl + 1);
+                print_indented!(self, "subpattern: ", depth_lvl + 2);
+                self.print_pat(subpattern, depth_lvl + 3);
+                print_indented!(self, "guard: ", depth_lvl + 2);
+                self.print_expr(*condition, depth_lvl + 3);
+                print_indented!(self, "}", depth_lvl + 1);
+            }
             PatKind::Error(_) => {
                 print_indented!(self, "Error", depth_lvl + 1);
             }
diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs
index 89ee963..e04cb26 100644
--- a/compiler/rustc_mir_transform/src/copy_prop.rs
+++ b/compiler/rustc_mir_transform/src/copy_prop.rs
@@ -58,7 +58,8 @@ fn is_required(&self) -> bool {
     }
 }
 
-/// Utility to help performing substitution of `*pattern` by `target`.
+/// Utility to help performing substitution: for all key-value pairs in `copy_classes`,
+/// all occurrences of the key get replaced by the value.
 struct Replacer<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     unified: DenseBitSet<Local>,
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 245ee6e..e9a20aa 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -48,8 +48,15 @@
 //! # Handling of references
 //!
 //! We handle references by assigning a different "provenance" index to each Ref/RawPtr rvalue.
-//! This ensure that we do not spuriously merge borrows that should not be merged. Meanwhile, we
-//! consider all the derefs of an immutable reference to a freeze type to give the same value:
+//! This ensure that we do not spuriously merge borrows that should not be merged. For instance:
+//! ```ignore (MIR)
+//! _x = &_a;
+//! _a = 0;
+//! _y = &_a; // cannot be turned into `_y = _x`!
+//! ```
+//!
+//! On top of that, we consider all the derefs of an immutable reference to a freeze type to give
+//! the same value:
 //! ```ignore (MIR)
 //! _a = *_b // _b is &Freeze
 //! _c = *_b // replaced by _c = _a
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
index cd74e87..433cad1 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
@@ -797,12 +797,16 @@ pub(in crate::solve) fn const_conditions_for_destruct<I: Interner>(
         | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
         | ty::Error(_) => Ok(vec![]),
 
-        // Coroutines and closures could implement `[const] Drop`,
+        // Closures are [const] Destruct when all of their upvars (captures) are [const] Destruct.
+        ty::Closure(_, args) => {
+            let closure_args = args.as_closure();
+            Ok(vec![ty::TraitRef::new(cx, destruct_def_id, [closure_args.tupled_upvars_ty()])])
+        }
+        // Coroutines could implement `[const] Drop`,
         // but they don't really need to right now.
-        ty::Closure(_, _)
-        | ty::CoroutineClosure(_, _)
-        | ty::Coroutine(_, _)
-        | ty::CoroutineWitness(_, _) => Err(NoSolution),
+        ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) | ty::CoroutineWitness(_, _) => {
+            Err(NoSolution)
+        }
 
         // FIXME(unsafe_binders): Unsafe binders could implement `[const] Drop`
         // if their inner type implements it.
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index f4f7182..0e852d2 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -4499,3 +4499,111 @@ pub(super) fn from_token(token: &Token) -> Option<Self> {
         }
     }
 }
+
+#[derive(Diagnostic)]
+#[diag(
+    "this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression"
+)]
+pub(crate) struct BreakWithLabelAndLoop {
+    #[subdiagnostic]
+    pub sub: BreakWithLabelAndLoopSub,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion("wrap this expression in parentheses", applicability = "machine-applicable")]
+pub(crate) struct BreakWithLabelAndLoopSub {
+    #[suggestion_part(code = "(")]
+    pub left: Span,
+    #[suggestion_part(code = ")")]
+    pub right: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag("prefix `'r` is reserved")]
+pub(crate) struct RawPrefix {
+    #[label("reserved prefix")]
+    pub label: Span,
+    #[suggestion(
+        "insert whitespace here to avoid this being parsed as a prefix in Rust 2021",
+        code = " ",
+        applicability = "machine-applicable"
+    )]
+    pub suggestion: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag("unicode codepoint changing visible direction of text present in comment")]
+#[note(
+    "these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen"
+)]
+pub(crate) struct UnicodeTextFlow {
+    #[label(
+        "{$num_codepoints ->
+            [1] this comment contains an invisible unicode text flow control codepoint
+            *[other] this comment contains invisible unicode text flow control codepoints
+        }"
+    )]
+    pub comment_span: Span,
+    #[subdiagnostic]
+    pub characters: Vec<UnicodeCharNoteSub>,
+    #[subdiagnostic]
+    pub suggestions: Option<UnicodeTextFlowSuggestion>,
+
+    pub num_codepoints: usize,
+}
+
+#[derive(Subdiagnostic)]
+#[label("{$c_debug}")]
+pub(crate) struct UnicodeCharNoteSub {
+    #[primary_span]
+    pub span: Span,
+    pub c_debug: String,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    "if their presence wasn't intentional, you can remove them",
+    applicability = "machine-applicable",
+    style = "hidden"
+)]
+pub(crate) struct UnicodeTextFlowSuggestion {
+    #[suggestion_part(code = "")]
+    pub spans: Vec<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag("prefix `{$prefix}` is unknown")]
+pub(crate) struct ReservedPrefix {
+    #[label("unknown prefix")]
+    pub label: Span,
+    #[suggestion(
+        "insert whitespace here to avoid this being parsed as a prefix in Rust 2021",
+        code = " ",
+        applicability = "machine-applicable"
+    )]
+    pub suggestion: Span,
+
+    pub prefix: String,
+}
+
+#[derive(Diagnostic)]
+#[diag("will be parsed as a guarded string in Rust 2024")]
+pub(crate) struct ReservedStringLint {
+    #[suggestion(
+        "insert whitespace here to avoid this being parsed as a guarded string in Rust 2024",
+        code = " ",
+        applicability = "machine-applicable"
+    )]
+    pub suggestion: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag("reserved token in Rust 2024")]
+pub(crate) struct ReservedMultihashLint {
+    #[suggestion(
+        "insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024",
+        code = " ",
+        applicability = "machine-applicable"
+    )]
+    pub suggestion: Span,
+}
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index cd90655..2223e6a 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -4,12 +4,11 @@
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::util::unicode::{TEXT_FLOW_CONTROL_CHARS, contains_text_flow_control_chars};
 use rustc_errors::codes::*;
-use rustc_errors::{Applicability, Diag, DiagCtxtHandle, StashKey};
+use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, StashKey};
 use rustc_lexer::{
     Base, Cursor, DocStyle, FrontmatterAllowed, LiteralKind, RawStrError, is_horizontal_whitespace,
 };
 use rustc_literal_escaper::{EscapeError, Mode, check_for_errors};
-use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::lint::builtin::{
     RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX,
     TEXT_DIRECTION_CODEPOINT_IN_COMMENT, TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
@@ -388,7 +387,10 @@ fn next_token_from_cursor(&mut self) -> (Token, bool) {
                             RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
                             prefix_span,
                             ast::CRATE_NODE_ID,
-                            BuiltinLintDiag::RawPrefix(prefix_span),
+                            errors::RawPrefix {
+                                label: prefix_span,
+                                suggestion: prefix_span.shrink_to_hi()
+                            },
                         );
 
                         // Reset the state so we just lex the `'r`.
@@ -498,11 +500,41 @@ fn lint_unicode_text_flow(&self, start: BytePos) {
         let content = self.str_from(content_start);
         if contains_text_flow_control_chars(content) {
             let span = self.mk_sp(start, self.pos);
-            self.psess.buffer_lint(
+            let content = content.to_string();
+            self.psess.dyn_buffer_lint(
                 TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
                 span,
                 ast::CRATE_NODE_ID,
-                BuiltinLintDiag::UnicodeTextFlow(span, content.to_string()),
+                move |dcx, level| {
+                    let spans: Vec<_> = content
+                        .char_indices()
+                        .filter_map(|(i, c)| {
+                            TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| {
+                                let lo = span.lo() + BytePos(2 + i as u32);
+                                (c, span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32)))
+                            })
+                        })
+                        .collect();
+                    let characters = spans
+                        .iter()
+                        .map(|&(c, span)| errors::UnicodeCharNoteSub {
+                            span,
+                            c_debug: format!("{c:?}"),
+                        })
+                        .collect();
+                    let suggestions =
+                        (!spans.is_empty()).then_some(errors::UnicodeTextFlowSuggestion {
+                            spans: spans.iter().map(|(_c, span)| *span).collect(),
+                        });
+
+                    errors::UnicodeTextFlow {
+                        comment_span: span,
+                        characters,
+                        suggestions,
+                        num_codepoints: spans.len(),
+                    }
+                    .into_diag(dcx, level)
+                },
             );
         }
     }
@@ -1038,7 +1070,11 @@ fn report_unknown_prefix(&self, start: BytePos) {
                 RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
                 prefix_span,
                 ast::CRATE_NODE_ID,
-                BuiltinLintDiag::ReservedPrefix(prefix_span, prefix.to_string()),
+                errors::ReservedPrefix {
+                    label: prefix_span,
+                    suggestion: prefix_span.shrink_to_hi(),
+                    prefix: prefix.to_string(),
+                },
             );
         }
     }
@@ -1112,11 +1148,18 @@ fn maybe_report_guarded_str(&mut self, start: BytePos, str_before: &'src str) ->
             })
         } else {
             // Before Rust 2024, only emit a lint for migration.
-            self.psess.buffer_lint(
+            self.psess.dyn_buffer_lint(
                 RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX,
                 span,
                 ast::CRATE_NODE_ID,
-                BuiltinLintDiag::ReservedString { is_string, suggestion: space_span },
+                move |dcx, level| {
+                    if is_string {
+                        errors::ReservedStringLint { suggestion: space_span }.into_diag(dcx, level)
+                    } else {
+                        errors::ReservedMultihashLint { suggestion: space_span }
+                            .into_diag(dcx, level)
+                    }
+                },
             );
 
             // For backwards compatibility, roll back to after just the first `#`
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index adfc68f..c18e8c6 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -15,14 +15,13 @@
 use rustc_ast::{
     self as ast, AnonConst, Arm, AssignOp, AssignOpKind, AttrStyle, AttrVec, BinOp, BinOpKind,
     BlockCheckMode, CaptureBy, ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl,
-    FnRetTy, Label, MacCall, MetaItemLit, MgcaDisambiguation, Movability, Param, RangeLimits,
-    StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind, YieldKind,
+    FnRetTy, Guard, Label, MacCall, MetaItemLit, MgcaDisambiguation, Movability, Param,
+    RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind, YieldKind,
 };
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic};
 use rustc_literal_escaper::unescape_char;
 use rustc_session::errors::{ExprParenthesesNeeded, report_lit_error};
-use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
 use rustc_span::edition::Edition;
 use rustc_span::{BytePos, ErrorGuaranteed, Ident, Pos, Span, Spanned, Symbol, kw, respan, sym};
@@ -1921,11 +1920,17 @@ fn parse_expr_break(&mut self) -> PResult<'a, Box<Expr>> {
                         _ => false,
                     }
                 {
+                    let span = expr.span;
                     self.psess.buffer_lint(
                         BREAK_WITH_LABEL_AND_LOOP,
                         lo.to(expr.span),
                         ast::CRATE_NODE_ID,
-                        BuiltinLintDiag::BreakWithLabelAndLoop(expr.span),
+                        errors::BreakWithLabelAndLoop {
+                            sub: errors::BreakWithLabelAndLoopSub {
+                                left: span.shrink_to_lo(),
+                                right: span.shrink_to_hi(),
+                            },
+                        },
                     );
                 }
 
@@ -2762,7 +2767,7 @@ pub fn parse_expr_cond(
 
     /// Parses a `let $pat = $expr` pseudo-expression.
     fn parse_expr_let(&mut self, restrictions: Restrictions) -> PResult<'a, Box<Expr>> {
-        let recovered = if !restrictions.contains(Restrictions::ALLOW_LET) {
+        let recovered: Recovered = if !restrictions.contains(Restrictions::ALLOW_LET) {
             let err = errors::ExpectedExpressionFoundLet {
                 span: self.token.span,
                 reason: errors::ForbiddenLetReason::OtherForbidden,
@@ -3458,20 +3463,54 @@ pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> {
         })
     }
 
-    fn parse_match_arm_guard(&mut self) -> PResult<'a, Option<Box<Expr>>> {
+    pub(crate) fn eat_metavar_guard(&mut self) -> Option<Box<Guard>> {
+        self.eat_metavar_seq_with_matcher(
+            |mv_kind| matches!(mv_kind, MetaVarKind::Guard),
+            |this| this.parse_match_arm_guard(),
+        )
+        .flatten()
+    }
+
+    fn parse_match_arm_guard(&mut self) -> PResult<'a, Option<Box<Guard>>> {
+        if let Some(guard) = self.eat_metavar_guard() {
+            return Ok(Some(guard));
+        }
+
         if !self.eat_keyword(exp!(If)) {
             // No match arm guard present.
             return Ok(None);
         }
+        self.expect_match_arm_guard_cond(ForceCollect::No).map(Some)
+    }
 
-        let mut cond = self.parse_match_guard_condition()?;
+    pub(crate) fn expect_match_arm_guard(
+        &mut self,
+        force_collect: ForceCollect,
+    ) -> PResult<'a, Box<Guard>> {
+        if let Some(guard) = self.eat_metavar_guard() {
+            return Ok(guard);
+        }
+
+        self.expect_keyword(exp!(If))?;
+        self.expect_match_arm_guard_cond(force_collect)
+    }
+
+    fn expect_match_arm_guard_cond(
+        &mut self,
+        force_collect: ForceCollect,
+    ) -> PResult<'a, Box<Guard>> {
+        let leading_if_span = self.prev_token.span;
+
+        let mut cond = self.parse_match_guard_condition(force_collect)?;
+        let cond_span = cond.span;
 
         CondChecker::new(self, LetChainsPolicy::AlwaysAllowed).visit_expr(&mut cond);
 
-        Ok(Some(cond))
+        let guard = Guard { cond: *cond, span_with_leading_if: leading_if_span.to(cond_span) };
+        Ok(Box::new(guard))
     }
 
-    fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Pat, Option<Box<Expr>>)> {
+    fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Pat, Option<Box<Guard>>)> {
         if self.token == token::OpenParen {
             let left = self.token.span;
             let pat = self.parse_pat_no_top_guard(
@@ -3487,10 +3526,10 @@ fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Pat, Option<Box<Expr
                 // FIXME(guard_patterns): convert this to a normal guard instead
                 let span = pat.span;
                 let ast::PatKind::Paren(subpat) = pat.kind else { unreachable!() };
-                let ast::PatKind::Guard(_, mut cond) = subpat.kind else { unreachable!() };
-                self.psess.gated_spans.ungate_last(sym::guard_patterns, cond.span);
+                let ast::PatKind::Guard(_, mut guard) = subpat.kind else { unreachable!() };
+                self.psess.gated_spans.ungate_last(sym::guard_patterns, guard.span());
                 let mut checker = CondChecker::new(self, LetChainsPolicy::AlwaysAllowed);
-                checker.visit_expr(&mut cond);
+                checker.visit_expr(&mut guard.cond);
 
                 let right = self.prev_token.span;
                 self.dcx().emit_err(errors::ParenthesesInMatchPat {
@@ -3498,14 +3537,10 @@ fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Pat, Option<Box<Expr
                     sugg: errors::ParenthesesInMatchPatSugg { left, right },
                 });
 
-                Ok((
-                    self.mk_pat(span, ast::PatKind::Wild),
-                    (if let Some(guar) = checker.found_incorrect_let_chain {
-                        Some(self.mk_expr_err(cond.span, guar))
-                    } else {
-                        Some(cond)
-                    }),
-                ))
+                if let Some(guar) = checker.found_incorrect_let_chain {
+                    guard.cond = *self.mk_expr_err(guard.span(), guar);
+                }
+                Ok((self.mk_pat(span, ast::PatKind::Wild), Some(guard)))
             } else {
                 Ok((pat, self.parse_match_arm_guard()?))
             }
@@ -3521,33 +3556,47 @@ fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Pat, Option<Box<Expr
         }
     }
 
-    fn parse_match_guard_condition(&mut self) -> PResult<'a, Box<Expr>> {
+    fn parse_match_guard_condition(
+        &mut self,
+        force_collect: ForceCollect,
+    ) -> PResult<'a, Box<Expr>> {
         let attrs = self.parse_outer_attributes()?;
-        match self.parse_expr_res(Restrictions::ALLOW_LET | Restrictions::IN_IF_GUARD, attrs) {
-            Ok((expr, _)) => Ok(expr),
-            Err(mut err) => {
-                if self.prev_token == token::OpenBrace {
-                    let sugg_sp = self.prev_token.span.shrink_to_lo();
-                    // Consume everything within the braces, let's avoid further parse
-                    // errors.
-                    self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
-                    let msg = "you might have meant to start a match arm after the match guard";
-                    if self.eat(exp!(CloseBrace)) {
-                        let applicability = if self.token != token::FatArrow {
-                            // We have high confidence that we indeed didn't have a struct
-                            // literal in the match guard, but rather we had some operation
-                            // that ended in a path, immediately followed by a block that was
-                            // meant to be the match arm.
-                            Applicability::MachineApplicable
-                        } else {
-                            Applicability::MaybeIncorrect
-                        };
-                        err.span_suggestion_verbose(sugg_sp, msg, "=> ", applicability);
+        let expr = self.collect_tokens(
+            None,
+            AttrWrapper::empty(),
+            force_collect,
+            |this, _empty_attrs| {
+                match this
+                    .parse_expr_res(Restrictions::ALLOW_LET | Restrictions::IN_IF_GUARD, attrs)
+                {
+                    Ok((expr, _)) => Ok((expr, Trailing::No, UsePreAttrPos::No)),
+                    Err(mut err) => {
+                        if this.prev_token == token::OpenBrace {
+                            let sugg_sp = this.prev_token.span.shrink_to_lo();
+                            // Consume everything within the braces, let's avoid further parse
+                            // errors.
+                            this.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore);
+                            let msg =
+                                "you might have meant to start a match arm after the match guard";
+                            if this.eat(exp!(CloseBrace)) {
+                                let applicability = if this.token != token::FatArrow {
+                                    // We have high confidence that we indeed didn't have a struct
+                                    // literal in the match guard, but rather we had some operation
+                                    // that ended in a path, immediately followed by a block that was
+                                    // meant to be the match arm.
+                                    Applicability::MachineApplicable
+                                } else {
+                                    Applicability::MaybeIncorrect
+                                };
+                                err.span_suggestion_verbose(sugg_sp, msg, "=> ", applicability);
+                            }
+                        }
+                        Err(err)
                     }
                 }
-                Err(err)
-            }
-        }
+            },
+        )?;
+        Ok(expr)
     }
 
     pub(crate) fn is_builtin(&self) -> bool {
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 36ca8a7..8c1c3c7 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1788,4 +1788,5 @@ pub enum ParseNtResult {
     Meta(Box<ast::AttrItem>),
     Path(Box<ast::Path>),
     Vis(Box<ast::Visibility>),
+    Guard(Box<ast::Guard>),
 }
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 706b454..ddf1b10 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -31,7 +31,8 @@ fn may_be_ident(kind: MetaVarKind) -> bool {
 
                 MetaVarKind::Item
                 | MetaVarKind::Block
-                | MetaVarKind::Vis => false,
+                | MetaVarKind::Vis
+                | MetaVarKind::Guard => false,
 
                 MetaVarKind::Ident
                 | MetaVarKind::Lifetime
@@ -86,7 +87,8 @@ fn may_be_ident(kind: MetaVarKind) -> bool {
                     | MetaVarKind::Ty { .. }
                     | MetaVarKind::Meta { .. }
                     | MetaVarKind::Path
-                    | MetaVarKind::Vis => false,
+                    | MetaVarKind::Vis
+                    | MetaVarKind::Guard => false,
                     MetaVarKind::Lifetime | MetaVarKind::Ident | MetaVarKind::TT => {
                         unreachable!()
                     }
@@ -103,6 +105,7 @@ fn may_be_ident(kind: MetaVarKind) -> bool {
                 token::Lifetime(..) | token::NtLifetime(..) => true,
                 _ => false,
             },
+            NonterminalKind::Guard => token.is_keyword(kw::If),
             NonterminalKind::TT | NonterminalKind::Item | NonterminalKind::Stmt => {
                 token.kind.close_delim().is_none()
             }
@@ -196,6 +199,9 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, ParseN
                     }))
                 }
             }
+            NonterminalKind::Guard => {
+                Ok(ParseNtResult::Guard(self.expect_match_arm_guard(ForceCollect::Yes)?))
+            }
         }
     }
 }
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 7ee7781..a21d19b 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -6,8 +6,9 @@
 use rustc_ast::util::parser::ExprPrecedence;
 use rustc_ast::visit::{self, Visitor};
 use rustc_ast::{
-    self as ast, Arm, AttrVec, BindingMode, ByRef, Expr, ExprKind, LocalKind, MacCall, Mutability,
-    Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt, StmtKind,
+    self as ast, Arm, AttrVec, BindingMode, ByRef, Expr, ExprKind, Guard, LocalKind, MacCall,
+    Mutability, Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax, Stmt,
+    StmtKind,
 };
 use rustc_ast_pretty::pprust;
 use rustc_errors::{Applicability, Diag, DiagArgValue, PResult, StashKey};
@@ -110,11 +111,19 @@ pub fn parse_pat_allow_top_guard(
         let pat = self.parse_pat_no_top_guard(expected, rc, ra, rt)?;
 
         if self.eat_keyword(exp!(If)) {
-            let cond = self.parse_expr()?;
+            let guard = if let Some(guard) = self.eat_metavar_guard() {
+                guard
+            } else {
+                let leading_if_span = self.prev_token.span;
+                let cond = self.parse_expr()?;
+                let cond_span = cond.span;
+                Box::new(Guard { cond: *cond, span_with_leading_if: leading_if_span.to(cond_span) })
+            };
+
             // Feature-gate guard patterns
-            self.psess.gated_spans.gate(sym::guard_patterns, cond.span);
-            let span = pat.span.to(cond.span);
-            Ok(self.mk_pat(span, PatKind::Guard(Box::new(pat), cond)))
+            self.psess.gated_spans.gate(sym::guard_patterns, guard.span());
+            let span = pat.span.to(guard.span());
+            Ok(self.mk_pat(span, PatKind::Guard(Box::new(pat), guard)))
         } else {
             Ok(pat)
         }
@@ -601,17 +610,18 @@ fn maybe_add_suggestions_then_emit(
                                 }
                                 Some(guard) => {
                                     // Are parentheses required around the old guard?
-                                    let wrap_guard = guard.precedence() <= ExprPrecedence::LAnd;
+                                    let wrap_guard =
+                                        guard.cond.precedence() <= ExprPrecedence::LAnd;
 
                                     err.subdiagnostic(
                                         UnexpectedExpressionInPatternSugg::UpdateGuard {
                                             ident_span,
                                             guard_lo: if wrap_guard {
-                                                Some(guard.span.shrink_to_lo())
+                                                Some(guard.span().shrink_to_lo())
                                             } else {
                                                 None
                                             },
-                                            guard_hi: guard.span.shrink_to_hi(),
+                                            guard_hi: guard.span().shrink_to_hi(),
                                             guard_hi_paren: if wrap_guard { ")" } else { "" },
                                             ident,
                                             expr,
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 3b21024..5bd2ca3 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -362,7 +362,7 @@ fn parse_local(&mut self, super_: Option<Span>, attrs: AttrVec) -> PResult<'a, B
                 // init parsed, ty error
                 // Could parse the type as if it were the initializer, it is likely there was a
                 // typo in the code: `:` instead of `=`. Add suggestion and emit the error.
-                err.span_suggestion_short(
+                err.span_suggestion_verbose(
                     colon_sp,
                     "use `=` if you meant to assign",
                     " =",
@@ -1133,11 +1133,11 @@ pub fn parse_full_stmt(
                                 } else {
                                     false
                                 };
-                                if suggest_eq {
-                                    e.span_suggestion_short(
-                                        colon_sp,
+                                if suggest_eq && let Some(ty) = &local.ty {
+                                    e.span_suggestion_verbose(
+                                        local.pat.span.between(ty.span),
                                         "use `=` if you meant to assign",
-                                        "=",
+                                        " = ",
                                         Applicability::MaybeIncorrect,
                                     );
                                 }
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 9945802..26ba2b0 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -15,11 +15,8 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_data_structures::unord::UnordMap;
-use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey, msg};
-use rustc_feature::{
-    ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP,
-    BuiltinAttribute,
-};
+use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, msg};
+use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
 use rustc_hir::attrs::diagnostic::Directive;
 use rustc_hir::attrs::{
     AttributeKind, DocAttribute, DocInline, EiiDecl, EiiImpl, EiiImplResolution, InlineAttr,
@@ -30,8 +27,7 @@
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{
     self as hir, Attribute, CRATE_HIR_ID, Constness, FnSig, ForeignItem, GenericParamKind, HirId,
-    Item, ItemKind, MethodKind, Node, ParamName, PartialConstStability, Safety, Stability,
-    StabilityLevel, Target, TraitItem, find_attr,
+    Item, ItemKind, MethodKind, Node, ParamName, Safety, Target, TraitItem, find_attr,
 };
 use rustc_macros::Diagnostic;
 use rustc_middle::hir::nested_filter;
@@ -49,7 +45,7 @@
 };
 use rustc_session::parse::feature_err;
 use rustc_span::edition::Edition;
-use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol, sym};
+use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym};
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
 use rustc_trait_selection::traits::ObligationCtxt;
@@ -156,16 +152,6 @@ fn check_attributes(
                 Attribute::Parsed(AttributeKind::ProcMacroDerive { .. }) => {
                     self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
                 }
-                Attribute::Parsed(
-                    AttributeKind::Stability {
-                        span: attr_span,
-                        stability: Stability { level, feature },
-                    }
-                    | AttributeKind::RustcConstStability {
-                        span: attr_span,
-                        stability: PartialConstStability { level, feature, .. },
-                    },
-                ) => self.check_stability(*attr_span, span, level, *feature),
                 Attribute::Parsed(AttributeKind::Inline(InlineAttr::Force { .. }, ..)) => {} // handled separately below
                 Attribute::Parsed(AttributeKind::Inline(kind, attr_span)) => {
                     self.check_inline(hir_id, *attr_span, kind, target)
@@ -312,6 +298,7 @@ fn check_attributes(
                     | AttributeKind::RustcCoherenceIsCore(..)
                     | AttributeKind::RustcCoinductive(..)
                     | AttributeKind::RustcConfusables { .. }
+                    | AttributeKind::RustcConstStability { .. }
                     | AttributeKind::RustcConstStableIndirect
                     | AttributeKind::RustcConversionSuggestion
                     | AttributeKind::RustcDeallocator
@@ -384,6 +371,7 @@ fn check_attributes(
                     | AttributeKind::RustcTrivialFieldReads
                     | AttributeKind::RustcUnsafeSpecializationMarker(..)
                     | AttributeKind::ShouldPanic { .. }
+                    | AttributeKind::Stability { .. }
                     | AttributeKind::TestRunner(..)
                     | AttributeKind::ThreadLocal
                     | AttributeKind::TypeLengthLimit { .. }
@@ -1570,24 +1558,6 @@ fn check_rustc_allow_const_fn_unstable(
         }
     }
 
-    fn check_stability(
-        &self,
-        attr_span: Span,
-        item_span: Span,
-        level: &StabilityLevel,
-        feature: Symbol,
-    ) {
-        // Stable *language* features shouldn't be used as unstable library features.
-        // (Not doing this for stable library features is checked by tidy.)
-        if level.is_unstable()
-            && ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some()
-        {
-            self.tcx
-                .dcx()
-                .emit_err(errors::UnstableAttrForAlreadyStableFeature { attr_span, item_span });
-        }
-    }
-
     fn check_deprecated(&self, hir_id: HirId, attr_span: Span, target: Target) {
         match target {
             Target::AssocConst | Target::Method(..) | Target::AssocTy
@@ -1937,27 +1907,6 @@ fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
     }
 
     fn visit_where_predicate(&mut self, where_predicate: &'tcx hir::WherePredicate<'tcx>) {
-        // FIXME(where_clause_attrs): Currently, as the following check shows,
-        // only `#[cfg]` and `#[cfg_attr]` are allowed, but it should be removed
-        // if we allow more attributes (e.g., tool attributes and `allow/deny/warn`)
-        // in where clauses. After that, only `self.check_attributes` should be enough.
-        let spans = self
-            .tcx
-            .hir_attrs(where_predicate.hir_id)
-            .iter()
-            // FIXME: We shouldn't need to special-case `doc`!
-            .filter(|attr| {
-                matches!(
-                    attr,
-                    Attribute::Parsed(AttributeKind::DocComment { .. } | AttributeKind::Doc(_))
-                        | Attribute::Unparsed(_)
-                )
-            })
-            .map(|attr| attr.span())
-            .collect::<Vec<_>>();
-        if !spans.is_empty() {
-            self.tcx.dcx().emit_err(errors::UnsupportedAttributesInWhere { span: spans.into() });
-        }
         self.check_attributes(
             where_predicate.hir_id,
             where_predicate.span,
@@ -2055,64 +2004,6 @@ fn is_c_like_enum(item: &Item<'_>) -> bool {
     }
 }
 
-// FIXME: Fix "Cannot determine resolution" error and remove built-in macros
-// from this check.
-fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
-    // Check for builtin attributes at the crate level
-    // which were unsuccessfully resolved due to cannot determine
-    // resolution for the attribute macro error.
-    const ATTRS_TO_CHECK: &[Symbol] =
-        &[sym::derive, sym::test, sym::test_case, sym::global_allocator, sym::bench];
-
-    for attr in attrs {
-        // FIXME(jdonszelmann): all attrs should be combined here cleaning this up some day.
-        let (span, name) = if let Some(a) =
-            ATTRS_TO_CHECK.iter().find(|attr_to_check| attr.has_name(**attr_to_check))
-        {
-            (attr.span(), *a)
-        } else if let Attribute::Parsed(AttributeKind::Repr {
-            reprs: _,
-            first_span: first_attr_span,
-        }) = attr
-        {
-            (*first_attr_span, sym::repr)
-        } else {
-            continue;
-        };
-
-        let item = tcx
-            .hir_free_items()
-            .map(|id| tcx.hir_item(id))
-            .find(|item| !item.span.is_dummy()) // Skip prelude `use`s
-            .map(|item| errors::ItemFollowingInnerAttr {
-                span: if let Some(ident) = item.kind.ident() { ident.span } else { item.span },
-                kind: tcx.def_descr(item.owner_id.to_def_id()),
-            });
-        let err = tcx.dcx().create_err(errors::InvalidAttrAtCrateLevel {
-            span,
-            sugg_span: tcx
-                .sess
-                .source_map()
-                .span_to_snippet(span)
-                .ok()
-                .filter(|src| src.starts_with("#!["))
-                .map(|_| span.with_lo(span.lo() + BytePos(1)).with_hi(span.lo() + BytePos(2))),
-            name,
-            item,
-        });
-
-        if let Attribute::Unparsed(p) = attr {
-            tcx.dcx().try_steal_replace_and_emit_err(
-                p.path.span,
-                StashKey::UndeterminedMacroResolution,
-                err,
-            );
-        } else {
-            err.emit();
-        }
-    }
-}
-
 fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>) {
     let attrs = tcx.hir_attrs(item.hir_id());
 
@@ -2128,7 +2019,6 @@ fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
     tcx.hir_visit_item_likes_in_module(module_def_id, check_attr_visitor);
     if module_def_id.to_local_def_id().is_top_level_module() {
         check_attr_visitor.check_attributes(CRATE_HIR_ID, DUMMY_SP, Target::Mod, None);
-        check_invalid_crate_level_attr(tcx, tcx.hir_krate_attrs());
     }
     if check_attr_visitor.abort.get() {
         tcx.dcx().abort_if_errors()
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 15c91de..30634c8 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -157,7 +157,7 @@ fn handle_res(&mut self, res: Res) {
             Res::Def(_, def_id) => self.check_def_id(def_id),
             Res::SelfTyParam { trait_: t } => self.check_def_id(t),
             Res::SelfTyAlias { alias_to: i, .. } => self.check_def_id(i),
-            Res::ToolMod | Res::NonMacroAttr(..) | Res::Err => {}
+            Res::ToolMod | Res::NonMacroAttr(..) | Res::OpenMod(..) | Res::Err => {}
         }
     }
 
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 6efbcd7..f9dc696 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -3,8 +3,7 @@
 
 use rustc_errors::codes::*;
 use rustc_errors::{
-    Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level,
-    MultiSpan, msg,
+    Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level, MultiSpan, msg,
 };
 use rustc_hir::Target;
 use rustc_macros::{Diagnostic, Subdiagnostic};
@@ -447,44 +446,6 @@ pub(crate) struct LangItemOnIncorrectTarget {
     pub actual_target: Target,
 }
 
-pub(crate) struct InvalidAttrAtCrateLevel {
-    pub span: Span,
-    pub sugg_span: Option<Span>,
-    pub name: Symbol,
-    pub item: Option<ItemFollowingInnerAttr>,
-}
-
-#[derive(Clone, Copy)]
-pub(crate) struct ItemFollowingInnerAttr {
-    pub span: Span,
-    pub kind: &'static str,
-}
-
-impl<G: EmissionGuarantee> Diagnostic<'_, G> for InvalidAttrAtCrateLevel {
-    #[track_caller]
-    fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
-        let mut diag =
-            Diag::new(dcx, level, msg!("`{$name}` attribute cannot be used at crate level"));
-        diag.span(self.span);
-        diag.arg("name", self.name);
-        // Only emit an error with a suggestion if we can create a string out
-        // of the attribute span
-        if let Some(span) = self.sugg_span {
-            diag.span_suggestion_verbose(
-                span,
-                msg!("perhaps you meant to use an outer attribute"),
-                String::new(),
-                Applicability::MachineApplicable,
-            );
-        }
-        if let Some(item) = self.item {
-            diag.arg("kind", item.kind);
-            diag.span_label(item.span, msg!("the inner attribute doesn't annotate this {$kind}"));
-        }
-        diag
-    }
-}
-
 #[derive(Diagnostic)]
 #[diag("duplicate diagnostic item in crate `{$crate_name}`: `{$name}`")]
 pub(crate) struct DuplicateDiagnosticItemInCrate {
@@ -872,17 +833,6 @@ pub(crate) struct CannotStabilizeDeprecated {
 }
 
 #[derive(Diagnostic)]
-#[diag("can't mark as unstable using an already stable feature")]
-pub(crate) struct UnstableAttrForAlreadyStableFeature {
-    #[primary_span]
-    #[label("this feature is already stable")]
-    #[help("consider removing the attribute")]
-    pub attr_span: Span,
-    #[label("the stability attribute annotates this item")]
-    pub item_span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag("{$descr} has missing stability attribute")]
 pub(crate) struct MissingStabilityAttr<'a> {
     #[primary_span]
@@ -1201,14 +1151,6 @@ pub(crate) struct RustcConstStableIndirectPairing {
 }
 
 #[derive(Diagnostic)]
-#[diag("most attributes are not supported in `where` clauses")]
-#[help("only `#[cfg]` and `#[cfg_attr]` are supported")]
-pub(crate) struct UnsupportedAttributesInWhere {
-    #[primary_span]
-    pub span: MultiSpan,
-}
-
-#[derive(Diagnostic)]
 pub(crate) enum UnexportableItem<'a> {
     #[diag("{$descr}'s are not exportable")]
     Item {
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index dc38f2d..0226c54 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -462,7 +462,8 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> {
         let arity;
         let fields: Vec<_>;
         match &pat.kind {
-            PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat),
+            PatKind::Binding { subpattern: Some(subpat), .. }
+            | PatKind::Guard { subpattern: subpat, .. } => return self.lower_pat(subpat),
             PatKind::Missing | PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
                 ctor = Wildcard;
                 fields = vec![];
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 63860df..663f872 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1595,13 +1595,14 @@ fn check_assoc_item(
         let mut check = self.check(item.def_id.expect_local(), vis, effective_vis);
 
         let is_assoc_ty = item.is_type();
-        check.hard_error = is_assoc_ty && !item.is_impl_trait_in_trait();
+        check.hard_error = is_assoc_ty;
         check.generics().predicates();
         if assoc_has_type_of(self.tcx, item) {
-            check.hard_error = check.hard_error && item.defaultness(self.tcx).has_value();
             check.ty();
         }
         if is_assoc_ty && item.container == AssocContainer::Trait {
+            // FIXME: too much breakage from reporting hard errors here, better wait for a fix
+            // from proper associated type normalization.
             check.hard_error = false;
             check.bounds();
         }
diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml
index 1c3f0f9..02d3b01 100644
--- a/compiler/rustc_query_impl/Cargo.toml
+++ b/compiler/rustc_query_impl/Cargo.toml
@@ -10,7 +10,6 @@
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_hir = { path = "../rustc_hir" }
-rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_serialize = { path = "../rustc_serialize" }
diff --git a/compiler/rustc_query_impl/src/dep_kind_vtables.rs b/compiler/rustc_query_impl/src/dep_kind_vtables.rs
index 597c8b2..b70fe30 100644
--- a/compiler/rustc_query_impl/src/dep_kind_vtables.rs
+++ b/compiler/rustc_query_impl/src/dep_kind_vtables.rs
@@ -4,7 +4,7 @@
 use rustc_middle::query::QueryCache;
 
 use crate::GetQueryVTable;
-use crate::plumbing::{force_from_dep_node_inner, promote_from_disk_inner};
+use crate::plumbing::promote_from_disk_inner;
 
 /// [`DepKindVTable`] constructors for special dep kinds that aren't queries.
 #[expect(non_snake_case, reason = "use non-snake case to avoid collision with query names")]
@@ -96,32 +96,31 @@ pub(crate) fn Metadata<'tcx>() -> DepKindVTable<'tcx> {
 /// Shared implementation of the [`DepKindVTable`] constructor for queries.
 /// Called from macro-generated code for each query.
 pub(crate) fn make_dep_kind_vtable_for_query<'tcx, Q>(
-    is_anon: bool,
     is_cache_on_disk: bool,
     is_eval_always: bool,
+    is_no_force: bool,
 ) -> DepKindVTable<'tcx>
 where
     Q: GetQueryVTable<'tcx>,
 {
-    let key_fingerprint_style = if is_anon {
-        KeyFingerprintStyle::Opaque
-    } else {
-        <Q::Cache as QueryCache>::Key::key_fingerprint_style()
-    };
-
     // A query dep-node can only be forced or promoted if it can recover a key
     // from its key fingerprint.
+    let key_fingerprint_style = <Q::Cache as QueryCache>::Key::key_fingerprint_style();
     let can_recover = key_fingerprint_style.is_maybe_recoverable();
-    if is_anon {
-        assert!(!can_recover);
-    }
 
     DepKindVTable {
         is_eval_always,
         key_fingerprint_style,
-        force_from_dep_node_fn: can_recover.then_some(force_from_dep_node_inner::<Q>),
-        promote_from_disk_fn: (can_recover && is_cache_on_disk)
-            .then_some(promote_from_disk_inner::<Q>),
+        force_from_dep_node_fn: (can_recover && !is_no_force).then_some(
+            |tcx, dep_node, _prev_index| {
+                let query = Q::query_vtable(tcx);
+                crate::execution::force_query_dep_node(tcx, query, dep_node)
+            },
+        ),
+        promote_from_disk_fn: (can_recover && is_cache_on_disk).then_some(|tcx, dep_node| {
+            let query = Q::query_vtable(tcx);
+            promote_from_disk_inner(tcx, query, dep_node)
+        }),
     }
 }
 
@@ -133,12 +132,12 @@ macro_rules! define_dep_kind_vtables {
                 fn $name:ident($K:ty) -> $V:ty
                 {
                     // Search for (QMODLIST) to find all occurrences of this query modifier list.
-                    anon: $anon:literal,
                     arena_cache: $arena_cache:literal,
                     cache_on_disk: $cache_on_disk:literal,
                     depth_limit: $depth_limit:literal,
                     eval_always: $eval_always:literal,
                     feedable: $feedable:literal,
+                    no_force: $no_force:literal,
                     no_hash: $no_hash:literal,
                     returns_error_guaranteed: $returns_error_guaranteed:literal,
                     separate_provide_extern: $separate_provide_extern:literal,
@@ -165,9 +164,9 @@ fn $name:ident($K:ty) -> $V:ty
                 $crate::dep_kind_vtables::make_dep_kind_vtable_for_query::<
                     $crate::query_impl::$name::VTableGetter,
                 >(
-                    $anon,
                     $cache_on_disk,
                     $eval_always,
+                    $no_force,
                 )
             ),*
         ];
diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs
index aea0bb4..8844d40 100644
--- a/compiler/rustc_query_impl/src/execution.rs
+++ b/compiler/rustc_query_impl/src/execution.rs
@@ -8,8 +8,8 @@
 use rustc_errors::FatalError;
 use rustc_middle::dep_graph::{DepGraphData, DepNodeKey, SerializedDepNodeIndex};
 use rustc_middle::query::{
-    ActiveKeyStatus, CycleError, EnsureMode, QueryCache, QueryJob, QueryJobId, QueryKey,
-    QueryLatch, QueryMode, QueryState, QueryVTable,
+    ActiveKeyStatus, Cycle, EnsureMode, QueryCache, QueryJob, QueryJobId, QueryKey, QueryLatch,
+    QueryMode, QueryState, QueryVTable,
 };
 use rustc_middle::ty::TyCtxt;
 use rustc_middle::verify_ich::incremental_verify_ich;
@@ -17,8 +17,8 @@
 use tracing::warn;
 
 use crate::dep_graph::{DepNode, DepNodeIndex};
-use crate::job::{QueryJobInfo, QueryJobMap, find_cycle_in_stack, report_cycle};
-use crate::plumbing::{current_query_job, next_job_id, start_query};
+use crate::job::{QueryJobInfo, QueryJobMap, create_cycle_error, find_cycle_in_stack};
+use crate::plumbing::{current_query_job, loadable_from_disk, next_job_id, start_query};
 use crate::query_impl::for_each_query_vtable;
 
 #[inline]
@@ -108,14 +108,14 @@ fn collect_active_query_jobs_inner<'tcx, C>(
 
 #[cold]
 #[inline(never)]
-fn mk_cycle<'tcx, C: QueryCache>(
+fn handle_cycle<'tcx, C: QueryCache>(
     query: &'tcx QueryVTable<'tcx, C>,
     tcx: TyCtxt<'tcx>,
     key: C::Key,
-    cycle_error: CycleError<'tcx>,
+    cycle: Cycle<'tcx>,
 ) -> C::Value {
-    let error = report_cycle(tcx, &cycle_error);
-    (query.value_from_cycle_error)(tcx, key, cycle_error, error)
+    let error = create_cycle_error(tcx, &cycle);
+    (query.handle_cycle_error_fn)(tcx, key, cycle, error)
 }
 
 /// Guard object representing the responsibility to execute a query job and
@@ -194,7 +194,7 @@ fn drop(&mut self) {
 
 #[cold]
 #[inline(never)]
-fn cycle_error<'tcx, C: QueryCache>(
+fn find_and_handle_cycle<'tcx, C: QueryCache>(
     query: &'tcx QueryVTable<'tcx, C>,
     tcx: TyCtxt<'tcx>,
     key: C::Key,
@@ -205,8 +205,8 @@ fn cycle_error<'tcx, C: QueryCache>(
     // We need the complete map to ensure we find a cycle to break.
     let job_map = collect_active_query_jobs(tcx, CollectActiveJobsKind::FullNoContention);
 
-    let error = find_cycle_in_stack(try_execute, job_map, &current_query_job(), span);
-    (mk_cycle(query, tcx, key, error), None)
+    let cycle = find_cycle_in_stack(try_execute, job_map, &current_query_job(), span);
+    (handle_cycle(query, tcx, key, cycle), None)
 }
 
 #[inline(always)]
@@ -250,7 +250,7 @@ fn wait_for_query<'tcx, C: QueryCache>(
 
             (v, Some(index))
         }
-        Err(cycle) => (mk_cycle(query, tcx, key, cycle), None),
+        Err(cycle) => (handle_cycle(query, tcx, key, cycle), None),
     }
 }
 
@@ -261,9 +261,7 @@ fn try_execute_query<'tcx, C: QueryCache, const INCR: bool>(
     tcx: TyCtxt<'tcx>,
     span: Span,
     key: C::Key,
-    // If present, some previous step has already created a `DepNode` for this
-    // query+key, which we should reuse instead of creating a new one.
-    dep_node: Option<DepNode>,
+    dep_node: Option<DepNode>, // `None` for non-incremental, `Some` for incremental
 ) -> (C::Value, Option<DepNodeIndex>) {
     let key_hash = sharded::make_hash(&key);
     let mut state_lock = query.state.active.lock_shard_by_hash(key_hash);
@@ -298,11 +296,9 @@ fn try_execute_query<'tcx, C: QueryCache, const INCR: bool>(
             // panic occurs while executing the query (or any intermediate plumbing).
             let job_guard = ActiveJobGuard { state: &query.state, key, key_hash };
 
-            debug_assert_eq!(tcx.dep_graph.is_fully_enabled(), INCR);
-
             // Delegate to another function to actually execute the query job.
             let (value, dep_node_index) = if INCR {
-                execute_job_incr(query, tcx, key, dep_node, id)
+                execute_job_incr(query, tcx, key, dep_node.unwrap(), id)
             } else {
                 execute_job_non_incr(query, tcx, key, id)
             };
@@ -334,7 +330,7 @@ fn try_execute_query<'tcx, C: QueryCache, const INCR: bool>(
 
                         // If we are single-threaded we know that we have cycle error,
                         // so we just return the error.
-                        cycle_error(query, tcx, key, id, span)
+                        find_and_handle_cycle(query, tcx, key, id, span)
                     }
                 }
                 ActiveKeyStatus::Poisoned => FatalError.raise(),
@@ -418,27 +414,23 @@ fn execute_job_incr<'tcx, C: QueryCache>(
     query: &'tcx QueryVTable<'tcx, C>,
     tcx: TyCtxt<'tcx>,
     key: C::Key,
-    mut dep_node_opt: Option<DepNode>,
+    dep_node: DepNode,
     job_id: QueryJobId,
 ) -> (C::Value, DepNodeIndex) {
     let dep_graph_data =
         tcx.dep_graph.data().expect("should always be present in incremental mode");
 
-    if !query.anon && !query.eval_always {
-        // `to_dep_node` is expensive for some `DepKind`s.
-        let dep_node =
-            dep_node_opt.get_or_insert_with(|| DepNode::construct(tcx, query.dep_kind, &key));
-
+    if !query.eval_always {
         // The diagnostics for this query will be promoted to the current session during
         // `try_mark_green()`, so we can ignore them here.
         if let Some(ret) = start_query(job_id, false, || try {
-            let (prev_index, dep_node_index) = dep_graph_data.try_mark_green(tcx, dep_node)?;
+            let (prev_index, dep_node_index) = dep_graph_data.try_mark_green(tcx, &dep_node)?;
             let value = load_from_disk_or_invoke_provider_green(
                 tcx,
                 dep_graph_data,
                 query,
                 key,
-                dep_node,
+                &dep_node,
                 prev_index,
                 dep_node_index,
             );
@@ -451,17 +443,6 @@ fn execute_job_incr<'tcx, C: QueryCache>(
     let prof_timer = tcx.prof.query_provider();
 
     let (result, dep_node_index) = start_query(job_id, query.depth_limit, || {
-        if query.anon {
-            // Call the query provider inside an anon task.
-            return dep_graph_data.with_anon_task_inner(tcx, query.dep_kind, || {
-                (query.invoke_provider_fn)(tcx, key)
-            });
-        }
-
-        // `to_dep_node` is expensive for some `DepKind`s.
-        let dep_node =
-            dep_node_opt.unwrap_or_else(|| DepNode::construct(tcx, query.dep_kind, &key));
-
         // Call the query provider.
         dep_graph_data.with_task(
             dep_node,
@@ -495,94 +476,62 @@ fn load_from_disk_or_invoke_provider_green<'tcx, C: QueryCache>(
 
     debug_assert!(dep_graph_data.is_index_green(prev_index));
 
-    // First we try to load the result from the on-disk cache.
-    // Some things are never cached on disk.
-    if let Some(value) = (query.try_load_from_disk_fn)(tcx, key, prev_index, dep_node_index) {
-        if std::intrinsics::unlikely(tcx.sess.opts.unstable_opts.query_dep_graph) {
-            dep_graph_data.mark_debug_loaded_from_disk(*dep_node)
-        }
+    // First try to load the result from the on-disk cache. Some things are never cached on disk.
+    let value;
+    let verify;
+    match (query.try_load_from_disk_fn)(tcx, key, prev_index, dep_node_index) {
+        Some(loaded_value) => {
+            if std::intrinsics::unlikely(tcx.sess.opts.unstable_opts.query_dep_graph) {
+                dep_graph_data.mark_debug_loaded_from_disk(*dep_node)
+            }
 
-        let prev_fingerprint = dep_graph_data.prev_value_fingerprint_of(prev_index);
-        // If `-Zincremental-verify-ich` is specified, re-hash results from
-        // the cache and make sure that they have the expected fingerprint.
+            value = loaded_value;
+
+            let prev_fingerprint = dep_graph_data.prev_value_fingerprint_of(prev_index);
+            // If `-Zincremental-verify-ich` is specified, re-hash results from
+            // the cache and make sure that they have the expected fingerprint.
+            //
+            // If not, we still seek to verify a subset of fingerprints loaded
+            // from disk. Re-hashing results is fairly expensive, so we can't
+            // currently afford to verify every hash. This subset should still
+            // give us some coverage of potential bugs.
+            verify = prev_fingerprint.split().1.as_u64().is_multiple_of(32)
+                || tcx.sess.opts.unstable_opts.incremental_verify_ich;
+        }
+        None => {
+            // We could not load a result from the on-disk cache, so recompute. The dep-graph for
+            // this computation is already in-place, so we can just call the query provider.
+            let prof_timer = tcx.prof.query_provider();
+            value = tcx.dep_graph.with_ignore(|| (query.invoke_provider_fn)(tcx, key));
+            prof_timer.finish_with_query_invocation_id(dep_node_index.into());
+
+            verify = true;
+        }
+    };
+
+    if verify {
+        // Verify that re-running the query produced a result with the expected hash.
+        // This catches bugs in query implementations, turning them into ICEs.
+        // For example, a query might sort its result by `DefId` - since `DefId`s are
+        // not stable across compilation sessions, the result could get up getting sorted
+        // in a different order when the query is re-run, even though all of the inputs
+        // (e.g. `DefPathHash` values) were green.
         //
-        // If not, we still seek to verify a subset of fingerprints loaded
-        // from disk. Re-hashing results is fairly expensive, so we can't
-        // currently afford to verify every hash. This subset should still
-        // give us some coverage of potential bugs though.
-        let try_verify = prev_fingerprint.split().1.as_u64().is_multiple_of(32);
-        if std::intrinsics::unlikely(
-            try_verify || tcx.sess.opts.unstable_opts.incremental_verify_ich,
-        ) {
-            incremental_verify_ich(
-                tcx,
-                dep_graph_data,
-                &value,
-                prev_index,
-                query.hash_value_fn,
-                query.format_value,
-            );
-        }
-
-        return value;
+        // See issue #82920 for an example of a miscompilation that would get turned into
+        // an ICE by this check
+        incremental_verify_ich(
+            tcx,
+            dep_graph_data,
+            &value,
+            prev_index,
+            query.hash_value_fn,
+            query.format_value,
+        );
     }
 
-    // We always expect to find a cached result for things that
-    // can be forced from `DepNode`.
-    debug_assert!(
-        !(query.will_cache_on_disk_for_key_fn)(tcx, key)
-            || !tcx.key_fingerprint_style(dep_node.kind).is_maybe_recoverable(),
-        "missing on-disk cache entry for {dep_node:?}"
-    );
-
-    // Sanity check for the logic in `ensure`: if the node is green and the result loadable,
-    // we should actually be able to load it.
-    debug_assert!(
-        !(query.is_loadable_from_disk_fn)(tcx, key, prev_index),
-        "missing on-disk cache entry for loadable {dep_node:?}"
-    );
-
-    // We could not load a result from the on-disk cache, so
-    // recompute.
-    let prof_timer = tcx.prof.query_provider();
-
-    // The dep-graph for this computation is already in-place.
-    // Call the query provider.
-    let value = tcx.dep_graph.with_ignore(|| (query.invoke_provider_fn)(tcx, key));
-
-    prof_timer.finish_with_query_invocation_id(dep_node_index.into());
-
-    // Verify that re-running the query produced a result with the expected hash
-    // This catches bugs in query implementations, turning them into ICEs.
-    // For example, a query might sort its result by `DefId` - since `DefId`s are
-    // not stable across compilation sessions, the result could get up getting sorted
-    // in a different order when the query is re-run, even though all of the inputs
-    // (e.g. `DefPathHash` values) were green.
-    //
-    // See issue #82920 for an example of a miscompilation that would get turned into
-    // an ICE by this check
-    incremental_verify_ich(
-        tcx,
-        dep_graph_data,
-        &value,
-        prev_index,
-        query.hash_value_fn,
-        query.format_value,
-    );
-
     value
 }
 
-/// Return value struct for [`check_if_ensure_can_skip_execution`].
-struct EnsureCanSkip {
-    /// If true, the current `tcx.ensure_ok()` or `tcx.ensure_done()` query
-    /// can return early without actually trying to execute.
-    skip_execution: bool,
-    /// A dep node that was prepared while checking whether execution can be
-    /// skipped, to be reused by execution itself if _not_ skipped.
-    dep_node: Option<DepNode>,
-}
-
 /// Checks whether a `tcx.ensure_ok()` or `tcx.ensure_done()` query call can
 /// return early without actually trying to execute.
 ///
@@ -590,23 +539,19 @@ struct EnsureCanSkip {
 /// on having the dependency graph (and in some cases a disk-cached value)
 /// from the previous incr-comp session.
 #[inline(never)]
-fn check_if_ensure_can_skip_execution<'tcx, C: QueryCache>(
+fn ensure_can_skip_execution<'tcx, C: QueryCache>(
     query: &'tcx QueryVTable<'tcx, C>,
     tcx: TyCtxt<'tcx>,
     key: C::Key,
+    dep_node: DepNode,
     ensure_mode: EnsureMode,
-) -> EnsureCanSkip {
+) -> bool {
     // Queries with `eval_always` should never skip execution.
     if query.eval_always {
-        return EnsureCanSkip { skip_execution: false, dep_node: None };
+        return false;
     }
 
-    // Ensuring an anonymous query makes no sense
-    assert!(!query.anon);
-
-    let dep_node = DepNode::construct(tcx, query.dep_kind, &key);
-
-    let serialized_dep_node_index = match tcx.dep_graph.try_mark_green(tcx, &dep_node) {
+    match tcx.dep_graph.try_mark_green(tcx, &dep_node) {
         None => {
             // A None return from `try_mark_green` means that this is either
             // a new dep node or that the dep node has already been marked red.
@@ -614,28 +559,27 @@ fn check_if_ensure_can_skip_execution<'tcx, C: QueryCache>(
             // DepNodeIndex. We must invoke the query itself. The performance cost
             // this introduces should be negligible as we'll immediately hit the
             // in-memory cache, or another query down the line will.
-            return EnsureCanSkip { skip_execution: false, dep_node: Some(dep_node) };
+            false
         }
         Some((serialized_dep_node_index, dep_node_index)) => {
             tcx.dep_graph.read_index(dep_node_index);
             tcx.prof.query_cache_hit(dep_node_index.into());
-            serialized_dep_node_index
-        }
-    };
+            match ensure_mode {
+                // In ensure-ok mode, we can skip execution for this key if the
+                // node is green. It must have succeeded in the previous
+                // session, and therefore would succeed in the current session
+                // if executed.
+                EnsureMode::Ok => true,
 
-    match ensure_mode {
-        EnsureMode::Ok => {
-            // In ensure-ok mode, we can skip execution for this key if the node
-            // is green. It must have succeeded in the previous session, and
-            // therefore would succeed in the current session if executed.
-            EnsureCanSkip { skip_execution: true, dep_node: None }
-        }
-        EnsureMode::Done => {
-            // In ensure-done mode, we can only skip execution for this key if
-            // there's a disk-cached value available to load later if needed,
-            // which guarantees the query provider will never run for this key.
-            let is_loadable = (query.is_loadable_from_disk_fn)(tcx, key, serialized_dep_node_index);
-            EnsureCanSkip { skip_execution: is_loadable, dep_node: Some(dep_node) }
+                // In ensure-done mode, we can only skip execution for this key
+                // if there's a disk-cached value available to load later if
+                // needed, which guarantees the query provider will never run
+                // for this key.
+                EnsureMode::Done => {
+                    (query.will_cache_on_disk_for_key_fn)(tcx, key)
+                        && loadable_from_disk(tcx, serialized_dep_node_index)
+                }
+            }
         }
     }
 }
@@ -649,8 +593,6 @@ pub(super) fn execute_query_non_incr_inner<'tcx, C: QueryCache>(
     span: Span,
     key: C::Key,
 ) -> C::Value {
-    debug_assert!(!tcx.dep_graph.is_fully_enabled());
-
     ensure_sufficient_stack(|| try_execute_query::<C, false>(query, tcx, span, key, None).0)
 }
 
@@ -664,48 +606,44 @@ pub(super) fn execute_query_incr_inner<'tcx, C: QueryCache>(
     key: C::Key,
     mode: QueryMode,
 ) -> Option<C::Value> {
-    debug_assert!(tcx.dep_graph.is_fully_enabled());
+    let dep_node = DepNode::construct(tcx, query.dep_kind, &key);
 
     // Check if query execution can be skipped, for `ensure_ok` or `ensure_done`.
-    // This might have the side-effect of creating a suitable DepNode, which
-    // we should reuse for execution instead of creating a new one.
-    let dep_node: Option<DepNode> = match mode {
-        QueryMode::Ensure { ensure_mode } => {
-            let EnsureCanSkip { skip_execution, dep_node } =
-                check_if_ensure_can_skip_execution(query, tcx, key, ensure_mode);
-            if skip_execution {
-                // Return early to skip execution.
-                return None;
-            }
-            dep_node
-        }
-        QueryMode::Get => None,
-    };
+    if let QueryMode::Ensure { ensure_mode } = mode
+        && ensure_can_skip_execution(query, tcx, key, dep_node, ensure_mode)
+    {
+        return None;
+    }
 
-    let (result, dep_node_index) =
-        ensure_sufficient_stack(|| try_execute_query::<C, true>(query, tcx, span, key, dep_node));
+    let (result, dep_node_index) = ensure_sufficient_stack(|| {
+        try_execute_query::<C, true>(query, tcx, span, key, Some(dep_node))
+    });
     if let Some(dep_node_index) = dep_node_index {
         tcx.dep_graph.read_index(dep_node_index)
     }
     Some(result)
 }
 
-pub(crate) fn force_query<'tcx, C: QueryCache>(
-    query: &'tcx QueryVTable<'tcx, C>,
+/// Inner implementation of [`DepKindVTable::force_from_dep_node_fn`][force_fn]
+/// for query nodes.
+///
+/// [force_fn]: rustc_middle::dep_graph::DepKindVTable::force_from_dep_node_fn
+pub(crate) fn force_query_dep_node<'tcx, C: QueryCache>(
     tcx: TyCtxt<'tcx>,
-    key: C::Key,
+    query: &'tcx QueryVTable<'tcx, C>,
     dep_node: DepNode,
-) {
-    // We may be concurrently trying both execute and force a query.
-    // Ensure that only one of them runs the query.
-    if let Some((_, index)) = query.cache.lookup(&key) {
-        tcx.prof.query_cache_hit(index.into());
-        return;
-    }
-
-    debug_assert!(!query.anon);
+) -> bool {
+    let Some(key) = C::Key::try_recover_key(tcx, &dep_node) else {
+        // We couldn't recover a key from the node's key fingerprint.
+        // Tell the caller that we couldn't force the node.
+        return false;
+    };
 
     ensure_sufficient_stack(|| {
         try_execute_query::<C, true>(query, tcx, DUMMY_SP, key, Some(dep_node))
     });
+
+    // We did manage to recover a key and force the node, though it's up to
+    // the caller to check whether the node ended up marked red or green.
+    true
 }
diff --git a/compiler/rustc_query_impl/src/from_cycle_error.rs b/compiler/rustc_query_impl/src/handle_cycle_error.rs
similarity index 92%
rename from compiler/rustc_query_impl/src/from_cycle_error.rs
rename to compiler/rustc_query_impl/src/handle_cycle_error.rs
index 0c6082e..5676669 100644
--- a/compiler/rustc_query_impl/src/from_cycle_error.rs
+++ b/compiler/rustc_query_impl/src/handle_cycle_error.rs
@@ -10,33 +10,33 @@
 use rustc_hir::def::{DefKind, Res};
 use rustc_middle::bug;
 use rustc_middle::queries::{QueryVTables, TaggedQueryKey};
-use rustc_middle::query::CycleError;
+use rustc_middle::query::Cycle;
 use rustc_middle::query::erase::erase_val;
 use rustc_middle::ty::layout::LayoutError;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::{ErrorGuaranteed, Span};
 
-use crate::job::report_cycle;
+use crate::job::create_cycle_error;
 
 pub(crate) fn specialize_query_vtables<'tcx>(vtables: &mut QueryVTables<'tcx>) {
-    vtables.fn_sig.value_from_cycle_error = |tcx, key, _, err| {
+    vtables.fn_sig.handle_cycle_error_fn = |tcx, key, _, err| {
         let guar = err.delay_as_bug();
         erase_val(fn_sig(tcx, key, guar))
     };
 
-    vtables.check_representability.value_from_cycle_error =
+    vtables.check_representability.handle_cycle_error_fn =
         |tcx, _, cycle, _err| check_representability(tcx, cycle);
 
-    vtables.check_representability_adt_ty.value_from_cycle_error =
+    vtables.check_representability_adt_ty.handle_cycle_error_fn =
         |tcx, _, cycle, _err| check_representability(tcx, cycle);
 
-    vtables.variances_of.value_from_cycle_error = |tcx, key, _, err| {
+    vtables.variances_of.handle_cycle_error_fn = |tcx, key, _, err| {
         let _guar = err.delay_as_bug();
         erase_val(variances_of(tcx, key))
     };
 
-    vtables.layout_of.value_from_cycle_error = |tcx, _, cycle, err| {
+    vtables.layout_of.handle_cycle_error_fn = |tcx, _, cycle, err| {
         let _guar = err.delay_as_bug();
         erase_val(Err(layout_of(tcx, cycle)))
     }
@@ -72,10 +72,10 @@ fn fn_sig<'tcx>(
     )))
 }
 
-fn check_representability<'tcx>(tcx: TyCtxt<'tcx>, cycle_error: CycleError<'tcx>) -> ! {
+fn check_representability<'tcx>(tcx: TyCtxt<'tcx>, cycle: Cycle<'tcx>) -> ! {
     let mut item_and_field_ids = Vec::new();
     let mut representable_ids = FxHashSet::default();
-    for frame in &cycle_error.cycle {
+    for frame in &cycle.frames {
         if let TaggedQueryKey::check_representability(def_id) = frame.tagged_key
             && tcx.def_kind(def_id) == DefKind::Field
         {
@@ -88,7 +88,7 @@ fn check_representability<'tcx>(tcx: TyCtxt<'tcx>, cycle_error: CycleError<'tcx>
             item_and_field_ids.push((item_id.expect_local(), field_id));
         }
     }
-    for frame in &cycle_error.cycle {
+    for frame in &cycle.frames {
         if let TaggedQueryKey::check_representability_adt_ty(key) = frame.tagged_key
             && let Some(adt) = key.ty_adt_def()
             && let Some(def_id) = adt.did().as_local()
@@ -127,14 +127,11 @@ fn search_for_cycle_permutation<Q, T>(
     otherwise()
 }
 
-fn layout_of<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    cycle_error: CycleError<'tcx>,
-) -> &'tcx ty::layout::LayoutError<'tcx> {
+fn layout_of<'tcx>(tcx: TyCtxt<'tcx>, cycle: Cycle<'tcx>) -> &'tcx ty::layout::LayoutError<'tcx> {
     let diag = search_for_cycle_permutation(
-        &cycle_error.cycle,
-        |cycle| {
-            if let TaggedQueryKey::layout_of(key) = cycle[0].tagged_key
+        &cycle.frames,
+        |frames| {
+            if let TaggedQueryKey::layout_of(key) = frames[0].tagged_key
                 && let ty::Coroutine(def_id, _) = key.value.kind()
                 && let Some(def_id) = def_id.as_local()
                 && let def_kind = tcx.def_kind(def_id)
@@ -158,7 +155,7 @@ fn layout_of<'tcx>(
                     tcx.def_kind_descr_article(def_kind, def_id.to_def_id()),
                     tcx.def_kind_descr(def_kind, def_id.to_def_id()),
                 );
-                for (i, frame) in cycle.iter().enumerate() {
+                for (i, frame) in frames.iter().enumerate() {
                     let TaggedQueryKey::layout_of(frame_key) = frame.tagged_key else {
                         continue;
                     };
@@ -169,7 +166,7 @@ fn layout_of<'tcx>(
                         continue;
                     };
                     let frame_span =
-                        frame.tagged_key.default_span(tcx, cycle[(i + 1) % cycle.len()].span);
+                        frame.tagged_key.default_span(tcx, frames[(i + 1) % frames.len()].span);
                     if frame_span.is_dummy() {
                         continue;
                     }
@@ -203,7 +200,7 @@ fn layout_of<'tcx>(
                 ControlFlow::Continue(())
             }
         },
-        || report_cycle(tcx, &cycle_error),
+        || create_cycle_error(tcx, &cycle),
     );
 
     let guar = diag.emit();
diff --git a/compiler/rustc_query_impl/src/job.rs b/compiler/rustc_query_impl/src/job.rs
index 213fc79..a27a6f4 100644
--- a/compiler/rustc_query_impl/src/job.rs
+++ b/compiler/rustc_query_impl/src/job.rs
@@ -7,9 +7,7 @@
 use rustc_errors::{Diag, DiagCtxtHandle};
 use rustc_hir::def::DefKind;
 use rustc_middle::queries::TaggedQueryKey;
-use rustc_middle::query::{
-    CycleError, QueryJob, QueryJobId, QueryLatch, QueryStackFrame, QueryWaiter,
-};
+use rustc_middle::query::{Cycle, QueryJob, QueryJobId, QueryLatch, QueryStackFrame, QueryWaiter};
 use rustc_middle::ty::TyCtxt;
 use rustc_span::{DUMMY_SP, Span};
 
@@ -58,29 +56,28 @@ pub(crate) fn find_cycle_in_stack<'tcx>(
     job_map: QueryJobMap<'tcx>,
     current_job: &Option<QueryJobId>,
     span: Span,
-) -> CycleError<'tcx> {
-    // Find the waitee amongst `current_job` parents
-    let mut cycle = Vec::new();
+) -> Cycle<'tcx> {
+    // Find the waitee amongst `current_job` parents.
+    let mut frames = Vec::new();
     let mut current_job = Option::clone(current_job);
 
     while let Some(job) = current_job {
         let info = &job_map.map[&job];
-        cycle.push(QueryStackFrame { span: info.job.span, tagged_key: info.tagged_key });
+        frames.push(QueryStackFrame { span: info.job.span, tagged_key: info.tagged_key });
 
         if job == id {
-            cycle.reverse();
+            frames.reverse();
 
-            // This is the end of the cycle
-            // The span entry we included was for the usage
-            // of the cycle itself, and not part of the cycle
-            // Replace it with the span which caused the cycle to form
-            cycle[0].span = span;
-            // Find out why the cycle itself was used
+            // This is the end of the cycle. The span entry we included was for
+            // the usage of the cycle itself, and not part of the cycle.
+            // Replace it with the span which caused the cycle to form.
+            frames[0].span = span;
+            // Find out why the cycle itself was used.
             let usage = try {
                 let parent = info.job.parent?;
                 QueryStackFrame { span: info.job.span, tagged_key: job_map.tagged_key_of(parent) }
             };
-            return CycleError { usage, cycle };
+            return Cycle { usage, frames };
         }
 
         current_job = info.job.parent;
@@ -319,9 +316,9 @@ struct EntryPoint {
             .map(|(span, job)| QueryStackFrame { span, tagged_key: job_map.tagged_key_of(job) });
 
         // Create the cycle error
-        let error = CycleError {
+        let error = Cycle {
             usage,
-            cycle: stack
+            frames: stack
                 .iter()
                 .map(|&(span, job)| QueryStackFrame {
                     span,
@@ -454,27 +451,27 @@ pub fn print_query_stack<'tcx>(
 
 #[inline(never)]
 #[cold]
-pub(crate) fn report_cycle<'tcx>(
+pub(crate) fn create_cycle_error<'tcx>(
     tcx: TyCtxt<'tcx>,
-    CycleError { usage, cycle: stack }: &CycleError<'tcx>,
+    Cycle { usage, frames }: &Cycle<'tcx>,
 ) -> Diag<'tcx> {
-    assert!(!stack.is_empty());
+    assert!(!frames.is_empty());
 
-    let span = stack[0].tagged_key.default_span(tcx, stack[1 % stack.len()].span);
+    let span = frames[0].tagged_key.default_span(tcx, frames[1 % frames.len()].span);
 
     let mut cycle_stack = Vec::new();
 
     use crate::error::StackCount;
-    let stack_bottom = stack[0].tagged_key.description(tcx);
-    let stack_count = if stack.len() == 1 {
+    let stack_bottom = frames[0].tagged_key.description(tcx);
+    let stack_count = if frames.len() == 1 {
         StackCount::Single { stack_bottom: stack_bottom.clone() }
     } else {
         StackCount::Multiple { stack_bottom: stack_bottom.clone() }
     };
 
-    for i in 1..stack.len() {
-        let frame = &stack[i];
-        let span = frame.tagged_key.default_span(tcx, stack[(i + 1) % stack.len()].span);
+    for i in 1..frames.len() {
+        let frame = &frames[i];
+        let span = frame.tagged_key.default_span(tcx, frames[(i + 1) % frames.len()].span);
         cycle_stack
             .push(crate::error::CycleStack { span, desc: frame.tagged_key.description(tcx) });
     }
@@ -484,12 +481,12 @@ pub(crate) fn report_cycle<'tcx>(
         usage: usage.tagged_key.description(tcx),
     });
 
-    let alias = if stack
+    let alias = if frames
         .iter()
         .all(|frame| frame.tagged_key.def_kind(tcx) == Some(DefKind::TyAlias))
     {
         Some(crate::error::Alias::Ty)
-    } else if stack.iter().all(|frame| frame.tagged_key.def_kind(tcx) == Some(DefKind::TraitAlias))
+    } else if frames.iter().all(|frame| frame.tagged_key.def_kind(tcx) == Some(DefKind::TraitAlias))
     {
         Some(crate::error::Alias::Trait)
     } else {
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 2f69082..de03b48 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -22,7 +22,7 @@
 mod dep_kind_vtables;
 mod error;
 mod execution;
-mod from_cycle_error;
+mod handle_cycle_error;
 mod job;
 mod plumbing;
 mod profiling_support;
@@ -49,10 +49,11 @@ pub fn query_system<'tcx>(
     incremental: bool,
 ) -> QuerySystem<'tcx> {
     let mut query_vtables = query_impl::make_query_vtables(incremental);
-    from_cycle_error::specialize_query_vtables(&mut query_vtables);
+    handle_cycle_error::specialize_query_vtables(&mut query_vtables);
     QuerySystem {
         arenas: Default::default(),
         query_vtables,
+        side_effects: Default::default(),
         on_disk_cache,
         local_providers,
         extern_providers,
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index b8aa125..ef4fff2 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -2,28 +2,24 @@
 
 use rustc_data_structures::unord::UnordMap;
 use rustc_hir::limit::Limit;
-use rustc_index::Idx;
 use rustc_middle::bug;
 #[expect(unused_imports, reason = "used by doc comments")]
 use rustc_middle::dep_graph::DepKindVTable;
-use rustc_middle::dep_graph::{DepKind, DepNode, DepNodeIndex, DepNodeKey, SerializedDepNodeIndex};
+use rustc_middle::dep_graph::{DepNode, DepNodeIndex, DepNodeKey, SerializedDepNodeIndex};
 use rustc_middle::query::erase::{Erasable, Erased};
-use rustc_middle::query::on_disk_cache::{
-    AbsoluteBytePos, CacheDecoder, CacheEncoder, EncodedDepNodeIndex,
-};
+use rustc_middle::query::on_disk_cache::{CacheDecoder, CacheEncoder};
 use rustc_middle::query::{QueryCache, QueryJobId, QueryMode, QueryVTable, erase};
 use rustc_middle::ty::TyCtxt;
-use rustc_middle::ty::codec::TyEncoder;
 use rustc_middle::ty::tls::{self, ImplicitCtxt};
 use rustc_serialize::{Decodable, Encodable};
 use rustc_span::DUMMY_SP;
 use rustc_span::def_id::LOCAL_CRATE;
 
 use crate::error::{QueryOverflow, QueryOverflowNote};
-use crate::execution::{all_inactive, force_query};
+use crate::execution::all_inactive;
 use crate::job::find_dep_kind_root;
 use crate::query_impl::for_each_query_vtable;
-use crate::{CollectActiveJobsKind, GetQueryVTable, collect_active_query_jobs};
+use crate::{CollectActiveJobsKind, collect_active_query_jobs};
 
 fn depth_limit_error<'tcx>(tcx: TyCtxt<'tcx>, job: QueryJobId) {
     let job_map = collect_active_query_jobs(tcx, CollectActiveJobsKind::Full);
@@ -79,13 +75,9 @@ pub(crate) fn start_query<R>(
     })
 }
 
-pub(crate) fn encode_query_values<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    encoder: &mut CacheEncoder<'_, 'tcx>,
-    query_result_index: &mut EncodedDepNodeIndex,
-) {
+pub(crate) fn encode_query_values<'tcx>(tcx: TyCtxt<'tcx>, encoder: &mut CacheEncoder<'_, 'tcx>) {
     for_each_query_vtable!(CACHE_ON_DISK, tcx, |query| {
-        encode_query_values_inner(tcx, query, encoder, query_result_index)
+        encode_query_values_inner(tcx, query, encoder)
     });
 }
 
@@ -93,7 +85,6 @@ fn encode_query_values_inner<'a, 'tcx, C, V>(
     tcx: TyCtxt<'tcx>,
     query: &'tcx QueryVTable<'tcx, C>,
     encoder: &mut CacheEncoder<'a, 'tcx>,
-    query_result_index: &mut EncodedDepNodeIndex,
 ) where
     C: QueryCache<Value = Erased<V>>,
     V: Erasable + Encodable<CacheEncoder<'a, 'tcx>>,
@@ -103,14 +94,7 @@ fn encode_query_values_inner<'a, 'tcx, C, V>(
     assert!(all_inactive(&query.state));
     query.cache.for_each(&mut |key, value, dep_node| {
         if (query.will_cache_on_disk_for_key_fn)(tcx, *key) {
-            let dep_node = SerializedDepNodeIndex::new(dep_node.index());
-
-            // Record position of the cache entry.
-            query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position())));
-
-            // Encode the type check tables with the `SerializedDepNodeIndex`
-            // as tag.
-            encoder.encode_tagged(dep_node, &erase::restore_val::<V>(*value));
+            encoder.encode_query_value::<V>(dep_node, &erase::restore_val::<V>(*value));
         }
     });
 }
@@ -151,15 +135,15 @@ fn verify_query_key_hashes_inner<'tcx, C: QueryCache>(
     });
 }
 
-/// Implementation of [`DepKindVTable::promote_from_disk_fn`] for queries.
-pub(crate) fn promote_from_disk_inner<'tcx, Q: GetQueryVTable<'tcx>>(
+/// Inner implementation of [`DepKindVTable::promote_from_disk_fn`] for queries.
+pub(crate) fn promote_from_disk_inner<'tcx, C: QueryCache>(
     tcx: TyCtxt<'tcx>,
+    query: &'tcx QueryVTable<'tcx, C>,
     dep_node: DepNode,
 ) {
-    let query = Q::query_vtable(tcx);
     debug_assert!(tcx.dep_graph.is_green(&dep_node));
 
-    let key = <Q::Cache as QueryCache>::Key::try_recover_key(tcx, &dep_node).unwrap_or_else(|| {
+    let key = C::Key::try_recover_key(tcx, &dep_node).unwrap_or_else(|| {
         panic!(
             "Failed to recover key for {dep_node:?} with key fingerprint {}",
             dep_node.key_fingerprint
@@ -214,44 +198,9 @@ pub(crate) fn try_load_from_disk<'tcx, V>(
     // details.
     let value = tcx
         .dep_graph
-        .with_query_deserialization(|| on_disk_cache.try_load_query_result(tcx, prev_index));
+        .with_query_deserialization(|| on_disk_cache.try_load_query_value(tcx, prev_index));
 
     prof_timer.finish_with_query_invocation_id(index.into());
 
     value
 }
-
-/// Implementation of [`DepKindVTable::force_from_dep_node_fn`] for queries.
-pub(crate) fn force_from_dep_node_inner<'tcx, Q: GetQueryVTable<'tcx>>(
-    tcx: TyCtxt<'tcx>,
-    dep_node: DepNode,
-    // Needed by the vtable function signature, but not used when forcing queries.
-    _prev_index: SerializedDepNodeIndex,
-) -> bool {
-    let query = Q::query_vtable(tcx);
-
-    // We must avoid ever having to call `force_from_dep_node()` for a
-    // `DepNode::codegen_unit`:
-    // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
-    // would always end up having to evaluate the first caller of the
-    // `codegen_unit` query that *is* reconstructible. This might very well be
-    // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
-    // to re-trigger calling the `codegen_unit` query with the right key. At
-    // that point we would already have re-done all the work we are trying to
-    // avoid doing in the first place.
-    // The solution is simple: Just explicitly call the `codegen_unit` query for
-    // each CGU, right after partitioning. This way `try_mark_green` will always
-    // hit the cache instead of having to go through `force_from_dep_node`.
-    // This assertion makes sure, we actually keep applying the solution above.
-    debug_assert!(
-        dep_node.kind != DepKind::codegen_unit,
-        "calling force_from_dep_node() on dep_kinds::codegen_unit"
-    );
-
-    if let Some(key) = <Q::Cache as QueryCache>::Key::try_recover_key(tcx, &dep_node) {
-        force_query(query, tcx, key, dep_node);
-        true
-    } else {
-        false
-    }
-}
diff --git a/compiler/rustc_query_impl/src/query_impl.rs b/compiler/rustc_query_impl/src/query_impl.rs
index caf4c7d..60ddf3e 100644
--- a/compiler/rustc_query_impl/src/query_impl.rs
+++ b/compiler/rustc_query_impl/src/query_impl.rs
@@ -16,12 +16,12 @@ macro_rules! define_queries {
                 fn $name:ident($K:ty) -> $V:ty
                 {
                     // Search for (QMODLIST) to find all occurrences of this query modifier list.
-                    anon: $anon:literal,
                     arena_cache: $arena_cache:literal,
                     cache_on_disk: $cache_on_disk:literal,
                     depth_limit: $depth_limit:literal,
                     eval_always: $eval_always:literal,
                     feedable: $feedable:literal,
+                    no_force: $no_force:literal,
                     no_hash: $no_hash:literal,
                     returns_error_guaranteed: $returns_error_guaranteed:literal,
                     separate_provide_extern: $separate_provide_extern:literal,
@@ -132,7 +132,6 @@ pub(crate) fn make_query_vtable<'tcx>(incremental: bool)
 
                     QueryVTable {
                         name: stringify!($name),
-                        anon: $anon,
                         eval_always: $eval_always,
                         depth_limit: $depth_limit,
                         feedable: $feedable,
@@ -166,19 +165,11 @@ pub(crate) fn make_query_vtable<'tcx>(incremental: bool)
                         #[cfg(not($cache_on_disk))]
                         try_load_from_disk_fn: |_tcx, _key, _prev_index, _index| None,
 
-                        #[cfg($cache_on_disk)]
-                        is_loadable_from_disk_fn: |tcx, key, index| -> bool {
-                            rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) &&
-                                $crate::plumbing::loadable_from_disk(tcx, index)
-                        },
-                        #[cfg(not($cache_on_disk))]
-                        is_loadable_from_disk_fn: |_tcx, _key, _index| false,
-
                         // The default just emits `err` and then aborts.
-                        // `from_cycle_error::specialize_query_vtables` overwrites this default for
-                        // certain queries.
-                        value_from_cycle_error: |_tcx, _key, _cycle, err| {
-                            $crate::from_cycle_error::default(err)
+                        // `handle_cycle_error::specialize_query_vtables` overwrites this default
+                        // for certain queries.
+                        handle_cycle_error_fn: |_tcx, _key, _cycle, err| {
+                            $crate::handle_cycle_error::default(err)
                         },
 
                         #[cfg($no_hash)]
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index d9d42cf..29b5cdb2c 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -357,6 +357,7 @@ fn build_reduced_graph_for_external_crate_res(
             | Res::SelfTyParam { .. }
             | Res::SelfTyAlias { .. }
             | Res::SelfCtor(..)
+            | Res::OpenMod(..)
             | Res::Err => bug!("unexpected resolution: {:?}", res),
         }
     }
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 45fdea8..8e150b7 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -36,7 +36,7 @@
 use rustc_span::{DUMMY_SP, Ident, Span, kw};
 
 use crate::imports::{Import, ImportKind};
-use crate::{DeclKind, IdentKey, LateDecl, Resolver, module_to_string};
+use crate::{DeclKind, IdentKey, LateDecl, Resolver, errors, module_to_string};
 
 struct UnusedImport {
     use_tree: ast::UseTree,
@@ -554,7 +554,7 @@ pub(crate) fn check_unused(&mut self, krate: &ast::Crate) {
                 UNUSED_QUALIFICATIONS,
                 unn_qua.node_id,
                 unn_qua.path_span,
-                BuiltinLintDiag::UnusedQualifications { removal_span: unn_qua.removal_span },
+                errors::UnusedQualifications { removal_span: unn_qua.removal_span },
             );
         }
 
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index f114682..97c88064 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1740,8 +1740,8 @@ pub(crate) fn unresolved_macro_suggestions(
                 Res::Def(DefKind::Macro(kinds), _) => {
                     format!("{} {}", kinds.article(), kinds.descr())
                 }
-                Res::ToolMod => {
-                    // Don't confuse the user with tool modules.
+                Res::ToolMod | Res::OpenMod(..) => {
+                    // Don't confuse the user with tool modules or open modules.
                     continue;
                 }
                 Res::Def(DefKind::Trait, _) if macro_kind == MacroKind::Derive => {
@@ -1978,7 +1978,8 @@ fn decl_description(&self, b: Decl<'_>, ident: Ident, scope: Scope<'_>) -> Strin
             let (built_in, from) = match scope {
                 Scope::StdLibPrelude | Scope::MacroUsePrelude => ("", " from prelude"),
                 Scope::ExternPreludeFlags
-                    if self.tcx.sess.opts.externs.get(ident.as_str()).is_some() =>
+                    if self.tcx.sess.opts.externs.get(ident.as_str()).is_some()
+                        || matches!(res, Res::OpenMod(..)) =>
                 {
                     ("", " passed with `--extern`")
                 }
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index 24c923d..c9dad4d 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -1583,3 +1583,108 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
         diag
     }
 }
+
+#[derive(Diagnostic)]
+#[diag("lifetime parameter `{$ident}` never used")]
+pub(crate) struct UnusedLifetime {
+    #[suggestion("elide the unused lifetime", code = "", applicability = "machine-applicable")]
+    pub deletion_span: Option<Span>,
+
+    pub ident: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag("ambiguous glob re-exports")]
+pub(crate) struct AmbiguousGlobReexports {
+    #[label("the name `{$name}` in the {$namespace} namespace is first re-exported here")]
+    pub first_reexport: Span,
+    #[label("but the name `{$name}` in the {$namespace} namespace is also re-exported here")]
+    pub duplicate_reexport: Span,
+
+    pub name: String,
+    pub namespace: String,
+}
+
+#[derive(Diagnostic)]
+#[diag("private item shadows public glob re-export")]
+pub(crate) struct HiddenGlobReexports {
+    #[note(
+        "the name `{$name}` in the {$namespace} namespace is supposed to be publicly re-exported here"
+    )]
+    pub glob_reexport: Span,
+    #[note("but the private item here shadows it")]
+    pub private_item: Span,
+
+    pub name: String,
+    pub namespace: String,
+}
+
+#[derive(Diagnostic)]
+#[diag("the item `{$ident}` is imported redundantly")]
+pub(crate) struct RedundantImport {
+    #[subdiagnostic]
+    pub subs: Vec<RedundantImportSub>,
+    pub ident: Ident,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum RedundantImportSub {
+    #[label("the item `{$ident}` is already imported here")]
+    ImportedHere {
+        #[primary_span]
+        span: Span,
+        ident: Ident,
+    },
+    #[label("the item `{$ident}` is already defined here")]
+    DefinedHere {
+        #[primary_span]
+        span: Span,
+        ident: Ident,
+    },
+    #[label("the item `{$ident}` is already imported by the extern prelude")]
+    ImportedPrelude {
+        #[primary_span]
+        span: Span,
+        ident: Ident,
+    },
+    #[label("the item `{$ident}` is already defined by the extern prelude")]
+    DefinedPrelude {
+        #[primary_span]
+        span: Span,
+        ident: Ident,
+    },
+}
+
+#[derive(Diagnostic)]
+#[diag("unnecessary qualification")]
+pub(crate) struct UnusedQualifications {
+    #[suggestion(
+        "remove the unnecessary path segments",
+        style = "verbose",
+        code = "",
+        applicability = "machine-applicable"
+    )]
+    pub removal_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(
+    "{$elided ->
+        [true] `&` without an explicit lifetime name cannot be used here
+        *[false] `'_` cannot be used here
+    }"
+)]
+pub(crate) struct AssociatedConstElidedLifetime {
+    #[suggestion(
+        "use the `'static` lifetime",
+        style = "verbose",
+        code = "{code}",
+        applicability = "machine-applicable"
+    )]
+    pub span: Span,
+
+    pub code: &'static str,
+    pub elided: bool,
+    #[note("cannot automatically infer `'static` because of other lifetimes in scope")]
+    pub lifetimes_in_scope: MultiSpan,
+}
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 7cfd5b5..1c53d5d 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -26,7 +26,7 @@
     AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingKey, CmResolver, Decl, DeclKind,
     Determinacy, Finalize, IdentKey, ImportKind, LateDecl, Module, ModuleKind, ModuleOrUniformRoot,
     ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, Scope, ScopeSet,
-    Segment, Stage, Used, errors,
+    Segment, Stage, Symbol, Used, errors,
 };
 
 #[derive(Copy, Clone)]
@@ -386,7 +386,6 @@ pub(crate) fn resolve_ident_in_lexical_scope(
     }
 
     /// Resolve an identifier in the specified set of scopes.
-    #[instrument(level = "debug", skip(self))]
     pub(crate) fn resolve_ident_in_scope_set<'r>(
         self: CmResolver<'r, 'ra, 'tcx>,
         orig_ident: Ident,
@@ -976,6 +975,14 @@ pub(crate) fn resolve_ident_in_module<'r>(
                     ignore_import,
                 )
             }
+            ModuleOrUniformRoot::OpenModule(sym) => {
+                let open_ns_name = format!("{}::{}", sym.as_str(), ident.name);
+                let ns_ident = IdentKey::with_root_ctxt(Symbol::intern(&open_ns_name));
+                match self.extern_prelude_get_flag(ns_ident, ident.span, finalize.is_some()) {
+                    Some(decl) => Ok(decl),
+                    None => Err(Determinacy::Determined),
+                }
+            }
             ModuleOrUniformRoot::ModuleAndExternPrelude(module) => self.resolve_ident_in_scope_set(
                 ident,
                 ScopeSet::ModuleAndExternPrelude(ns, module),
@@ -1366,7 +1373,7 @@ fn single_import_can_define_name<'r>(
                 &single_import.parent_scope,
                 None,
                 ignore_decl,
-                ignore_import,
+                None,
             ) {
                 Err(Determined) => continue,
                 Ok(binding)
@@ -1962,7 +1969,10 @@ fn record_segment_res<'r, 'ra, 'tcx>(
                     }
 
                     let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res);
-                    if let Some(def_id) = binding.res().module_like_def_id() {
+                    if let Res::OpenMod(sym) = binding.res() {
+                        module = Some(ModuleOrUniformRoot::OpenModule(sym));
+                        record_segment_res(self.reborrow(), finalize, res, id);
+                    } else if let Some(def_id) = binding.res().module_like_def_id() {
                         if self.mods_with_parse_errors.contains(&def_id) {
                             module_had_parse_errors = true;
                         }
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 7696b4b..6507ee3 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -6,13 +6,12 @@
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_data_structures::intern::Interned;
 use rustc_errors::codes::*;
-use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err};
+use rustc_errors::{Applicability, Diagnostic, MultiSpan, pluralize, struct_span_code_err};
 use rustc_hir::def::{self, DefKind, PartialRes};
 use rustc_hir::def_id::{DefId, LocalDefIdMap};
 use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport};
 use rustc_middle::span_bug;
 use rustc_middle::ty::Visibility;
-use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::lint::builtin::{
     AMBIGUOUS_GLOB_REEXPORTS, EXPORTED_PRIVATE_DEPENDENCIES, HIDDEN_GLOB_REEXPORTS,
     PUB_USE_OF_PRIVATE_EXTERN_CRATE, REDUNDANT_IMPORTS, UNUSED_IMPORTS,
@@ -26,9 +25,10 @@
 use crate::Namespace::{self, *};
 use crate::diagnostics::{DiagMode, Suggestion, import_candidates};
 use crate::errors::{
-    CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
-    CannotBeReexportedPrivateNS, CannotDetermineImportResolution, CannotGlobImportAllCrates,
-    ConsiderAddingMacroExport, ConsiderMarkingAsPub, ConsiderMarkingAsPubCrate,
+    self, CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS,
+    CannotBeReexportedPrivate, CannotBeReexportedPrivateNS, CannotDetermineImportResolution,
+    CannotGlobImportAllCrates, ConsiderAddingMacroExport, ConsiderMarkingAsPub,
+    ConsiderMarkingAsPubCrate,
 };
 use crate::ref_mut::CmCell;
 use crate::{
@@ -41,7 +41,7 @@
 
 /// A potential import declaration in the process of being planted into a module.
 /// Also used for lazily planting names from `--extern` flags to extern prelude.
-#[derive(Clone, Copy, Default, PartialEq)]
+#[derive(Clone, Copy, Default, PartialEq, Debug)]
 pub(crate) enum PendingDecl<'ra> {
     Ready(Option<Decl<'ra>>),
     #[default]
@@ -721,11 +721,11 @@ pub(crate) fn lint_reexports(&mut self, exported_ambiguities: FxHashSet<Decl<'ra
                         AMBIGUOUS_GLOB_REEXPORTS,
                         import.root_id,
                         import.root_span,
-                        BuiltinLintDiag::AmbiguousGlobReexports {
+                        errors::AmbiguousGlobReexports {
                             name: key.ident.name.to_string(),
                             namespace: key.ns.descr().to_string(),
-                            first_reexport_span: import.root_span,
-                            duplicate_reexport_span: amb_binding.span,
+                            first_reexport: import.root_span,
+                            duplicate_reexport: amb_binding.span,
                         },
                     );
                 }
@@ -753,11 +753,11 @@ pub(crate) fn lint_reexports(&mut self, exported_ambiguities: FxHashSet<Decl<'ra
                                 HIDDEN_GLOB_REEXPORTS,
                                 binding_id,
                                 binding.span,
-                                BuiltinLintDiag::HiddenGlobReexports {
+                                errors::HiddenGlobReexports {
                                     name: key.ident.name.to_string(),
                                     namespace: key.ns.descr().to_owned(),
-                                    glob_reexport_span: glob_decl.span,
-                                    private_item_span: binding.span,
+                                    glob_reexport: glob_decl.span,
+                                    private_item: binding.span,
                                 },
                             );
                         }
@@ -1535,11 +1535,31 @@ pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'ra>) -> boo
             let mut redundant_spans: Vec<_> = redundant_span.present_items().collect();
             redundant_spans.sort();
             redundant_spans.dedup();
-            self.lint_buffer.buffer_lint(
+            self.lint_buffer.dyn_buffer_lint(
                 REDUNDANT_IMPORTS,
                 id,
                 import.span,
-                BuiltinLintDiag::RedundantImport(redundant_spans, source),
+                move |dcx, level| {
+                    let ident = source;
+                    let subs = redundant_spans
+                        .into_iter()
+                        .map(|(span, is_imported)| match (span.is_dummy(), is_imported) {
+                            (false, true) => {
+                                errors::RedundantImportSub::ImportedHere { span, ident }
+                            }
+                            (false, false) => {
+                                errors::RedundantImportSub::DefinedHere { span, ident }
+                            }
+                            (true, true) => {
+                                errors::RedundantImportSub::ImportedPrelude { span, ident }
+                            }
+                            (true, false) => {
+                                errors::RedundantImportSub::DefinedPrelude { span, ident }
+                            }
+                        })
+                        .collect();
+                    errors::RedundantImport { subs, ident }.into_diag(dcx, level)
+                },
             );
             return true;
         }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index a484a51..b3a6fe9 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1882,13 +1882,21 @@ fn resolve_anonymous_lifetime(
                         );
                         return;
                     } else if emit_lint {
+                        let lt_span = if elided {
+                            lifetime.ident.span.shrink_to_hi()
+                        } else {
+                            lifetime.ident.span
+                        };
+                        let code = if elided { "'static " } else { "'static" };
+
                         self.r.lint_buffer.buffer_lint(
                             lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
                             node_id,
                             lifetime.ident.span,
-                            lint::BuiltinLintDiag::AssociatedConstElidedLifetime {
+                            crate::errors::AssociatedConstElidedLifetime {
                                 elided,
-                                span: lifetime.ident.span,
+                                code,
+                                span: lt_span,
                                 lifetimes_in_scope: lifetimes_in_scope.into(),
                             },
                         );
@@ -4065,7 +4073,7 @@ fn check_consistent_bindings(&mut self, pat: &'ast Pat) {
     fn resolve_arm(&mut self, arm: &'ast Arm) {
         self.with_rib(ValueNS, RibKind::Normal, |this| {
             this.resolve_pattern_top(&arm.pat, PatternSource::Match);
-            visit_opt!(this, visit_expr, &arm.guard);
+            visit_opt!(this, visit_expr, arm.guard.as_ref().map(|g| &g.cond));
             visit_opt!(this, visit_expr, &arm.body);
         });
     }
@@ -4207,7 +4215,7 @@ fn resolve_pattern_inner(
                     let subpat_bindings = bindings.pop().unwrap().1;
                     self.with_rib(ValueNS, RibKind::Normal, |this| {
                         *this.innermost_rib_bindings(ValueNS) = subpat_bindings.clone();
-                        this.resolve_expr(guard, None);
+                        this.resolve_expr(&guard.cond, None);
                     });
                     // Propagate the subpattern's bindings upwards.
                     // FIXME(guard_patterns): For `if let` guards, we'll also need to get the
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index e24389e..cf04823 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1272,7 +1272,7 @@ fn suggest_typo(
                 Some((pat_sp, Some(ty_sp), None))
                     if ty_sp.contains(base_error.span) && base_error.could_be_expr =>
                 {
-                    err.span_suggestion_short(
+                    err.span_suggestion_verbose(
                         pat_sp.between(ty_sp),
                         "use `=` if you meant to assign",
                         " = ",
@@ -3381,7 +3381,7 @@ pub(crate) fn detect_and_suggest_const_parameter_error(
             && def_id.is_local()
             && let Some(local_def_id) = def_id.as_local()
             && let Some(struct_generics) = self.r.struct_generics.get(&local_def_id)
-            && let target_param = &struct_generics.params[idx]
+            && let Some(target_param) = &struct_generics.params.get(idx)
             && let GenericParamKind::Const { ty, .. } = &target_param.kind
             && let TyKind::Path(_, path) = &ty.kind
         {
@@ -3653,7 +3653,8 @@ pub(crate) fn maybe_report_lifetime_uses(
                         param.ident.span,
                         lint::BuiltinLintDiag::SingleUseLifetime {
                             param_span: param.ident.span,
-                            use_span: Some((use_span, elidable)),
+                            use_span,
+                            elidable,
                             deletion_span,
                             ident: param.ident,
                         },
@@ -3669,12 +3670,7 @@ pub(crate) fn maybe_report_lifetime_uses(
                             lint::builtin::UNUSED_LIFETIMES,
                             param.id,
                             param.ident.span,
-                            lint::BuiltinLintDiag::SingleUseLifetime {
-                                param_span: param.ident.span,
-                                use_span: None,
-                                deletion_span,
-                                ident: param.ident,
-                            },
+                            errors::UnusedLifetime { deletion_span, ident: param.ident },
                         );
                     }
                 }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 27d4182..72d5cdc 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -61,6 +61,7 @@
 use rustc_hir::{PrimTy, TraitCandidate, find_attr};
 use rustc_index::bit_set::DenseBitSet;
 use rustc_metadata::creader::CStore;
+use rustc_middle::bug;
 use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport};
 use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::query::Providers;
@@ -445,6 +446,11 @@ enum ModuleOrUniformRoot<'ra> {
     /// Used only for resolving single-segment imports. The reason it exists is that import paths
     /// are always split into two parts, the first of which should be some kind of module.
     CurrentScope,
+
+    /// Virtual module for the resolution of base names of namespaced crates,
+    /// where the base name doesn't correspond to a module in the extern prelude.
+    /// E.g. `my_api::utils` is in the prelude, but `my_api` is not.
+    OpenModule(Symbol),
 }
 
 #[derive(Debug)]
@@ -541,6 +547,13 @@ fn name(&self) -> Option<Symbol> {
             ModuleKind::Def(.., name) => name,
         }
     }
+
+    fn opt_def_id(&self) -> Option<DefId> {
+        match self {
+            ModuleKind::Def(_, def_id, _) => Some(*def_id),
+            _ => None,
+        }
+    }
 }
 
 /// Combination of a symbol and its macros 2.0 normalized hygiene context.
@@ -778,10 +791,7 @@ fn def_id(self) -> DefId {
     }
 
     fn opt_def_id(self) -> Option<DefId> {
-        match self.kind {
-            ModuleKind::Def(_, def_id, _) => Some(def_id),
-            _ => None,
-        }
+        self.kind.opt_def_id()
     }
 
     // `self` resolves to the first module ancestor that `is_normal`.
@@ -1105,13 +1115,20 @@ fn determined(&self) -> bool {
     }
 }
 
+#[derive(Debug)]
 struct ExternPreludeEntry<'ra> {
     /// Name declaration from an `extern crate` item.
     /// The boolean flag is true is `item_decl` is non-redundant, happens either when
     /// `flag_decl` is `None`, or when `extern crate` introducing `item_decl` used renaming.
     item_decl: Option<(Decl<'ra>, Span, /* introduced by item */ bool)>,
     /// Name declaration from an `--extern` flag, lazily populated on first use.
-    flag_decl: Option<CacheCell<(PendingDecl<'ra>, /* finalized */ bool)>>,
+    flag_decl: Option<
+        CacheCell<(
+            PendingDecl<'ra>,
+            /* finalized */ bool,
+            /* open flag (namespaced crate) */ bool,
+        )>,
+    >,
 }
 
 impl ExternPreludeEntry<'_> {
@@ -1122,7 +1139,14 @@ fn introduced_by_item(&self) -> bool {
     fn flag() -> Self {
         ExternPreludeEntry {
             item_decl: None,
-            flag_decl: Some(CacheCell::new((PendingDecl::Pending, false))),
+            flag_decl: Some(CacheCell::new((PendingDecl::Pending, false, false))),
+        }
+    }
+
+    fn open_flag() -> Self {
+        ExternPreludeEntry {
+            item_decl: None,
+            flag_decl: Some(CacheCell::new((PendingDecl::Pending, false, true))),
         }
     }
 
@@ -1430,14 +1454,19 @@ fn new_module(
         &'ra self,
         parent: Option<Module<'ra>>,
         kind: ModuleKind,
+        vis: Visibility<DefId>,
         expn_id: ExpnId,
         span: Span,
         no_implicit_prelude: bool,
     ) -> Module<'ra> {
         let self_decl = match kind {
-            ModuleKind::Def(def_kind, def_id, _) => {
-                Some(self.new_pub_def_decl(Res::Def(def_kind, def_id), span, LocalExpnId::ROOT))
-            }
+            ModuleKind::Def(def_kind, def_id, _) => Some(self.new_def_decl(
+                Res::Def(def_kind, def_id),
+                vis,
+                span,
+                LocalExpnId::ROOT,
+                None,
+            )),
             ModuleKind::Block => None,
         };
         Module(Interned::new_unchecked(self.modules.alloc(ModuleData::new(
@@ -1619,6 +1648,7 @@ pub fn new(
         let graph_root = arenas.new_module(
             None,
             ModuleKind::Def(DefKind::Mod, root_def_id, None),
+            Visibility::Public,
             ExpnId::root(),
             crate_span,
             attr::contains_name(attrs, sym::no_implicit_prelude),
@@ -1628,6 +1658,7 @@ pub fn new(
         let empty_module = arenas.new_module(
             None,
             ModuleKind::Def(DefKind::Mod, root_def_id, None),
+            Visibility::Public,
             ExpnId::root(),
             DUMMY_SP,
             true,
@@ -1643,35 +1674,7 @@ pub fn new(
         let mut invocation_parents = FxHashMap::default();
         invocation_parents.insert(LocalExpnId::ROOT, InvocationParent::ROOT);
 
-        let mut extern_prelude: FxIndexMap<_, _> = tcx
-            .sess
-            .opts
-            .externs
-            .iter()
-            .filter_map(|(name, entry)| {
-                // Make sure `self`, `super`, `_` etc do not get into extern prelude.
-                // FIXME: reject `--extern self` and similar in option parsing instead.
-                if entry.add_prelude
-                    && let name = Symbol::intern(name)
-                    && name.can_be_raw()
-                {
-                    let ident = IdentKey::with_root_ctxt(name);
-                    Some((ident, ExternPreludeEntry::flag()))
-                } else {
-                    None
-                }
-            })
-            .collect();
-
-        if !attr::contains_name(attrs, sym::no_core) {
-            let ident = IdentKey::with_root_ctxt(sym::core);
-            extern_prelude.insert(ident, ExternPreludeEntry::flag());
-            if !attr::contains_name(attrs, sym::no_std) {
-                let ident = IdentKey::with_root_ctxt(sym::std);
-                extern_prelude.insert(ident, ExternPreludeEntry::flag());
-            }
-        }
-
+        let extern_prelude = build_extern_prelude(tcx, attrs);
         let registered_tools = tcx.registered_tools(());
         let edition = tcx.sess.edition();
 
@@ -1757,7 +1760,9 @@ fn new_local_module(
         span: Span,
         no_implicit_prelude: bool,
     ) -> Module<'ra> {
-        let module = self.arenas.new_module(parent, kind, expn_id, span, no_implicit_prelude);
+        let vis =
+            kind.opt_def_id().map_or(Visibility::Public, |def_id| self.tcx.visibility(def_id));
+        let module = self.arenas.new_module(parent, kind, vis, expn_id, span, no_implicit_prelude);
         self.local_modules.push(module);
         if let Some(def_id) = module.opt_def_id() {
             self.local_module_map.insert(def_id.expect_local(), module);
@@ -1773,7 +1778,9 @@ fn new_extern_module(
         span: Span,
         no_implicit_prelude: bool,
     ) -> Module<'ra> {
-        let module = self.arenas.new_module(parent, kind, expn_id, span, no_implicit_prelude);
+        let vis =
+            kind.opt_def_id().map_or(Visibility::Public, |def_id| self.tcx.visibility(def_id));
+        let module = self.arenas.new_module(parent, kind, vis, expn_id, span, no_implicit_prelude);
         self.extern_module_map.borrow_mut().insert(module.def_id(), module);
         module
     }
@@ -2326,10 +2333,10 @@ fn extern_prelude_get_flag(
     ) -> Option<Decl<'ra>> {
         let entry = self.extern_prelude.get(&ident);
         entry.and_then(|entry| entry.flag_decl.as_ref()).and_then(|flag_decl| {
-            let (pending_decl, finalized) = flag_decl.get();
+            let (pending_decl, finalized, is_open) = flag_decl.get();
             let decl = match pending_decl {
                 PendingDecl::Ready(decl) => {
-                    if finalize && !finalized {
+                    if finalize && !finalized && !is_open {
                         self.cstore_mut().process_path_extern(
                             self.tcx,
                             ident.name,
@@ -2340,18 +2347,28 @@ fn extern_prelude_get_flag(
                 }
                 PendingDecl::Pending => {
                     debug_assert!(!finalized);
-                    let crate_id = if finalize {
-                        self.cstore_mut().process_path_extern(self.tcx, ident.name, orig_ident_span)
+                    if is_open {
+                        let res = Res::OpenMod(ident.name);
+                        Some(self.arenas.new_pub_def_decl(res, DUMMY_SP, LocalExpnId::ROOT))
                     } else {
-                        self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)
-                    };
-                    crate_id.map(|crate_id| {
-                        let res = Res::Def(DefKind::Mod, crate_id.as_def_id());
-                        self.arenas.new_pub_def_decl(res, DUMMY_SP, LocalExpnId::ROOT)
-                    })
+                        let crate_id = if finalize {
+                            self.cstore_mut().process_path_extern(
+                                self.tcx,
+                                ident.name,
+                                orig_ident_span,
+                            )
+                        } else {
+                            self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)
+                        };
+                        crate_id.map(|crate_id| {
+                            let def_id = crate_id.as_def_id();
+                            let res = Res::Def(DefKind::Mod, def_id);
+                            self.arenas.new_pub_def_decl(res, DUMMY_SP, LocalExpnId::ROOT)
+                        })
+                    }
                 }
             };
-            flag_decl.set((PendingDecl::Ready(decl), finalize || finalized));
+            flag_decl.set((PendingDecl::Ready(decl), finalize || finalized, is_open));
             decl.or_else(|| finalize.then_some(self.dummy_decl))
         })
     }
@@ -2393,7 +2410,9 @@ fn resolve_rustdoc_path(
             PathResult::Module(ModuleOrUniformRoot::ExternPrelude) | PathResult::Failed { .. } => {
                 None
             }
-            PathResult::Module(..) | PathResult::Indeterminate => unreachable!(),
+            path_result @ (PathResult::Module(..) | PathResult::Indeterminate) => {
+                bug!("got invalid path_result: {path_result:?}")
+            }
         }
     }
 
@@ -2511,6 +2530,60 @@ fn resolve_main(&mut self) {
     }
 }
 
+fn build_extern_prelude<'tcx, 'ra>(
+    tcx: TyCtxt<'tcx>,
+    attrs: &[ast::Attribute],
+) -> FxIndexMap<IdentKey, ExternPreludeEntry<'ra>> {
+    let mut extern_prelude: FxIndexMap<IdentKey, ExternPreludeEntry<'ra>> = tcx
+        .sess
+        .opts
+        .externs
+        .iter()
+        .filter_map(|(name, entry)| {
+            // Make sure `self`, `super`, `_` etc do not get into extern prelude.
+            // FIXME: reject `--extern self` and similar in option parsing instead.
+            if entry.add_prelude
+                && let sym = Symbol::intern(name)
+                && sym.can_be_raw()
+            {
+                Some((IdentKey::with_root_ctxt(sym), ExternPreludeEntry::flag()))
+            } else {
+                None
+            }
+        })
+        .collect();
+
+    // Add open base entries for namespaced crates whose base segment
+    // is missing from the prelude (e.g. `foo::bar` without `foo`).
+    // These are necessary in order to resolve the open modules, whereas
+    // the namespaced names are necessary in `extern_prelude` for actually
+    // resolving the namespaced crates.
+    let missing_open_bases: Vec<IdentKey> = extern_prelude
+        .keys()
+        .filter_map(|ident| {
+            let (base, _) = ident.name.as_str().split_once("::")?;
+            let base_sym = Symbol::intern(base);
+            base_sym.can_be_raw().then(|| IdentKey::with_root_ctxt(base_sym))
+        })
+        .filter(|base_ident| !extern_prelude.contains_key(base_ident))
+        .collect();
+
+    extern_prelude.extend(
+        missing_open_bases.into_iter().map(|ident| (ident, ExternPreludeEntry::open_flag())),
+    );
+
+    // Inject `core` / `std` unless suppressed by attributes.
+    if !attr::contains_name(attrs, sym::no_core) {
+        extern_prelude.insert(IdentKey::with_root_ctxt(sym::core), ExternPreludeEntry::flag());
+
+        if !attr::contains_name(attrs, sym::no_std) {
+            extern_prelude.insert(IdentKey::with_root_ctxt(sym::std), ExternPreludeEntry::flag());
+        }
+    }
+
+    extern_prelude
+}
+
 fn names_to_string(names: impl Iterator<Item = Symbol>) -> String {
     let mut result = String::new();
     for (i, name) in names.enumerate().filter(|(_, name)| *name != kw::PathRoot) {
diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs
index ebbbe36..a7b54e6 100644
--- a/compiler/rustc_session/src/config/cfg.rs
+++ b/compiler/rustc_session/src/config/cfg.rs
@@ -229,6 +229,10 @@ macro_rules! ins_sym {
         if s == SanitizerSet::KERNELADDRESS {
             s = SanitizerSet::ADDRESS;
         }
+        // KHWASAN is still HWASAN under the hood, so it uses the same attribute.
+        if s == SanitizerSet::KERNELHWADDRESS {
+            s = SanitizerSet::HWADDRESS;
+        }
         ins_str!(sym::sanitize, &s.to_string());
     }
 
@@ -239,7 +243,7 @@ macro_rules! ins_sym {
         ins_none!(sym::sanitizer_cfi_normalize_integers);
     }
 
-    ins_sym!(sym::target_abi, sess.target.abi.desc_symbol());
+    ins_sym!(sym::target_abi, sess.target.cfg_abi.desc_symbol());
     ins_sym!(sym::target_arch, sess.target.arch.desc_symbol());
     ins_str!(sym::target_endian, sess.target.endian.as_str());
     ins_sym!(sym::target_env, sess.target.env.desc_symbol());
@@ -447,7 +451,7 @@ macro_rules! ins {
                 };
 
                 for target in Target::builtins().chain(iter::once(current_target.clone())) {
-                    values_target_abi.insert(target.options.abi.desc_symbol());
+                    values_target_abi.insert(target.options.cfg_abi.desc_symbol());
                     values_target_arch.insert(target.arch.desc_symbol());
                     values_target_endian.insert(Symbol::intern(target.options.endian.as_str()));
                     values_target_env.insert(target.options.env.desc_symbol());
diff --git a/compiler/rustc_session/src/config/externs.rs b/compiler/rustc_session/src/config/externs.rs
index d668d8b..ff76eaa 100644
--- a/compiler/rustc_session/src/config/externs.rs
+++ b/compiler/rustc_session/src/config/externs.rs
@@ -43,6 +43,13 @@ pub(crate) fn split_extern_opt<'a>(
         }
     };
 
+    // Reject paths with more than two segments.
+    if unstable_opts.namespaced_crates && crate_name.split("::").count() > 2 {
+        return Err(early_dcx.early_struct_fatal(format!(
+            "crate name `{crate_name}` passed to `--extern` can have at most two segments."
+        )));
+    }
+
     if !valid_crate_name(&crate_name, unstable_opts) {
         let mut error = early_dcx.early_struct_fatal(format!(
             "crate name `{crate_name}` passed to `--extern` is not a valid ASCII identifier"
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index fb1b3c8..7abaae1 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -106,6 +106,7 @@ pub(super) fn sanitizer(l: &TargetModifier, r: Option<&TargetModifier>) -> bool
             | SanitizerSet::SHADOWCALLSTACK
             | SanitizerSet::KCFI
             | SanitizerSet::KERNELADDRESS
+            | SanitizerSet::KERNELHWADDRESS
             | SanitizerSet::SAFESTACK
             | SanitizerSet::DATAFLOW;
 
@@ -817,7 +818,7 @@ mod desc {
     pub(crate) const parse_patchable_function_entry: &str = "either two comma separated integers (total_nops,prefix_nops), with prefix_nops <= total_nops, or one integer (total_nops)";
     pub(crate) const parse_opt_panic_strategy: &str = parse_panic_strategy;
     pub(crate) const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
-    pub(crate) const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread`, or 'realtime'";
+    pub(crate) const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `kernel-hwaddress`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread`, or 'realtime'";
     pub(crate) const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2";
     pub(crate) const parse_cfguard: &str =
         "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
@@ -1265,6 +1266,7 @@ pub(crate) fn parse_sanitizers(slot: &mut SanitizerSet, v: Option<&str>) -> bool
                     "dataflow" => SanitizerSet::DATAFLOW,
                     "kcfi" => SanitizerSet::KCFI,
                     "kernel-address" => SanitizerSet::KERNELADDRESS,
+                    "kernel-hwaddress" => SanitizerSet::KERNELHWADDRESS,
                     "leak" => SanitizerSet::LEAK,
                     "memory" => SanitizerSet::MEMORY,
                     "memtag" => SanitizerSet::MEMTAG,
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 2b15202..a8210f2 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -7,12 +7,12 @@
 use rustc_ast::attr::AttrIdGenerator;
 use rustc_ast::node_id::NodeId;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
-use rustc_data_structures::sync::{AppendOnlyVec, Lock};
+use rustc_data_structures::sync::{AppendOnlyVec, DynSend, Lock};
 use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter;
 use rustc_errors::emitter::{EmitterWithNote, stderr_destination};
 use rustc_errors::{
     BufferedEarlyLint, ColorConfig, DecorateDiagCompat, Diag, DiagCtxt, DiagCtxtHandle,
-    DiagMessage, EmissionGuarantee, MultiSpan, StashKey,
+    DiagMessage, EmissionGuarantee, Level, MultiSpan, StashKey,
 };
 use rustc_feature::{GateIssue, UnstableFeatures, find_feature_issue};
 use rustc_span::edition::Edition;
@@ -331,6 +331,23 @@ pub fn buffer_lint(
         self.opt_span_buffer_lint(lint, Some(span.into()), node_id, diagnostic.into())
     }
 
+    pub fn dyn_buffer_lint<
+        F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSend + 'static,
+    >(
+        &self,
+        lint: &'static Lint,
+        span: impl Into<MultiSpan>,
+        node_id: NodeId,
+        callback: F,
+    ) {
+        self.opt_span_buffer_lint(
+            lint,
+            Some(span.into()),
+            node_id,
+            DecorateDiagCompat::Dynamic(Box::new(callback)),
+        )
+    }
+
     pub(crate) fn opt_span_buffer_lint(
         &self,
         lint: &'static Lint,
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index fece46d..53eae0d 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -533,9 +533,12 @@ pub fn needs_plt(&self) -> bool {
     pub fn emit_lifetime_markers(&self) -> bool {
         self.opts.optimize != config::OptLevel::No
         // AddressSanitizer and KernelAddressSanitizer uses lifetimes to detect use after scope bugs.
+        //
         // MemorySanitizer uses lifetimes to detect use of uninitialized stack variables.
-        // HWAddressSanitizer will use lifetimes to detect use after scope bugs in the future.
-        || self.sanitizers().intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS)
+        //
+        // HWAddressSanitizer and KernelHWAddressSanitizer will use lifetimes to detect use after
+        // scope bugs in the future.
+        || self.sanitizers().intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS | SanitizerSet::KERNELHWADDRESS)
     }
 
     pub fn diagnostic_width(&self) -> usize {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 738c9b9..d3e25c2 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1028,6 +1028,7 @@
         global_registration,
         globs,
         gt,
+        guard,
         guard_patterns,
         half_open_range_patterns,
         half_open_range_patterns_in_slices,
@@ -1116,6 +1117,7 @@
         iterator_collect_fn,
         kcfi,
         kernel_address,
+        kernel_hwaddress,
         keylocker_x86,
         keyword,
         kind,
@@ -1192,6 +1194,7 @@
         macro_derive,
         macro_escape,
         macro_export,
+        macro_guard_matcher,
         macro_lifetime_matcher,
         macro_literal_matcher,
         macro_metavar_expr,
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index 27dd0b7..643eeaa 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -5,7 +5,7 @@
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_span::Symbol;
 
-use crate::spec::{Abi, Arch, RelocModel, Target};
+use crate::spec::{Arch, CfgAbi, RelocModel, Target};
 
 pub struct ModifierInfo {
     pub modifier: char,
@@ -1001,7 +1001,7 @@ pub fn parse(
                 _ => Err(&["C", "system", "efiapi"]),
             },
             InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => match name {
-                "C" | "system" => Ok(if target.abi == Abi::Spe {
+                "C" | "system" => Ok(if target.cfg_abi == CfgAbi::Spe {
                     InlineAsmClobberAbi::PowerPCSPE
                 } else {
                     InlineAsmClobberAbi::PowerPC
diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs
index fd0e118..a09b93c 100644
--- a/compiler/rustc_target/src/asm/powerpc.rs
+++ b/compiler/rustc_target/src/asm/powerpc.rs
@@ -4,7 +4,7 @@
 use rustc_span::Symbol;
 
 use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
-use crate::spec::{Abi, RelocModel, Target};
+use crate::spec::{CfgAbi, RelocModel, Target};
 
 def_reg_class! {
     PowerPC PowerPCInlineAsmRegClass {
@@ -105,9 +105,9 @@ fn reserved_v20to31(
     _is_clobber: bool,
 ) -> Result<(), &'static str> {
     if target.is_like_aix {
-        match &target.options.abi {
-            Abi::VecDefault => Err("v20-v31 (vs52-vs63) are reserved on vec-default ABI"),
-            Abi::VecExtAbi => Ok(()),
+        match &target.options.cfg_abi {
+            CfgAbi::VecDefault => Err("v20-v31 (vs52-vs63) are reserved on vec-default ABI"),
+            CfgAbi::VecExtAbi => Ok(()),
             abi => unreachable!("unrecognized AIX ABI: {abi}"),
         }
     } else {
@@ -122,7 +122,11 @@ fn spe_acc_target_check(
     target: &Target,
     _is_clobber: bool,
 ) -> Result<(), &'static str> {
-    if target.abi == Abi::Spe { Ok(()) } else { Err("spe_acc is only available on spe targets") }
+    if target.cfg_abi == CfgAbi::Spe {
+        Ok(())
+    } else {
+        Err("spe_acc is only available on spe targets")
+    }
 }
 
 def_regs! {
diff --git a/compiler/rustc_target/src/callconv/loongarch.rs b/compiler/rustc_target/src/callconv/loongarch.rs
index 054e9a0..6d3826a 100644
--- a/compiler/rustc_target/src/callconv/loongarch.rs
+++ b/compiler/rustc_target/src/callconv/loongarch.rs
@@ -4,7 +4,7 @@
 };
 
 use crate::callconv::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Uniform};
-use crate::spec::HasTargetSpec;
+use crate::spec::{HasTargetSpec, LlvmAbi};
 
 #[derive(Copy, Clone)]
 enum RegPassKind {
@@ -415,9 +415,9 @@ pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
     C: HasDataLayout + HasTargetSpec,
 {
     let xlen = cx.data_layout().pointer_size().bits();
-    let flen = match &cx.target_spec().llvm_abiname[..] {
-        "ilp32f" | "lp64f" => 32,
-        "ilp32d" | "lp64d" => 64,
+    let flen = match &cx.target_spec().llvm_abiname {
+        LlvmAbi::Ilp32f | LlvmAbi::Lp64f => 32,
+        LlvmAbi::Ilp32d | LlvmAbi::Lp64d => 64,
         _ => 0,
     };
 
diff --git a/compiler/rustc_target/src/callconv/powerpc64.rs b/compiler/rustc_target/src/callconv/powerpc64.rs
index 683b615..d807617 100644
--- a/compiler/rustc_target/src/callconv/powerpc64.rs
+++ b/compiler/rustc_target/src/callconv/powerpc64.rs
@@ -5,7 +5,7 @@
 use rustc_abi::{Endian, HasDataLayout, TyAbiInterface};
 
 use crate::callconv::{Align, ArgAbi, FnAbi, Reg, RegKind, Uniform};
-use crate::spec::{HasTargetSpec, Os};
+use crate::spec::{HasTargetSpec, LlvmAbi, Os};
 
 #[derive(Debug, Clone, Copy, PartialEq)]
 enum ABI {
@@ -106,9 +106,9 @@ pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout + HasTargetSpec,
 {
-    let abi = if cx.target_spec().options.llvm_abiname == "elfv2" {
+    let abi = if cx.target_spec().options.llvm_abiname == LlvmAbi::ElfV2 {
         ELFv2
-    } else if cx.target_spec().options.llvm_abiname == "elfv1" {
+    } else if cx.target_spec().options.llvm_abiname == LlvmAbi::ElfV1 {
         ELFv1
     } else if cx.target_spec().os == Os::Aix {
         AIX
diff --git a/compiler/rustc_target/src/callconv/riscv.rs b/compiler/rustc_target/src/callconv/riscv.rs
index 18efdc5..bc81ec9 100644
--- a/compiler/rustc_target/src/callconv/riscv.rs
+++ b/compiler/rustc_target/src/callconv/riscv.rs
@@ -10,7 +10,7 @@
 };
 
 use crate::callconv::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Uniform};
-use crate::spec::HasTargetSpec;
+use crate::spec::{HasTargetSpec, LlvmAbi};
 
 #[derive(Copy, Clone)]
 enum RegPassKind {
@@ -419,9 +419,9 @@ pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout + HasTargetSpec,
 {
-    let flen = match &cx.target_spec().llvm_abiname[..] {
-        "ilp32f" | "lp64f" => 32,
-        "ilp32d" | "lp64d" => 64,
+    let flen = match &cx.target_spec().llvm_abiname {
+        LlvmAbi::Ilp32f | LlvmAbi::Lp64f => 32,
+        LlvmAbi::Ilp32d | LlvmAbi::Lp64d => 64,
         _ => 0,
     };
     let xlen = cx.data_layout().pointer_size().bits();
diff --git a/compiler/rustc_target/src/spec/base/aix.rs b/compiler/rustc_target/src/spec/base/aix.rs
index 76e8fb7..41cf3e0 100644
--- a/compiler/rustc_target/src/spec/base/aix.rs
+++ b/compiler/rustc_target/src/spec/base/aix.rs
@@ -1,13 +1,13 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Abi, BinaryFormat, Cc, CodeModel, LinkOutputKind, LinkerFlavor, Os, TargetOptions, crt_objects,
-    cvs,
+    BinaryFormat, Cc, CfgAbi, CodeModel, LinkOutputKind, LinkerFlavor, Os, TargetOptions,
+    crt_objects, cvs,
 };
 
 pub(crate) fn opts() -> TargetOptions {
     TargetOptions {
-        abi: Abi::VecExtAbi,
+        cfg_abi: CfgAbi::VecExtAbi,
         code_model: Some(CodeModel::Large),
         cpu: "pwr7".into(),
         os: Os::Aix,
diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs
index 18b41d1..d1d91cb 100644
--- a/compiler/rustc_target/src/spec/base/apple/mod.rs
+++ b/compiler/rustc_target/src/spec/base/apple/mod.rs
@@ -4,7 +4,7 @@
 use std::str::FromStr;
 
 use crate::spec::{
-    Abi, BinaryFormat, Cc, DebuginfoKind, Env, FloatAbi, FramePointer, LinkerFlavor, Lld, Os,
+    BinaryFormat, Cc, CfgAbi, DebuginfoKind, Env, FloatAbi, FramePointer, LinkerFlavor, Lld, Os,
     RustcAbi, SplitDebuginfo, StackProbeType, StaticCow, Target, TargetOptions, cvs,
 };
 
@@ -108,11 +108,11 @@ fn target_env(self) -> Env {
     //
     // But let's continue setting them for backwards compatibility.
     // FIXME(madsmtm): Warn about using these in the future.
-    fn target_abi(self) -> Abi {
+    fn target_abi(self) -> CfgAbi {
         match self {
-            Self::Normal => Abi::Unspecified,
-            Self::MacCatalyst => Abi::MacAbi,
-            Self::Simulator => Abi::Sim,
+            Self::Normal => CfgAbi::Unspecified,
+            Self::MacCatalyst => CfgAbi::MacAbi,
+            Self::Simulator => CfgAbi::Sim,
         }
     }
 }
@@ -135,7 +135,7 @@ pub(crate) fn base(
         },
         os,
         env: env.target_env(),
-        abi: env.target_abi(),
+        cfg_abi: env.target_abi(),
         cpu: arch.target_cpu(env).into(),
         link_env_remove,
         vendor: "apple".into(),
diff --git a/compiler/rustc_target/src/spec/base/apple/tests.rs b/compiler/rustc_target/src/spec/base/apple/tests.rs
index fd3fd6d..f178698 100644
--- a/compiler/rustc_target/src/spec/base/apple/tests.rs
+++ b/compiler/rustc_target/src/spec/base/apple/tests.rs
@@ -4,7 +4,7 @@
     aarch64_apple_watchos_sim, i686_apple_darwin, x86_64_apple_darwin, x86_64_apple_ios,
     x86_64_apple_tvos, x86_64_apple_watchos_sim,
 };
-use crate::spec::{Abi, Env};
+use crate::spec::{CfgAbi, Env};
 
 #[test]
 fn simulator_targets_set_env() {
@@ -21,7 +21,7 @@ fn simulator_targets_set_env() {
     for target in &all_sim_targets {
         assert_eq!(target.env, Env::Sim);
         // Ensure backwards compat
-        assert_eq!(target.abi, Abi::Sim);
+        assert_eq!(target.cfg_abi, CfgAbi::Sim);
     }
 }
 
diff --git a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs
index 3bd8ebd..1a69c8e 100644
--- a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs
@@ -2,7 +2,7 @@
 
 use crate::spec::crt_objects::pre_mingw_self_contained;
 use crate::spec::{
-    Abi, BinaryFormat, Cc, DebuginfoKind, Env, LinkSelfContainedDefault, LinkerFlavor, Lld, Os,
+    BinaryFormat, Cc, CfgAbi, DebuginfoKind, Env, LinkSelfContainedDefault, LinkerFlavor, Lld, Os,
     SplitDebuginfo, TargetOptions, add_link_args, cvs,
 };
 
@@ -26,7 +26,7 @@ pub(crate) fn opts() -> TargetOptions {
         os: Os::Windows,
         env: Env::Gnu,
         vendor: "pc".into(),
-        abi: Abi::Llvm,
+        cfg_abi: CfgAbi::Llvm,
         linker: Some("clang".into()),
         dynamic_linking: true,
         dll_tls_export: false,
diff --git a/compiler/rustc_target/src/spec/base/windows_uwp_gnu.rs b/compiler/rustc_target/src/spec/base/windows_uwp_gnu.rs
index 0f009ff..d1adc89 100644
--- a/compiler/rustc_target/src/spec/base/windows_uwp_gnu.rs
+++ b/compiler/rustc_target/src/spec/base/windows_uwp_gnu.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Cc, LinkArgs, LinkerFlavor, Lld, TargetOptions, add_link_args, base};
+use crate::spec::{Cc, CfgAbi, LinkArgs, LinkerFlavor, Lld, TargetOptions, add_link_args, base};
 
 pub(crate) fn opts() -> TargetOptions {
     let base = base::windows_gnu::opts();
@@ -23,7 +23,7 @@ pub(crate) fn opts() -> TargetOptions {
     let late_link_args_static = LinkArgs::new();
 
     TargetOptions {
-        abi: Abi::Uwp,
+        cfg_abi: CfgAbi::Uwp,
         vendor: "uwp".into(),
         limit_rdylib_exports: false,
         late_link_args,
diff --git a/compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs b/compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs
index 1583298..b9b2f42 100644
--- a/compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs
+++ b/compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs
@@ -1,8 +1,8 @@
-use crate::spec::{Abi, LinkerFlavor, Lld, TargetOptions, base};
+use crate::spec::{CfgAbi, LinkerFlavor, Lld, TargetOptions, base};
 
 pub(crate) fn opts() -> TargetOptions {
     let mut opts =
-        TargetOptions { abi: Abi::Uwp, vendor: "uwp".into(), ..base::windows_msvc::opts() };
+        TargetOptions { cfg_abi: CfgAbi::Uwp, vendor: "uwp".into(), ..base::windows_msvc::opts() };
 
     opts.add_pre_link_args(LinkerFlavor::Msvc(Lld::No), &["/APPCONTAINER", "mincore.lib"]);
 
diff --git a/compiler/rustc_target/src/spec/json.rs b/compiler/rustc_target/src/spec/json.rs
index d8ef248..5507af0 100644
--- a/compiler/rustc_target/src/spec/json.rs
+++ b/compiler/rustc_target/src/spec/json.rs
@@ -5,14 +5,14 @@
 
 use super::crt_objects::CrtObjects;
 use super::{
-    Abi, Arch, BinaryFormat, CodeModel, DebuginfoKind, Env, FloatAbi, FramePointer, LinkArgsCli,
+    Arch, BinaryFormat, CfgAbi, CodeModel, DebuginfoKind, Env, FloatAbi, FramePointer, LinkArgsCli,
     LinkSelfContainedComponents, LinkSelfContainedDefault, LinkerFlavorCli, LldFlavor,
     MergeFunctions, Os, PanicStrategy, RelocModel, RelroLevel, RustcAbi, SanitizerSet,
     SmallDataThresholdSupport, SplitDebuginfo, StackProbeType, StaticCow, SymbolVisibility, Target,
     TargetKind, TargetOptions, TargetWarnings, TlsModel,
 };
 use crate::json::{Json, ToJson};
-use crate::spec::AbiMap;
+use crate::spec::{AbiMap, LlvmAbi};
 
 impl Target {
     /// Loads a target descriptor from a JSON object.
@@ -69,7 +69,9 @@ macro_rules! forward_opt {
         forward_opt!(c_enum_min_bits); // if None, matches c_int_width
         forward!(os);
         forward!(env);
-        forward!(abi);
+        if let Some(abi) = json.abi {
+            base.cfg_abi = abi;
+        }
         forward!(vendor);
         forward_opt!(linker);
         forward!(linker_flavor_json);
@@ -297,7 +299,7 @@ macro_rules! target_option_val {
         target_option_val!(c_int_width, "target-c-int-width");
         target_option_val!(os);
         target_option_val!(env);
-        target_option_val!(abi);
+        target_option_val!(cfg_abi, "abi");
         target_option_val!(vendor);
         target_option_val!(linker);
         target_option_val!(linker_flavor_json, "linker-flavor");
@@ -505,7 +507,7 @@ struct TargetSpecJson {
     c_enum_min_bits: Option<u64>,
     os: Option<Os>,
     env: Option<Env>,
-    abi: Option<Abi>,
+    abi: Option<CfgAbi>,
     vendor: Option<StaticCow<str>>,
     linker: Option<StaticCow<str>>,
     #[serde(rename = "linker-flavor")]
@@ -609,7 +611,7 @@ struct TargetSpecJson {
     #[serde(rename = "target-mcount")]
     mcount: Option<StaticCow<str>>,
     llvm_mcount_intrinsic: Option<StaticCow<str>>,
-    llvm_abiname: Option<StaticCow<str>>,
+    llvm_abiname: Option<LlvmAbi>,
     llvm_floatabi: Option<FloatAbi>,
     rustc_abi: Option<RustcAbi>,
     relax_elf_relocations: Option<bool>,
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 8683e4f..266290b 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1175,9 +1175,10 @@ impl SanitizerSet: u16 {
         const SHADOWCALLSTACK = 1 << 7;
         const KCFI    = 1 << 8;
         const KERNELADDRESS = 1 << 9;
-        const SAFESTACK = 1 << 10;
-        const DATAFLOW = 1 << 11;
-        const REALTIME = 1 << 12;
+        const KERNELHWADDRESS = 1 << 10;
+        const SAFESTACK = 1 << 11;
+        const DATAFLOW = 1 << 12;
+        const REALTIME = 1 << 13;
     }
 }
 rustc_data_structures::external_bitflags_debug! { SanitizerSet }
@@ -1191,24 +1192,32 @@ impl SanitizerSet {
         (SanitizerSet::ADDRESS, SanitizerSet::HWADDRESS),
         (SanitizerSet::ADDRESS, SanitizerSet::MEMTAG),
         (SanitizerSet::ADDRESS, SanitizerSet::KERNELADDRESS),
+        (SanitizerSet::ADDRESS, SanitizerSet::KERNELHWADDRESS),
         (SanitizerSet::ADDRESS, SanitizerSet::SAFESTACK),
         (SanitizerSet::LEAK, SanitizerSet::MEMORY),
         (SanitizerSet::LEAK, SanitizerSet::THREAD),
         (SanitizerSet::LEAK, SanitizerSet::KERNELADDRESS),
+        (SanitizerSet::LEAK, SanitizerSet::KERNELHWADDRESS),
         (SanitizerSet::LEAK, SanitizerSet::SAFESTACK),
         (SanitizerSet::MEMORY, SanitizerSet::THREAD),
         (SanitizerSet::MEMORY, SanitizerSet::HWADDRESS),
         (SanitizerSet::MEMORY, SanitizerSet::KERNELADDRESS),
+        (SanitizerSet::MEMORY, SanitizerSet::KERNELHWADDRESS),
         (SanitizerSet::MEMORY, SanitizerSet::SAFESTACK),
         (SanitizerSet::THREAD, SanitizerSet::HWADDRESS),
         (SanitizerSet::THREAD, SanitizerSet::KERNELADDRESS),
+        (SanitizerSet::THREAD, SanitizerSet::KERNELHWADDRESS),
         (SanitizerSet::THREAD, SanitizerSet::SAFESTACK),
         (SanitizerSet::HWADDRESS, SanitizerSet::MEMTAG),
         (SanitizerSet::HWADDRESS, SanitizerSet::KERNELADDRESS),
+        (SanitizerSet::HWADDRESS, SanitizerSet::KERNELHWADDRESS),
         (SanitizerSet::HWADDRESS, SanitizerSet::SAFESTACK),
         (SanitizerSet::CFI, SanitizerSet::KCFI),
         (SanitizerSet::MEMTAG, SanitizerSet::KERNELADDRESS),
+        (SanitizerSet::MEMTAG, SanitizerSet::KERNELHWADDRESS),
+        (SanitizerSet::KERNELADDRESS, SanitizerSet::KERNELHWADDRESS),
         (SanitizerSet::KERNELADDRESS, SanitizerSet::SAFESTACK),
+        (SanitizerSet::KERNELHWADDRESS, SanitizerSet::SAFESTACK),
     ];
 
     /// Return sanitizer's name
@@ -1221,6 +1230,7 @@ pub fn as_str(self) -> Option<&'static str> {
             SanitizerSet::DATAFLOW => "dataflow",
             SanitizerSet::KCFI => "kcfi",
             SanitizerSet::KERNELADDRESS => "kernel-address",
+            SanitizerSet::KERNELHWADDRESS => "kernel-hwaddress",
             SanitizerSet::LEAK => "leak",
             SanitizerSet::MEMORY => "memory",
             SanitizerSet::MEMTAG => "memtag",
@@ -1266,6 +1276,7 @@ fn from_str(s: &str) -> Result<Self, Self::Err> {
             "dataflow" => SanitizerSet::DATAFLOW,
             "kcfi" => SanitizerSet::KCFI,
             "kernel-address" => SanitizerSet::KERNELADDRESS,
+            "kernel-hwaddress" => SanitizerSet::KERNELHWADDRESS,
             "leak" => SanitizerSet::LEAK,
             "memory" => SanitizerSet::MEMORY,
             "memtag" => SanitizerSet::MEMTAG,
@@ -2065,7 +2076,10 @@ pub fn desc_symbol(&self) -> Symbol {
 }
 
 crate::target_spec_enum! {
-    pub enum Abi {
+    /// An enum representing possible values for `cfg(target_abi)`.
+    /// This field is not forwarded to LLVM so it does not by itself affect codegen.
+    /// See the `cfg_abi` field of [`TargetOptions`] for more details.
+    pub enum CfgAbi {
         Abi64 = "abi64",
         AbiV2 = "abiv2",
         AbiV2Hf = "abiv2hf",
@@ -2090,12 +2104,40 @@ pub enum Abi {
     other_variant = Other;
 }
 
-impl Abi {
+impl CfgAbi {
     pub fn desc_symbol(&self) -> Symbol {
         Symbol::intern(self.desc())
     }
 }
 
+crate::target_spec_enum! {
+    /// An enum representing possible values for the `llvm_abiname` field of [`TargetOptions`].
+    /// This field is used by LLVM on some targets to control which ABI to use.
+    pub enum LlvmAbi {
+        // RISC-V and LoongArch
+        Ilp32 = "ilp32",
+        Ilp32f = "ilp32f",
+        Ilp32d = "ilp32d",
+        Ilp32e = "ilp32e",
+        Ilp32s = "ilp32s",
+        Lp64 = "lp64",
+        Lp64f = "lp64f",
+        Lp64d = "lp64d",
+        Lp64e = "lp64e",
+        Lp64s = "lp64s",
+        // MIPS
+        O32 = "o32",
+        N32 = "n32",
+        N64 = "n64",
+        // PowerPC
+        ElfV1 = "elfv1",
+        ElfV2 = "elfv2",
+
+        Unspecified = "",
+    }
+    other_variant = Other;
+}
+
 /// Everything `rustc` knows about how to compile for a specific target.
 ///
 /// Every field here must be specified, and has no default value.
@@ -2221,13 +2263,18 @@ pub struct TargetOptions {
     pub os: Os,
     /// Environment name to use for conditional compilation (`target_env`). Defaults to [`Env::Unspecified`].
     pub env: Env,
-    /// ABI name to distinguish multiple ABIs on the same OS and architecture. For instance, `"eabi"`
-    /// or `"eabihf"`. Defaults to [`Abi::Unspecified`].
-    /// This field is *not* forwarded directly to LLVM and therefore does not control which ABI (in
-    /// the sense of function calling convention) is actually used; its primary purpose is
-    /// `cfg(target_abi)`. The actual calling convention is controlled by `llvm_abiname`,
-    /// `llvm_floatabi`, and `rustc_abi`.
-    pub abi: Abi,
+    /// ABI name to distinguish multiple ABIs on the same OS and architecture. For instance,
+    /// `"eabi"` or `"eabihf"`. Defaults to [`CfgAbi::Unspecified`].
+    /// The only purpose of this field is to control `cfg(target_abi)`. This does not control the
+    /// calling convention used by this target! The actual calling convention is controlled by
+    /// `llvm_abiname`, `llvm_floatabi`, and `rustc_abi`.
+    ///
+    /// In a target spec, this field generally *informs* the user about what the ABI is, but you
+    /// have to also set up other parts of the target spec to ensure that this information is
+    /// correct. In the rest of the compiler, do not check this field if what you actually need to
+    /// know about is the calling convention. Most targets have an open-ended set of values for this
+    /// field.
+    pub cfg_abi: CfgAbi,
     /// Vendor name to use for conditional compilation (`target_vendor`). Defaults to "unknown".
     #[rustc_lint_opt_deny_field_access(
         "use `Target::is_like_*` instead of this field; see https://github.com/rust-lang/rust/issues/100343 for rationale"
@@ -2537,7 +2584,7 @@ pub struct TargetOptions {
 
     /// LLVM ABI name, corresponds to the '-mabi' parameter available in multilib C compilers
     /// and the `-target-abi` flag in llc. In the LLVM API this is `MCOptions.ABIName`.
-    pub llvm_abiname: StaticCow<str>,
+    pub llvm_abiname: LlvmAbi,
 
     /// Control the float ABI to use, for architectures that support it. The only architecture we
     /// currently use this for is ARM. Corresponds to the `-float-abi` flag in llc. In the LLVM API
@@ -2550,7 +2597,6 @@ pub struct TargetOptions {
     /// Picks a specific ABI for this target. This is *not* just for "Rust" ABI functions,
     /// it can also affect "C" ABI functions; the point is that this flag is interpreted by
     /// rustc and not forwarded to LLVM.
-    /// So far, this is only used on x86.
     pub rustc_abi: Option<RustcAbi>,
 
     /// Whether or not RelaxElfRelocation flag will be passed to the linker
@@ -2739,7 +2785,7 @@ fn default() -> TargetOptions {
             c_int_width: 32,
             os: Os::None,
             env: Env::Unspecified,
-            abi: Abi::Unspecified,
+            cfg_abi: CfgAbi::Unspecified,
             vendor: "unknown".into(),
             linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
             linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
@@ -2835,7 +2881,7 @@ fn default() -> TargetOptions {
             merge_functions: MergeFunctions::Aliases,
             mcount: "mcount".into(),
             llvm_mcount_intrinsic: None,
-            llvm_abiname: "".into(),
+            llvm_abiname: LlvmAbi::Unspecified,
             llvm_floatabi: None,
             rustc_abi: None,
             relax_elf_relocations: false,
@@ -3183,71 +3229,106 @@ macro_rules! check_matches {
             );
         }
 
+        // Ensure built-in targets don't use the `Other` variants.
+        if kind == TargetKind::Builtin {
+            check!(
+                !matches!(self.arch, Arch::Other(_)),
+                "`Arch::Other` is only meant for JSON targets"
+            );
+            check!(!matches!(self.os, Os::Other(_)), "`Os::Other` is only meant for JSON targets");
+            check!(
+                !matches!(self.env, Env::Other(_)),
+                "`Env::Other` is only meant for JSON targets"
+            );
+            check!(
+                !matches!(self.cfg_abi, CfgAbi::Other(_)),
+                "`CfgAbi::Other` is only meant for JSON targets"
+            );
+            check!(
+                !matches!(self.llvm_abiname, LlvmAbi::Other(_)),
+                "`LlvmAbi::Other` is only meant for JSON targets"
+            );
+        }
+
         // Check ABI flag consistency, for the architectures where we have proper ABI treatment.
         // To ensure targets are trated consistently, please consult with the team before allowing
         // new cases.
         match self.arch {
             Arch::X86 => {
-                check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on x86-32");
+                check!(
+                    self.llvm_abiname == LlvmAbi::Unspecified,
+                    "`llvm_abiname` is unused on x86-32"
+                );
                 check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on x86-32");
                 check_matches!(
-                    (&self.rustc_abi, &self.abi),
+                    (&self.rustc_abi, &self.cfg_abi),
                     // FIXME: we do not currently set a target_abi for softfloat targets here,
                     // but we probably should, so we already allow it.
-                    (Some(RustcAbi::Softfloat), Abi::SoftFloat | Abi::Unspecified | Abi::Other(_))
-                        | (
-                            Some(RustcAbi::X86Sse2) | None,
-                            Abi::Uwp | Abi::Llvm | Abi::Sim | Abi::Unspecified | Abi::Other(_)
-                        ),
+                    (
+                        Some(RustcAbi::Softfloat),
+                        CfgAbi::SoftFloat | CfgAbi::Unspecified | CfgAbi::Other(_)
+                    ) | (
+                        Some(RustcAbi::X86Sse2) | None,
+                        CfgAbi::Uwp
+                            | CfgAbi::Llvm
+                            | CfgAbi::Sim
+                            | CfgAbi::Unspecified
+                            | CfgAbi::Other(_)
+                    ),
                     "invalid x86-32 Rust-specific ABI and `cfg(target_abi)` combination:\n\
                     Rust-specific ABI: {:?}\n\
                     cfg(target_abi): {}",
                     self.rustc_abi,
-                    self.abi,
+                    self.cfg_abi,
                 );
             }
             Arch::X86_64 => {
-                check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on x86-64");
+                check!(
+                    self.llvm_abiname == LlvmAbi::Unspecified,
+                    "`llvm_abiname` is unused on x86-64"
+                );
                 check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on x86-64");
                 // FIXME: we do not currently set a target_abi for softfloat targets here, but we
                 // probably should, so we already allow it.
                 // FIXME: Ensure that target_abi = "x32" correlates with actually using that ABI.
                 // Do any of the others need a similar check?
                 check_matches!(
-                    (&self.rustc_abi, &self.abi),
-                    (Some(RustcAbi::Softfloat), Abi::SoftFloat | Abi::Unspecified | Abi::Other(_))
-                        | (
-                            None,
-                            Abi::X32
-                                | Abi::Llvm
-                                | Abi::Fortanix
-                                | Abi::Uwp
-                                | Abi::MacAbi
-                                | Abi::Sim
-                                | Abi::Unspecified
-                                | Abi::Other(_)
-                        ),
+                    (&self.rustc_abi, &self.cfg_abi),
+                    (
+                        Some(RustcAbi::Softfloat),
+                        CfgAbi::SoftFloat | CfgAbi::Unspecified | CfgAbi::Other(_)
+                    ) | (
+                        None,
+                        CfgAbi::X32
+                            | CfgAbi::Llvm
+                            | CfgAbi::Fortanix
+                            | CfgAbi::Uwp
+                            | CfgAbi::MacAbi
+                            | CfgAbi::Sim
+                            | CfgAbi::Unspecified
+                            | CfgAbi::Other(_)
+                    ),
                     "invalid x86-64 Rust-specific ABI and `cfg(target_abi)` combination:\n\
                     Rust-specific ABI: {:?}\n\
                     cfg(target_abi): {}",
                     self.rustc_abi,
-                    self.abi,
+                    self.cfg_abi,
                 );
             }
             Arch::RiscV32 => {
                 check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on RISC-V");
                 check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on RISC-V");
                 check_matches!(
-                    (&*self.llvm_abiname, &self.abi),
-                    ("ilp32", Abi::Unspecified | Abi::Other(_))
-                        | ("ilp32f", Abi::Unspecified | Abi::Other(_))
-                        | ("ilp32d", Abi::Unspecified | Abi::Other(_))
-                        | ("ilp32e", Abi::Ilp32e),
+                    (&self.llvm_abiname, &self.cfg_abi),
+                    (LlvmAbi::Ilp32, CfgAbi::Unspecified | CfgAbi::Other(_))
+                        | (LlvmAbi::Ilp32f, CfgAbi::Unspecified | CfgAbi::Other(_))
+                        | (LlvmAbi::Ilp32d, CfgAbi::Unspecified | CfgAbi::Other(_))
+                        | (LlvmAbi::Ilp32e, CfgAbi::Ilp32e),
                     "invalid RISC-V ABI name and `cfg(target_abi)` combination:\n\
                      ABI name: {}\n\
                      cfg(target_abi): {}",
                     self.llvm_abiname,
-                    self.abi,
+                    self.cfg_abi,
                 );
             }
             Arch::RiscV64 => {
@@ -3255,68 +3336,77 @@ macro_rules! check_matches {
                 check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on RISC-V");
                 check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on RISC-V");
                 check_matches!(
-                    (&*self.llvm_abiname, &self.abi),
-                    ("lp64", Abi::Unspecified | Abi::Other(_))
-                        | ("lp64f", Abi::Unspecified | Abi::Other(_))
-                        | ("lp64d", Abi::Unspecified | Abi::Other(_))
-                        | ("lp64e", Abi::Unspecified | Abi::Other(_)),
+                    (&self.llvm_abiname, &self.cfg_abi),
+                    (LlvmAbi::Lp64, CfgAbi::Unspecified | CfgAbi::Other(_))
+                        | (LlvmAbi::Lp64f, CfgAbi::Unspecified | CfgAbi::Other(_))
+                        | (LlvmAbi::Lp64d, CfgAbi::Unspecified | CfgAbi::Other(_))
+                        | (LlvmAbi::Lp64e, CfgAbi::Unspecified | CfgAbi::Other(_)),
                     "invalid RISC-V ABI name and `cfg(target_abi)` combination:\n\
                      ABI name: {}\n\
                      cfg(target_abi): {}",
                     self.llvm_abiname,
-                    self.abi,
+                    self.cfg_abi,
                 );
             }
             Arch::Arm => {
-                check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on ARM");
+                check!(
+                    self.llvm_abiname == LlvmAbi::Unspecified,
+                    "`llvm_abiname` is unused on ARM"
+                );
                 check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on ARM");
                 check_matches!(
-                    (&self.llvm_floatabi, &self.abi),
+                    (&self.llvm_floatabi, &self.cfg_abi),
                     (
                         Some(FloatAbi::Hard),
-                        Abi::EabiHf | Abi::Uwp | Abi::Unspecified | Abi::Other(_)
-                    ) | (Some(FloatAbi::Soft), Abi::Eabi),
+                        CfgAbi::EabiHf | CfgAbi::Uwp | CfgAbi::Unspecified | CfgAbi::Other(_)
+                    ) | (Some(FloatAbi::Soft), CfgAbi::Eabi),
                     "Invalid combination of float ABI and `cfg(target_abi)` for ARM target\n\
                      float ABI: {:?}\n\
                      cfg(target_abi): {}",
                     self.llvm_floatabi,
-                    self.abi,
+                    self.cfg_abi,
                 )
             }
             Arch::AArch64 => {
-                check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on aarch64");
+                check!(
+                    self.llvm_abiname == LlvmAbi::Unspecified,
+                    "`llvm_abiname` is unused on aarch64"
+                );
                 check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on aarch64");
                 // FIXME: Ensure that target_abi = "ilp32" correlates with actually using that ABI.
                 // Do any of the others need a similar check?
                 check_matches!(
-                    (&self.rustc_abi, &self.abi),
-                    (Some(RustcAbi::Softfloat), Abi::SoftFloat)
+                    (&self.rustc_abi, &self.cfg_abi),
+                    (Some(RustcAbi::Softfloat), CfgAbi::SoftFloat)
                         | (
                             None,
-                            Abi::Ilp32
-                                | Abi::Llvm
-                                | Abi::MacAbi
-                                | Abi::Sim
-                                | Abi::Uwp
-                                | Abi::Unspecified
-                                | Abi::Other(_)
+                            CfgAbi::Ilp32
+                                | CfgAbi::Llvm
+                                | CfgAbi::MacAbi
+                                | CfgAbi::Sim
+                                | CfgAbi::Uwp
+                                | CfgAbi::Unspecified
+                                | CfgAbi::Other(_)
                         ),
                     "invalid aarch64 Rust-specific ABI and `cfg(target_abi)` combination:\n\
                     Rust-specific ABI: {:?}\n\
                     cfg(target_abi): {}",
                     self.rustc_abi,
-                    self.abi,
+                    self.cfg_abi,
                 );
             }
             Arch::PowerPC => {
-                check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on PowerPC");
+                check!(
+                    self.llvm_abiname == LlvmAbi::Unspecified,
+                    "`llvm_abiname` is unused on PowerPC"
+                );
                 check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on PowerPC");
                 check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on PowerPC");
                 // FIXME: Check that `target_abi` matches the actually configured ABI (with or
                 // without SPE).
                 check_matches!(
-                    self.abi,
-                    Abi::Spe | Abi::Unspecified | Abi::Other(_),
+                    self.cfg_abi,
+                    CfgAbi::Spe | CfgAbi::Unspecified | CfgAbi::Other(_),
                     "invalid `target_abi` for PowerPC"
                 );
             }
@@ -3328,116 +3418,123 @@ macro_rules! check_matches {
                     // FIXME: Check that `target_abi` matches the actually configured ABI
                     // (vec-default vs vec-ext).
                     check_matches!(
-                        (&*self.llvm_abiname, &self.abi),
-                        ("", Abi::VecDefault | Abi::VecExtAbi),
+                        (&self.llvm_abiname, &self.cfg_abi),
+                        (LlvmAbi::Unspecified, CfgAbi::VecDefault | CfgAbi::VecExtAbi),
                         "invalid PowerPC64 AIX ABI name and `cfg(target_abi)` combination:\n\
                         ABI name: {}\n\
                         cfg(target_abi): {}",
                         self.llvm_abiname,
-                        self.abi,
+                        self.cfg_abi,
                     );
                 } else if self.endian == Endian::Big {
                     check_matches!(
-                        (&*self.llvm_abiname, &self.abi),
-                        ("elfv1", Abi::ElfV1) | ("elfv2", Abi::ElfV2),
+                        (&self.llvm_abiname, &self.cfg_abi),
+                        (LlvmAbi::ElfV1, CfgAbi::ElfV1) | (LlvmAbi::ElfV2, CfgAbi::ElfV2),
                         "invalid PowerPC64 big-endian ABI name and `cfg(target_abi)` combination:\n\
                         ABI name: {}\n\
                         cfg(target_abi): {}",
                         self.llvm_abiname,
-                        self.abi,
+                        self.cfg_abi,
                     );
                 } else {
                     check_matches!(
-                        (&*self.llvm_abiname, &self.abi),
-                        ("elfv2", Abi::ElfV2),
+                        (&self.llvm_abiname, &self.cfg_abi),
+                        (LlvmAbi::ElfV2, CfgAbi::ElfV2),
                         "invalid PowerPC64 little-endian ABI name and `cfg(target_abi)` combination:\n\
                         ABI name: {}\n\
                         cfg(target_abi): {}",
                         self.llvm_abiname,
-                        self.abi,
+                        self.cfg_abi,
                     );
                 }
             }
             Arch::S390x => {
-                check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on s390x");
+                check!(
+                    self.llvm_abiname == LlvmAbi::Unspecified,
+                    "`llvm_abiname` is unused on s390x"
+                );
                 check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on s390x");
                 check_matches!(
-                    (&self.rustc_abi, &self.abi),
-                    (Some(RustcAbi::Softfloat), Abi::SoftFloat)
-                        | (None, Abi::Unspecified | Abi::Other(_)),
+                    (&self.rustc_abi, &self.cfg_abi),
+                    (Some(RustcAbi::Softfloat), CfgAbi::SoftFloat)
+                        | (None, CfgAbi::Unspecified | CfgAbi::Other(_)),
                     "invalid s390x Rust-specific ABI and `cfg(target_abi)` combination:\n\
                     Rust-specific ABI: {:?}\n\
                     cfg(target_abi): {}",
                     self.rustc_abi,
-                    self.abi,
+                    self.cfg_abi,
                 );
             }
             Arch::LoongArch32 => {
                 check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on LoongArch");
                 check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on LoongArch");
                 check_matches!(
-                    (&*self.llvm_abiname, &self.abi),
-                    ("ilp32s", Abi::SoftFloat)
-                        | ("ilp32f", Abi::Unspecified | Abi::Other(_))
-                        | ("ilp32d", Abi::Unspecified | Abi::Other(_)),
+                    (&self.llvm_abiname, &self.cfg_abi),
+                    (LlvmAbi::Ilp32s, CfgAbi::SoftFloat)
+                        | (LlvmAbi::Ilp32f, CfgAbi::Unspecified | CfgAbi::Other(_))
+                        | (LlvmAbi::Ilp32d, CfgAbi::Unspecified | CfgAbi::Other(_)),
                     "invalid LoongArch ABI name and `cfg(target_abi)` combination:\n\
                      ABI name: {}\n\
                      cfg(target_abi): {}",
                     self.llvm_abiname,
-                    self.abi,
+                    self.cfg_abi,
                 );
             }
             Arch::LoongArch64 => {
                 check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on LoongArch");
                 check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on LoongArch");
                 check_matches!(
-                    (&*self.llvm_abiname, &self.abi),
-                    ("lp64s", Abi::SoftFloat)
-                        | ("lp64f", Abi::Unspecified | Abi::Other(_))
-                        | ("lp64d", Abi::Unspecified | Abi::Other(_)),
+                    (&self.llvm_abiname, &self.cfg_abi),
+                    (LlvmAbi::Lp64s, CfgAbi::SoftFloat)
+                        | (LlvmAbi::Lp64f, CfgAbi::Unspecified | CfgAbi::Other(_))
+                        | (LlvmAbi::Lp64d, CfgAbi::Unspecified | CfgAbi::Other(_)),
                     "invalid LoongArch ABI name and `cfg(target_abi)` combination:\n\
                      ABI name: {}\n\
                      cfg(target_abi): {}",
                     self.llvm_abiname,
-                    self.abi,
+                    self.cfg_abi,
                 );
             }
             Arch::Mips | Arch::Mips32r6 => {
                 check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on MIPS");
                 check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on MIPS");
                 check_matches!(
-                    (&*self.llvm_abiname, &self.abi),
-                    ("o32", Abi::Unspecified | Abi::Other(_)),
+                    (&self.llvm_abiname, &self.cfg_abi),
+                    (LlvmAbi::O32, CfgAbi::Unspecified | CfgAbi::Other(_)),
                     "invalid MIPS ABI name and `cfg(target_abi)` combination:\n\
                      ABI name: {}\n\
                      cfg(target_abi): {}",
                     self.llvm_abiname,
-                    self.abi,
+                    self.cfg_abi,
                 );
             }
             Arch::Mips64 | Arch::Mips64r6 => {
                 check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on MIPS");
                 check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on MIPS");
                 check_matches!(
-                    (&*self.llvm_abiname, &self.abi),
+                    (&self.llvm_abiname, &self.cfg_abi),
                     // No in-tree targets use "n32" but at least for now we let out-of-tree targets
                     // experiment with that.
-                    ("n64", Abi::Abi64) | ("n32", Abi::Unspecified | Abi::Other(_)),
+                    (LlvmAbi::N64, CfgAbi::Abi64)
+                        | (LlvmAbi::N32, CfgAbi::Unspecified | CfgAbi::Other(_)),
                     "invalid MIPS ABI name and `cfg(target_abi)` combination:\n\
                      ABI name: {}\n\
                      cfg(target_abi): {}",
                     self.llvm_abiname,
-                    self.abi,
+                    self.cfg_abi,
                 );
             }
             Arch::CSky => {
-                check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on CSky");
+                check!(
+                    self.llvm_abiname == LlvmAbi::Unspecified,
+                    "`llvm_abiname` is unused on CSky"
+                );
                 check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on CSky");
                 check!(self.rustc_abi.is_none(), "`rustc_abi` is unused on CSky");
                 // FIXME: Check that `target_abi` matches the actually configured ABI (v2 vs v2hf).
                 check_matches!(
-                    self.abi,
-                    Abi::AbiV2 | Abi::AbiV2Hf,
+                    self.cfg_abi,
+                    CfgAbi::AbiV2 | CfgAbi::AbiV2Hf,
                     "invalid `target_abi` for CSky"
                 );
             }
@@ -3446,11 +3543,14 @@ macro_rules! check_matches {
                 // Ensure consistency among built-in targets, but give JSON targets the opportunity
                 // to experiment with these.
                 if kind == TargetKind::Builtin {
-                    check!(self.llvm_abiname.is_empty(), "`llvm_abiname` is unused on {arch}");
+                    check!(
+                        self.llvm_abiname == LlvmAbi::Unspecified,
+                        "`llvm_abiname` is unused on {arch}"
+                    );
                     check!(self.llvm_floatabi.is_none(), "`llvm_floatabi` is unused on {arch}");
                     check_matches!(
-                        self.abi,
-                        Abi::Unspecified | Abi::Other(_),
+                        self.cfg_abi,
+                        CfgAbi::Unspecified | CfgAbi::Other(_),
                         "`target_abi` is unused on {arch}"
                     );
                 }
@@ -3665,7 +3765,7 @@ pub fn object_architecture(
                 // it using a custom target specification. N32
                 // is an ILP32 ABI like the Aarch64_Ilp32
                 // and X86_64_X32 cases above and below this one.
-                if self.options.llvm_abiname.as_ref() == "n32" {
+                if self.options.llvm_abiname == LlvmAbi::N32 {
                     Architecture::Mips64_N32
                 } else {
                     Architecture::Mips64
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 4abd555..8a432ca 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
@@ -1,7 +1,7 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Abi, Arch, FramePointer, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+    Arch, CfgAbi, FramePointer, StackProbeType, Target, TargetMetadata, TargetOptions, base,
 };
 
 pub(crate) fn target() -> Target {
@@ -20,7 +20,7 @@ pub(crate) fn target() -> Target {
         data_layout: "E-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: Arch::AArch64,
         options: TargetOptions {
-            abi: Abi::Ilp32,
+            cfg_abi: CfgAbi::Ilp32,
             features: "+v8a,+outline-atomics".into(),
             // the AAPCS64 expects use of non-leaf frame pointers per
             // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs
index e204c64..77a57f9 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs
@@ -8,13 +8,13 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, RustcAbi, SanitizerSet,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, RustcAbi, SanitizerSet,
     StackProbeType, Target, TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
     let opts = TargetOptions {
-        abi: Abi::SoftFloat,
+        cfg_abi: CfgAbi::SoftFloat,
         rustc_abi: Some(RustcAbi::Softfloat),
         linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
         linker: Some("rust-lld".into()),
@@ -22,7 +22,9 @@ pub(crate) fn target() -> Target {
         relocation_model: RelocModel::Static,
         disable_redzone: true,
         max_atomic_width: Some(128),
-        supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
+        supported_sanitizers: SanitizerSet::KCFI
+            | SanitizerSet::KERNELADDRESS
+            | SanitizerSet::KERNELHWADDRESS,
         stack_probes: StackProbeType::Inline,
         panic_strategy: PanicStrategy::Abort,
         endian: Endian::Big,
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 22f2717..e8e7b84 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
@@ -1,5 +1,5 @@
 use crate::spec::{
-    Abi, Arch, FramePointer, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+    Arch, CfgAbi, FramePointer, StackProbeType, Target, TargetMetadata, TargetOptions, base,
 };
 
 pub(crate) fn target() -> Target {
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
         arch: Arch::AArch64,
         options: TargetOptions {
-            abi: Abi::Ilp32,
+            cfg_abi: CfgAbi::Ilp32,
             features: "+v8a,+outline-atomics".into(),
             // the AAPCS64 expects use of non-leaf frame pointers per
             // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
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 1c16603..13d3b77 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs
@@ -21,7 +21,9 @@ pub(crate) fn target() -> Target {
             &["--fix-cortex-a53-843419"],
         ),
         features: "+v8a,+strict-align,+neon".into(),
-        supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
+        supported_sanitizers: SanitizerSet::KCFI
+            | SanitizerSet::KERNELADDRESS
+            | SanitizerSet::KERNELHWADDRESS,
         relocation_model: RelocModel::Static,
         disable_redzone: true,
         max_atomic_width: Some(128),
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 ed2e2fb..0587689 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
@@ -7,13 +7,13 @@
 // For example, `-C target-cpu=cortex-a53`.
 
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, RustcAbi, SanitizerSet,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, RustcAbi, SanitizerSet,
     StackProbeType, Target, TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
     let opts = TargetOptions {
-        abi: Abi::SoftFloat,
+        cfg_abi: CfgAbi::SoftFloat,
         rustc_abi: Some(RustcAbi::Softfloat),
         linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
         linker: Some("rust-lld".into()),
@@ -21,7 +21,9 @@ pub(crate) fn target() -> Target {
         relocation_model: RelocModel::Static,
         disable_redzone: true,
         max_atomic_width: Some(128),
-        supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
+        supported_sanitizers: SanitizerSet::KCFI
+            | SanitizerSet::KERNELADDRESS
+            | SanitizerSet::KERNELHWADDRESS,
         stack_probes: StackProbeType::Inline,
         panic_strategy: PanicStrategy::Abort,
         default_uwtable: true,
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs
index 19b7ebe..1e06d3a 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs
@@ -21,7 +21,9 @@ pub(crate) fn target() -> Target {
             &["--fix-cortex-a53-843419"],
         ),
         features: "+v8a,+strict-align,+neon".into(),
-        supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
+        supported_sanitizers: SanitizerSet::KCFI
+            | SanitizerSet::KERNELADDRESS
+            | SanitizerSet::KERNELHWADDRESS,
         relocation_model: RelocModel::Static,
         disable_redzone: true,
         max_atomic_width: Some(128),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none.rs b/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none.rs
index 8f8bbb4..680d896 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none.rs
@@ -8,7 +8,9 @@ pub(crate) fn target() -> Target {
         // based off the aarch64-unknown-none target at time of addition
         linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
         linker: Some("rust-lld".into()),
-        supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
+        supported_sanitizers: SanitizerSet::KCFI
+            | SanitizerSet::KERNELADDRESS
+            | SanitizerSet::KERNELHWADDRESS,
         relocation_model: RelocModel::Static,
         disable_redzone: true,
         max_atomic_width: Some(128),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none_softfloat.rs
index 6f11f97..ee9a6b8 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none_softfloat.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64v8r_unknown_none_softfloat.rs
@@ -1,18 +1,20 @@
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, RustcAbi, SanitizerSet,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, RustcAbi, SanitizerSet,
     StackProbeType, Target, TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
     let opts = TargetOptions {
-        abi: Abi::SoftFloat,
+        cfg_abi: CfgAbi::SoftFloat,
         rustc_abi: Some(RustcAbi::Softfloat),
         linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
         linker: Some("rust-lld".into()),
         relocation_model: RelocModel::Static,
         disable_redzone: true,
         max_atomic_width: Some(128),
-        supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
+        supported_sanitizers: SanitizerSet::KCFI
+            | SanitizerSet::KERNELADDRESS
+            | SanitizerSet::KERNELHWADDRESS,
         stack_probes: StackProbeType::Inline,
         panic_strategy: PanicStrategy::Abort,
         default_uwtable: true,
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 7dc6509..5b0951b 100644
--- a/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Abi, Arch, FloatAbi, SanitizerSet, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    Arch, CfgAbi, FloatAbi, SanitizerSet, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -13,7 +15,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             // https://developer.android.com/ndk/guides/abis.html#armeabi
             features: "+strict-align,+v5te".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 cc63ffa..5275113 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             features: "+strict-align,+v6".into(),
             max_atomic_width: Some(64),
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 1cae42c..7dd36d6 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             features: "+strict-align,+v6,+vfp2".into(),
             max_atomic_width: Some(64),
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 25ef767..5dce420 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             // Most of these settings are copied from the arm_unknown_linux_gnueabi
             // target.
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 99995e2..5b1d1e2 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             // Most of these settings are copied from the arm_unknown_linux_gnueabihf
             // target.
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 73374bc..df9ecd6 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
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             features: "+strict-align,+v8,+crc".into(),
             endian: Endian::Big,
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 7a62464..a460852 100644
--- a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs
@@ -3,8 +3,8 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Abi, Arch, Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
-    TargetOptions,
+    Arch, Cc, CfgAbi, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target,
+    TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -20,7 +20,7 @@ pub(crate) fn target() -> Target {
         data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             endian: Endian::Big,
             linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
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 33147c5..4452b3b 100644
--- a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs
@@ -3,8 +3,8 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Abi, Arch, Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
-    TargetOptions,
+    Arch, Cc, CfgAbi, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target,
+    TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -20,7 +20,7 @@ pub(crate) fn target() -> Target {
         data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             endian: Endian::Big,
             linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
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 c917531..176bdec 100644
--- a/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs
@@ -9,7 +9,7 @@
 //! The default link script is very likely wrong, so you should use
 //! `-Clink-arg=-Tmy_script.ld` to override that with a correct linker script.
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -24,7 +24,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             asm_args: cvs!["-mthumb-interwork", "-march=armv4t", "-mlittle-endian",],
             features: "+soft-float,+strict-align".into(),
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 8c38601..9d95a2b 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             features: "+soft-float,+strict-align".into(),
             // Atomic operations provided by compiler-builtins
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 b8ae881..17065c8 100644
--- a/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs
@@ -1,6 +1,6 @@
 //! Targets the ARMv5TE architecture, with `a32` code by default.
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             asm_args: cvs!["-mthumb-interwork", "-march=armv5te", "-mlittle-endian",],
             features: "+soft-float,+strict-align".into(),
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 d1fded2..17ad14c 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             features: "+soft-float,+strict-align".into(),
             // Atomic operations provided by compiler-builtins
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 2daf2ab..b5a31a9 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             features: "+soft-float,+strict-align".into(),
             // Atomic operations provided by compiler-builtins
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 b05df3a..ac07c87 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             features: "+soft-float,+strict-align".into(),
             // Atomic operations provided by compiler-builtins
diff --git a/compiler/rustc_target/src/spec/targets/armv6_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv6_none_eabi.rs
index 48a196b..c2c6ec4 100644
--- a/compiler/rustc_target/src/spec/targets/armv6_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv6_none_eabi.rs
@@ -1,6 +1,6 @@
 //! Targets the ARMv6K architecture, with `a32` code by default.
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             asm_args: cvs!["-mthumb-interwork", "-march=armv6", "-mlittle-endian",],
             features: "+soft-float,+strict-align,+v6k".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv6_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv6_none_eabihf.rs
index 8bc6b06..d4886ee 100644
--- a/compiler/rustc_target/src/spec/targets/armv6_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv6_none_eabihf.rs
@@ -1,6 +1,6 @@
 //! Targets the ARMv6K architecture, with `a32` code by default, and hard-float ABI
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             asm_args: cvs!["-mthumb-interwork", "-march=armv6", "-mlittle-endian",],
             features: "+strict-align,+v6k,+vfp2,-d32".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 6d6dfee..bd71c83 100644
--- a/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             features: "+v6,+vfp2".into(),
             max_atomic_width: Some(64),
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 cb931e6..5e5468d 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             features: "+v6,+vfp2".into(),
             max_atomic_width: Some(64),
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 ed2ab47..d2bdf74 100644
--- a/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs
+++ b/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs
@@ -1,5 +1,5 @@
 use crate::spec::{
-    Abi, Arch, Cc, Env, FloatAbi, LinkerFlavor, Lld, Os, RelocModel, Target, TargetMetadata,
+    Arch, Cc, CfgAbi, Env, FloatAbi, LinkerFlavor, Lld, Os, RelocModel, Target, TargetMetadata,
     TargetOptions, cvs,
 };
 
@@ -29,7 +29,7 @@ pub(crate) fn target() -> Target {
             env: Env::Newlib,
             vendor: "nintendo".into(),
             cpu: "mpcore".into(),
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             families: cvs!["unix"],
             linker: Some("arm-none-eabi-gcc".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 3ccb99c..99adc85 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs
@@ -1,5 +1,5 @@
 use crate::spec::{
-    Abi, Arch, Cc, FloatAbi, LinkerFlavor, Lld, SanitizerSet, Target, TargetMetadata,
+    Arch, Cc, CfgAbi, FloatAbi, LinkerFlavor, Lld, SanitizerSet, Target, TargetMetadata,
     TargetOptions, base,
 };
 
@@ -26,7 +26,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             features: "+v7,+thumb-mode,+thumb2,+vfp3d16,-neon".into(),
             supported_sanitizers: SanitizerSet::ADDRESS,
diff --git a/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs
index 382658a..90daac1 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs
@@ -1,5 +1,5 @@
 use crate::spec::{
-    Abi, Arch, Cc, Env, FloatAbi, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, Target,
+    Arch, Cc, CfgAbi, Env, FloatAbi, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, Target,
     TargetMetadata, TargetOptions, cvs,
 };
 
@@ -19,7 +19,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             os: Os::Rtems,
             families: cvs!["unix"],
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
             linker: None,
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 20e5c0ac..56d129d 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
@@ -1,7 +1,7 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Abi, Arch, Cc, Env, FloatAbi, LinkerFlavor, Lld, Os, RelocModel, Target, TargetMetadata,
+    Arch, Cc, CfgAbi, Env, FloatAbi, LinkerFlavor, Lld, Os, RelocModel, Target, TargetMetadata,
     TargetOptions, cvs,
 };
 
@@ -34,7 +34,7 @@ pub(crate) fn target() -> Target {
             c_int_width: 32,
             env: Env::Newlib,
             vendor: "sony".into(),
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
             no_default_libraries: false,
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 c358b53..cd6d8b7 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             features: "+v7,+vfp3d16,+thumb2,-neon".into(),
             max_atomic_width: Some(64),
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 8fad2ce..88f9b9e 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for glibc Linux on ARMv7 without thumb-mode, NEON or
 // hardfloat.
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             features: "+v7,+thumb2,+soft-float,-neon".into(),
             max_atomic_width: Some(64),
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 639a9d2..a1f90b3 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for glibc Linux on ARMv7 without NEON or
 // thumb-mode. See the thumbv7neon variant for enabling both.
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             // Info about features at https://wiki.debian.org/ArmHardFloatPort
             features: "+v7,+vfp3d16,+thumb2,-neon".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 9bf0b4f..66e1eb1 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for musl Linux on ARMv7 without thumb-mode, NEON or
 // hardfloat.
@@ -19,7 +19,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
 
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             features: "+v7,+thumb2,+soft-float,-neon".into(),
             max_atomic_width: Some(64),
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 fb7bd12..6ce45de 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for musl Linux on ARMv7 without thumb-mode or NEON.
 
@@ -18,7 +18,7 @@ pub(crate) fn target() -> Target {
         // Most of these settings are copied from the armv7_unknown_linux_gnueabihf
         // target.
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             features: "+v7,+vfp3d16,+thumb2,-neon".into(),
             max_atomic_width: Some(64),
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 318170f..1709bef 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for OpenHarmony on ARMv7 Linux with thumb-mode, but no NEON or
 // hardfloat.
@@ -19,7 +19,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
 
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             features: "+v7,+thumb2,+soft-float,-neon".into(),
             max_atomic_width: Some(64),
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 37a70da..979a02b 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for uclibc Linux on ARMv7 without NEON,
 // thumb-mode or hardfloat.
@@ -18,7 +18,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
 
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             features: "+v7,+thumb2,+soft-float,-neon".into(),
             cpu: "generic".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 8fb38d3..63845a1 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for uclibc Linux on ARMv7 without NEON or
 // thumb-mode. See the thumbv7neon variant for enabling both.
@@ -23,7 +23,7 @@ pub(crate) fn target() -> Target {
             cpu: "generic".into(),
             max_atomic_width: Some(64),
             mcount: "_mcount".into(),
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             ..base
         },
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 8869210..4000e39 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             features: "+v7,+vfp3d16,+thumb2,-neon".into(),
             max_atomic_width: Some(64),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs
index fb3954a..e561af2 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs
@@ -1,5 +1,5 @@
 use crate::spec::{
-    Abi, Arch, FloatAbi, LinkSelfContainedDefault, Os, PanicStrategy, RelroLevel, Target,
+    Arch, CfgAbi, FloatAbi, LinkSelfContainedDefault, Os, PanicStrategy, RelroLevel, Target,
     TargetMetadata, TargetOptions,
 };
 
@@ -19,7 +19,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             features: "+v7,+thumb2,+soft-float,-neon".into(),
             max_atomic_width: Some(64),
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 27e81c5..63f82a0 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -13,7 +13,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             // Info about features at https://wiki.debian.org/ArmHardFloatPort
             features: "+v7,+vfp3d16,+thumb2,-neon".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 bd18d6d..8723dc0 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
@@ -1,4 +1,6 @@
-use crate::spec::{Abi, Arch, FloatAbi, RelocModel, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    Arch, CfgAbi, FloatAbi, RelocModel, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let base = base::solid::opts();
@@ -14,7 +16,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             linker: Some("arm-kmc-eabi-gcc".into()),
             features: "+v7,+soft-float,+thumb2,-neon".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 cb652e6..b59ce32 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
@@ -1,4 +1,6 @@
-use crate::spec::{Abi, Arch, FloatAbi, RelocModel, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    Arch, CfgAbi, FloatAbi, RelocModel, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     let base = base::solid::opts();
@@ -14,7 +16,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             linker: Some("arm-kmc-eabi-gcc".into()),
             features: "+v7,+vfp3d16,+thumb2,-neon".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 e8c5c16..01d55ce 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs
@@ -1,6 +1,6 @@
 // Targets the Little-endian Cortex-A8 (and similar) processors (ARMv7-A)
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             features: "+soft-float,-neon,+strict-align".into(),
             max_atomic_width: Some(64),
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 32a79e3..cbeb409 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs
@@ -1,6 +1,6 @@
 // Targets the Little-endian Cortex-A8 (and similar) processors (ARMv7-A)
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             features: "+vfp3d16,-neon,+strict-align".into(),
             max_atomic_width: Some(64),
diff --git a/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabi.rs
index 5ab74e05..9af6bac 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabi.rs
@@ -5,13 +5,13 @@
 // configuration without hardware floating point support.
 
 use crate::spec::{
-    Abi, Arch, Cc, FloatAbi, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, Target,
+    Arch, Cc, CfgAbi, FloatAbi, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, Target,
     TargetMetadata, TargetOptions, cvs,
 };
 
 pub(crate) fn target() -> Target {
     let opts = TargetOptions {
-        abi: Abi::Eabi,
+        cfg_abi: CfgAbi::Eabi,
         llvm_floatabi: Some(FloatAbi::Soft),
         linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
         linker: Some("rust-lld".into()),
diff --git a/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabihf.rs
index 4ac07e2..5008f38 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabihf.rs
@@ -5,13 +5,13 @@
 // configuration with hardware floating point support.
 
 use crate::spec::{
-    Abi, Arch, Cc, FloatAbi, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, Target,
+    Arch, Cc, CfgAbi, FloatAbi, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, Target,
     TargetMetadata, TargetOptions, cvs,
 };
 
 pub(crate) fn target() -> Target {
     let opts = TargetOptions {
-        abi: Abi::EabiHf,
+        cfg_abi: CfgAbi::EabiHf,
         llvm_floatabi: Some(FloatAbi::Hard),
         linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
         linker: Some("rust-lld".into()),
diff --git a/compiler/rustc_target/src/spec/targets/armv7a_vex_v5.rs b/compiler/rustc_target/src/spec/targets/armv7a_vex_v5.rs
index b83d7b0..cf4ea3c 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_vex_v5.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_vex_v5.rs
@@ -1,5 +1,5 @@
 use crate::spec::{
-    Abi, Arch, Cc, Env, FloatAbi, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, Target,
+    Arch, Cc, CfgAbi, Env, FloatAbi, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, Target,
     TargetMetadata, TargetOptions,
 };
 
@@ -11,7 +11,7 @@ pub(crate) fn target() -> Target {
         env: Env::V5,
         os: Os::VexOs,
         cpu: "cortex-a9".into(),
-        abi: Abi::EabiHf,
+        cfg_abi: CfgAbi::EabiHf,
         is_like_vexos: true,
         llvm_floatabi: Some(FloatAbi::Hard),
         linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
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 114b079..382f862 100644
--- a/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs
@@ -1,6 +1,6 @@
 // Targets the Little-endian Cortex-R4/R5 processor (ARMv7-R)
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             max_atomic_width: Some(64),
             has_thumb_interworking: true,
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 1c6114f..b8d0ea2 100644
--- a/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs
@@ -1,6 +1,6 @@
 // Targets the Little-endian Cortex-R4F/R5F processor (ARMv7-R)
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             features: "+vfp3d16".into(),
             max_atomic_width: Some(64),
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 16006e4..a488637f 100644
--- a/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs
@@ -1,6 +1,6 @@
 // Targets the Little-endian Cortex-R52 processor (ARMv8-R)
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
 
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             // Armv8-R requires a minimum set of floating-point features equivalent to:
             // fp-armv8, SP-only, with 16 DP (32 SP) registers
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 176b853..72193fc 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
@@ -1,4 +1,6 @@
-use crate::spec::{Abi, Arch, Cc, LinkerFlavor, Lld, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, Target, TargetMetadata, TargetOptions, base,
+};
 
 // This target is for glibc Linux on Csky
 
@@ -16,7 +18,7 @@ pub(crate) fn target() -> Target {
         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: Arch::CSky,
         options: TargetOptions {
-            abi: Abi::AbiV2,
+            cfg_abi: CfgAbi::AbiV2,
             features: "+2e3,+3e7,+7e10,+cache,+dsp1e2,+dspe60,+e1,+e2,+edsp,+elrw,+hard-tp,+high-registers,+hwdiv,+mp,+mp1e2,+nvic,+trust".into(),
             late_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-l:libatomic.a"]),
             max_atomic_width: Some(32),
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 5af5449..cf44932 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
@@ -1,4 +1,6 @@
-use crate::spec::{Abi, Arch, Cc, LinkerFlavor, Lld, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, Target, TargetMetadata, TargetOptions, base,
+};
 
 // This target is for glibc Linux on Csky
 
@@ -16,7 +18,7 @@ pub(crate) fn target() -> Target {
         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: Arch::CSky,
         options: TargetOptions {
-            abi: Abi::AbiV2Hf,
+            cfg_abi: CfgAbi::AbiV2Hf,
             cpu: "ck860fv".into(),
             features: "+hard-float,+hard-float-abi,+2e3,+3e7,+7e10,+cache,+dsp1e2,+dspe60,+e1,+e2,+edsp,+elrw,+hard-tp,+high-registers,+hwdiv,+mp,+mp1e2,+nvic,+trust".into(),
             late_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-l:libatomic.a", "-mhard-float"]),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch32_unknown_none.rs b/compiler/rustc_target/src/spec/targets/loongarch32_unknown_none.rs
index d9a4708..2a53d42 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch32_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch32_unknown_none.rs
@@ -1,5 +1,6 @@
 use crate::spec::{
-    Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+    Arch, Cc, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -19,7 +20,7 @@ pub(crate) fn target() -> Target {
             features: "+f,+d".into(),
             linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
             linker: Some("rust-lld".into()),
-            llvm_abiname: "ilp32d".into(),
+            llvm_abiname: LlvmAbi::Ilp32d,
             max_atomic_width: Some(32),
             relocation_model: RelocModel::Static,
             panic_strategy: PanicStrategy::Abort,
diff --git a/compiler/rustc_target/src/spec/targets/loongarch32_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/loongarch32_unknown_none_softfloat.rs
index 896cf0f..e9a9260 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch32_unknown_none_softfloat.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch32_unknown_none_softfloat.rs
@@ -1,6 +1,6 @@
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
-    TargetOptions,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target,
+    TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -18,10 +18,10 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             cpu: "generic".into(),
             features: "-f,-d".into(),
-            abi: Abi::SoftFloat,
+            cfg_abi: CfgAbi::SoftFloat,
             linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
             linker: Some("rust-lld".into()),
-            llvm_abiname: "ilp32s".into(),
+            llvm_abiname: LlvmAbi::Ilp32s,
             max_atomic_width: Some(32),
             relocation_model: RelocModel::Static,
             panic_strategy: PanicStrategy::Abort,
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 5936ea5..180d064 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
@@ -1,4 +1,6 @@
-use crate::spec::{Arch, CodeModel, SanitizerSet, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    Arch, CodeModel, LlvmAbi, SanitizerSet, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -16,7 +18,7 @@ pub(crate) fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             cpu: "generic".into(),
             features: "+f,+d,+lsx,+relax".into(),
-            llvm_abiname: "lp64d".into(),
+            llvm_abiname: LlvmAbi::Lp64d,
             max_atomic_width: Some(64),
             supported_sanitizers: SanitizerSet::ADDRESS
                 | SanitizerSet::CFI
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
index 2951b34..246e28a 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Arch, CodeModel, SanitizerSet, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    Arch, CodeModel, LlvmAbi, SanitizerSet, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -16,7 +18,7 @@ pub(crate) fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             cpu: "generic".into(),
             features: "+f,+d,+lsx,+relax".into(),
-            llvm_abiname: "lp64d".into(),
+            llvm_abiname: LlvmAbi::Lp64d,
             max_atomic_width: Some(64),
             crt_static_default: false,
             supported_sanitizers: SanitizerSet::ADDRESS
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs
index 1dab4fe..461a7bd 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs
@@ -1,4 +1,6 @@
-use crate::spec::{Arch, CodeModel, SanitizerSet, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    Arch, CodeModel, LlvmAbi, SanitizerSet, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -16,7 +18,7 @@ pub(crate) fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             cpu: "generic".into(),
             features: "+f,+d,+lsx,+relax".into(),
-            llvm_abiname: "lp64d".into(),
+            llvm_abiname: LlvmAbi::Lp64d,
             max_atomic_width: Some(64),
             supported_sanitizers: SanitizerSet::ADDRESS
                 | SanitizerSet::CFI
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 d8b5095..2a9f0dc 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
@@ -1,6 +1,6 @@
 use crate::spec::{
-    Arch, Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
-    TargetOptions,
+    Arch, Cc, CodeModel, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target,
+    TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -20,7 +20,7 @@ pub(crate) fn target() -> Target {
             features: "+f,+d,-lsx".into(),
             linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
             linker: Some("rust-lld".into()),
-            llvm_abiname: "lp64d".into(),
+            llvm_abiname: LlvmAbi::Lp64d,
             max_atomic_width: Some(64),
             relocation_model: RelocModel::Static,
             panic_strategy: PanicStrategy::Abort,
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 efeb864..efed977 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
@@ -1,6 +1,6 @@
 use crate::spec::{
-    Abi, Arch, Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
-    TargetOptions,
+    Arch, Cc, CfgAbi, CodeModel, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target,
+    TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -18,10 +18,10 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             cpu: "generic".into(),
             features: "-f,-d".into(),
-            abi: Abi::SoftFloat,
+            cfg_abi: CfgAbi::SoftFloat,
             linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
             linker: Some("rust-lld".into()),
-            llvm_abiname: "lp64s".into(),
+            llvm_abiname: LlvmAbi::Lp64s,
             max_atomic_width: Some(64),
             relocation_model: RelocModel::Static,
             panic_strategy: PanicStrategy::Abort,
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 f90e689..8b02e12 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
@@ -2,7 +2,7 @@
 
 use rustc_abi::Endian;
 
-use crate::spec::{Abi, Arch, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -24,10 +24,10 @@ pub(crate) fn target() -> Target {
         arch: Arch::Mips64,
         options: TargetOptions {
             vendor: "openwrt".into(),
-            abi: Abi::Abi64,
+            cfg_abi: CfgAbi::Abi64,
             endian: Endian::Big,
             mcount: "_mcount".into(),
-            llvm_abiname: "n64".into(),
+            llvm_abiname: LlvmAbi::N64,
             ..base
         },
     }
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 ecb66b4..1494288 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
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Abi, Arch, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,14 +15,14 @@ pub(crate) fn target() -> Target {
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: Arch::Mips64,
         options: TargetOptions {
-            abi: Abi::Abi64,
+            cfg_abi: CfgAbi::Abi64,
             endian: Endian::Big,
             // NOTE(mips64r2) matches C toolchain
             cpu: "mips64r2".into(),
             features: "+mips64r2,+xgot".into(),
             max_atomic_width: Some(64),
             mcount: "_mcount".into(),
-            llvm_abiname: "n64".into(),
+            llvm_abiname: LlvmAbi::N64,
 
             ..base::linux_gnu::opts()
         },
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 ccb13fe..c5336fd 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
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Abi, Arch, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -20,10 +20,10 @@ pub(crate) fn target() -> Target {
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: Arch::Mips64,
         options: TargetOptions {
-            abi: Abi::Abi64,
+            cfg_abi: CfgAbi::Abi64,
             endian: Endian::Big,
             mcount: "_mcount".into(),
-            llvm_abiname: "n64".into(),
+            llvm_abiname: LlvmAbi::N64,
             ..base
         },
     }
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 2457bd8..665cf1d 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -13,13 +13,13 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: Arch::Mips64,
         options: TargetOptions {
-            abi: Abi::Abi64,
+            cfg_abi: CfgAbi::Abi64,
             // NOTE(mips64r2) matches C toolchain
             cpu: "mips64r2".into(),
             features: "+mips64r2,+xgot".into(),
             max_atomic_width: Some(64),
             mcount: "_mcount".into(),
-            llvm_abiname: "n64".into(),
+            llvm_abiname: LlvmAbi::N64,
 
             ..base::linux_gnu::opts()
         },
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 4135372..bd237ea 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -18,9 +18,9 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: Arch::Mips64,
         options: TargetOptions {
-            abi: Abi::Abi64,
+            cfg_abi: CfgAbi::Abi64,
             mcount: "_mcount".into(),
-            llvm_abiname: "n64".into(),
+            llvm_abiname: LlvmAbi::N64,
             ..base
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/mips_mti_none_elf.rs b/compiler/rustc_target/src/spec/targets/mips_mti_none_elf.rs
index ed024c6..32440cd 100644
--- a/compiler/rustc_target/src/spec/targets/mips_mti_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/mips_mti_none_elf.rs
@@ -1,7 +1,8 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+    Arch, Cc, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -24,7 +25,7 @@ pub(crate) fn target() -> Target {
             endian: Endian::Big,
             cpu: "mips32r2".into(),
 
-            llvm_abiname: "o32".into(),
+            llvm_abiname: LlvmAbi::O32,
             max_atomic_width: Some(32),
 
             features: "+mips32r2,+soft-float,+noabicalls".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 9eb3173..8bfa8ec 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
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Arch, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -18,7 +18,7 @@ pub(crate) fn target() -> Target {
             endian: Endian::Big,
             cpu: "mips32r2".into(),
             features: "+mips32r2,+fpxx,+nooddspreg".into(),
-            llvm_abiname: "o32".into(),
+            llvm_abiname: LlvmAbi::O32,
             max_atomic_width: Some(32),
             mcount: "_mcount".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 5737e42..316e59d 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
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Arch, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -20,7 +20,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Mips,
         options: TargetOptions {
             endian: Endian::Big,
-            llvm_abiname: "o32".into(),
+            llvm_abiname: LlvmAbi::O32,
             mcount: "_mcount".into(),
             ..base
         },
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 d9bfa12..b03dec5 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
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Arch, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -18,7 +18,7 @@ pub(crate) fn target() -> Target {
             endian: Endian::Big,
             cpu: "mips32r2".into(),
             features: "+mips32r2,+soft-float".into(),
-            llvm_abiname: "o32".into(),
+            llvm_abiname: LlvmAbi::O32,
             max_atomic_width: Some(32),
             mcount: "_mcount".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_mti_none_elf.rs b/compiler/rustc_target/src/spec/targets/mipsel_mti_none_elf.rs
index 767c57e..ce50ced 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_mti_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_mti_none_elf.rs
@@ -1,7 +1,8 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+    Arch, Cc, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -24,7 +25,7 @@ pub(crate) fn target() -> Target {
             endian: Endian::Little,
             cpu: "mips32r2".into(),
 
-            llvm_abiname: "o32".into(),
+            llvm_abiname: LlvmAbi::O32,
             max_atomic_width: Some(32),
 
             features: "+mips32r2,+soft-float,+noabicalls".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 bc8f29c..2fde3e9 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs
@@ -1,5 +1,6 @@
 use crate::spec::{
-    Arch, Cc, LinkerFlavor, Lld, Os, RelocModel, Target, TargetMetadata, TargetOptions, cvs,
+    Arch, Cc, LinkerFlavor, Lld, LlvmAbi, Os, RelocModel, Target, TargetMetadata, TargetOptions,
+    cvs,
 };
 
 // The PSP has custom linker requirements.
@@ -36,7 +37,7 @@ pub(crate) fn target() -> Target {
 
             // PSP does not support trap-on-condition instructions.
             llvm_args: cvs!["-mno-check-zero-division"],
-            llvm_abiname: "o32".into(),
+            llvm_abiname: LlvmAbi::O32,
             pre_link_args,
             link_script: Some(LINKER_SCRIPT.into()),
             ..Default::default()
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 06631fd..cb88c71 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs
@@ -1,5 +1,5 @@
 use crate::spec::{
-    Arch, Cc, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, Target, TargetMetadata,
+    Arch, Cc, LinkerFlavor, Lld, LlvmAbi, Os, PanicStrategy, RelocModel, Target, TargetMetadata,
     TargetOptions, cvs,
 };
 
@@ -41,7 +41,7 @@ pub(crate) fn target() -> Target {
 
             // PSX does not support trap-on-condition instructions.
             llvm_args: cvs!["-mno-check-zero-division"],
-            llvm_abiname: "o32".into(),
+            llvm_abiname: LlvmAbi::O32,
             panic_strategy: PanicStrategy::Abort,
             ..Default::default()
         },
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 752de46..0541e0e 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
@@ -1,4 +1,4 @@
-use crate::spec::{Arch, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             cpu: "mips32r2".into(),
             features: "+mips32r2,+fpxx,+nooddspreg".into(),
-            llvm_abiname: "o32".into(),
+            llvm_abiname: LlvmAbi::O32,
             max_atomic_width: Some(32),
             mcount: "_mcount".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 fb33752..5d0136a 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
@@ -1,4 +1,4 @@
-use crate::spec::{Arch, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
@@ -16,6 +16,6 @@ pub(crate) fn target() -> Target {
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: Arch::Mips,
-        options: TargetOptions { llvm_abiname: "o32".into(), mcount: "_mcount".into(), ..base },
+        options: TargetOptions { llvm_abiname: LlvmAbi::O32, mcount: "_mcount".into(), ..base },
     }
 }
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 830cdd1..0add21b 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
@@ -1,4 +1,4 @@
-use crate::spec::{Arch, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             cpu: "mips32r2".into(),
             features: "+mips32r2,+soft-float".into(),
-            llvm_abiname: "o32".into(),
+            llvm_abiname: LlvmAbi::O32,
             max_atomic_width: Some(32),
             mcount: "_mcount".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 2620629..5395c15 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Arch, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::netbsd::opts();
@@ -20,7 +20,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Mips,
         options: TargetOptions {
             features: "+soft-float".into(),
-            llvm_abiname: "o32".into(),
+            llvm_abiname: LlvmAbi::O32,
             mcount: "__mcount".into(),
             endian: Endian::Little,
             ..base
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 b66be0b..0e184c8 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs
@@ -3,7 +3,8 @@
 //! Can be used for MIPS M4K core (e.g. on PIC32MX devices)
 
 use crate::spec::{
-    Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+    Arch, Cc, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -23,7 +24,7 @@ pub(crate) fn target() -> Target {
             linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
             cpu: "mips32r2".into(),
             features: "+mips32r2,+soft-float,+noabicalls".into(),
-            llvm_abiname: "o32".into(),
+            llvm_abiname: LlvmAbi::O32,
             max_atomic_width: Some(32),
             linker: Some("rust-lld".into()),
             panic_strategy: PanicStrategy::Abort,
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 9b06336..8091650 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
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Arch, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -18,7 +18,7 @@ pub(crate) fn target() -> Target {
             endian: Endian::Big,
             cpu: "mips32r6".into(),
             features: "+mips32r6".into(),
-            llvm_abiname: "o32".into(),
+            llvm_abiname: LlvmAbi::O32,
             max_atomic_width: Some(32),
             mcount: "_mcount".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 a5a05d5..87db5a2 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
@@ -1,4 +1,4 @@
-use crate::spec::{Arch, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             cpu: "mips32r6".into(),
             features: "+mips32r6".into(),
-            llvm_abiname: "o32".into(),
+            llvm_abiname: LlvmAbi::O32,
             max_atomic_width: Some(32),
             mcount: "_mcount".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 fb97a2e..8e66407 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
@@ -1,6 +1,6 @@
 use rustc_abi::Endian;
 
-use crate::spec::{Abi, Arch, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,14 +15,14 @@ pub(crate) fn target() -> Target {
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: Arch::Mips64r6,
         options: TargetOptions {
-            abi: Abi::Abi64,
+            cfg_abi: CfgAbi::Abi64,
             endian: Endian::Big,
             // NOTE(mips64r6) matches C toolchain
             cpu: "mips64r6".into(),
             features: "+mips64r6".into(),
             max_atomic_width: Some(64),
             mcount: "_mcount".into(),
-            llvm_abiname: "n64".into(),
+            llvm_abiname: LlvmAbi::N64,
 
             ..base::linux_gnu::opts()
         },
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 5569624..5523f44 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -13,13 +13,13 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: Arch::Mips64r6,
         options: TargetOptions {
-            abi: Abi::Abi64,
+            cfg_abi: CfgAbi::Abi64,
             // NOTE(mips64r6) matches C toolchain
             cpu: "mips64r6".into(),
             features: "+mips64r6".into(),
             max_atomic_width: Some(64),
             mcount: "_mcount".into(),
-            llvm_abiname: "n64".into(),
+            llvm_abiname: LlvmAbi::N64,
 
             ..base::linux_gnu::opts()
         },
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 f5d5698..537b21c 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs
@@ -1,7 +1,8 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, LlvmAbi, StackProbeType, Target, TargetMetadata,
+    TargetOptions, base,
 };
 
 pub(crate) fn target() -> Target {
@@ -10,8 +11,8 @@ pub(crate) fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.max_atomic_width = Some(64);
     base.stack_probes = StackProbeType::Inline;
-    base.abi = Abi::ElfV2;
-    base.llvm_abiname = "elfv2".into();
+    base.cfg_abi = CfgAbi::ElfV2;
+    base.llvm_abiname = LlvmAbi::ElfV2;
 
     Target {
         llvm_target: "powerpc64-unknown-freebsd".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 e2dada2..df7f115 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
@@ -1,7 +1,8 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, LlvmAbi, StackProbeType, Target, TargetMetadata,
+    TargetOptions, base,
 };
 
 pub(crate) fn target() -> Target {
@@ -10,8 +11,8 @@ pub(crate) fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.max_atomic_width = Some(64);
     base.stack_probes = StackProbeType::Inline;
-    base.abi = Abi::ElfV1;
-    base.llvm_abiname = "elfv1".into();
+    base.cfg_abi = CfgAbi::ElfV1;
+    base.llvm_abiname = LlvmAbi::ElfV1;
 
     Target {
         llvm_target: "powerpc64-unknown-linux-gnu".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 130bcac..474d20d 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
@@ -1,7 +1,8 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, LlvmAbi, StackProbeType, Target, TargetMetadata,
+    TargetOptions, base,
 };
 
 pub(crate) fn target() -> Target {
@@ -10,8 +11,8 @@ pub(crate) fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.max_atomic_width = Some(64);
     base.stack_probes = StackProbeType::Inline;
-    base.abi = Abi::ElfV2;
-    base.llvm_abiname = "elfv2".into();
+    base.cfg_abi = CfgAbi::ElfV2;
+    base.llvm_abiname = LlvmAbi::ElfV2;
 
     Target {
         llvm_target: "powerpc64-unknown-linux-musl".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 082358e..052dbf5 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs
@@ -1,7 +1,8 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, LlvmAbi, StackProbeType, Target, TargetMetadata,
+    TargetOptions, base,
 };
 
 pub(crate) fn target() -> Target {
@@ -10,8 +11,8 @@ pub(crate) fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.max_atomic_width = Some(64);
     base.stack_probes = StackProbeType::Inline;
-    base.abi = Abi::ElfV2;
-    base.llvm_abiname = "elfv2".into();
+    base.cfg_abi = CfgAbi::ElfV2;
+    base.llvm_abiname = LlvmAbi::ElfV2;
 
     Target {
         llvm_target: "powerpc64-unknown-openbsd".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 f576d23..4a684fe 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs
@@ -1,7 +1,8 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, LlvmAbi, StackProbeType, Target, TargetMetadata,
+    TargetOptions, base,
 };
 
 pub(crate) fn target() -> Target {
@@ -10,8 +11,8 @@ pub(crate) fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.max_atomic_width = Some(64);
     base.stack_probes = StackProbeType::Inline;
-    base.abi = Abi::ElfV1;
-    base.llvm_abiname = "elfv1".into();
+    base.cfg_abi = CfgAbi::ElfV1;
+    base.llvm_abiname = LlvmAbi::ElfV1;
 
     Target {
         llvm_target: "powerpc64-unknown-linux-gnu".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 b2713af..35c477d 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs
@@ -1,5 +1,6 @@
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, LlvmAbi, StackProbeType, Target, TargetMetadata,
+    TargetOptions, base,
 };
 
 pub(crate) fn target() -> Target {
@@ -8,8 +9,8 @@ pub(crate) fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.max_atomic_width = Some(64);
     base.stack_probes = StackProbeType::Inline;
-    base.abi = Abi::ElfV2;
-    base.llvm_abiname = "elfv2".into();
+    base.cfg_abi = CfgAbi::ElfV2;
+    base.llvm_abiname = LlvmAbi::ElfV2;
 
     Target {
         llvm_target: "powerpc64le-unknown-freebsd".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 550ad56..ae2c871 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
@@ -1,5 +1,6 @@
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, LlvmAbi, StackProbeType, Target, TargetMetadata,
+    TargetOptions, base,
 };
 
 pub(crate) fn target() -> Target {
@@ -8,8 +9,8 @@ pub(crate) fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
     base.max_atomic_width = Some(64);
     base.stack_probes = StackProbeType::Inline;
-    base.abi = Abi::ElfV2;
-    base.llvm_abiname = "elfv2".into();
+    base.cfg_abi = CfgAbi::ElfV2;
+    base.llvm_abiname = LlvmAbi::ElfV2;
 
     Target {
         llvm_target: "powerpc64le-unknown-linux-gnu".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 38e3d09..0060a41 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
@@ -1,5 +1,6 @@
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, LlvmAbi, StackProbeType, Target, TargetMetadata,
+    TargetOptions, base,
 };
 
 pub(crate) fn target() -> Target {
@@ -10,8 +11,8 @@ pub(crate) fn target() -> Target {
     base.stack_probes = StackProbeType::Inline;
     // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
     base.crt_static_default = true;
-    base.abi = Abi::ElfV2;
-    base.llvm_abiname = "elfv2".into();
+    base.cfg_abi = CfgAbi::ElfV2;
+    base.llvm_abiname = LlvmAbi::ElfV2;
 
     Target {
         llvm_target: "powerpc64le-unknown-linux-musl".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 4962030..88655c9 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
@@ -1,7 +1,8 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions,
+    base,
 };
 
 pub(crate) fn target() -> Target {
@@ -22,7 +23,7 @@ pub(crate) fn target() -> Target {
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: Arch::PowerPC,
         options: TargetOptions {
-            abi: Abi::Spe,
+            cfg_abi: CfgAbi::Spe,
             endian: Endian::Big,
             features: "+secure-plt,+msync".into(),
             mcount: "_mcount".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs
index 210a80f..c61ceab 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs
@@ -1,7 +1,8 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions,
+    base,
 };
 
 pub(crate) fn target() -> Target {
@@ -22,7 +23,7 @@ pub(crate) fn target() -> Target {
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: Arch::PowerPC,
         options: TargetOptions {
-            abi: Abi::Spe,
+            cfg_abi: CfgAbi::Spe,
             endian: Endian::Big,
             features: "+msync".into(),
             mcount: "_mcount".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 041580f..8f7aaa0 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
@@ -1,7 +1,8 @@
 use rustc_abi::Endian;
 
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, TargetOptions,
+    base,
 };
 
 pub(crate) fn target() -> Target {
@@ -22,7 +23,7 @@ pub(crate) fn target() -> Target {
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: Arch::PowerPC,
         options: TargetOptions {
-            abi: Abi::Spe,
+            cfg_abi: CfgAbi::Spe,
             endian: Endian::Big,
             // feature msync would disable instruction 'fsync' which is not supported by fsl_p1p2
             features: "+secure-plt,+msync".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs
index 3ec8891..2e0a13f 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Arch, StackProbeType, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, LlvmAbi, StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -14,7 +14,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::RiscV32,
         options: TargetOptions {
             cpu: "generic-rv32".into(),
-            llvm_abiname: "ilp32d".into(),
+            llvm_abiname: LlvmAbi::Ilp32d,
             max_atomic_width: Some(32),
             features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
             stack_probes: StackProbeType::Inline,
diff --git a/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs
index 65dbd39..90dcf17 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs
@@ -1,6 +1,6 @@
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
-    TargetOptions,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target,
+    TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -19,12 +19,12 @@ pub(crate) fn target() -> Target {
         arch: Arch::RiscV32,
 
         options: TargetOptions {
-            abi: Abi::Ilp32e,
+            cfg_abi: CfgAbi::Ilp32e,
             linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
             linker: Some("rust-lld".into()),
             cpu: "generic-rv32".into(),
             // The ilp32e ABI specifies the `data_layout`
-            llvm_abiname: "ilp32e".into(),
+            llvm_abiname: LlvmAbi::Ilp32e,
             max_atomic_width: Some(32),
             atomic_cas: false,
             features: "+e,+forced-atomics".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs
index 0826326..cba1809 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs
@@ -1,6 +1,6 @@
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
-    TargetOptions,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target,
+    TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -19,12 +19,12 @@ pub(crate) fn target() -> Target {
         arch: Arch::RiscV32,
 
         options: TargetOptions {
-            abi: Abi::Ilp32e,
+            cfg_abi: CfgAbi::Ilp32e,
             linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
             linker: Some("rust-lld".into()),
             cpu: "generic-rv32".into(),
             // The ilp32e ABI specifies the `data_layout`
-            llvm_abiname: "ilp32e".into(),
+            llvm_abiname: LlvmAbi::Ilp32e,
             max_atomic_width: Some(32),
             atomic_cas: false,
             features: "+e,+m,+forced-atomics".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs
index e37a44e..9de6ef9 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs
@@ -1,6 +1,6 @@
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
-    TargetOptions,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target,
+    TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -19,12 +19,12 @@ pub(crate) fn target() -> Target {
         arch: Arch::RiscV32,
 
         options: TargetOptions {
-            abi: Abi::Ilp32e,
+            cfg_abi: CfgAbi::Ilp32e,
             linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
             linker: Some("rust-lld".into()),
             cpu: "generic-rv32".into(),
             // The ilp32e ABI specifies the `data_layout`
-            llvm_abiname: "ilp32e".into(),
+            llvm_abiname: LlvmAbi::Ilp32e,
             max_atomic_width: Some(32),
             atomic_cas: false,
             features: "+e,+m,+c,+forced-atomics".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 29b0f35..c11edf7 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
@@ -1,6 +1,8 @@
 use std::borrow::Cow;
 
-use crate::spec::{Arch, CodeModel, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    Arch, CodeModel, LlvmAbi, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -18,7 +20,7 @@ pub(crate) fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv32".into(),
             features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
-            llvm_abiname: "ilp32d".into(),
+            llvm_abiname: LlvmAbi::Ilp32d,
             max_atomic_width: Some(32),
             supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
             ..base::linux_gnu::opts()
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 2811605..e5618ea 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
@@ -1,6 +1,8 @@
 use std::borrow::Cow;
 
-use crate::spec::{Arch, CodeModel, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    Arch, CodeModel, LlvmAbi, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -18,7 +20,7 @@ pub(crate) fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv32".into(),
             features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
-            llvm_abiname: "ilp32d".into(),
+            llvm_abiname: LlvmAbi::Ilp32d,
             max_atomic_width: Some(32),
             supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
             ..base::linux_musl::opts()
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 bd6375f..2e4d83b 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
@@ -1,5 +1,6 @@
 use crate::spec::{
-    Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+    Arch, Cc, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -22,7 +23,7 @@ pub(crate) fn target() -> Target {
             max_atomic_width: Some(32),
             atomic_cas: false,
             features: "+forced-atomics".into(),
-            llvm_abiname: "ilp32".into(),
+            llvm_abiname: LlvmAbi::Ilp32,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
             emit_debug_gdb_scripts: false,
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 af25334..82cc02aa 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
@@ -1,5 +1,5 @@
 use crate::spec::{
-    Arch, Cc, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, Target, TargetMetadata,
+    Arch, Cc, LinkerFlavor, Lld, LlvmAbi, Os, PanicStrategy, RelocModel, Target, TargetMetadata,
     TargetOptions,
 };
 
@@ -32,7 +32,7 @@ pub(crate) fn target() -> Target {
             atomic_cas: true,
 
             features: "+m".into(),
-            llvm_abiname: "ilp32".into(),
+            llvm_abiname: LlvmAbi::Ilp32,
             executables: true,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
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 5aef58b..f47102c 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
@@ -1,5 +1,6 @@
 use crate::spec::{
-    Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+    Arch, Cc, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -22,7 +23,7 @@ pub(crate) fn target() -> Target {
             max_atomic_width: Some(32),
             atomic_cas: false,
             features: "+m,+forced-atomics".into(),
-            llvm_abiname: "ilp32".into(),
+            llvm_abiname: LlvmAbi::Ilp32,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
             emit_debug_gdb_scripts: false,
diff --git a/compiler/rustc_target/src/spec/targets/riscv32ima_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32ima_unknown_none_elf.rs
index c455f65..a963674 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32ima_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32ima_unknown_none_elf.rs
@@ -1,5 +1,6 @@
 use crate::spec::{
-    Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+    Arch, Cc, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -21,7 +22,7 @@ pub(crate) fn target() -> Target {
             cpu: "generic-rv32".into(),
             max_atomic_width: Some(32),
             features: "+m,+a".into(),
-            llvm_abiname: "ilp32".into(),
+            llvm_abiname: LlvmAbi::Ilp32,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
             emit_debug_gdb_scripts: false,
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 11a5626..8891527 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs
@@ -1,5 +1,5 @@
 use crate::spec::{
-    Arch, Env, Os, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, cvs,
+    Arch, Env, LlvmAbi, Os, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, cvs,
 };
 
 pub(crate) fn target() -> Target {
@@ -29,7 +29,7 @@ pub(crate) fn target() -> Target {
             atomic_cas: true,
 
             features: "+m,+a,+c".into(),
-            llvm_abiname: "ilp32".into(),
+            llvm_abiname: LlvmAbi::Ilp32,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
             emit_debug_gdb_scripts: false,
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 deca348..c27e7aa 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
@@ -1,5 +1,6 @@
 use crate::spec::{
-    Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+    Arch, Cc, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -21,7 +22,7 @@ pub(crate) fn target() -> Target {
             cpu: "generic-rv32".into(),
             max_atomic_width: Some(32),
             features: "+m,+a,+c".into(),
-            llvm_abiname: "ilp32".into(),
+            llvm_abiname: LlvmAbi::Ilp32,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
             emit_debug_gdb_scripts: false,
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs
index 7205fb6..3a5a942 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs
@@ -1,5 +1,5 @@
 use crate::spec::{
-    Arch, Cc, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, Target, TargetMetadata,
+    Arch, Cc, LinkerFlavor, Lld, LlvmAbi, Os, PanicStrategy, RelocModel, Target, TargetMetadata,
     TargetOptions, cvs,
 };
 
@@ -24,7 +24,7 @@ pub(crate) fn target() -> Target {
             cpu: "generic-rv32".into(),
             max_atomic_width: Some(32),
             features: "+m,+a,+c".into(),
-            llvm_abiname: "ilp32".into(),
+            llvm_abiname: LlvmAbi::Ilp32,
             panic_strategy: PanicStrategy::Unwind,
             relocation_model: RelocModel::Static,
             ..Default::default()
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 363e465..6d8bf30 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
@@ -1,5 +1,5 @@
 use crate::spec::{
-    Arch, Cc, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, Target, TargetMetadata,
+    Arch, Cc, LinkerFlavor, Lld, LlvmAbi, Os, PanicStrategy, RelocModel, Target, TargetMetadata,
     TargetOptions,
 };
 
@@ -23,7 +23,7 @@ pub(crate) fn target() -> Target {
             cpu: "generic-rv32".into(),
             max_atomic_width: Some(32),
             features: "+m,+a,+c".into(),
-            llvm_abiname: "ilp32".into(),
+            llvm_abiname: LlvmAbi::Ilp32,
             panic_strategy: PanicStrategy::Unwind,
             relocation_model: RelocModel::Static,
             ..Default::default()
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 b3a3ab9..614d81f 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs
@@ -1,5 +1,5 @@
 use crate::spec::{
-    Arch, Env, Os, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, cvs,
+    Arch, Env, LlvmAbi, Os, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, cvs,
 };
 
 pub(crate) fn target() -> Target {
@@ -26,7 +26,7 @@ pub(crate) fn target() -> Target {
             max_atomic_width: Some(32),
             atomic_cas: true,
 
-            llvm_abiname: "ilp32f".into(),
+            llvm_abiname: LlvmAbi::Ilp32f,
             features: "+m,+a,+c,+f".into(),
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
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 21f6835..bf519fb 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
@@ -1,5 +1,6 @@
 use crate::spec::{
-    Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+    Arch, Cc, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -20,7 +21,7 @@ pub(crate) fn target() -> Target {
             linker: Some("rust-lld".into()),
             cpu: "generic-rv32".into(),
             max_atomic_width: Some(32),
-            llvm_abiname: "ilp32f".into(),
+            llvm_abiname: LlvmAbi::Ilp32f,
             features: "+m,+a,+c,+f".into(),
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs
index 0bba2e4..045845a 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs
@@ -1,5 +1,5 @@
 use crate::spec::{
-    Arch, Cc, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, Target, TargetMetadata,
+    Arch, Cc, LinkerFlavor, Lld, LlvmAbi, Os, PanicStrategy, RelocModel, Target, TargetMetadata,
     TargetOptions, cvs,
 };
 
@@ -23,7 +23,7 @@ pub(crate) fn target() -> Target {
             linker: Some("rust-lld".into()),
             cpu: "generic-rv32".into(),
             max_atomic_width: Some(32),
-            llvm_abiname: "ilp32f".into(),
+            llvm_abiname: LlvmAbi::Ilp32f,
             features: "+m,+a,+c,+f".into(),
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
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 f903bbd..cfec1b5 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs
@@ -1,5 +1,5 @@
 use crate::spec::{
-    Arch, Env, Os, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, cvs,
+    Arch, Env, LlvmAbi, Os, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions, cvs,
 };
 
 pub(crate) fn target() -> Target {
@@ -32,7 +32,7 @@ pub(crate) fn target() -> Target {
             atomic_cas: true,
 
             features: "+m,+c".into(),
-            llvm_abiname: "ilp32".into(),
+            llvm_abiname: LlvmAbi::Ilp32,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
             emit_debug_gdb_scripts: false,
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 0b8e447..1010039 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
@@ -1,5 +1,6 @@
 use crate::spec::{
-    Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
+    Arch, Cc, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target, TargetMetadata,
+    TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -22,7 +23,7 @@ pub(crate) fn target() -> Target {
             max_atomic_width: Some(32),
             atomic_cas: false,
             features: "+m,+c,+forced-atomics".into(),
-            llvm_abiname: "ilp32".into(),
+            llvm_abiname: LlvmAbi::Ilp32,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
             emit_debug_gdb_scripts: false,
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs
index d1d7384..6143080 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs
@@ -1,5 +1,5 @@
 use crate::spec::{
-    Arch, Cc, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, Target, TargetMetadata,
+    Arch, Cc, LinkerFlavor, Lld, LlvmAbi, Os, PanicStrategy, RelocModel, Target, TargetMetadata,
     TargetOptions, cvs,
 };
 
@@ -24,7 +24,7 @@ pub(crate) fn target() -> Target {
             cpu: "generic-rv32".into(),
             max_atomic_width: Some(32),
             features: "+m,+c".into(),
-            llvm_abiname: "ilp32".into(),
+            llvm_abiname: LlvmAbi::Ilp32,
             panic_strategy: PanicStrategy::Unwind,
             relocation_model: RelocModel::Static,
             ..Default::default()
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 404f414..9842b9f 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
@@ -1,7 +1,8 @@
 use std::borrow::Cow;
 
 use crate::spec::{
-    Arch, CodeModel, SanitizerSet, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base,
+    Arch, CodeModel, LlvmAbi, SanitizerSet, SplitDebuginfo, Target, TargetMetadata, TargetOptions,
+    base,
 };
 
 pub(crate) fn target() -> Target {
@@ -20,7 +21,7 @@ pub(crate) fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv64".into(),
             features: "+m,+a,+f,+d,+c,+b,+v,+zicsr,+zifencei".into(),
-            llvm_abiname: "lp64d".into(),
+            llvm_abiname: LlvmAbi::Lp64d,
             supported_sanitizers: SanitizerSet::ADDRESS,
             max_atomic_width: Some(64),
             supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs
index c6fffc25..f3389b8 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Arch, StackProbeType, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, LlvmAbi, StackProbeType, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -14,7 +14,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::RiscV64,
         options: TargetOptions {
             cpu: "generic-rv64".into(),
-            llvm_abiname: "lp64d".into(),
+            llvm_abiname: LlvmAbi::Lp64d,
             max_atomic_width: Some(64),
             features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
             stack_probes: StackProbeType::Inline,
diff --git a/compiler/rustc_target/src/spec/targets/riscv64a23_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv64a23_unknown_linux_gnu.rs
index bbcf31f..f9a7d30 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64a23_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64a23_unknown_linux_gnu.rs
@@ -1,6 +1,8 @@
 use std::borrow::Cow;
 
-use crate::spec::{Arch, CodeModel, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    Arch, CodeModel, LlvmAbi, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -18,7 +20,7 @@ pub(crate) fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv64".into(),
             features: "+rva23u64".into(),
-            llvm_abiname: "lp64d".into(),
+            llvm_abiname: LlvmAbi::Lp64d,
             max_atomic_width: Some(64),
             supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
             ..base::linux_gnu::opts()
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 dbcfbc3..d59d026 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Arch, CodeModel, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CodeModel, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv64".into(),
             features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
-            llvm_abiname: "lp64d".into(),
+            llvm_abiname: LlvmAbi::Lp64d,
             max_atomic_width: Some(64),
             ..base::freebsd::opts()
         },
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 2127048..3944c4c 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
@@ -1,11 +1,13 @@
-use crate::spec::{Arch, CodeModel, SanitizerSet, StackProbeType, Target, TargetMetadata, base};
+use crate::spec::{
+    Arch, CodeModel, LlvmAbi, SanitizerSet, StackProbeType, Target, TargetMetadata, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::fuchsia::opts();
     base.code_model = Some(CodeModel::Medium);
     base.cpu = "generic-rv64".into();
     base.features = "+m,+a,+f,+d,+c,+zicsr,+zifencei".into();
-    base.llvm_abiname = "lp64d".into();
+    base.llvm_abiname = LlvmAbi::Lp64d;
     base.max_atomic_width = Some(64);
     base.stack_probes = StackProbeType::Inline;
     base.supported_sanitizers = SanitizerSet::SHADOWCALLSTACK;
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 68f6904..516610d 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs
@@ -1,5 +1,5 @@
 use crate::spec::{
-    Arch, CodeModel, RelocModel, Target, TargetMetadata, TargetOptions, TlsModel, base,
+    Arch, CodeModel, LlvmAbi, RelocModel, Target, TargetMetadata, TargetOptions, TlsModel, base,
 };
 
 pub(crate) fn target() -> Target {
@@ -21,7 +21,7 @@ pub(crate) fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             tls_model: TlsModel::LocalExec,
             max_atomic_width: Some(64),
-            llvm_abiname: "lp64d".into(),
+            llvm_abiname: LlvmAbi::Lp64d,
             ..base::hermit::opts()
         },
     }
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 333a63a..76c9ad6 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
@@ -1,6 +1,8 @@
 use std::borrow::Cow;
 
-use crate::spec::{Arch, CodeModel, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    Arch, CodeModel, LlvmAbi, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -18,7 +20,7 @@ pub(crate) fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv64".into(),
             features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
-            llvm_abiname: "lp64d".into(),
+            llvm_abiname: LlvmAbi::Lp64d,
             max_atomic_width: Some(64),
             supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
             ..base::linux_gnu::opts()
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 6eba099..8ed4e09 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
@@ -1,6 +1,8 @@
 use std::borrow::Cow;
 
-use crate::spec::{Arch, CodeModel, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{
+    Arch, CodeModel, LlvmAbi, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base,
+};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -18,7 +20,7 @@ pub(crate) fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv64".into(),
             features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
-            llvm_abiname: "lp64d".into(),
+            llvm_abiname: LlvmAbi::Lp64d,
             max_atomic_width: Some(64),
             supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
             ..base::linux_musl::opts()
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_managarm_mlibc.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_managarm_mlibc.rs
index a9ecf27..f837daf 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_managarm_mlibc.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_managarm_mlibc.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Arch, CodeModel, Target, TargetOptions, base};
+use crate::spec::{Arch, CodeModel, LlvmAbi, Target, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv64".into(),
             features: "+m,+a,+f,+d,+c".into(),
-            llvm_abiname: "lp64d".into(),
+            llvm_abiname: LlvmAbi::Lp64d,
             max_atomic_width: Some(64),
             ..base::managarm_mlibc::opts()
         },
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 bc929a0..564d9b2 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Arch, CodeModel, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CodeModel, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv64".into(),
             features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
-            llvm_abiname: "lp64d".into(),
+            llvm_abiname: LlvmAbi::Lp64d,
             max_atomic_width: Some(64),
             mcount: "__mcount".into(),
             ..base::netbsd::opts()
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 b06727e..f79cd50 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
@@ -1,6 +1,6 @@
 use crate::spec::{
-    Arch, Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, Target,
-    TargetMetadata, TargetOptions,
+    Arch, Cc, CodeModel, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, SanitizerSet,
+    Target, TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -19,7 +19,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
             linker: Some("rust-lld".into()),
-            llvm_abiname: "lp64d".into(),
+            llvm_abiname: LlvmAbi::Lp64d,
             cpu: "generic-rv64".into(),
             max_atomic_width: Some(64),
             features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs
index 7850cc8..9fde109 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs
@@ -1,6 +1,6 @@
 use crate::spec::{
-    Arch, Cc, CodeModel, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, SanitizerSet, Target,
-    TargetMetadata, TargetOptions, cvs,
+    Arch, Cc, CodeModel, LinkerFlavor, Lld, LlvmAbi, Os, PanicStrategy, RelocModel, SanitizerSet,
+    Target, TargetMetadata, TargetOptions, cvs,
 };
 
 pub(crate) fn target() -> Target {
@@ -21,7 +21,7 @@ pub(crate) fn target() -> Target {
             os: Os::NuttX,
             linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
             linker: Some("rust-lld".into()),
-            llvm_abiname: "lp64d".into(),
+            llvm_abiname: LlvmAbi::Lp64d,
             cpu: "generic-rv64".into(),
             max_atomic_width: Some(64),
             features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".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 fb7b077..b937007 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs
@@ -1,4 +1,4 @@
-use crate::spec::{Arch, CodeModel, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CodeModel, LlvmAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
             code_model: Some(CodeModel::Medium),
             cpu: "generic-rv64".into(),
             features: "+m,+a,+f,+d,+c,+zicsr,+zifencei".into(),
-            llvm_abiname: "lp64d".into(),
+            llvm_abiname: LlvmAbi::Lp64d,
             max_atomic_width: Some(64),
             ..base::openbsd::opts()
         },
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_redox.rs
index b6e8864..4213221 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_redox.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_redox.rs
@@ -1,11 +1,11 @@
-use crate::spec::{Arch, CodeModel, Target, TargetMetadata, base};
+use crate::spec::{Arch, CodeModel, LlvmAbi, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::redox::opts();
     base.code_model = Some(CodeModel::Medium);
     base.cpu = "generic-rv64".into();
     base.features = "+m,+a,+f,+d,+c".into();
-    base.llvm_abiname = "lp64d".into();
+    base.llvm_abiname = LlvmAbi::Lp64d;
     base.plt_by_default = false;
     base.max_atomic_width = Some(64);
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv64im_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64im_unknown_none_elf.rs
index 6aae40a..fb36efb 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64im_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64im_unknown_none_elf.rs
@@ -1,6 +1,6 @@
 use crate::spec::{
-    Arch, Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata,
-    TargetOptions,
+    Arch, Cc, CodeModel, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target,
+    TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -23,7 +23,7 @@ pub(crate) fn target() -> Target {
             max_atomic_width: Some(64),
             atomic_cas: false,
             features: "+m,+forced-atomics".into(),
-            llvm_abiname: "lp64".into(),
+            llvm_abiname: LlvmAbi::Lp64,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
             code_model: Some(CodeModel::Medium),
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 60ee41b..65c3f1a 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
@@ -1,6 +1,6 @@
 use crate::spec::{
-    Arch, Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, Target,
-    TargetMetadata, TargetOptions,
+    Arch, Cc, CodeModel, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, SanitizerSet,
+    Target, TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
@@ -22,7 +22,7 @@ pub(crate) fn target() -> Target {
             cpu: "generic-rv64".into(),
             max_atomic_width: Some(64),
             features: "+m,+a,+c".into(),
-            llvm_abiname: "lp64".into(),
+            llvm_abiname: LlvmAbi::Lp64,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
             code_model: Some(CodeModel::Medium),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs
index b1a1817..469c0d1 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs
@@ -1,6 +1,6 @@
 use crate::spec::{
-    Arch, Cc, CodeModel, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, SanitizerSet, Target,
-    TargetMetadata, TargetOptions, cvs,
+    Arch, Cc, CodeModel, LinkerFlavor, Lld, LlvmAbi, Os, PanicStrategy, RelocModel, SanitizerSet,
+    Target, TargetMetadata, TargetOptions, cvs,
 };
 
 pub(crate) fn target() -> Target {
@@ -24,7 +24,7 @@ pub(crate) fn target() -> Target {
             cpu: "generic-rv64".into(),
             max_atomic_width: Some(64),
             features: "+m,+a,+c".into(),
-            llvm_abiname: "lp64".into(),
+            llvm_abiname: LlvmAbi::Lp64,
             panic_strategy: PanicStrategy::Abort,
             relocation_model: RelocModel::Static,
             code_model: Some(CodeModel::Medium),
diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_none_softfloat.rs
index 7d42c1f..8c41109 100644
--- a/compiler/rustc_target/src/spec/targets/s390x_unknown_none_softfloat.rs
+++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_none_softfloat.rs
@@ -1,13 +1,13 @@
 use rustc_abi::{Align, Endian};
 
 use crate::spec::{
-    Abi, Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, RustcAbi, SanitizerSet,
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, RustcAbi, SanitizerSet,
     StackProbeType, Target, TargetMetadata, TargetOptions,
 };
 
 pub(crate) fn target() -> Target {
     let opts = TargetOptions {
-        abi: Abi::SoftFloat,
+        cfg_abi: CfgAbi::SoftFloat,
         cpu: "z10".into(),
         endian: Endian::Big,
         features: "+soft-float,-vector".into(),
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 dfb8ccb..83bbfff 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs
@@ -9,7 +9,7 @@
 //! The default link script is very likely wrong, so you should use
 //! `-Clink-arg=-Tmy_script.ld` to override that with a correct linker script.
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -24,7 +24,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             asm_args: cvs!["-mthumb-interwork", "-march=armv4t", "-mlittle-endian",],
             features: "+soft-float,+strict-align".into(),
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 3b41208..7d2f910 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs
@@ -1,6 +1,6 @@
 //! Targets the ARMv5TE architecture, with `t32` code by default.
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             asm_args: cvs!["-mthumb-interwork", "-march=armv5te", "-mlittle-endian",],
             features: "+soft-float,+strict-align".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv6_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv6_none_eabi.rs
index 077f028..45a1221 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv6_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv6_none_eabi.rs
@@ -1,6 +1,6 @@
 //! Targets the ARMv6K architecture, with `t32` code by default.
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             asm_args: cvs!["-mthumb-interwork", "-march=armv6", "-mlittle-endian",],
             features: "+soft-float,+strict-align,+v6k".into(),
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 cc81cb9..19b5919 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs
@@ -1,6 +1,6 @@
 // Targets the Cortex-M0, Cortex-M0+ and Cortex-M1 processors (ARMv6-M architecture)
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
 
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             // The ARMv6-M architecture doesn't support unaligned loads/stores so we disable them
             // with +strict-align.
diff --git a/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs
index 8b58d2e..2536152 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs
@@ -1,6 +1,6 @@
 // Targets the Cortex-M0, Cortex-M0+ and Cortex-M1 processors (ARMv6-M architecture)
 
-use crate::spec::{Abi, Arch, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -18,7 +18,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             families: cvs!["unix"],
             os: Os::NuttX,
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             // The ARMv6-M architecture doesn't support unaligned loads/stores so we disable them
             // with +strict-align.
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabi.rs
index ce11e3f..011307a 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabi.rs
@@ -1,6 +1,6 @@
 // Targets the Little-endian Cortex-A8 (and similar) processors (ARMv7-A)
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             features: "+soft-float,-neon,+strict-align".into(),
             max_atomic_width: Some(64),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabihf.rs
index 12210e9..4baa73c 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabihf.rs
@@ -1,6 +1,6 @@
 // Targets the Little-endian Cortex-A8 (and similar) processors (ARMv7-A)
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             features: "+vfp3d16,-neon,+strict-align".into(),
             max_atomic_width: Some(64),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabi.rs
index 17d25a6..8eaebe7 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabi.rs
@@ -4,7 +4,7 @@
 // and will use software floating point operations. This matches the NuttX EABI
 // configuration without hardware floating point support.
 
-use crate::spec::{Abi, Arch, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -22,7 +22,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             families: cvs!["unix"],
             os: Os::NuttX,
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             // Cortex-A7/A8/A9 with software floating point
             features: "+soft-float,-neon".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabihf.rs
index a4e1700..ea070f0 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabihf.rs
@@ -7,7 +7,7 @@
 // This target uses the "hard" floating convention (ABI) where floating point values
 // are passed to/from subroutines via FPU registers (S0, S1, D0, D1, etc.).
 
-use crate::spec::{Abi, Arch, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -25,7 +25,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             families: cvs!["unix"],
             os: Os::NuttX,
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             // Cortex-A7/A8/A9 support VFPv3-D32/VFPv4-D32 with optional double-precision
             // and NEON SIMD instructions
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 6e6975c..a9d7660 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs
@@ -9,7 +9,7 @@
 // To opt-in to hardware accelerated floating point operations, you can use, for example,
 // `-C target-feature=+vfp4` or `-C target-cpu=cortex-m4`.
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -25,7 +25,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
 
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             max_atomic_width: Some(32),
             ..base::arm_none::opts()
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 6a7fe14..6af82f8 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs
@@ -8,7 +8,7 @@
 //
 // To opt into double precision hardware support, use the `-C target-feature=+fp64` flag.
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -24,7 +24,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
 
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             // vfp4 is the lowest common denominator between the Cortex-M4F (vfp4) and the
             // Cortex-M7 (vfp5).
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs
index 1017327..3166a01 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs
@@ -9,7 +9,7 @@
 // To opt-in to hardware accelerated floating point operations, you can use, for example,
 // `-C target-feature=+vfp4` or `-C target-cpu=cortex-m4`.
 
-use crate::spec::{Abi, Arch, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -27,7 +27,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             families: cvs!["unix"],
             os: Os::NuttX,
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             max_atomic_width: Some(32),
             ..base::arm_none::opts()
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs
index 1f24155..3e5e7da 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs
@@ -8,7 +8,7 @@
 //
 // To opt into double precision hardware support, use the `-C target-feature=+fp64` flag.
 
-use crate::spec::{Abi, Arch, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -26,7 +26,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             families: cvs!["unix"],
             os: Os::NuttX,
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             // vfp4 is the lowest common denominator between the Cortex-M4F (vfp4) and the
             // Cortex-M7 (vfp5).
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 8851f7b..d38d2ac 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs
@@ -1,6 +1,6 @@
 // Targets the Cortex-M3 processor (ARMv7-M)
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
 
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             max_atomic_width: Some(32),
             ..base::arm_none::opts()
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs
index 9f0261c..7e42c91 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs
@@ -1,6 +1,6 @@
 // Targets the Cortex-M3 processor (ARMv7-M)
 
-use crate::spec::{Abi, Arch, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -18,7 +18,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             families: cvs!["unix"],
             os: Os::NuttX,
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             max_atomic_width: Some(32),
             ..base::arm_none::opts()
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 3ffa301..56c581b 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs
@@ -1,5 +1,5 @@
 use crate::spec::{
-    Abi, Arch, Cc, FloatAbi, LinkerFlavor, Lld, Target, TargetMetadata, TargetOptions, base,
+    Arch, Cc, CfgAbi, FloatAbi, LinkerFlavor, Lld, Target, TargetMetadata, TargetOptions, base,
 };
 
 // This target if is for the Android v7a ABI in thumb mode with
@@ -25,7 +25,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".into(),
             max_atomic_width: Some(64),
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 36b9951..5829d37 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for glibc Linux on ARMv7 with thumb mode enabled
 // (for consistency with Android and Debian-based distributions)
@@ -21,7 +21,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             // Info about features at https://wiki.debian.org/ArmHardFloatPort
             features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".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 41c4bc9..dc4f898 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
@@ -1,4 +1,4 @@
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 // This target is for musl Linux on ARMv7 with thumb mode enabled
 // (for consistency with Android and Debian-based distributions)
@@ -22,7 +22,7 @@ pub(crate) fn target() -> Target {
         // Most of these settings are copied from the thumbv7neon_unknown_linux_gnueabihf
         // target.
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             features: "+v7,+thumb-mode,+thumb2,+vfp3,+neon".into(),
             max_atomic_width: Some(64),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabi.rs
index bf71d31..da66a53 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabi.rs
@@ -1,6 +1,6 @@
 // Targets the Little-endian Cortex-R4/R5 processor (ARMv7-R)
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             max_atomic_width: Some(64),
             has_thumb_interworking: true,
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabihf.rs
index 88b5e67..d591db8 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabihf.rs
@@ -1,6 +1,6 @@
 // Targets the Little-endian Cortex-R4F/R5F processor (ARMv7-R)
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: Arch::Arm,
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             features: "+vfp3d16".into(),
             max_atomic_width: Some(64),
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 7426eb9..b9193a2 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
@@ -1,6 +1,6 @@
 // Targets the Cortex-M23 processor (Baseline ARMv8-M)
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
 
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             // ARMv8-M baseline doesn't support unaligned loads/stores so we disable them
             // with +strict-align.
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs
index a74719b..1e786a4 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs
@@ -1,6 +1,6 @@
 // Targets the Cortex-M23 processor (Baseline ARMv8-M)
 
-use crate::spec::{Abi, Arch, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -18,7 +18,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             families: cvs!["unix"],
             os: Os::NuttX,
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             // ARMv8-M baseline doesn't support unaligned loads/stores so we disable them
             // with +strict-align.
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 540d4bd..a3a8da4 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
@@ -1,7 +1,7 @@
 // Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile),
 // without the Floating Point extension.
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
 
         options: TargetOptions {
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             max_atomic_width: Some(32),
             ..base::arm_none::opts()
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 2287cce..d8058ba 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
@@ -1,7 +1,7 @@
 // Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile),
 // with the Floating Point extension.
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
 
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             // If the Floating Point extension is implemented in the Cortex-M33
             // processor, the Cortex-M33 Technical Reference Manual states that
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs
index ec10729..e132066 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs
@@ -1,7 +1,7 @@
 // Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile),
 // without the Floating Point extension.
 
-use crate::spec::{Abi, Arch, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -19,7 +19,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             families: cvs!["unix"],
             os: Os::NuttX,
-            abi: Abi::Eabi,
+            cfg_abi: CfgAbi::Eabi,
             llvm_floatabi: Some(FloatAbi::Soft),
             max_atomic_width: Some(32),
             ..base::arm_none::opts()
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs
index 9ff924b..e3ba784 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs
@@ -1,7 +1,7 @@
 // Targets the Cortex-M33 processor (Armv8-M Mainline architecture profile),
 // with the Floating Point extension.
 
-use crate::spec::{Abi, Arch, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Os, Target, TargetMetadata, TargetOptions, base, cvs};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -19,7 +19,7 @@ pub(crate) fn target() -> Target {
         options: TargetOptions {
             families: cvs!["unix"],
             os: Os::NuttX,
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             // If the Floating Point extension is implemented in the Cortex-M33
             // processor, the Cortex-M33 Technical Reference Manual states that
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv8r_none_eabihf.rs
index 87434cd..459dff9 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv8r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv8r_none_eabihf.rs
@@ -1,6 +1,6 @@
 // Targets the Little-endian Cortex-R52 processor (ARMv8-R)
 
-use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base};
+use crate::spec::{Arch, CfgAbi, FloatAbi, Target, TargetMetadata, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     Target {
@@ -16,7 +16,7 @@ pub(crate) fn target() -> Target {
         arch: Arch::Arm,
 
         options: TargetOptions {
-            abi: Abi::EabiHf,
+            cfg_abi: CfgAbi::EabiHf,
             llvm_floatabi: Some(FloatAbi::Hard),
             // Armv8-R requires a minimum set of floating-point features equivalent to:
             // fp-armv8, SP-only, with 16 DP (32 SP) registers
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 cd074a4..1204719 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
@@ -1,7 +1,7 @@
 use std::borrow::Cow;
 
 use crate::spec::{
-    Abi, Arch, Cc, Env, LinkerFlavor, Lld, Os, Target, TargetMetadata, TargetOptions, cvs,
+    Arch, Cc, CfgAbi, Env, LinkerFlavor, Lld, Os, Target, TargetMetadata, TargetOptions, cvs,
 };
 
 pub(crate) fn target() -> Target {
@@ -60,7 +60,7 @@ pub(crate) fn target() -> Target {
         os: Os::Unknown,
         env: Env::Sgx,
         vendor: "fortanix".into(),
-        abi: Abi::Fortanix,
+        cfg_abi: CfgAbi::Fortanix,
         linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
         linker: Some("rust-lld".into()),
         max_atomic_width: Some(64),
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 7e06a71..793d235 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
@@ -1,9 +1,11 @@
-use crate::spec::{Abi, Arch, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, base};
+use crate::spec::{
+    Arch, Cc, CfgAbi, LinkerFlavor, Lld, StackProbeType, Target, TargetMetadata, base,
+};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_gnu::opts();
     base.cpu = "x86-64".into();
-    base.abi = Abi::X32;
+    base.cfg_abi = CfgAbi::X32;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mx32"]);
     base.stack_probes = StackProbeType::Inline;
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index 80674ab..e2647e4 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -5,7 +5,7 @@
 use rustc_macros::HashStable_Generic;
 use rustc_span::{Symbol, sym};
 
-use crate::spec::{Arch, FloatAbi, RustcAbi, Target};
+use crate::spec::{Arch, FloatAbi, LlvmAbi, RustcAbi, Target};
 
 /// Features that control behaviour of rustc, rather than the codegen.
 /// These exist globally and are not in the target-specific lists below.
@@ -756,8 +756,10 @@ pub fn toggle_allowed(&self) -> Result<(), &'static str> {
     // tidy-alphabetical-end
 ];
 
-const BPF_FEATURES: &[(&str, Stability, ImpliedFeatures)] =
-    &[("alu32", Unstable(sym::bpf_target_feature), &[])];
+const BPF_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+    ("alu32", Unstable(sym::bpf_target_feature), &[]),
+    ("allows-misaligned-mem-access", Unstable(sym::bpf_target_feature), &[]),
+];
 
 static CSKY_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
@@ -1174,20 +1176,20 @@ pub fn abi_required_features(&self) -> FeatureConstraints {
             Arch::RiscV32 | Arch::RiscV64 => {
                 // RISC-V handles ABI in a very sane way, being fully explicit via `llvm_abiname`
                 // about what the intended ABI is.
-                match &*self.llvm_abiname {
-                    "ilp32d" | "lp64d" => {
+                match &self.llvm_abiname {
+                    LlvmAbi::Ilp32d | LlvmAbi::Lp64d => {
                         // Requires d (which implies f), incompatible with e and zfinx.
                         FeatureConstraints { required: &["d"], incompatible: &["e", "zfinx"] }
                     }
-                    "ilp32f" | "lp64f" => {
+                    LlvmAbi::Ilp32f | LlvmAbi::Lp64f => {
                         // Requires f, incompatible with e and zfinx.
                         FeatureConstraints { required: &["f"], incompatible: &["e", "zfinx"] }
                     }
-                    "ilp32" | "lp64" => {
+                    LlvmAbi::Ilp32 | LlvmAbi::Lp64 => {
                         // Requires nothing, incompatible with e.
                         FeatureConstraints { required: &[], incompatible: &["e"] }
                     }
-                    "ilp32e" => {
+                    LlvmAbi::Ilp32e => {
                         // ilp32e is documented to be incompatible with features that need aligned
                         // load/stores > 32 bits, like `d`. (One could also just generate more
                         // complicated code to align the stack when needed, but the RISCV
@@ -1198,7 +1200,7 @@ pub fn abi_required_features(&self) -> FeatureConstraints {
                         // a program while the rest doesn't know they even exist.
                         FeatureConstraints { required: &[], incompatible: &["d"] }
                     }
-                    "lp64e" => {
+                    LlvmAbi::Lp64e => {
                         // As above, `e` is not required.
                         NOTHING
                     }
@@ -1208,16 +1210,16 @@ pub fn abi_required_features(&self) -> FeatureConstraints {
             Arch::LoongArch32 | Arch::LoongArch64 => {
                 // LoongArch handles ABI in a very sane way, being fully explicit via `llvm_abiname`
                 // about what the intended ABI is.
-                match &*self.llvm_abiname {
-                    "ilp32d" | "lp64d" => {
+                match &self.llvm_abiname {
+                    LlvmAbi::Ilp32d | LlvmAbi::Lp64d => {
                         // Requires d (which implies f), incompatible with nothing.
                         FeatureConstraints { required: &["d"], incompatible: &[] }
                     }
-                    "ilp32f" | "lp64f" => {
+                    LlvmAbi::Ilp32f | LlvmAbi::Lp64f => {
                         // Requires f, incompatible with nothing.
                         FeatureConstraints { required: &["f"], incompatible: &[] }
                     }
-                    "ilp32s" | "lp64s" => {
+                    LlvmAbi::Ilp32s | LlvmAbi::Lp64s => {
                         // The soft-float ABI does not require any features and is also not
                         // incompatible with any features. Rust targets explicitly specify the
                         // LLVM ABI names, which allows for enabling hard-float support even on
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 6bf0817..eeccf1e 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -2299,6 +2299,11 @@ pub(super) fn report_similar_impl_candidates(
             // FIXME: this could use a better heuristic, like just checking
             // that args[1..] is the same.
             let all_traits_equal = traits.len() == 1;
+            let mut types: Vec<_> =
+                candidates.iter().map(|(c, _)| c.self_ty().to_string()).collect();
+            types.sort();
+            types.dedup();
+            let all_types_equal = types.len() == 1;
 
             let end = if candidates.len() <= 9 || self.tcx.sess.opts.verbose {
                 candidates.len()
@@ -2312,6 +2317,11 @@ pub(super) fn report_similar_impl_candidates(
                 for (c, def_id) in &candidates {
                     let msg = if all_traits_equal {
                         format!("`{}`", self.tcx.short_string(c.self_ty(), err.long_ty_path()))
+                    } else if all_types_equal {
+                        format!(
+                            "`{}`",
+                            self.tcx.short_string(c.print_only_trait_path(), err.long_ty_path())
+                        )
                     } else {
                         format!(
                             "`{}` implements `{}`",
@@ -2321,13 +2331,19 @@ pub(super) fn report_similar_impl_candidates(
                     };
                     span.push_span_label(self.tcx.def_span(*def_id), msg);
                 }
-                err.span_help(
-                    span,
+                let msg = if all_types_equal {
+                    format!(
+                        "`{}` implements trait `{}`",
+                        self.tcx.short_string(candidates[0].0.self_ty(), err.long_ty_path()),
+                        self.tcx.short_string(trait_ref.print_trait_sugared(), err.long_ty_path()),
+                    )
+                } else {
                     format!(
                         "the following {other}types implement trait `{}`",
-                        trait_ref.print_trait_sugared(),
-                    ),
-                );
+                        self.tcx.short_string(trait_ref.print_trait_sugared(), err.long_ty_path()),
+                    )
+                };
+                err.span_help(span, msg);
             } else {
                 let candidate_names: Vec<String> = candidates
                     .iter()
@@ -2337,6 +2353,12 @@ pub(super) fn report_similar_impl_candidates(
                                 "\n  {}",
                                 self.tcx.short_string(c.self_ty(), err.long_ty_path())
                             )
+                        } else if all_types_equal {
+                            format!(
+                                "\n  {}",
+                                self.tcx
+                                    .short_string(c.print_only_trait_path(), err.long_ty_path())
+                            )
                         } else {
                             format!(
                                 "\n  `{}` implements `{}`",
@@ -2347,9 +2369,21 @@ pub(super) fn report_similar_impl_candidates(
                         }
                     })
                     .collect();
+                let msg = if all_types_equal {
+                    format!(
+                        "`{}` implements trait `{}`",
+                        self.tcx.short_string(candidates[0].0.self_ty(), err.long_ty_path()),
+                        self.tcx.short_string(trait_ref.print_trait_sugared(), err.long_ty_path()),
+                    )
+                } else {
+                    format!(
+                        "the following {other}types implement trait `{}`",
+                        self.tcx.short_string(trait_ref.print_trait_sugared(), err.long_ty_path()),
+                    )
+                };
+
                 err.help(format!(
-                    "the following {other}types implement trait `{}`:{}{}",
-                    trait_ref.print_trait_sugared(),
+                    "{msg}:{}{}",
                     candidate_names[..end].join(""),
                     if candidates.len() > 9 && !self.tcx.sess.opts.verbose {
                         format!("\nand {} others", candidates.len() - 8)
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
index d08e0fa..4ae6584 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
@@ -124,8 +124,11 @@ pub(crate) fn on_unimplemented_components(
                 }
             }
 
-            if let Some(true) = self_ty.ty_adt_def().map(|def| def.did().is_local()) {
-                crate_local = true;
+            if let Some(adt) = self_ty.ty_adt_def() {
+                if adt.did().is_local() {
+                    crate_local = true;
+                }
+                self_types.push(format!("{{{}}}", adt.descr()))
             }
 
             // Allow targeting all integers using `{integral}`, even if the exact type was resolved
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index ee2f8d9..4a6d5eb 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -4037,12 +4037,13 @@ pub fn can_suggest_derive(
             _ => return false,
         };
         let is_derivable_trait = match diagnostic_name {
-            sym::Default => !adt.is_enum(),
+            sym::Copy | sym::Clone => true,
+            _ if adt.is_union() => false,
             sym::PartialEq | sym::PartialOrd => {
                 let rhs_ty = trait_pred.skip_binder().trait_ref.args.type_at(1);
                 trait_pred.skip_binder().self_ty() == rhs_ty
             }
-            sym::Eq | sym::Ord | sym::Clone | sym::Copy | sym::Hash | sym::Debug => true,
+            sym::Eq | sym::Ord | sym::Hash | sym::Debug | sym::Default => true,
             _ => false,
         };
         is_derivable_trait &&
diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs
index 026ab3a..469e24c 100644
--- a/compiler/rustc_trait_selection/src/traits/effects.rs
+++ b/compiler/rustc_trait_selection/src/traits/effects.rs
@@ -472,12 +472,17 @@ fn evaluate_host_effect_for_destruct_goal<'tcx>(
         | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
         | ty::Error(_) => thin_vec![],
 
-        // Coroutines and closures could implement `[const] Drop`,
+        // Closures are [const] Destruct when all of their upvars (captures) are [const] Destruct.
+        ty::Closure(_, args) => {
+            let closure_args = args.as_closure();
+            thin_vec![ty::TraitRef::new(tcx, destruct_def_id, [closure_args.tupled_upvars_ty()])]
+        }
+
+        // Coroutines could implement `[const] Drop`,
         // but they don't really need to right now.
-        ty::Closure(_, _)
-        | ty::CoroutineClosure(_, _)
-        | ty::Coroutine(_, _)
-        | ty::CoroutineWitness(_, _) => return Err(EvaluationFailure::NoSolution),
+        ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) | ty::CoroutineWitness(_, _) => {
+            return Err(EvaluationFailure::NoSolution);
+        }
 
         // FIXME(unsafe_binders): Unsafe binders could implement `[const] Drop`
         // if their inner type implements it.
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 4a0a99e..b8f5336 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -942,14 +942,53 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
                 // FIXME(#27579) RFC also considers adding trait
                 // obligations that don't refer to Self and
                 // checking those
-                if let Some(principal) = data.principal_def_id() {
+                if let Some(principal) = data.principal() {
+                    let principal_def_id = principal.skip_binder().def_id;
                     self.out.push(traits::Obligation::with_depth(
                         tcx,
                         self.cause(ObligationCauseCode::WellFormed(None)),
                         self.recursion_depth,
                         self.param_env,
-                        ty::Binder::dummy(ty::PredicateKind::DynCompatible(principal)),
+                        ty::Binder::dummy(ty::PredicateKind::DynCompatible(principal_def_id)),
                     ));
+
+                    // For the most part we don't add wf predicates corresponding to
+                    // the trait ref's generic arguments which allows code like this
+                    // to compile:
+                    // ```rust
+                    // trait Trait<T: Sized> {}
+                    // fn foo(_: &dyn Trait<[u32]>) {}
+                    // ```
+                    //
+                    // However, we sometimes incidentally check that const arguments
+                    // have the correct type as a side effect of the anon const
+                    // desugaring. To make this "consistent" for users we explicitly
+                    // check `ConstArgHasType` clauses so that const args that don't
+                    // go through an anon const still have their types checked.
+                    //
+                    // See also: https://rustc-dev-guide.rust-lang.org/const-generics.html
+                    let args = principal.skip_binder().with_self_ty(self.tcx(), t).args;
+                    let obligations =
+                        self.nominal_obligations(principal_def_id, args).into_iter().filter(|o| {
+                            let kind = o.predicate.kind().skip_binder();
+                            match kind {
+                                ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(
+                                    ct,
+                                    _,
+                                )) if matches!(ct.kind(), ty::ConstKind::Param(..)) => {
+                                    // ConstArgHasType clauses are not higher kinded. Assert as
+                                    // such so we can fix this up if that ever changes.
+                                    assert!(o.predicate.kind().bound_vars().is_empty());
+                                    // In stable rust, variables from the trait object binder
+                                    // cannot be referenced by a ConstArgHasType clause. However,
+                                    // under `generic_const_parameter_types`, it can. Ignore those
+                                    // predicates for now, to not have HKT-ConstArgHasTypes.
+                                    !kind.has_escaping_bound_vars()
+                                }
+                                _ => false,
+                            }
+                        });
+                    self.out.extend(obligations);
                 }
 
                 if !t.has_escaping_bound_vars() {
diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs
index cef964a..c83e0bb 100644
--- a/compiler/rustc_ty_utils/src/representability.rs
+++ b/compiler/rustc_ty_utils/src/representability.rs
@@ -19,7 +19,7 @@ fn check_representability(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         DefKind::Struct | DefKind::Union | DefKind::Enum => {
             for variant in tcx.adt_def(def_id).variants() {
                 for field in variant.fields.iter() {
-                    let _ = tcx.check_representability(field.did.expect_local());
+                    tcx.ensure_ok().check_representability(field.did.expect_local());
                 }
             }
         }
@@ -35,7 +35,7 @@ fn check_representability_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) {
         // This one must be a query rather than a vanilla `check_representability_adt_ty` call. See
         // the comment on `check_representability_adt_ty` below for why.
         ty::Adt(..) => {
-            let _ = tcx.check_representability_adt_ty(ty);
+            tcx.ensure_ok().check_representability_adt_ty(ty);
         }
         // FIXME(#11924) allow zero-length arrays?
         ty::Array(ty, _) => {
@@ -58,7 +58,7 @@ fn check_representability_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) {
 //     -> check_representability_adt_ty(Bar<Foo>)
 //     -> check_representability(Foo)
 //
-// For the diagnostic output (in `Value::from_cycle_error`), we want to detect
+// For the diagnostic output (in `check_representability`), we want to detect
 // that the `Foo` in the *second* field of the struct is culpable. This
 // requires traversing the HIR of the struct and calling `params_in_repr(Bar)`.
 // But we can't call params_in_repr for a given type unless it is known to be
@@ -69,7 +69,7 @@ fn check_representability_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) {
 fn check_representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) {
     let ty::Adt(adt, args) = ty.kind() else { bug!("expected adt") };
     if let Some(def_id) = adt.did().as_local() {
-        let _ = tcx.check_representability(def_id);
+        tcx.ensure_ok().check_representability(def_id);
     }
     // At this point, we know that the item of the ADT type is representable;
     // but the type parameters may cause a cycle with an upstream type
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 78f3a19..7a84a87 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -117,7 +117,7 @@ fn adt_sizedness_constraint<'tcx>(
     (def_id, sizedness): (DefId, SizedTraitKind),
 ) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
     if let Some(def_id) = def_id.as_local() {
-        let _ = tcx.check_representability(def_id);
+        tcx.ensure_ok().check_representability(def_id);
     }
 
     let def = tcx.adt_def(def_id);
diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs
index 4ddfcde..d46b197 100644
--- a/library/alloc/src/collections/binary_heap/mod.rs
+++ b/library/alloc/src/collections/binary_heap/mod.rs
@@ -1364,6 +1364,37 @@ pub fn as_slice(&self) -> &[T] {
         self.data.as_slice()
     }
 
+    /// Returns a mutable slice of all values in the underlying vector.
+    ///
+    /// # Safety
+    ///
+    /// The caller must ensure that the slice remains a max-heap, i.e. for all indices
+    /// `0 < i < slice.len()`, `slice[(i - 1) / 2] >= slice[i]`, before the borrow ends
+    /// and the binary heap is used.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(binary_heap_as_mut_slice)]
+    ///
+    /// use std::collections::BinaryHeap;
+    ///
+    /// let mut heap = BinaryHeap::<u32>::from([1, 2, 3, 4, 5, 6, 7]);
+    ///
+    /// unsafe {
+    ///     for value in heap.as_mut_slice() {
+    ///         *value = (*value).saturating_mul(2);
+    ///     }
+    /// }
+    /// ```
+    #[must_use]
+    #[unstable(feature = "binary_heap_as_mut_slice", issue = "154009")]
+    pub unsafe fn as_mut_slice(&mut self) -> &mut [T] {
+        self.data.as_mut_slice()
+    }
+
     /// Consumes the `BinaryHeap` and returns the underlying vector
     /// in arbitrary order.
     ///
diff --git a/library/alloc/src/collections/btree/append.rs b/library/alloc/src/collections/btree/append.rs
index 66ea22e..cc8d793 100644
--- a/library/alloc/src/collections/btree/append.rs
+++ b/library/alloc/src/collections/btree/append.rs
@@ -1,38 +1,8 @@
 use core::alloc::Allocator;
-use core::iter::FusedIterator;
 
-use super::merge_iter::MergeIterInner;
 use super::node::{self, Root};
 
 impl<K, V> Root<K, V> {
-    /// Appends all key-value pairs from the union of two ascending iterators,
-    /// incrementing a `length` variable along the way. The latter makes it
-    /// easier for the caller to avoid a leak when a drop handler panicks.
-    ///
-    /// If both iterators produce the same key, this method drops the pair from
-    /// the left iterator and appends the pair from the right iterator.
-    ///
-    /// If you want the tree to end up in a strictly ascending order, like for
-    /// a `BTreeMap`, both iterators should produce keys in strictly ascending
-    /// order, each greater than all keys in the tree, including any keys
-    /// already in the tree upon entry.
-    pub(super) fn append_from_sorted_iters<I, A: Allocator + Clone>(
-        &mut self,
-        left: I,
-        right: I,
-        length: &mut usize,
-        alloc: A,
-    ) where
-        K: Ord,
-        I: Iterator<Item = (K, V)> + FusedIterator,
-    {
-        // We prepare to merge `left` and `right` into a sorted sequence in linear time.
-        let iter = MergeIter(MergeIterInner::new(left, right));
-
-        // Meanwhile, we build a tree from the sorted sequence in linear time.
-        self.bulk_push(iter, length, alloc)
-    }
-
     /// Pushes all key-value pairs to the end of the tree, incrementing a
     /// `length` variable along the way. The latter makes it easier for the
     /// caller to avoid a leak when the iterator panicks.
@@ -94,24 +64,3 @@ pub(super) fn bulk_push<I, A: Allocator + Clone>(
         self.fix_right_border_of_plentiful();
     }
 }
-
-// An iterator for merging two sorted sequences into one
-struct MergeIter<K, V, I: Iterator<Item = (K, V)>>(MergeIterInner<I>);
-
-impl<K: Ord, V, I> Iterator for MergeIter<K, V, I>
-where
-    I: Iterator<Item = (K, V)> + FusedIterator,
-{
-    type Item = (K, V);
-
-    /// If two keys are equal, returns the key from the left and the value from the right.
-    fn next(&mut self) -> Option<(K, V)> {
-        let (a_next, b_next) = self.0.nexts(|a: &(K, V), b: &(K, V)| K::cmp(&a.0, &b.0));
-        match (a_next, b_next) {
-            (Some((a_k, _)), Some((_, b_v))) => Some((a_k, b_v)),
-            (Some(a), None) => Some(a),
-            (None, Some(b)) => Some(b),
-            (None, None) => None,
-        }
-    }
-}
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index fdeb9e3..e7a10d2 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -1219,26 +1219,8 @@ pub fn append(&mut self, other: &mut Self)
         K: Ord,
         A: Clone,
     {
-        // Do we have to append anything at all?
-        if other.is_empty() {
-            return;
-        }
-
-        // We can just swap `self` and `other` if `self` is empty.
-        if self.is_empty() {
-            mem::swap(self, other);
-            return;
-        }
-
-        let self_iter = mem::replace(self, Self::new_in((*self.alloc).clone())).into_iter();
-        let other_iter = mem::replace(other, Self::new_in((*self.alloc).clone())).into_iter();
-        let root = self.root.get_or_insert_with(|| Root::new((*self.alloc).clone()));
-        root.append_from_sorted_iters(
-            self_iter,
-            other_iter,
-            &mut self.length,
-            (*self.alloc).clone(),
-        )
+        let other = mem::replace(other, Self::new_in((*self.alloc).clone()));
+        self.merge(other, |_key, _self_val, other_val| other_val);
     }
 
     /// Moves all elements from `other` into `self`, leaving `other` empty.
diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs
index 73546ca..6434874 100644
--- a/library/alloc/src/collections/btree/map/tests.rs
+++ b/library/alloc/src/collections/btree/map/tests.rs
@@ -2224,7 +2224,7 @@ fn test_append_drop_leak() {
 
     catch_unwind(move || left.append(&mut right)).unwrap_err();
     assert_eq!(a.dropped(), 1);
-    assert_eq!(b.dropped(), 1); // should be 2 were it not for Rust issue #47949
+    assert_eq!(b.dropped(), 2);
     assert_eq!(c.dropped(), 2);
 }
 
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 7ac9cdc..bcd9e09 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -148,6 +148,7 @@
 #![feature(slice_range)]
 #![feature(std_internals)]
 #![feature(temporary_niche_types)]
+#![feature(titlecase)]
 #![feature(transmutability)]
 #![feature(trivial_clone)]
 #![feature(trusted_fused)]
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 8a65161..3f31387 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -2424,9 +2424,6 @@ unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Rc<T, A> {}
 #[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
 unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for UniqueRc<T, A> {}
 
-#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
-unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Weak<T, A> {}
-
 #[unstable(feature = "deref_pure_trait", issue = "87121")]
 unsafe impl<T: ?Sized, A: Allocator> DerefPure for Rc<T, A> {}
 
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 2c9fadb..8a5f095 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -2426,9 +2426,6 @@ fn deref(&self) -> &T {
 #[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
 unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Arc<T, A> {}
 
-#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
-unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Weak<T, A> {}
-
 #[unstable(feature = "deref_pure_trait", issue = "87121")]
 unsafe impl<T: ?Sized, A: Allocator> DerefPure for Arc<T, A> {}
 
diff --git a/library/alloc/src/vec/splice.rs b/library/alloc/src/vec/splice.rs
index 3eb8ca4..99ebcb4 100644
--- a/library/alloc/src/vec/splice.rs
+++ b/library/alloc/src/vec/splice.rs
@@ -1,4 +1,4 @@
-use core::{ptr, slice};
+use core::ptr;
 
 use super::{Drain, Vec};
 use crate::alloc::{Allocator, Global};
@@ -107,15 +107,13 @@ unsafe fn fill<I: Iterator<Item = T>>(&mut self, replace_with: &mut I) -> bool {
         let vec = unsafe { self.vec.as_mut() };
         let range_start = vec.len;
         let range_end = self.tail_start;
-        let range_slice = unsafe {
-            slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start)
-        };
+        // The elements in this range are not initialized so we avoid creating a slice.
 
-        for place in range_slice {
+        for idx in range_start..range_end {
             let Some(new_item) = replace_with.next() else {
                 return false;
             };
-            unsafe { ptr::write(place, new_item) };
+            unsafe { vec.as_mut_ptr().add(idx).write(new_item) };
             vec.len += 1;
         }
         true
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index f31cadb..d67693f 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -2719,18 +2719,6 @@ fn assert_coerce_unsized(
 }
 
 #[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
-unsafe impl<T: ?Sized> PinCoerceUnsized for UnsafeCell<T> {}
-
-#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
-unsafe impl<T: ?Sized> PinCoerceUnsized for SyncUnsafeCell<T> {}
-
-#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
-unsafe impl<T: ?Sized> PinCoerceUnsized for Cell<T> {}
-
-#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
-unsafe impl<T: ?Sized> PinCoerceUnsized for RefCell<T> {}
-
-#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
 unsafe impl<'b, T: ?Sized> PinCoerceUnsized for Ref<'b, T> {}
 
 #[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 87b328c..e9c3b04 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -778,7 +778,72 @@ pub const fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] {
     pub fn is_alphabetic(self) -> bool {
         match self {
             'a'..='z' | 'A'..='Z' => true,
-            c => c > '\x7f' && unicode::Alphabetic(c),
+            '\0'..='\u{A9}' => false,
+            _ => unicode::Alphabetic(self),
+        }
+    }
+
+    /// Returns `true` if this `char` has the `Cased` property.
+    /// A character is cased if and only if it is uppercase, lowercase, or titlecase.
+    ///
+    /// `Cased` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and
+    /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`].
+    ///
+    /// [Unicode Standard]: https://www.unicode.org/versions/latest/
+    /// [ucd]: https://www.unicode.org/reports/tr44/
+    /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(titlecase)]
+    /// assert!('A'.is_cased());
+    /// assert!('a'.is_cased());
+    /// assert!(!'京'.is_cased());
+    /// ```
+    #[must_use]
+    #[unstable(feature = "titlecase", issue = "153892")]
+    #[inline]
+    pub fn is_cased(self) -> bool {
+        match self {
+            'a'..='z' | 'A'..='Z' => true,
+            '\0'..='\u{A9}' => false,
+            _ => unicode::Cased(self),
+        }
+    }
+
+    /// Returns the case of this character:
+    /// [`Some(CharCase::Upper)`][`CharCase::Upper`] if [`self.is_uppercase()`][`char::is_uppercase`],
+    /// [`Some(CharCase::Lower)`][`CharCase::Lower`] if [`self.is_lowercase()`][`char::is_lowercase`],
+    /// [`Some(CharCase::Title)`][`CharCase::Title`] if [`self.is_titlecase()`][`char::is_titlecase`], and
+    /// `None` if [`!self.is_cased()`][`char::is_cased`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(titlecase)]
+    /// use core::char::CharCase;
+    /// assert_eq!('a'.case(), Some(CharCase::Lower));
+    /// assert_eq!('δ'.case(), Some(CharCase::Lower));
+    /// assert_eq!('A'.case(), Some(CharCase::Upper));
+    /// assert_eq!('Δ'.case(), Some(CharCase::Upper));
+    /// assert_eq!('Ç…'.case(), Some(CharCase::Title));
+    /// assert_eq!('中'.case(), None);
+    /// ```
+    #[must_use]
+    #[unstable(feature = "titlecase", issue = "153892")]
+    #[inline]
+    pub fn case(self) -> Option<CharCase> {
+        match self {
+            'a'..='z' => Some(CharCase::Lower),
+            'A'..='Z' => Some(CharCase::Upper),
+            '\0'..='\u{A9}' => None,
+            _ if !unicode::Cased(self) => None,
+            _ if unicode::Lowercase(self) => Some(CharCase::Lower),
+            _ if unicode::Uppercase(self) => Some(CharCase::Upper),
+            _ => Some(CharCase::Title),
         }
     }
 
@@ -819,7 +884,42 @@ pub fn is_alphabetic(self) -> bool {
     pub const fn is_lowercase(self) -> bool {
         match self {
             'a'..='z' => true,
-            c => c > '\x7f' && unicode::Lowercase(c),
+            '\0'..='\u{A9}' => false,
+            _ => unicode::Lowercase(self),
+        }
+    }
+
+    /// Returns `true` if this `char` has the general category for titlecase letters.
+    /// Conceptually, these characters consist of an uppercase portion followed by a lowercase portion.
+    ///
+    /// Titlecase letters (code points with the general category of `Lt`) are described in Chapter 4
+    /// (Character Properties) of the [Unicode Standard] and specified in the [Unicode Character
+    /// Database][ucd] [`UnicodeData.txt`].
+    ///
+    /// [Unicode Standard]: https://www.unicode.org/versions/latest/
+    /// [ucd]: https://www.unicode.org/reports/tr44/
+    /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(titlecase)]
+    /// assert!('Ç…'.is_titlecase());
+    /// assert!('ῼ'.is_titlecase());
+    /// assert!(!'D'.is_titlecase());
+    /// assert!(!'z'.is_titlecase());
+    /// assert!(!'中'.is_titlecase());
+    /// assert!(!' '.is_titlecase());
+    /// ```
+    #[must_use]
+    #[unstable(feature = "titlecase", issue = "153892")]
+    #[inline]
+    pub fn is_titlecase(self) -> bool {
+        match self {
+            '\0'..='\u{01C4}' => false,
+            _ => self.is_cased() && !self.is_lowercase() && !self.is_uppercase(),
         }
     }
 
@@ -860,7 +960,8 @@ pub const fn is_lowercase(self) -> bool {
     pub const fn is_uppercase(self) -> bool {
         match self {
             'A'..='Z' => true,
-            c => c > '\x7f' && unicode::Uppercase(c),
+            '\0'..='\u{BF}' => false,
+            _ => unicode::Uppercase(self),
         }
     }
 
@@ -893,7 +994,8 @@ pub const fn is_uppercase(self) -> bool {
     pub const fn is_whitespace(self) -> bool {
         match self {
             ' ' | '\x09'..='\x0d' => true,
-            c => c > '\x7f' && unicode::White_Space(c),
+            '\0'..='\u{84}' => false,
+            _ => unicode::White_Space(self),
         }
     }
 
@@ -920,10 +1022,10 @@ pub const fn is_whitespace(self) -> bool {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn is_alphanumeric(self) -> bool {
-        if self.is_ascii() {
-            self.is_ascii_alphanumeric()
-        } else {
-            unicode::Alphabetic(self) || unicode::N(self)
+        match self {
+            'a'..='z' | 'A'..='Z' | '0'..='9' => true,
+            '\0'..='\u{A9}' => false,
+            _ => unicode::Alphabetic(self) || unicode::N(self),
         }
     }
 
@@ -969,23 +1071,7 @@ pub fn is_control(self) -> bool {
     #[must_use]
     #[inline]
     pub(crate) fn is_grapheme_extended(self) -> bool {
-        !self.is_ascii() && unicode::Grapheme_Extend(self)
-    }
-
-    /// Returns `true` if this `char` has the `Cased` property.
-    ///
-    /// `Cased` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and
-    /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`].
-    ///
-    /// [Unicode Standard]: https://www.unicode.org/versions/latest/
-    /// [ucd]: https://www.unicode.org/reports/tr44/
-    /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
-    #[must_use]
-    #[inline]
-    #[doc(hidden)]
-    #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
-    pub fn is_cased(self) -> bool {
-        if self.is_ascii() { self.is_ascii_alphabetic() } else { unicode::Cased(self) }
+        self > '\u{02FF}' && unicode::Grapheme_Extend(self)
     }
 
     /// Returns `true` if this `char` has the `Case_Ignorable` property.
@@ -1047,7 +1133,8 @@ pub fn is_case_ignorable(self) -> bool {
     pub fn is_numeric(self) -> bool {
         match self {
             '0'..='9' => true,
-            c => c > '\x7f' && unicode::N(c),
+            '\0'..='\u{B1}' => false,
+            _ => unicode::N(self),
         }
     }
 
@@ -1110,7 +1197,7 @@ pub fn is_numeric(self) -> bool {
     /// // convert into themselves.
     /// assert_eq!('å±±'.to_lowercase().to_string(), "å±±");
     /// ```
-    #[must_use = "this returns the lowercase character as a new iterator, \
+    #[must_use = "this returns the lowercased character as a new iterator, \
                   without modifying the original"]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -1118,9 +1205,115 @@ pub fn to_lowercase(self) -> ToLowercase {
         ToLowercase(CaseMappingIter::new(conversions::to_lower(self)))
     }
 
+    /// Returns an iterator that yields the titlecase mapping of this `char` as one or more
+    /// `char`s.
+    ///
+    /// This is usually, but not always, equivalent to the uppercase mapping
+    /// returned by [`Self::to_uppercase`]. Prefer this method when seeking to capitalize
+    /// Only The First Letter of a word, but use [`Self::to_uppercase`] for ALL CAPS.
+    ///
+    /// If this `char` does not have an titlecase mapping, the iterator yields the same `char`.
+    ///
+    /// If this `char` has a one-to-one titlecase mapping given by the [Unicode Character
+    /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`.
+    ///
+    /// [ucd]: https://www.unicode.org/reports/tr44/
+    /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
+    ///
+    /// If this `char` requires special considerations (e.g. multiple `char`s) the iterator yields
+    /// the `char`(s) given by [`SpecialCasing.txt`].
+    ///
+    /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
+    ///
+    /// This operation performs an unconditional mapping without tailoring. That is, the conversion
+    /// is independent of context and language.
+    ///
+    /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in
+    /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion.
+    ///
+    /// [Unicode Standard]: https://www.unicode.org/versions/latest/
+    ///
+    /// # Examples
+    ///
+    /// As an iterator:
+    ///
+    /// ```
+    /// #![feature(titlecase)]
+    /// for c in 'ß'.to_titlecase() {
+    ///     print!("{c}");
+    /// }
+    /// println!();
+    /// ```
+    ///
+    /// Using `println!` directly:
+    ///
+    /// ```
+    /// #![feature(titlecase)]
+    /// println!("{}", 'ß'.to_titlecase());
+    /// ```
+    ///
+    /// Both are equivalent to:
+    ///
+    /// ```
+    /// println!("Ss");
+    /// ```
+    ///
+    /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
+    ///
+    /// ```
+    /// #![feature(titlecase)]
+    /// assert_eq!('c'.to_titlecase().to_string(), "C");
+    /// assert_eq!('dž'.to_titlecase().to_string(), "Dž");
+    /// assert_eq!('ῼ'.to_titlecase().to_string(), "ῼ");
+    ///
+    /// // Sometimes the result is more than one character:
+    /// assert_eq!('ß'.to_titlecase().to_string(), "Ss");
+    ///
+    /// // Characters that do not have separate cased forms
+    /// // convert into themselves.
+    /// assert_eq!('å±±'.to_titlecase().to_string(), "å±±");
+    /// ```
+    ///
+    /// # Note on locale
+    ///
+    /// In Turkish and Azeri, the equivalent of 'i' in Latin has five forms instead of two:
+    ///
+    /// * 'Dotless': I / ı, sometimes written ï
+    /// * 'Dotted': İ / i
+    ///
+    /// Note that the lowercase dotted 'i' is the same as the Latin. Therefore:
+    ///
+    /// ```
+    /// #![feature(titlecase)]
+    /// let upper_i = 'i'.to_titlecase().to_string();
+    /// ```
+    ///
+    /// The value of `upper_i` here relies on the language of the text: if we're
+    /// in `en-US`, it should be `"I"`, but if we're in `tr-TR` or `az-AZ`, it should
+    /// be `"İ"`. `to_titlecase()` does not take this into account, and so:
+    ///
+    /// ```
+    /// #![feature(titlecase)]
+    /// let upper_i = 'i'.to_titlecase().to_string();
+    ///
+    /// assert_eq!(upper_i, "I");
+    /// ```
+    ///
+    /// holds across languages.
+    #[must_use = "this returns the titlecased character as a new iterator, \
+                  without modifying the original"]
+    #[unstable(feature = "titlecase", issue = "153892")]
+    #[inline]
+    pub fn to_titlecase(self) -> ToTitlecase {
+        ToTitlecase(CaseMappingIter::new(conversions::to_title(self)))
+    }
+
     /// Returns an iterator that yields the uppercase mapping of this `char` as one or more
     /// `char`s.
     ///
+    /// Prefer this method when converting a word into ALL CAPS, but consider [`Self::to_titlecase`]
+    /// instead if you seek to capitalize Only The First Letter.
+    ///
     /// If this `char` does not have an uppercase mapping, the iterator yields the same `char`.
     ///
     /// If this `char` has a one-to-one uppercase mapping given by the [Unicode Character
@@ -1170,9 +1363,11 @@ pub fn to_lowercase(self) -> ToLowercase {
     ///
     /// ```
     /// assert_eq!('c'.to_uppercase().to_string(), "C");
+    /// assert_eq!('dž'.to_uppercase().to_string(), "DŽ");
     ///
     /// // Sometimes the result is more than one character:
     /// assert_eq!('ſt'.to_uppercase().to_string(), "ST");
+    /// assert_eq!('ῼ'.to_uppercase().to_string(), "ΩΙ");
     ///
     /// // Characters that do not have both uppercase and lowercase
     /// // convert into themselves.
@@ -1181,7 +1376,7 @@ pub fn to_lowercase(self) -> ToLowercase {
     ///
     /// # Note on locale
     ///
-    /// In Turkish, the equivalent of 'i' in Latin has five forms instead of two:
+    /// In Turkish and Azeri, the equivalent of 'i' in Latin has five forms instead of two:
     ///
     /// * 'Dotless': I / ı, sometimes written ï
     /// * 'Dotted': İ / i
@@ -1193,7 +1388,7 @@ pub fn to_lowercase(self) -> ToLowercase {
     /// ```
     ///
     /// The value of `upper_i` here relies on the language of the text: if we're
-    /// in `en-US`, it should be `"I"`, but if we're in `tr_TR`, it should
+    /// in `en-US`, it should be `"I"`, but if we're in `tr-TR` or `az-AZ`, it should
     /// be `"İ"`. `to_uppercase()` does not take this into account, and so:
     ///
     /// ```
@@ -1203,7 +1398,7 @@ pub fn to_lowercase(self) -> ToLowercase {
     /// ```
     ///
     /// holds across languages.
-    #[must_use = "this returns the uppercase character as a new iterator, \
+    #[must_use = "this returns the uppercased character as a new iterator, \
                   without modifying the original"]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -1446,7 +1641,7 @@ pub const fn make_ascii_lowercase(&mut self) {
     #[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
     #[inline]
     pub const fn is_ascii_alphabetic(&self) -> bool {
-        matches!(*self, 'A'..='Z' | 'a'..='z')
+        matches!(*self, 'a'..='z' | 'A'..='Z')
     }
 
     /// Checks if the value is an ASCII uppercase character:
diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs
index 82a3f6f..3231c41 100644
--- a/library/core/src/char/mod.rs
+++ b/library/core/src/char/mod.rs
@@ -363,13 +363,21 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 }
 
 macro_rules! casemappingiter_impls {
-    ($(#[$attr:meta])* $ITER_NAME:ident) => {
+    (
+        #[$stab:meta]
+        #[$dendstab:meta]
+        #[$fusedstab:meta]
+        #[$exactstab:meta]
+        #[$displaystab:meta]
+        $(#[$attr:meta])*
+        $ITER_NAME:ident
+    ) => {
         $(#[$attr])*
-        #[stable(feature = "rust1", since = "1.0.0")]
+        #[$stab]
         #[derive(Debug, Clone)]
         pub struct $ITER_NAME(CaseMappingIter);
 
-        #[stable(feature = "rust1", since = "1.0.0")]
+        #[$stab]
         impl Iterator for $ITER_NAME {
             type Item = char;
             fn next(&mut self) -> Option<char> {
@@ -405,7 +413,7 @@ unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
             }
         }
 
-        #[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
+        #[$dendstab]
         impl DoubleEndedIterator for $ITER_NAME {
             fn next_back(&mut self) -> Option<char> {
                 self.0.next_back()
@@ -423,10 +431,10 @@ fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
             }
         }
 
-        #[stable(feature = "fused", since = "1.26.0")]
+        #[$fusedstab]
         impl FusedIterator for $ITER_NAME {}
 
-        #[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
+        #[$exactstab]
         impl ExactSizeIterator for $ITER_NAME {
             fn len(&self) -> usize {
                 self.0.len()
@@ -453,7 +461,7 @@ unsafe impl TrustedRandomAccessNoCoerce for $ITER_NAME {
         #[unstable(feature = "std_internals", issue = "none")]
         unsafe impl TrustedRandomAccess for $ITER_NAME {}
 
-        #[stable(feature = "char_struct_display", since = "1.16.0")]
+        #[$displaystab]
         impl fmt::Display for $ITER_NAME {
             #[inline]
             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -464,16 +472,11 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 }
 
 casemappingiter_impls! {
-    /// Returns an iterator that yields the lowercase equivalent of a `char`.
-    ///
-    /// This `struct` is created by the [`to_lowercase`] method on [`char`]. See
-    /// its documentation for more.
-    ///
-    /// [`to_lowercase`]: char::to_lowercase
-    ToLowercase
-}
-
-casemappingiter_impls! {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
+    #[stable(feature = "fused", since = "1.26.0")]
+    #[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
+    #[stable(feature = "char_struct_display", since = "1.16.0")]
     /// Returns an iterator that yields the uppercase equivalent of a `char`.
     ///
     /// This `struct` is created by the [`to_uppercase`] method on [`char`]. See
@@ -483,6 +486,36 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     ToUppercase
 }
 
+casemappingiter_impls! {
+    #[unstable(feature = "titlecase", issue = "153892")]
+    #[unstable(feature = "titlecase", issue = "153892")]
+    #[unstable(feature = "titlecase", issue = "153892")]
+    #[unstable(feature = "titlecase", issue = "153892")]
+    #[unstable(feature = "titlecase", issue = "153892")]
+    /// Returns an iterator that yields the titlecase equivalent of a `char`.
+    ///
+    /// This `struct` is created by the [`to_titlecase`] method on [`char`]. See
+    /// its documentation for more.
+    ///
+    /// [`to_titlecase`]: char::to_titlecase
+    ToTitlecase
+}
+
+casemappingiter_impls! {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
+    #[stable(feature = "fused", since = "1.26.0")]
+    #[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
+    #[stable(feature = "char_struct_display", since = "1.16.0")]
+    /// Returns an iterator that yields the lowercase equivalent of a `char`.
+    ///
+    /// This `struct` is created by the [`to_lowercase`] method on [`char`]. See
+    /// its documentation for more.
+    ///
+    /// [`to_lowercase`]: char::to_lowercase
+    ToLowercase
+}
+
 #[derive(Debug, Clone)]
 struct CaseMappingIter(core::array::IntoIter<char, 3>);
 
@@ -603,3 +636,23 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 #[stable(feature = "u8_from_char", since = "1.59.0")]
 impl Error for TryFromCharError {}
+
+/// The case of a cased character,
+/// as returned by [`char::case`].
+///
+/// Titlecase characters conceptually are composed of an uppercase portion
+/// followed by a lowercase portion.
+/// The variant discriminants represent this:
+/// the most significant bit represents whether the case
+/// conceptually starts as uppercase, while the least significant bit
+/// represents whether it conceptually ends as uppercase.
+#[unstable(feature = "titlecase", issue = "153892")]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub enum CharCase {
+    /// Lowercase. Corresponds to the `Lowercase` Unicode property.
+    Lower = 0b00,
+    /// Titlecase. Corresponds to the `Titlecase_Letter` Unicode general category.
+    Title = 0b10,
+    /// Uppercase. Corresponds to the `Uppercase` Unicode property.
+    Upper = 0b11,
+}
diff --git a/library/core/src/ffi/va_list.rs b/library/core/src/ffi/va_list.rs
index b6dfe3a..f0f58a0 100644
--- a/library/core/src/ffi/va_list.rs
+++ b/library/core/src/ffi/va_list.rs
@@ -244,7 +244,7 @@ pub(crate) const fn duplicate(&self) -> Self {
 
 #[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
 impl<'f> const Clone for VaList<'f> {
-    #[inline]
+    #[inline] // Avoid codegen when not used to help backends that don't support VaList.
     fn clone(&self) -> Self {
         // We only implement Clone and not Copy because some future target might not be able to
         // implement Copy (e.g. because it allocates). For the same reason we use an intrinsic
@@ -256,6 +256,7 @@ fn clone(&self) -> Self {
 
 #[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
 impl<'f> const Drop for VaList<'f> {
+    #[inline] // Avoid codegen when not used to help backends that don't support VaList.
     fn drop(&mut self) {
         // SAFETY: this variable argument list is being dropped, so won't be read from again.
         unsafe { va_end(self) }
@@ -326,7 +327,7 @@ impl<'f> VaList<'f> {
     ///
     /// Calling this function with an incompatible type, an invalid value, or when there
     /// are no more variable arguments, is unsound.
-    #[inline]
+    #[inline] // Avoid codegen when not used to help backends that don't support VaList.
     #[rustc_const_unstable(feature = "const_c_variadic", issue = "151787")]
     pub const unsafe fn arg<T: VaArgSafe>(&mut self) -> T {
         // SAFETY: the caller must uphold the safety contract for `va_arg`.
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 05d8e0d..ecd1e34 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -1037,9 +1037,10 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(
     on(
-        crate_local,
+        all(crate_local, not(Self = "{union}")),
         note = "add `#[derive(Debug)]` to `{Self}` or manually `impl {This} for {Self}`"
     ),
+    on(all(crate_local, Self = "{union}"), note = "manually `impl {This} for {Self}`"),
     on(
         from_desugaring = "FormatLiteral",
         label = "`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{This}`"
diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs
index dfa27e3..e9302a6 100644
--- a/library/core/src/fmt/num.rs
+++ b/library/core/src/fmt/num.rs
@@ -594,6 +594,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 // Include wasm32 in here since it doesn't reflect the native pointer size, and
 // often cares strongly about getting a smaller code size.
 #[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
+#[doc(auto_cfg = false)]
 mod imp {
     use super::*;
     impl_Display!(i8, u8, i16, u16, i32, u32, i64, u64, isize, usize; as u64 into display_u64);
@@ -601,6 +602,7 @@ mod imp {
 }
 
 #[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]
+#[doc(auto_cfg = false)]
 mod imp {
     use super::*;
     impl_Display!(i8, u8, i16, u16, i32, u32, isize, usize; as u32 into display_u32);
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index 68e4f1c..128df65 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -2502,14 +2502,6 @@ const fn compiletime$(<$($binders)*>)?($($arg: $ty),*) $( -> $ret )? {
 /// particular value, ever. However, the compiler will generally make it
 /// return `true` only if the value of the argument is actually known.
 ///
-/// # Stability concerns
-///
-/// While it is safe to call, this intrinsic may behave differently in
-/// a `const` context than otherwise. See the [`const_eval_select()`]
-/// documentation for an explanation of the issues this can cause. Unlike
-/// `const_eval_select`, this intrinsic isn't guaranteed to behave
-/// deterministically even in a `const` context.
-///
 /// # Type Requirements
 ///
 /// `T` must be either a `bool`, a `char`, a primitive numeric type (e.g. `f32`,
@@ -2590,6 +2582,12 @@ pub const fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
 /// assertions are enabled whenever the *user crate* has UB checks enabled. However, if the
 /// user has UB checks disabled, the checks will still get optimized out. This intrinsic is
 /// primarily used by [`crate::ub_checks::assert_unsafe_precondition`].
+///
+/// # Consteval
+///
+/// In consteval, this function currently returns `true`. This is because the value of the `ub_checks`
+/// configuration can differ across crates, but we need this function to always return the same
+/// value in consteval in order to avoid unsoundness.
 #[rustc_intrinsic_const_stable_indirect] // just for UB checks
 #[inline(always)]
 #[rustc_intrinsic]
@@ -2609,6 +2607,12 @@ pub const fn ub_checks() -> bool {
 /// `#[inline]`), gating assertions on `overflow_checks()` rather than `cfg!(overflow_checks)` means that
 /// assertions are enabled whenever the *user crate* has overflow checks enabled. However if the
 /// user has overflow checks disabled, the checks will still get optimized out.
+///
+/// # Consteval
+///
+/// In consteval, this function currently returns `true`. This is because the value of the `overflow_checks`
+/// configuration can differ across crates, but we need this function to always return the same
+/// value in consteval in order to avoid unsoundness.
 #[inline(always)]
 #[rustc_intrinsic]
 pub const fn overflow_checks() -> bool {
diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs
index bb94ed0..f64dea2 100644
--- a/library/core/src/iter/adapters/intersperse.rs
+++ b/library/core/src/iter/adapters/intersperse.rs
@@ -1,5 +1,4 @@
 use crate::fmt;
-use crate::iter::{Fuse, FusedIterator};
 
 /// An iterator adapter that places a separator between all elements.
 ///
@@ -14,15 +13,7 @@ pub struct Intersperse<I: Iterator>
     started: bool,
     separator: I::Item,
     next_item: Option<I::Item>,
-    iter: Fuse<I>,
-}
-
-#[unstable(feature = "iter_intersperse", issue = "79524")]
-impl<I> FusedIterator for Intersperse<I>
-where
-    I: FusedIterator,
-    I::Item: Clone,
-{
+    iter: I,
 }
 
 impl<I: Iterator> Intersperse<I>
@@ -30,7 +21,7 @@ impl<I: Iterator> Intersperse<I>
     I::Item: Clone,
 {
     pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self {
-        Self { started: false, separator, next_item: None, iter: iter.fuse() }
+        Self { started: false, separator, next_item: None, iter }
     }
 }
 
@@ -57,8 +48,9 @@ fn next(&mut self) -> Option<Self::Item> {
                 }
             }
         } else {
-            self.started = true;
-            self.iter.next()
+            let item = self.iter.next();
+            self.started = item.is_some();
+            item
         }
     }
 
@@ -95,15 +87,7 @@ pub struct IntersperseWith<I, G>
     started: bool,
     separator: G,
     next_item: Option<I::Item>,
-    iter: Fuse<I>,
-}
-
-#[unstable(feature = "iter_intersperse", issue = "79524")]
-impl<I, G> FusedIterator for IntersperseWith<I, G>
-where
-    I: FusedIterator,
-    G: FnMut() -> I::Item,
-{
+    iter: I,
 }
 
 #[unstable(feature = "iter_intersperse", issue = "79524")]
@@ -146,7 +130,7 @@ impl<I, G> IntersperseWith<I, G>
     G: FnMut() -> I::Item,
 {
     pub(in crate::iter) fn new(iter: I, separator: G) -> Self {
-        Self { started: false, separator, next_item: None, iter: iter.fuse() }
+        Self { started: false, separator, next_item: None, iter }
     }
 }
 
@@ -173,8 +157,9 @@ fn next(&mut self) -> Option<Self::Item> {
                 }
             }
         } else {
-            self.started = true;
-            self.iter.next()
+            let item = self.iter.next();
+            self.started = item.is_some();
+            item
         }
     }
 
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 2e82f45..11b1c04 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -635,11 +635,24 @@ fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter>
     /// of the original iterator.
     ///
     /// Specifically on fused iterators, it is guaranteed that the new iterator
-    /// places a copy of `separator` between adjacent `Some(_)` items. However,
-    /// for non-fused iterators, [`intersperse`] will create a new iterator that
-    /// is a fused version of the original iterator and place a copy of `separator`
-    /// between adjacent `Some(_)` items. This behavior for non-fused iterators
-    /// is subject to change.
+    /// places a copy of `separator` between *adjacent* `Some(_)` items. For non-fused iterators,
+    /// it is guaranteed that [`intersperse`] will create a new iterator that places a copy
+    /// of `separator` between `Some(_)` items, particularly just right before the subsequent
+    /// `Some(_)` item.
+    ///
+    /// For example, consider the following non-fused iterator:
+    ///
+    /// ```text
+    /// Some(1) -> Some(2) -> None -> Some(3) -> Some(4) -> ...
+    /// ```
+    ///
+    /// If this non-fused iterator were to be interspersed with `0`,
+    /// then the interspersed iterator will produce:
+    ///
+    /// ```text
+    /// Some(1) -> Some(0) -> Some(2) -> None -> Some(0) -> Some(3) -> Some(0) ->
+    /// Some(4) -> ...
+    /// ```
     ///
     /// In case `separator` does not implement [`Clone`] or needs to be
     /// computed every time, use [`intersperse_with`].
@@ -688,10 +701,23 @@ fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
     ///
     /// Specifically on fused iterators, it is guaranteed that the new iterator
     /// places an item generated by `separator` between adjacent `Some(_)` items.
-    /// However, for non-fused iterators, [`intersperse_with`] will create a new
-    /// iterator that is a fused version of the original iterator and place an item
-    /// generated by `separator` between adjacent `Some(_)` items. This
-    /// behavior for non-fused iterators is subject to change.
+    /// For non-fused iterators, it is guaranteed that [`intersperse_with`] will
+    /// create a new iterator that places an item generated by `separator` between `Some(_)`
+    /// items, particularly just right before the subsequent `Some(_)` item.
+    ///
+    /// For example, consider the following non-fused iterator:
+    ///
+    /// ```text
+    /// Some(1) -> Some(2) -> None -> Some(3) -> Some(4) -> ...
+    /// ```
+    ///
+    /// If this non-fused iterator were to be interspersed with a `separator` closure
+    /// that returns `0` repeatedly, the interspersed iterator will produce:
+    ///
+    /// ```text
+    /// Some(1) -> Some(0) -> Some(2) -> None -> Some(0) -> Some(3) -> Some(0) ->
+    /// Some(4) -> ...
+    /// ```
     ///
     /// The `separator` closure will be called exactly once each time an item
     /// is placed between two adjacent items from the underlying iterator;
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index ae8324c..27dbe6d 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -447,7 +447,7 @@ pub const fn rotate_right(self, n: u32) -> Self {
         pub const fn funnel_shl(self, rhs: Self, n: u32) -> Self {
             assert!(n < Self::BITS, "attempt to funnel shift left with overflow");
             // SAFETY: just checked that `shift` is in-range
-            unsafe { intrinsics::unchecked_funnel_shl(self, rhs, n) }
+            unsafe { self.unchecked_funnel_shl(rhs, n) }
         }
 
         /// Performs a right funnel shift (concatenates `self` and `rhs`, with `self`
@@ -482,7 +482,61 @@ pub const fn funnel_shl(self, rhs: Self, n: u32) -> Self {
         pub const fn funnel_shr(self, rhs: Self, n: u32) -> Self {
             assert!(n < Self::BITS, "attempt to funnel shift right with overflow");
             // SAFETY: just checked that `shift` is in-range
-            unsafe { intrinsics::unchecked_funnel_shr(self, rhs, n) }
+            unsafe { self.unchecked_funnel_shr(rhs, n) }
+        }
+
+        /// Unchecked funnel shift left.
+        ///
+        /// # Safety
+        ///
+        /// This results in undefined behavior if `n` is greater than or equal to
+        #[doc = concat!("`", stringify!($SelfT) , "::BITS`,")]
+        /// i.e. when [`funnel_shl`](Self::funnel_shl) would panic.
+        ///
+        #[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")]
+        #[unstable(feature = "funnel_shifts", issue = "145686")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline(always)]
+        #[track_caller]
+        pub const unsafe fn unchecked_funnel_shl(self, low: Self, n: u32) -> Self {
+            assert_unsafe_precondition!(
+                check_language_ub,
+                concat!(stringify!($SelfT), "::unchecked_funnel_shl cannot overflow"),
+                (n: u32 = n) => n < <$ActualT>::BITS,
+            );
+
+            // SAFETY: this is guaranteed to be safe by the caller.
+            unsafe {
+                intrinsics::unchecked_funnel_shl(self, low, n)
+            }
+        }
+
+        /// Unchecked funnel shift right.
+        ///
+        /// # Safety
+        ///
+        /// This results in undefined behavior if `n` is greater than or equal to
+        #[doc = concat!("`", stringify!($SelfT) , "::BITS`,")]
+        /// i.e. when [`funnel_shr`](Self::funnel_shr) would panic.
+        ///
+        #[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")]
+        #[unstable(feature = "funnel_shifts", issue = "145686")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline(always)]
+        #[track_caller]
+        pub const unsafe fn unchecked_funnel_shr(self, low: Self, n: u32) -> Self {
+            assert_unsafe_precondition!(
+                check_language_ub,
+                concat!(stringify!($SelfT), "::unchecked_funnel_shr cannot overflow"),
+                (n: u32 = n) => n < <$ActualT>::BITS,
+            );
+
+            // SAFETY: this is guaranteed to be safe by the caller.
+            unsafe {
+                intrinsics::unchecked_funnel_shr(self, low, n)
+            }
         }
 
         /// Performs a carry-less multiplication, returning the lower bits.
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index eb92e62..ffdcd9f 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -1829,9 +1829,10 @@ impl<Ptr, U> DispatchFromDyn<Pin<U>> for Pin<Ptr>
 ///
 /// # Safety
 ///
-/// If this type implements `Deref`, then the concrete type returned by `deref`
-/// and `deref_mut` must not change without a modification. The following
-/// operations are not considered modifications:
+/// Given a pointer of this type, the concrete type returned by its
+/// `deref` method and (if it implements `DerefMut`) its `deref_mut` method
+/// must be the same type and must not change without a modification.
+/// The following operations are not considered modifications:
 ///
 /// * Moving the pointer.
 /// * Performing unsizing coercions on the pointer.
@@ -1842,7 +1843,7 @@ impl<Ptr, U> DispatchFromDyn<Pin<U>> for Pin<Ptr>
 /// to. The concrete type of a slice is an array of the same element type and
 /// the length specified in the metadata. The concrete type of a sized type
 /// is the type itself.
-pub unsafe trait PinCoerceUnsized {}
+pub unsafe trait PinCoerceUnsized: Deref {}
 
 #[stable(feature = "pin", since = "1.33.0")]
 unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a T {}
@@ -1853,12 +1854,6 @@ unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a mut T {}
 #[stable(feature = "pin", since = "1.33.0")]
 unsafe impl<T: PinCoerceUnsized> PinCoerceUnsized for Pin<T> {}
 
-#[stable(feature = "pin", since = "1.33.0")]
-unsafe impl<T: ?Sized> PinCoerceUnsized for *const T {}
-
-#[stable(feature = "pin", since = "1.33.0")]
-unsafe impl<T: ?Sized> PinCoerceUnsized for *mut T {}
-
 /// Constructs a <code>[Pin]<[&mut] T></code>, by pinning a `value: T` locally.
 ///
 /// Unlike [`Box::pin`], this does not create a new heap allocation. As explained
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index 8be7d3a..2421fea 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -4,7 +4,6 @@
 use crate::mem::{MaybeUninit, SizedTypeProperties, transmute};
 use crate::num::NonZero;
 use crate::ops::{CoerceUnsized, DispatchFromDyn};
-use crate::pin::PinCoerceUnsized;
 use crate::ptr::Unique;
 use crate::slice::{self, SliceIndex};
 use crate::ub_checks::assert_unsafe_precondition;
@@ -139,8 +138,9 @@ pub const fn dangling() -> Self {
     ///
     /// This is an [Exposed Provenance][crate::ptr#exposed-provenance] API.
     #[stable(feature = "nonnull_provenance", since = "1.89.0")]
+    #[rustc_const_unstable(feature = "const_nonnull_with_exposed_provenance", issue = "154215")]
     #[inline]
-    pub fn with_exposed_provenance(addr: NonZero<usize>) -> Self {
+    pub const fn with_exposed_provenance(addr: NonZero<usize>) -> Self {
         // SAFETY: we know `addr` is non-zero.
         unsafe {
             let ptr = crate::ptr::with_exposed_provenance_mut(addr.get());
@@ -1692,9 +1692,6 @@ impl<T: PointeeSized, U: PointeeSized> CoerceUnsized<NonNull<U>> for NonNull<T>
 #[unstable(feature = "dispatch_from_dyn", issue = "none")]
 impl<T: PointeeSized, U: PointeeSized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
 
-#[stable(feature = "pin", since = "1.33.0")]
-unsafe impl<T: PointeeSized> PinCoerceUnsized for NonNull<T> {}
-
 #[stable(feature = "nonnull", since = "1.25.0")]
 impl<T: PointeeSized> fmt::Debug for NonNull<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs
index 3160c9d..6e55f0e 100644
--- a/library/core/src/ptr/unique.rs
+++ b/library/core/src/ptr/unique.rs
@@ -2,7 +2,6 @@
 use crate::fmt;
 use crate::marker::{PhantomData, PointeeSized, Unsize};
 use crate::ops::{CoerceUnsized, DispatchFromDyn};
-use crate::pin::PinCoerceUnsized;
 use crate::ptr::NonNull;
 
 /// A wrapper around a raw non-null `*mut T` that indicates that the possessor
@@ -176,9 +175,6 @@ impl<T: PointeeSized, U: PointeeSized> CoerceUnsized<Unique<U>> for Unique<T> wh
 #[unstable(feature = "ptr_internals", issue = "none")]
 impl<T: PointeeSized, U: PointeeSized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
 
-#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
-unsafe impl<T: PointeeSized> PinCoerceUnsized for Unique<T> {}
-
 #[unstable(feature = "ptr_internals", issue = "none")]
 impl<T: PointeeSized> fmt::Debug for Unique<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/library/core/src/range/iter.rs b/library/core/src/range/iter.rs
index c1d4fbb..23ace6e 100644
--- a/library/core/src/range/iter.rs
+++ b/library/core/src/range/iter.rs
@@ -298,9 +298,9 @@ impl ExactSizeIterator for RangeInclusiveIter<$t> { }
 #[derive(Debug, Clone)]
 pub struct RangeFromIter<A> {
     start: A,
-    /// Whether the first element of the iterator has yielded.
+    /// Whether the maximum value of the iterator has yielded.
     /// Only used when overflow checks are enabled.
-    first: bool,
+    exhausted: bool,
 }
 
 impl<A: Step> RangeFromIter<A> {
@@ -309,10 +309,12 @@ impl<A: Step> RangeFromIter<A> {
     #[rustc_inherit_overflow_checks]
     #[unstable(feature = "new_range_api", issue = "125687")]
     pub fn remainder(self) -> RangeFrom<A> {
-        if intrinsics::overflow_checks() {
-            if !self.first {
-                return RangeFrom { start: Step::forward(self.start, 1) };
-            }
+        // Need to handle this case even if overflow-checks are disabled,
+        // because a `RangeFromIter` could be exhausted in a crate with
+        // overflow-checks enabled, but then passed to a crate with them
+        // disabled before this is called.
+        if self.exhausted {
+            return RangeFrom { start: Step::forward(self.start, 1) };
         }
 
         RangeFrom { start: self.start }
@@ -326,14 +328,29 @@ impl<A: Step> Iterator for RangeFromIter<A> {
     #[inline]
     #[rustc_inherit_overflow_checks]
     fn next(&mut self) -> Option<A> {
-        if intrinsics::overflow_checks() {
-            if self.first {
-                self.first = false;
-                return Some(self.start.clone());
-            }
-
+        if self.exhausted {
+            // This should panic if overflow checks are enabled, since
+            // `forward_checked` returned `None` in prior iteration.
             self.start = Step::forward(self.start.clone(), 1);
-            return Some(self.start.clone());
+
+            // If we get here, if means this iterator was exhausted by a crate
+            // with overflow-checks enabled, but now we're iterating in a crate with
+            // overflow-checks disabled. Since we successfully incremented `self.start`
+            // above (in many cases this will wrap around to MIN), we now unset
+            // the flag so we don't repeat this process in the next iteration.
+            //
+            // This could also happen if `forward_checked` returned None but
+            // (for whatever reason, not applicable to any std implementors)
+            // `forward` doesn't panic when overflow-checks are enabled. In that
+            // case, this is also the correct behavior.
+            self.exhausted = false;
+        }
+        if intrinsics::overflow_checks() {
+            let Some(n) = Step::forward_checked(self.start.clone(), 1) else {
+                self.exhausted = true;
+                return Some(self.start.clone());
+            };
+            return Some(mem::replace(&mut self.start, n));
         }
 
         let n = Step::forward(self.start.clone(), 1);
@@ -348,18 +365,22 @@ fn size_hint(&self) -> (usize, Option<usize>) {
     #[inline]
     #[rustc_inherit_overflow_checks]
     fn nth(&mut self, n: usize) -> Option<A> {
+        // Typically `forward` will cause an overflow-check panic here,
+        // but unset the exhausted flag to handle the uncommon cases.
+        // See the comments in `next` for more details.
+        if self.exhausted {
+            self.start = Step::forward(self.start.clone(), 1);
+            self.exhausted = false;
+        }
         if intrinsics::overflow_checks() {
-            if self.first {
-                self.first = false;
-
-                let plus_n = Step::forward(self.start.clone(), n);
-                self.start = plus_n.clone();
-                return Some(plus_n);
-            }
-
             let plus_n = Step::forward(self.start.clone(), n);
-            self.start = Step::forward(plus_n.clone(), 1);
-            return Some(self.start.clone());
+            if let Some(plus_n1) = Step::forward_checked(plus_n.clone(), 1) {
+                self.start = plus_n1;
+            } else {
+                self.start = plus_n.clone();
+                self.exhausted = true;
+            }
+            return Some(plus_n);
         }
 
         let plus_n = Step::forward(self.start.clone(), n);
@@ -380,6 +401,6 @@ impl<A: Step> IntoIterator for RangeFrom<A> {
     type IntoIter = RangeFromIter<A>;
 
     fn into_iter(self) -> Self::IntoIter {
-        RangeFromIter { start: self.start, first: true }
+        RangeFromIter { start: self.start, exhausted: false }
     }
 }
diff --git a/library/core/src/unicode/mod.rs b/library/core/src/unicode/mod.rs
index 4c220e3..22a1166 100644
--- a/library/core/src/unicode/mod.rs
+++ b/library/core/src/unicode/mod.rs
@@ -4,12 +4,12 @@
 
 // for use in alloc, not re-exported in std.
 #[rustfmt::skip]
-pub use unicode_data::case_ignorable::lookup as Case_Ignorable;
-pub use unicode_data::cased::lookup as Cased;
 pub use unicode_data::conversions;
 
 #[rustfmt::skip]
 pub(crate) use unicode_data::alphabetic::lookup as Alphabetic;
+pub(crate) use unicode_data::case_ignorable::lookup as Case_Ignorable;
+pub(crate) use unicode_data::cased::lookup as Cased;
 pub(crate) use unicode_data::grapheme_extend::lookup as Grapheme_Extend;
 pub(crate) use unicode_data::lowercase::lookup as Lowercase;
 pub(crate) use unicode_data::n::lookup as N;
diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs
index dd37126..f602cd5 100644
--- a/library/core/src/unicode/unicode_data.rs
+++ b/library/core/src/unicode/unicode_data.rs
@@ -9,7 +9,8 @@
 // White_Space     :   256 bytes,     19 codepoints in   8 ranges (U+000085 - U+003001) using cascading
 // to_lower        :  1112 bytes,   1462 codepoints in 185 ranges (U+0000C0 - U+01E921) using 2-level LUT
 // to_upper        :  1998 bytes,   1554 codepoints in 299 ranges (U+0000B5 - U+01E943) using 2-level LUT
-// Total           :  9657 bytes
+// to_title        :   340 bytes,    135 codepoints in  49 ranges (U+0000DF - U+00FB17) using 2-level LUT
+// Total           :  9997 bytes
 
 #[inline(always)]
 const fn bitset_search<
@@ -823,14 +824,10 @@ unsafe fn reconstruct(plane: u16, low: u16) -> char {
         unsafe { char::from_u32_unchecked(((plane as u32) << 16) | (low as u32)) }
     }
 
-    fn lookup(input: char, ascii: char, l1_lut: &L1Lut) -> [char; 3] {
-        if input.is_ascii() {
-            return [ascii, '\0', '\0'];
-        }
-
+    fn lookup(input: char, l1_lut: &L1Lut) -> Option<[char; 3]> {
         let (input_high, input_low) = deconstruct(input);
         let Some(l2_lut) = l1_lut.l2_luts.get(input_high as usize) else {
-            return [input, '\0', '\0'];
+            return None;
         };
 
         let idx = l2_lut.singles.binary_search_by(|(range, _)| {
@@ -844,6 +841,7 @@ unsafe fn reconstruct(plane: u16, low: u16) -> char {
                 Ordering::Equal
             }
         });
+
         if let Ok(idx) = idx {
             // SAFETY: binary search guarantees that the index is in bounds.
             let &(range, output_delta) = unsafe { l2_lut.singles.get_unchecked(idx) };
@@ -852,7 +850,7 @@ unsafe fn reconstruct(plane: u16, low: u16) -> char {
                 let output_low = input_low.wrapping_add_signed(output_delta);
                 // SAFETY: Table data are guaranteed to be valid Unicode.
                 let output = unsafe { reconstruct(input_high, output_low) };
-                return [output, '\0', '\0'];
+                return Some([output, '\0', '\0']);
             }
         };
 
@@ -861,18 +859,37 @@ unsafe fn reconstruct(plane: u16, low: u16) -> char {
             let &(_, output_lows) = unsafe { l2_lut.multis.get_unchecked(idx) };
             // SAFETY: Table data are guaranteed to be valid Unicode.
             let output = output_lows.map(|output_low| unsafe { reconstruct(input_high, output_low) });
-            return output;
+            return Some(output);
         };
 
-        [input, '\0', '\0']
+        None
     }
 
     pub fn to_lower(c: char) -> [char; 3] {
-        lookup(c, c.to_ascii_lowercase(), &LOWERCASE_LUT)
+        // https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%253AChanges_When_Lowercased%253A%5D-%5B%253AASCII%253A%5D&abb=on
+        if c < '\u{C0}' {
+            return [c.to_ascii_lowercase(), '\0', '\0'];
+        }
+
+        lookup(c, &LOWERCASE_LUT).unwrap_or([c, '\0', '\0'])
     }
 
     pub fn to_upper(c: char) -> [char; 3] {
-        lookup(c, c.to_ascii_uppercase(), &UPPERCASE_LUT)
+        // https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%253AChanges_When_Uppercased%253A%5D-%5B%253AASCII%253A%5D&abb=on
+        if c < '\u{B5}' {
+            return [c.to_ascii_uppercase(), '\0', '\0'];
+        }
+
+        lookup(c, &UPPERCASE_LUT).unwrap_or([c, '\0', '\0'])
+    }
+
+    pub fn to_title(c: char) -> [char; 3] {
+        // https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%253AChanges_When_Titlecased%253A%5D-%5B%253AASCII%253A%5D&abb=on
+        if c < '\u{B5}' {
+            return [c.to_ascii_uppercase(), '\0', '\0'];
+        }
+
+        lookup(c, &TITLECASE_LUT).or_else(|| lookup(c, &UPPERCASE_LUT)).unwrap_or([c, '\0', '\0'])
     }
 
     static LOWERCASE_LUT: L1Lut = L1Lut {
@@ -1150,4 +1167,45 @@ unsafe fn reconstruct(plane: u16, low: u16) -> char {
             },
         ],
     };
+
+    static TITLECASE_LUT: L1Lut = L1Lut {
+        l2_luts: [
+            L2Lut {
+                singles: &[ // 26 entries, 156 bytes
+                    (Range::singleton(0x01c4), 1), (Range::singleton(0x01c5), 0),
+                    (Range::singleton(0x01c6), -1), (Range::singleton(0x01c7), 1),
+                    (Range::singleton(0x01c8), 0), (Range::singleton(0x01c9), -1),
+                    (Range::singleton(0x01ca), 1), (Range::singleton(0x01cb), 0),
+                    (Range::singleton(0x01cc), -1), (Range::singleton(0x01f1), 1),
+                    (Range::singleton(0x01f2), 0), (Range::singleton(0x01f3), -1),
+                    (Range::step_by_1(0x10d0..=0x10fa), 0), (Range::step_by_1(0x10fd..=0x10ff), 0),
+                    (Range::step_by_1(0x1f80..=0x1f87), 8), (Range::step_by_1(0x1f88..=0x1f8f), 0),
+                    (Range::step_by_1(0x1f90..=0x1f97), 8), (Range::step_by_1(0x1f98..=0x1f9f), 0),
+                    (Range::step_by_1(0x1fa0..=0x1fa7), 8), (Range::step_by_1(0x1fa8..=0x1faf), 0),
+                    (Range::singleton(0x1fb3), 9), (Range::singleton(0x1fbc), 0), (Range::singleton(0x1fc3), 9),
+                    (Range::singleton(0x1fcc), 0), (Range::singleton(0x1ff3), 9), (Range::singleton(0x1ffc), 0),
+                ],
+                multis: &[ // 23 entries, 184 bytes
+                    (0x00df, [0x0053, 0x0073, 0x0000]), (0x0587, [0x0535, 0x0582, 0x0000]),
+                    (0x1fb2, [0x1fba, 0x0345, 0x0000]), (0x1fb4, [0x0386, 0x0345, 0x0000]),
+                    (0x1fb7, [0x0391, 0x0342, 0x0345]), (0x1fc2, [0x1fca, 0x0345, 0x0000]),
+                    (0x1fc4, [0x0389, 0x0345, 0x0000]), (0x1fc7, [0x0397, 0x0342, 0x0345]),
+                    (0x1ff2, [0x1ffa, 0x0345, 0x0000]), (0x1ff4, [0x038f, 0x0345, 0x0000]),
+                    (0x1ff7, [0x03a9, 0x0342, 0x0345]), (0xfb00, [0x0046, 0x0066, 0x0000]),
+                    (0xfb01, [0x0046, 0x0069, 0x0000]), (0xfb02, [0x0046, 0x006c, 0x0000]),
+                    (0xfb03, [0x0046, 0x0066, 0x0069]), (0xfb04, [0x0046, 0x0066, 0x006c]),
+                    (0xfb05, [0x0053, 0x0074, 0x0000]), (0xfb06, [0x0053, 0x0074, 0x0000]),
+                    (0xfb13, [0x0544, 0x0576, 0x0000]), (0xfb14, [0x0544, 0x0565, 0x0000]),
+                    (0xfb15, [0x0544, 0x056b, 0x0000]), (0xfb16, [0x054e, 0x0576, 0x0000]),
+                    (0xfb17, [0x0544, 0x056d, 0x0000]),
+                ],
+            },
+            L2Lut {
+                singles: &[ // 0 entries, 0 bytes
+                ],
+                multis: &[ // 0 entries, 0 bytes
+                ],
+            },
+        ],
+    };
 }
diff --git a/library/coretests/benches/lib.rs b/library/coretests/benches/lib.rs
index 6b65eca..e8dc815 100644
--- a/library/coretests/benches/lib.rs
+++ b/library/coretests/benches/lib.rs
@@ -8,7 +8,9 @@
 #![feature(iter_array_chunks)]
 #![feature(iter_next_chunk)]
 #![feature(iter_advance_by)]
+#![feature(num_internals)]
 #![feature(uint_gather_scatter_bits)]
+#![allow(internal_features)]
 
 extern crate test;
 
diff --git a/library/coretests/tests/array.rs b/library/coretests/tests/array.rs
index 2b44290..43fed94 100644
--- a/library/coretests/tests/array.rs
+++ b/library/coretests/tests/array.rs
@@ -646,7 +646,7 @@ fn array_mixed_equality_integers() {
 
 #[test]
 fn array_mixed_equality_nans() {
-    let array3: [f32; 3] = [1.0, std::f32::NAN, 3.0];
+    let array3: [f32; 3] = [1.0, f32::NAN, 3.0];
 
     let slice3: &[f32] = &{ array3 };
     assert!(!(array3 == slice3));
@@ -741,3 +741,18 @@ const fn maybe_doubler(x: usize) -> Option<usize> {
     struct Zst;
     assert_eq!([(); 10].try_map(|()| Some(Zst)), Some([const { Zst }; 10]));
 }
+
+#[test]
+const fn extra_const_array_ops() {
+    let x: [u8; 4] =
+        { std::array::from_fn(const |i| i + 4).map(const |x| x * 2).map(const |x| x as _) };
+    let y = 4;
+    struct Z(u16);
+    impl const Drop for Z {
+        fn drop(&mut self) {}
+    }
+    let w = Z(2);
+    let _x: [u8; 4] = {
+        std::array::from_fn(const |_| x[0] + y).map(const |x| x * (w.0 as u8)).map(const |x| x as _)
+    };
+}
diff --git a/library/coretests/tests/char.rs b/library/coretests/tests/char.rs
index f0f6a24..877017f 100644
--- a/library/coretests/tests/char.rs
+++ b/library/coretests/tests/char.rs
@@ -1,5 +1,6 @@
+use std::char::{self, CharCase};
+use std::str;
 use std::str::FromStr;
-use std::{char, str};
 
 #[test]
 fn test_convert() {
@@ -40,6 +41,30 @@ fn test_from_str() {
 }
 
 #[test]
+fn test_is_cased() {
+    assert!('a'.is_cased());
+    assert!('ö'.is_cased());
+    assert!('ß'.is_cased());
+    assert!('Ü'.is_cased());
+    assert!('P'.is_cased());
+    assert!('ª'.is_cased());
+    assert!(!'攂'.is_cased());
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Miri is too slow
+fn test_char_case() {
+    for c in '\0'..='\u{10FFFF}' {
+        match c.case() {
+            None => assert!(!c.is_cased()),
+            Some(CharCase::Lower) => assert!(c.is_lowercase()),
+            Some(CharCase::Upper) => assert!(c.is_uppercase()),
+            Some(CharCase::Title) => assert!(c.is_titlecase()),
+        }
+    }
+}
+
+#[test]
 fn test_is_lowercase() {
     assert!('a'.is_lowercase());
     assert!('ö'.is_lowercase());
@@ -49,6 +74,17 @@ fn test_is_lowercase() {
 }
 
 #[test]
+fn test_is_titlecase() {
+    assert!('Ç…'.is_titlecase());
+    assert!('ᾨ'.is_titlecase());
+    assert!(!'h'.is_titlecase());
+    assert!(!'ä'.is_titlecase());
+    assert!(!'ß'.is_titlecase());
+    assert!(!'Ö'.is_titlecase());
+    assert!(!'T'.is_titlecase());
+}
+
+#[test]
 fn test_is_uppercase() {
     assert!(!'h'.is_uppercase());
     assert!(!'ä'.is_uppercase());
@@ -58,6 +94,27 @@ fn test_is_uppercase() {
 }
 
 #[test]
+fn titlecase_fast_path() {
+    for c in '\0'..='\u{01C4}' {
+        assert!(!(c.is_cased() && !c.is_lowercase() && !c.is_uppercase()))
+    }
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Miri is too slow
+fn at_most_one_case() {
+    for c in '\0'..='\u{10FFFF}' {
+        assert_eq!(
+            !c.is_cased() as u8
+                + c.is_lowercase() as u8
+                + c.is_uppercase() as u8
+                + c.is_titlecase() as u8,
+            1
+        );
+    }
+}
+
+#[test]
 fn test_is_whitespace() {
     assert!(' '.is_whitespace());
     assert!('\u{2007}'.is_whitespace());
diff --git a/library/coretests/tests/iter/adapters/intersperse.rs b/library/coretests/tests/iter/adapters/intersperse.rs
index df6be79..bcb7709 100644
--- a/library/coretests/tests/iter/adapters/intersperse.rs
+++ b/library/coretests/tests/iter/adapters/intersperse.rs
@@ -153,10 +153,6 @@ fn test_try_fold_specialization_intersperse_err() {
     assert_eq!(iter.next(), None);
 }
 
-// FIXME(iter_intersperse): `intersperse` current behavior may change for
-// non-fused iterators, so this test will likely have to
-// be adjusted; see PR #152855 and issue #79524
-// if `intersperse` doesn't change, remove this FIXME.
 #[test]
 fn test_non_fused_iterator_intersperse() {
     #[derive(Debug)]
@@ -183,24 +179,26 @@ fn next(&mut self) -> Option<Self::Item> {
     }
 
     let counter = 0;
-    // places a 2 between `Some(_)` items
+    // places a 1 between `Some(_)` items
     let non_fused_iter = TestCounter { counter };
-    let mut intersperse_iter = non_fused_iter.intersperse(2);
-    // Since `intersperse` currently transforms the original
-    // iterator into a fused iterator, this intersperse_iter
-    // should always have `None`
-    for _ in 0..counter + 6 {
-        assert_eq!(intersperse_iter.next(), None);
-    }
+    let mut intersperse_iter = non_fused_iter.intersperse(1);
+    // Interspersed iter produces:
+    // `None` -> `Some(2)` -> `None` -> `Some(1)` -> Some(4)` -> `None` ->  `Some(1)` ->
+    // `Some(6)` -> and then `None` endlessly
+    assert_eq!(intersperse_iter.next(), None);
+    assert_eq!(intersperse_iter.next(), Some(2));
+    assert_eq!(intersperse_iter.next(), None);
+    assert_eq!(intersperse_iter.next(), Some(1));
+    assert_eq!(intersperse_iter.next(), Some(4));
+    assert_eq!(intersperse_iter.next(), None);
+    assert_eq!(intersperse_iter.next(), Some(1));
+    assert_eq!(intersperse_iter.next(), Some(6));
+    assert_eq!(intersperse_iter.next(), None);
 
-    // Extra check to make sure it is `None` after processing 6 items
+    // Extra check to make sure it is `None` after processing all items
     assert_eq!(intersperse_iter.next(), None);
 }
 
-// FIXME(iter_intersperse): `intersperse` current behavior may change for
-// non-fused iterators, so this test will likely have to
-// be adjusted; see PR #152855 and issue #79524
-// if `intersperse` doesn't change, remove this FIXME.
 #[test]
 fn test_non_fused_iterator_intersperse_2() {
     #[derive(Debug)]
@@ -228,35 +226,26 @@ fn next(&mut self) -> Option<Self::Item> {
     }
 
     let counter = 0;
-    // places a 2 between `Some(_)` items
+    // places a 100 between `Some(_)` items
     let non_fused_iter = TestCounter { counter };
-    let mut intersperse_iter = non_fused_iter.intersperse(2);
-    // Since `intersperse` currently transforms the original
-    // iterator into a fused iterator, this interspersed iter
-    // will be `Some(1)` -> `Some(2)` -> `Some(2)` -> and then
-    // `None` endlessly
-    let mut items_processed = 0;
-    for num in 0..counter + 6 {
-        if num < 3 {
-            if num % 2 != 0 {
-                assert_eq!(intersperse_iter.next(), Some(2));
-            } else {
-                items_processed += 1;
-                assert_eq!(intersperse_iter.next(), Some(items_processed));
-            }
-        } else {
-            assert_eq!(intersperse_iter.next(), None);
-        }
-    }
+    let mut intersperse_iter = non_fused_iter.intersperse(100);
+    // Interspersed iter produces:
+    // `Some(1)` -> `Some(100)` -> `Some(2)` -> `None` -> `Some(100)`
+    //  -> `Some(4)` -> `Some(100)` -> `Some(5)` -> `None` endlessly
+    assert_eq!(intersperse_iter.next(), Some(1));
+    assert_eq!(intersperse_iter.next(), Some(100));
+    assert_eq!(intersperse_iter.next(), Some(2));
+    assert_eq!(intersperse_iter.next(), None);
+    assert_eq!(intersperse_iter.next(), Some(100));
+    assert_eq!(intersperse_iter.next(), Some(4));
+    assert_eq!(intersperse_iter.next(), Some(100));
+    assert_eq!(intersperse_iter.next(), Some(5));
+    assert_eq!(intersperse_iter.next(), None);
 
     // Extra check to make sure it is `None` after processing 6 items
     assert_eq!(intersperse_iter.next(), None);
 }
 
-// FIXME(iter_intersperse): `intersperse_with` current behavior may change for
-// non-fused iterators, so this test will likely have to
-// be adjusted; see PR #152855 and issue #79524
-// if `intersperse_with` doesn't change, remove this FIXME.
 #[test]
 fn test_non_fused_iterator_intersperse_with() {
     #[derive(Debug)]
@@ -285,22 +274,24 @@ fn next(&mut self) -> Option<Self::Item> {
     let counter = 0;
     let non_fused_iter = TestCounter { counter };
     // places a 2 between `Some(_)` items
-    let mut intersperse_iter = non_fused_iter.intersperse_with(|| 2);
-    // Since `intersperse` currently transforms the original
-    // iterator into a fused iterator, this intersperse_iter
-    // should always have `None`
-    for _ in 0..counter + 6 {
-        assert_eq!(intersperse_iter.next(), None);
-    }
+    let mut intersperse_iter = non_fused_iter.intersperse_with(|| 1);
+    // Interspersed iter produces:
+    // `None` -> `Some(2)` -> `None` -> `Some(1)` -> Some(4)` -> `None` ->  `Some(1)` ->
+    // `Some(6)` -> and then `None` endlessly
+    assert_eq!(intersperse_iter.next(), None);
+    assert_eq!(intersperse_iter.next(), Some(2));
+    assert_eq!(intersperse_iter.next(), None);
+    assert_eq!(intersperse_iter.next(), Some(1));
+    assert_eq!(intersperse_iter.next(), Some(4));
+    assert_eq!(intersperse_iter.next(), None);
+    assert_eq!(intersperse_iter.next(), Some(1));
+    assert_eq!(intersperse_iter.next(), Some(6));
+    assert_eq!(intersperse_iter.next(), None);
 
     // Extra check to make sure it is `None` after processing 6 items
     assert_eq!(intersperse_iter.next(), None);
 }
 
-// FIXME(iter_intersperse): `intersperse_with` current behavior may change for
-// non-fused iterators, so this test will likely have to
-// be adjusted; see PR #152855 and issue #79524
-// if `intersperse_with` doesn't change, remove this FIXME.
 #[test]
 fn test_non_fused_iterator_intersperse_with_2() {
     #[derive(Debug)]
@@ -328,26 +319,21 @@ fn next(&mut self) -> Option<Self::Item> {
     }
 
     let counter = 0;
-    // places a 2 between `Some(_)` items
+    // places a 100 between `Some(_)` items
     let non_fused_iter = TestCounter { counter };
-    let mut intersperse_iter = non_fused_iter.intersperse(2);
-    // Since `intersperse` currently transforms the original
-    // iterator into a fused iterator, this interspersed iter
-    // will be `Some(1)` -> `Some(2)` -> `Some(2)` -> and then
-    // `None` endlessly
-    let mut items_processed = 0;
-    for num in 0..counter + 6 {
-        if num < 3 {
-            if num % 2 != 0 {
-                assert_eq!(intersperse_iter.next(), Some(2));
-            } else {
-                items_processed += 1;
-                assert_eq!(intersperse_iter.next(), Some(items_processed));
-            }
-        } else {
-            assert_eq!(intersperse_iter.next(), None);
-        }
-    }
+    let mut intersperse_iter = non_fused_iter.intersperse_with(|| 100);
+    // Interspersed iter produces:
+    // `Some(1)` -> `Some(100)` -> `Some(2)` -> `None` -> `Some(100)`
+    //  -> `Some(4)` -> `Some(100)` -> `Some(5)` -> `None` endlessly
+    assert_eq!(intersperse_iter.next(), Some(1));
+    assert_eq!(intersperse_iter.next(), Some(100));
+    assert_eq!(intersperse_iter.next(), Some(2));
+    assert_eq!(intersperse_iter.next(), None);
+    assert_eq!(intersperse_iter.next(), Some(100));
+    assert_eq!(intersperse_iter.next(), Some(4));
+    assert_eq!(intersperse_iter.next(), Some(100));
+    assert_eq!(intersperse_iter.next(), Some(5));
+    assert_eq!(intersperse_iter.next(), None);
 
     // Extra check to make sure it is `None` after processing 6 items
     assert_eq!(intersperse_iter.next(), None);
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index b0ba070..fba144c 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -17,6 +17,7 @@
 #![feature(const_bool)]
 #![feature(const_cell_traits)]
 #![feature(const_clone)]
+#![feature(const_closures)]
 #![feature(const_cmp)]
 #![feature(const_convert)]
 #![feature(const_default)]
@@ -112,6 +113,7 @@
 #![feature(step_trait)]
 #![feature(str_internals)]
 #![feature(strict_provenance_lints)]
+#![feature(titlecase)]
 #![feature(trusted_len)]
 #![feature(trusted_random_access)]
 #![feature(try_blocks)]
diff --git a/library/coretests/tests/num/int_macros.rs b/library/coretests/tests/num/int_macros.rs
index 37336f4..2b641f5 100644
--- a/library/coretests/tests/num/int_macros.rs
+++ b/library/coretests/tests/num/int_macros.rs
@@ -2,7 +2,8 @@
     ($T:ident, $U:ident) => {
         use core::num::ParseIntError;
         use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
-        use core::$T::*;
+        const MAX: $T = $T::MAX;
+        const MIN: $T = $T::MIN;
 
         const UMAX: $U = $U::MAX;
 
diff --git a/library/coretests/tests/num/uint_macros.rs b/library/coretests/tests/num/uint_macros.rs
index 240c66f..8dfa092 100644
--- a/library/coretests/tests/num/uint_macros.rs
+++ b/library/coretests/tests/num/uint_macros.rs
@@ -2,15 +2,14 @@
     ($T:ident) => {
         use core::num::ParseIntError;
         use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
-        use core::$T::*;
 
         use crate::num;
 
         #[test]
         fn test_overflows() {
-            assert!(MAX > 0);
-            assert!(MIN <= 0);
-            assert!((MIN + MAX).wrapping_add(1) == 0);
+            assert!($T::MAX > 0);
+            assert!($T::MIN <= 0);
+            assert!(($T::MIN + $T::MAX).wrapping_add(1) == 0);
         }
 
         #[test]
@@ -25,7 +24,7 @@ fn test_bitwise_operators() {
             assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T));
             assert!(0b1110 as $T == (0b0111 as $T).shl(1));
             assert!(0b0111 as $T == (0b1110 as $T).shr(1));
-            assert!(MAX - (0b1011 as $T) == (0b1011 as $T).not());
+            assert!($T::MAX - (0b1011 as $T) == (0b1011 as $T).not());
         }
 
         const A: $T = 0b0101100;
@@ -361,7 +360,7 @@ fn test_pow() {
                     assert_eq_const_safe!($T: R.wrapping_pow(2), 1 as $T);
                     assert_eq_const_safe!(Option<$T>: R.checked_pow(2), None);
                     assert_eq_const_safe!(($T, bool): R.overflowing_pow(2), (1 as $T, true));
-                    assert_eq_const_safe!($T: R.saturating_pow(2), MAX);
+                    assert_eq_const_safe!($T: R.saturating_pow(2), $T::MAX);
                 }
             }
 
@@ -468,14 +467,14 @@ fn test_div_ceil() {
             fn test_next_multiple_of() {
                 assert_eq_const_safe!($T: (16 as $T).next_multiple_of(8), 16);
                 assert_eq_const_safe!($T: (23 as $T).next_multiple_of(8), 24);
-                assert_eq_const_safe!($T: MAX.next_multiple_of(1), MAX);
+                assert_eq_const_safe!($T: $T::MAX.next_multiple_of(1), $T::MAX);
             }
 
             fn test_checked_next_multiple_of() {
                 assert_eq_const_safe!(Option<$T>: (16 as $T).checked_next_multiple_of(8), Some(16));
                 assert_eq_const_safe!(Option<$T>: (23 as $T).checked_next_multiple_of(8), Some(24));
                 assert_eq_const_safe!(Option<$T>: (1 as $T).checked_next_multiple_of(0), None);
-                assert_eq_const_safe!(Option<$T>: MAX.checked_next_multiple_of(2), None);
+                assert_eq_const_safe!(Option<$T>: $T::MAX.checked_next_multiple_of(2), None);
             }
 
             fn test_is_next_multiple_of() {
diff --git a/library/coretests/tests/pin.rs b/library/coretests/tests/pin.rs
index b3fb06e..37a729a 100644
--- a/library/coretests/tests/pin.rs
+++ b/library/coretests/tests/pin.rs
@@ -45,22 +45,6 @@ mod pin_coerce_unsized {
     pub trait MyTrait {}
     impl MyTrait for String {}
 
-    // These Pins should continue to compile.
-    // Do note that these instances of Pin types cannot be used
-    // meaningfully because all methods require a Deref/DerefMut
-    // bounds on the pointer type and Cell, RefCell and UnsafeCell
-    // do not implement Deref/DerefMut.
-
-    pub fn cell(arg: Pin<Cell<Box<String>>>) -> Pin<Cell<Box<dyn MyTrait>>> {
-        arg
-    }
-    pub fn ref_cell(arg: Pin<RefCell<Box<String>>>) -> Pin<RefCell<Box<dyn MyTrait>>> {
-        arg
-    }
-    pub fn unsafe_cell(arg: Pin<UnsafeCell<Box<String>>>) -> Pin<UnsafeCell<Box<dyn MyTrait>>> {
-        arg
-    }
-
     // These sensible Pin coercions are possible.
     pub fn pin_mut_ref(arg: Pin<&mut String>) -> Pin<&mut dyn MyTrait> {
         arg
@@ -68,15 +52,6 @@ pub fn pin_mut_ref(arg: Pin<&mut String>) -> Pin<&mut dyn MyTrait> {
     pub fn pin_ref(arg: Pin<&String>) -> Pin<&dyn MyTrait> {
         arg
     }
-    pub fn pin_ptr(arg: Pin<*const String>) -> Pin<*const dyn MyTrait> {
-        arg
-    }
-    pub fn pin_ptr_mut(arg: Pin<*mut String>) -> Pin<*mut dyn MyTrait> {
-        arg
-    }
-    pub fn pin_non_null(arg: Pin<NonNull<String>>) -> Pin<NonNull<dyn MyTrait>> {
-        arg
-    }
     pub fn nesting_pins(arg: Pin<Pin<&String>>) -> Pin<Pin<&dyn MyTrait>> {
         arg
     }
diff --git a/library/coretests/tests/unicode.rs b/library/coretests/tests/unicode.rs
index 1fae74f..a8a221d 100644
--- a/library/coretests/tests/unicode.rs
+++ b/library/coretests/tests/unicode.rs
@@ -27,17 +27,21 @@ fn test_boolean_property(ranges: &[RangeInclusive<char>], lookup: fn(char) -> bo
 }
 
 #[track_caller]
-fn test_case_mapping(ranges: &[(char, [char; 3])], lookup: fn(char) -> [char; 3]) {
+fn test_case_mapping(
+    ranges: &[(char, [char; 3])],
+    lookup: fn(char) -> [char; 3],
+    fallback: fn(char) -> [char; 3],
+) {
     let mut start = '\u{80}';
     for &(key, val) in ranges {
         for c in start..key {
-            assert_eq!(lookup(c), [c, '\0', '\0'], "{c:?}");
+            assert_eq!(lookup(c), fallback(c), "{c:?}");
         }
         assert_eq!(lookup(key), val, "{key:?}");
         start = char::from_u32(key as u32 + 1).unwrap();
     }
     for c in start..=char::MAX {
-        assert_eq!(lookup(c), [c, '\0', '\0'], "{c:?}");
+        assert_eq!(lookup(c), fallback(c), "{c:?}");
     }
 }
 
@@ -45,6 +49,7 @@ fn test_boolean_property(ranges: &[RangeInclusive<char>], lookup: fn(char) -> bo
 #[cfg_attr(miri, ignore)] // Miri is too slow
 fn alphabetic() {
     test_boolean_property(test_data::ALPHABETIC, unicode_data::alphabetic::lookup);
+    test_boolean_property(test_data::ALPHABETIC, char::is_alphabetic);
 }
 
 #[test]
@@ -57,6 +62,7 @@ fn case_ignorable() {
 #[cfg_attr(miri, ignore)] // Miri is too slow
 fn cased() {
     test_boolean_property(test_data::CASED, unicode_data::cased::lookup);
+    test_boolean_property(test_data::CASED, char::is_cased);
 }
 
 #[test]
@@ -69,34 +75,52 @@ fn grapheme_extend() {
 #[cfg_attr(miri, ignore)] // Miri is too slow
 fn lowercase() {
     test_boolean_property(test_data::LOWERCASE, unicode_data::lowercase::lookup);
+    test_boolean_property(test_data::LOWERCASE, char::is_lowercase);
 }
 
 #[test]
 #[cfg_attr(miri, ignore)] // Miri is too slow
 fn n() {
     test_boolean_property(test_data::N, unicode_data::n::lookup);
+    test_boolean_property(test_data::N, char::is_numeric);
 }
 
 #[test]
 #[cfg_attr(miri, ignore)] // Miri is too slow
 fn uppercase() {
     test_boolean_property(test_data::UPPERCASE, unicode_data::uppercase::lookup);
+    test_boolean_property(test_data::UPPERCASE, char::is_uppercase);
 }
 
 #[test]
 #[cfg_attr(miri, ignore)] // Miri is too slow
 fn white_space() {
     test_boolean_property(test_data::WHITE_SPACE, unicode_data::white_space::lookup);
+    test_boolean_property(test_data::WHITE_SPACE, char::is_whitespace);
 }
 
 #[test]
 #[cfg_attr(miri, ignore)] // Miri is too slow
 fn to_lowercase() {
-    test_case_mapping(test_data::TO_LOWER, unicode_data::conversions::to_lower);
+    test_case_mapping(test_data::TO_LOWER, unicode_data::conversions::to_lower, |c| {
+        [c, '\0', '\0']
+    });
 }
 
 #[test]
 #[cfg_attr(miri, ignore)] // Miri is too slow
 fn to_uppercase() {
-    test_case_mapping(test_data::TO_UPPER, unicode_data::conversions::to_upper);
+    test_case_mapping(test_data::TO_UPPER, unicode_data::conversions::to_upper, |c| {
+        [c, '\0', '\0']
+    });
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Miri is too slow
+fn to_titlecase() {
+    test_case_mapping(
+        test_data::TO_TITLE,
+        unicode_data::conversions::to_title,
+        unicode_data::conversions::to_upper,
+    );
 }
diff --git a/library/coretests/tests/unicode/test_data.rs b/library/coretests/tests/unicode/test_data.rs
index cfc6954..3071aed 100644
--- a/library/coretests/tests/unicode/test_data.rs
+++ b/library/coretests/tests/unicode/test_data.rs
@@ -2900,3 +2900,81 @@
     ('\u{1e942}', ['\u{1e920}', '\u{0}', '\u{0}']),
     ('\u{1e943}', ['\u{1e921}', '\u{0}', '\u{0}']),
 ];
+
+#[rustfmt::skip]
+pub(super) static TO_TITLE: &[(char, [char; 3]); 135] = &[
+    ('\u{df}', ['S', 's', '\u{0}']), ('\u{1c4}', ['\u{1c5}', '\u{0}', '\u{0}']),
+    ('\u{1c5}', ['\u{1c5}', '\u{0}', '\u{0}']), ('\u{1c6}', ['\u{1c5}', '\u{0}', '\u{0}']),
+    ('\u{1c7}', ['\u{1c8}', '\u{0}', '\u{0}']), ('\u{1c8}', ['\u{1c8}', '\u{0}', '\u{0}']),
+    ('\u{1c9}', ['\u{1c8}', '\u{0}', '\u{0}']), ('\u{1ca}', ['\u{1cb}', '\u{0}', '\u{0}']),
+    ('\u{1cb}', ['\u{1cb}', '\u{0}', '\u{0}']), ('\u{1cc}', ['\u{1cb}', '\u{0}', '\u{0}']),
+    ('\u{1f1}', ['\u{1f2}', '\u{0}', '\u{0}']), ('\u{1f2}', ['\u{1f2}', '\u{0}', '\u{0}']),
+    ('\u{1f3}', ['\u{1f2}', '\u{0}', '\u{0}']), ('\u{587}', ['\u{535}', '\u{582}', '\u{0}']),
+    ('\u{10d0}', ['\u{10d0}', '\u{0}', '\u{0}']), ('\u{10d1}', ['\u{10d1}', '\u{0}', '\u{0}']),
+    ('\u{10d2}', ['\u{10d2}', '\u{0}', '\u{0}']), ('\u{10d3}', ['\u{10d3}', '\u{0}', '\u{0}']),
+    ('\u{10d4}', ['\u{10d4}', '\u{0}', '\u{0}']), ('\u{10d5}', ['\u{10d5}', '\u{0}', '\u{0}']),
+    ('\u{10d6}', ['\u{10d6}', '\u{0}', '\u{0}']), ('\u{10d7}', ['\u{10d7}', '\u{0}', '\u{0}']),
+    ('\u{10d8}', ['\u{10d8}', '\u{0}', '\u{0}']), ('\u{10d9}', ['\u{10d9}', '\u{0}', '\u{0}']),
+    ('\u{10da}', ['\u{10da}', '\u{0}', '\u{0}']), ('\u{10db}', ['\u{10db}', '\u{0}', '\u{0}']),
+    ('\u{10dc}', ['\u{10dc}', '\u{0}', '\u{0}']), ('\u{10dd}', ['\u{10dd}', '\u{0}', '\u{0}']),
+    ('\u{10de}', ['\u{10de}', '\u{0}', '\u{0}']), ('\u{10df}', ['\u{10df}', '\u{0}', '\u{0}']),
+    ('\u{10e0}', ['\u{10e0}', '\u{0}', '\u{0}']), ('\u{10e1}', ['\u{10e1}', '\u{0}', '\u{0}']),
+    ('\u{10e2}', ['\u{10e2}', '\u{0}', '\u{0}']), ('\u{10e3}', ['\u{10e3}', '\u{0}', '\u{0}']),
+    ('\u{10e4}', ['\u{10e4}', '\u{0}', '\u{0}']), ('\u{10e5}', ['\u{10e5}', '\u{0}', '\u{0}']),
+    ('\u{10e6}', ['\u{10e6}', '\u{0}', '\u{0}']), ('\u{10e7}', ['\u{10e7}', '\u{0}', '\u{0}']),
+    ('\u{10e8}', ['\u{10e8}', '\u{0}', '\u{0}']), ('\u{10e9}', ['\u{10e9}', '\u{0}', '\u{0}']),
+    ('\u{10ea}', ['\u{10ea}', '\u{0}', '\u{0}']), ('\u{10eb}', ['\u{10eb}', '\u{0}', '\u{0}']),
+    ('\u{10ec}', ['\u{10ec}', '\u{0}', '\u{0}']), ('\u{10ed}', ['\u{10ed}', '\u{0}', '\u{0}']),
+    ('\u{10ee}', ['\u{10ee}', '\u{0}', '\u{0}']), ('\u{10ef}', ['\u{10ef}', '\u{0}', '\u{0}']),
+    ('\u{10f0}', ['\u{10f0}', '\u{0}', '\u{0}']), ('\u{10f1}', ['\u{10f1}', '\u{0}', '\u{0}']),
+    ('\u{10f2}', ['\u{10f2}', '\u{0}', '\u{0}']), ('\u{10f3}', ['\u{10f3}', '\u{0}', '\u{0}']),
+    ('\u{10f4}', ['\u{10f4}', '\u{0}', '\u{0}']), ('\u{10f5}', ['\u{10f5}', '\u{0}', '\u{0}']),
+    ('\u{10f6}', ['\u{10f6}', '\u{0}', '\u{0}']), ('\u{10f7}', ['\u{10f7}', '\u{0}', '\u{0}']),
+    ('\u{10f8}', ['\u{10f8}', '\u{0}', '\u{0}']), ('\u{10f9}', ['\u{10f9}', '\u{0}', '\u{0}']),
+    ('\u{10fa}', ['\u{10fa}', '\u{0}', '\u{0}']), ('\u{10fd}', ['\u{10fd}', '\u{0}', '\u{0}']),
+    ('\u{10fe}', ['\u{10fe}', '\u{0}', '\u{0}']), ('\u{10ff}', ['\u{10ff}', '\u{0}', '\u{0}']),
+    ('\u{1f80}', ['\u{1f88}', '\u{0}', '\u{0}']), ('\u{1f81}', ['\u{1f89}', '\u{0}', '\u{0}']),
+    ('\u{1f82}', ['\u{1f8a}', '\u{0}', '\u{0}']), ('\u{1f83}', ['\u{1f8b}', '\u{0}', '\u{0}']),
+    ('\u{1f84}', ['\u{1f8c}', '\u{0}', '\u{0}']), ('\u{1f85}', ['\u{1f8d}', '\u{0}', '\u{0}']),
+    ('\u{1f86}', ['\u{1f8e}', '\u{0}', '\u{0}']), ('\u{1f87}', ['\u{1f8f}', '\u{0}', '\u{0}']),
+    ('\u{1f88}', ['\u{1f88}', '\u{0}', '\u{0}']), ('\u{1f89}', ['\u{1f89}', '\u{0}', '\u{0}']),
+    ('\u{1f8a}', ['\u{1f8a}', '\u{0}', '\u{0}']), ('\u{1f8b}', ['\u{1f8b}', '\u{0}', '\u{0}']),
+    ('\u{1f8c}', ['\u{1f8c}', '\u{0}', '\u{0}']), ('\u{1f8d}', ['\u{1f8d}', '\u{0}', '\u{0}']),
+    ('\u{1f8e}', ['\u{1f8e}', '\u{0}', '\u{0}']), ('\u{1f8f}', ['\u{1f8f}', '\u{0}', '\u{0}']),
+    ('\u{1f90}', ['\u{1f98}', '\u{0}', '\u{0}']), ('\u{1f91}', ['\u{1f99}', '\u{0}', '\u{0}']),
+    ('\u{1f92}', ['\u{1f9a}', '\u{0}', '\u{0}']), ('\u{1f93}', ['\u{1f9b}', '\u{0}', '\u{0}']),
+    ('\u{1f94}', ['\u{1f9c}', '\u{0}', '\u{0}']), ('\u{1f95}', ['\u{1f9d}', '\u{0}', '\u{0}']),
+    ('\u{1f96}', ['\u{1f9e}', '\u{0}', '\u{0}']), ('\u{1f97}', ['\u{1f9f}', '\u{0}', '\u{0}']),
+    ('\u{1f98}', ['\u{1f98}', '\u{0}', '\u{0}']), ('\u{1f99}', ['\u{1f99}', '\u{0}', '\u{0}']),
+    ('\u{1f9a}', ['\u{1f9a}', '\u{0}', '\u{0}']), ('\u{1f9b}', ['\u{1f9b}', '\u{0}', '\u{0}']),
+    ('\u{1f9c}', ['\u{1f9c}', '\u{0}', '\u{0}']), ('\u{1f9d}', ['\u{1f9d}', '\u{0}', '\u{0}']),
+    ('\u{1f9e}', ['\u{1f9e}', '\u{0}', '\u{0}']), ('\u{1f9f}', ['\u{1f9f}', '\u{0}', '\u{0}']),
+    ('\u{1fa0}', ['\u{1fa8}', '\u{0}', '\u{0}']), ('\u{1fa1}', ['\u{1fa9}', '\u{0}', '\u{0}']),
+    ('\u{1fa2}', ['\u{1faa}', '\u{0}', '\u{0}']), ('\u{1fa3}', ['\u{1fab}', '\u{0}', '\u{0}']),
+    ('\u{1fa4}', ['\u{1fac}', '\u{0}', '\u{0}']), ('\u{1fa5}', ['\u{1fad}', '\u{0}', '\u{0}']),
+    ('\u{1fa6}', ['\u{1fae}', '\u{0}', '\u{0}']), ('\u{1fa7}', ['\u{1faf}', '\u{0}', '\u{0}']),
+    ('\u{1fa8}', ['\u{1fa8}', '\u{0}', '\u{0}']), ('\u{1fa9}', ['\u{1fa9}', '\u{0}', '\u{0}']),
+    ('\u{1faa}', ['\u{1faa}', '\u{0}', '\u{0}']), ('\u{1fab}', ['\u{1fab}', '\u{0}', '\u{0}']),
+    ('\u{1fac}', ['\u{1fac}', '\u{0}', '\u{0}']), ('\u{1fad}', ['\u{1fad}', '\u{0}', '\u{0}']),
+    ('\u{1fae}', ['\u{1fae}', '\u{0}', '\u{0}']), ('\u{1faf}', ['\u{1faf}', '\u{0}', '\u{0}']),
+    ('\u{1fb2}', ['\u{1fba}', '\u{345}', '\u{0}']),
+    ('\u{1fb3}', ['\u{1fbc}', '\u{0}', '\u{0}']), ('\u{1fb4}', ['\u{386}', '\u{345}', '\u{0}']),
+    ('\u{1fb7}', ['\u{391}', '\u{342}', '\u{345}']),
+    ('\u{1fbc}', ['\u{1fbc}', '\u{0}', '\u{0}']),
+    ('\u{1fc2}', ['\u{1fca}', '\u{345}', '\u{0}']),
+    ('\u{1fc3}', ['\u{1fcc}', '\u{0}', '\u{0}']), ('\u{1fc4}', ['\u{389}', '\u{345}', '\u{0}']),
+    ('\u{1fc7}', ['\u{397}', '\u{342}', '\u{345}']),
+    ('\u{1fcc}', ['\u{1fcc}', '\u{0}', '\u{0}']),
+    ('\u{1ff2}', ['\u{1ffa}', '\u{345}', '\u{0}']),
+    ('\u{1ff3}', ['\u{1ffc}', '\u{0}', '\u{0}']), ('\u{1ff4}', ['\u{38f}', '\u{345}', '\u{0}']),
+    ('\u{1ff7}', ['\u{3a9}', '\u{342}', '\u{345}']),
+    ('\u{1ffc}', ['\u{1ffc}', '\u{0}', '\u{0}']), ('\u{fb00}', ['F', 'f', '\u{0}']),
+    ('\u{fb01}', ['F', 'i', '\u{0}']), ('\u{fb02}', ['F', 'l', '\u{0}']),
+    ('\u{fb03}', ['F', 'f', 'i']), ('\u{fb04}', ['F', 'f', 'l']),
+    ('\u{fb05}', ['S', 't', '\u{0}']), ('\u{fb06}', ['S', 't', '\u{0}']),
+    ('\u{fb13}', ['\u{544}', '\u{576}', '\u{0}']),
+    ('\u{fb14}', ['\u{544}', '\u{565}', '\u{0}']),
+    ('\u{fb15}', ['\u{544}', '\u{56b}', '\u{0}']),
+    ('\u{fb16}', ['\u{54e}', '\u{576}', '\u{0}']),
+    ('\u{fb17}', ['\u{544}', '\u{56d}', '\u{0}']),
+];
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 1b7a41d..7a8ccdb 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -62,7 +62,7 @@
 rand = { version = "0.9.0", default-features = false, features = ["alloc"] }
 rand_xorshift = "0.4.0"
 
-[target.'cfg(any(all(target_family = "wasm", target_os = "unknown"), target_os = "xous", target_os = "vexos", all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
+[target.'cfg(any(all(target_family = "wasm", not(any(unix, target_os = "wasi"))), target_os = "xous", target_os = "vexos", all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
 dlmalloc = { version = "0.2.10", features = ['rustc-dep-of-std'] }
 
 [target.x86_64-fortanix-unknown-sgx.dependencies]
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index edf0127..d3e4417 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -15,7 +15,7 @@
 use crate::num::NonZero;
 use crate::ops::Try;
 use crate::path::{Path, PathBuf};
-use crate::sys::{env as env_imp, os as os_imp};
+use crate::sys::{env as env_imp, paths as paths_imp};
 use crate::{array, fmt, io, sys};
 
 /// Returns the current working directory as a [`PathBuf`].
@@ -51,7 +51,7 @@
 #[doc(alias = "GetCurrentDirectory")]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn current_dir() -> io::Result<PathBuf> {
-    os_imp::getcwd()
+    paths_imp::getcwd()
 }
 
 /// Changes the current working directory to the specified path.
@@ -78,7 +78,7 @@ pub fn current_dir() -> io::Result<PathBuf> {
 #[doc(alias = "chdir", alias = "SetCurrentDirectory", alias = "SetCurrentDirectoryW")]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn set_current_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
-    os_imp::chdir(path.as_ref())
+    paths_imp::chdir(path.as_ref())
 }
 
 /// An iterator over a snapshot of the environment variables of this process.
@@ -444,7 +444,7 @@ pub unsafe fn remove_var<K: AsRef<OsStr>>(key: K) {
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "env", since = "1.0.0")]
 pub struct SplitPaths<'a> {
-    inner: os_imp::SplitPaths<'a>,
+    inner: paths_imp::SplitPaths<'a>,
 }
 
 /// Parses input according to platform conventions for the `PATH`
@@ -480,7 +480,7 @@ pub struct SplitPaths<'a> {
 /// ```
 #[stable(feature = "env", since = "1.0.0")]
 pub fn split_paths<T: AsRef<OsStr> + ?Sized>(unparsed: &T) -> SplitPaths<'_> {
-    SplitPaths { inner: os_imp::split_paths(unparsed.as_ref()) }
+    SplitPaths { inner: paths_imp::split_paths(unparsed.as_ref()) }
 }
 
 #[stable(feature = "env", since = "1.0.0")]
@@ -508,7 +508,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 #[derive(Debug)]
 #[stable(feature = "env", since = "1.0.0")]
 pub struct JoinPathsError {
-    inner: os_imp::JoinPathsError,
+    inner: paths_imp::JoinPathsError,
 }
 
 /// Joins a collection of [`Path`]s appropriately for the `PATH`
@@ -579,7 +579,7 @@ pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
     I: IntoIterator<Item = T>,
     T: AsRef<OsStr>,
 {
-    os_imp::join_paths(paths.into_iter()).map_err(|e| JoinPathsError { inner: e })
+    paths_imp::join_paths(paths.into_iter()).map_err(|e| JoinPathsError { inner: e })
 }
 
 #[stable(feature = "env", since = "1.0.0")]
@@ -641,7 +641,7 @@ fn description(&self) -> &str {
 #[must_use]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn home_dir() -> Option<PathBuf> {
-    os_imp::home_dir()
+    paths_imp::home_dir()
 }
 
 /// Returns the path of a temporary directory.
@@ -701,7 +701,7 @@ pub fn home_dir() -> Option<PathBuf> {
 #[doc(alias = "GetTempPath", alias = "GetTempPath2")]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn temp_dir() -> PathBuf {
-    os_imp::temp_dir()
+    paths_imp::temp_dir()
 }
 
 /// Returns the full filesystem path of the current running executable.
@@ -752,7 +752,7 @@ pub fn temp_dir() -> PathBuf {
 /// ```
 #[stable(feature = "env", since = "1.0.0")]
 pub fn current_exe() -> io::Result<PathBuf> {
-    os_imp::current_exe()
+    paths_imp::current_exe()
 }
 
 /// An iterator over the arguments of a process, yielding a [`String`] value for
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 885bf37..9643d3f 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -815,7 +815,8 @@ pub fn sync_data(&self) -> io::Result<()> {
 
     /// Acquire an exclusive lock on the file. Blocks until the lock can be acquired.
     ///
-    /// This acquires an exclusive lock; no other file handle to this file may acquire another lock.
+    /// This acquires an exclusive lock; no other file handle to this file, in this or any other
+    /// process, may acquire another lock.
     ///
     /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`],
     /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with
@@ -868,8 +869,8 @@ pub fn lock(&self) -> io::Result<()> {
 
     /// Acquire a shared (non-exclusive) lock on the file. Blocks until the lock can be acquired.
     ///
-    /// This acquires a shared lock; more than one file handle may hold a shared lock, but none may
-    /// hold an exclusive lock at the same time.
+    /// This acquires a shared lock; more than one file handle, in this or any other process, may
+    /// hold a shared lock, but none may hold an exclusive lock at the same time.
     ///
     /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`],
     /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with
@@ -923,7 +924,8 @@ pub fn lock_shared(&self) -> io::Result<()> {
     /// Returns `Err(TryLockError::WouldBlock)` if a different lock is already held on this file
     /// (via another handle/descriptor).
     ///
-    /// This acquires an exclusive lock; no other file handle to this file may acquire another lock.
+    /// This acquires an exclusive lock; no other file handle to this file, in this or any other
+    /// process, may acquire another lock.
     ///
     /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`],
     /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with
@@ -987,8 +989,8 @@ pub fn try_lock(&self) -> Result<(), TryLockError> {
     /// Returns `Err(TryLockError::WouldBlock)` if a different lock is already held on this file
     /// (via another handle/descriptor).
     ///
-    /// This acquires a shared lock; more than one file handle may hold a shared lock, but none may
-    /// hold an exclusive lock at the same time.
+    /// This acquires a shared lock; more than one file handle, in this or any other process, may
+    /// hold a shared lock, but none may hold an exclusive lock at the same time.
     ///
     /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`],
     /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with
diff --git a/library/std/src/io/copy/tests.rs b/library/std/src/io/copy/tests.rs
index 25b1ece..7bdba3a 100644
--- a/library/std/src/io/copy/tests.rs
+++ b/library/std/src/io/copy/tests.rs
@@ -97,16 +97,17 @@ fn copy_specializes_to_vec() {
 
 #[test]
 fn copy_specializes_from_vecdeque() {
-    let mut source = VecDeque::with_capacity(100 * 1024);
-    for _ in 0..20 * 1024 {
+    let num: usize = if cfg!(miri) { 512 } else { 20 * 1024 };
+    let mut source = VecDeque::with_capacity(4 * num);
+    for _ in 0..num {
         source.push_front(0);
     }
-    for _ in 0..20 * 1024 {
+    for _ in 0..num {
         source.push_back(0);
     }
     let mut sink = WriteObserver { observed_buffer: 0 };
-    assert_eq!(40 * 1024u64, io::copy(&mut source, &mut sink).unwrap());
-    assert_eq!(20 * 1024, sink.observed_buffer);
+    assert_eq!(2 * num as u64, io::copy(&mut source, &mut sink).unwrap());
+    assert_eq!(num, sink.observed_buffer);
 }
 
 #[test]
diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs
index 73f3e58..7fd46b3 100644
--- a/library/std/src/os/windows/fs.rs
+++ b/library/std/src/os/windows/fs.rs
@@ -138,6 +138,8 @@ fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
 }
 
 /// Windows-specific extensions to [`fs::OpenOptions`].
+// WARNING: This trait is not sealed. DON'T add any new methods!
+// Add them to OpenOptionsExt2 instead.
 #[stable(feature = "open_options_ext", since = "1.10.0")]
 pub trait OpenOptionsExt {
     /// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`]
@@ -305,18 +307,6 @@ pub trait OpenOptionsExt {
     ///     https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-security_impersonation_level
     #[stable(feature = "open_options_ext", since = "1.10.0")]
     fn security_qos_flags(&mut self, flags: u32) -> &mut Self;
-
-    /// If set to `true`, prevent the "last access time" of the file from being changed.
-    ///
-    /// Default to `false`.
-    #[unstable(feature = "windows_freeze_file_times", issue = "149715")]
-    fn freeze_last_access_time(&mut self, freeze: bool) -> &mut Self;
-
-    /// If set to `true`, prevent the "last write time" of the file from being changed.
-    ///
-    /// Default to `false`.
-    #[unstable(feature = "windows_freeze_file_times", issue = "149715")]
-    fn freeze_last_write_time(&mut self, freeze: bool) -> &mut Self;
 }
 
 #[stable(feature = "open_options_ext", since = "1.10.0")]
@@ -345,7 +335,28 @@ fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions {
         self.as_inner_mut().security_qos_flags(flags);
         self
     }
+}
 
+#[unstable(feature = "windows_freeze_file_times", issue = "149715")]
+pub trait OpenOptionsExt2: Sealed {
+    /// If set to `true`, prevent the "last access time" of the file from being changed.
+    ///
+    /// Default to `false`.
+    #[unstable(feature = "windows_freeze_file_times", issue = "149715")]
+    fn freeze_last_access_time(&mut self, freeze: bool) -> &mut Self;
+
+    /// If set to `true`, prevent the "last write time" of the file from being changed.
+    ///
+    /// Default to `false`.
+    #[unstable(feature = "windows_freeze_file_times", issue = "149715")]
+    fn freeze_last_write_time(&mut self, freeze: bool) -> &mut Self;
+}
+
+#[unstable(feature = "sealed", issue = "none")]
+impl Sealed for OpenOptions {}
+
+#[unstable(feature = "windows_freeze_file_times", issue = "149715")]
+impl OpenOptionsExt2 for OpenOptions {
     fn freeze_last_access_time(&mut self, freeze: bool) -> &mut Self {
         self.as_inner_mut().freeze_last_access_time(freeze);
         self
diff --git a/library/std/src/sys/args/windows.rs b/library/std/src/sys/args/windows.rs
index c198865..3c6995e 100644
--- a/library/std/src/sys/args/windows.rs
+++ b/library/std/src/sys/args/windows.rs
@@ -12,9 +12,9 @@
 use crate::os::windows::prelude::*;
 use crate::path::{Path, PathBuf};
 use crate::sys::helpers::WStrUnits;
-use crate::sys::pal::os::current_exe;
 use crate::sys::pal::{ensure_no_nuls, fill_utf16_buf};
 use crate::sys::path::get_long_path;
+use crate::sys::paths::current_exe;
 use crate::sys::{AsInner, c, to_u16s};
 use crate::{io, iter, ptr};
 
diff --git a/library/std/src/sys/env/unix.rs b/library/std/src/sys/env/unix.rs
index 66805ce..7a19f97 100644
--- a/library/std/src/sys/env/unix.rs
+++ b/library/std/src/sys/env/unix.rs
@@ -38,8 +38,25 @@ pub unsafe fn environ() -> *mut *const *const c_char {
     unsafe { libc::_NSGetEnviron() as *mut *const *const c_char }
 }
 
+// On FreeBSD, environ comes from CRT rather than libc
+#[cfg(target_os = "freebsd")]
+pub unsafe fn environ() -> *mut *const *const c_char {
+    use crate::sync::LazyLock;
+
+    struct Environ(*mut *const *const c_char);
+    unsafe impl Send for Environ {}
+    unsafe impl Sync for Environ {}
+
+    static ENVIRON: LazyLock<Environ> = LazyLock::new(|| {
+        Environ(unsafe {
+            libc::dlsym(libc::RTLD_DEFAULT, c"environ".as_ptr()) as *mut *const *const c_char
+        })
+    });
+    ENVIRON.0
+}
+
 // Use the `environ` static which is part of POSIX.
-#[cfg(not(target_vendor = "apple"))]
+#[cfg(not(any(target_os = "freebsd", target_vendor = "apple")))]
 pub unsafe fn environ() -> *mut *const *const c_char {
     unsafe extern "C" {
         static mut environ: *const *const c_char;
diff --git a/library/std/src/sys/io/error/windows.rs b/library/std/src/sys/io/error/windows.rs
index d760708..c093443 100644
--- a/library/std/src/sys/io/error/windows.rs
+++ b/library/std/src/sys/io/error/windows.rs
@@ -1,6 +1,9 @@
 use crate::sys::pal::{api, c};
 use crate::{io, ptr};
 
+#[cfg(test)]
+mod tests;
+
 pub fn errno() -> i32 {
     api::get_last_error().code as i32
 }
diff --git a/library/std/src/sys/pal/windows/os/tests.rs b/library/std/src/sys/io/error/windows/tests.rs
similarity index 92%
rename from library/std/src/sys/pal/windows/os/tests.rs
rename to library/std/src/sys/io/error/windows/tests.rs
index 458d6e1..7fc545a 100644
--- a/library/std/src/sys/pal/windows/os/tests.rs
+++ b/library/std/src/sys/io/error/windows/tests.rs
@@ -1,5 +1,5 @@
 use crate::io::Error;
-use crate::sys::c;
+use crate::sys::pal::c;
 
 // tests `error_string` above
 #[test]
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index 5ad2397..fe0c103 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -18,6 +18,7 @@
 pub mod net;
 pub mod os_str;
 pub mod path;
+pub mod paths;
 pub mod pipe;
 pub mod platform_version;
 pub mod process;
diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs
index f10a090..b18dc5b 100644
--- a/library/std/src/sys/pal/hermit/mod.rs
+++ b/library/std/src/sys/pal/hermit/mod.rs
@@ -22,7 +22,6 @@
 use crate::sys::env;
 
 pub mod futex;
-pub mod os;
 pub mod time;
 
 pub fn unsupported<T>() -> io::Result<T> {
diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs
deleted file mode 100644
index 188cade..0000000
--- a/library/std/src/sys/pal/hermit/os.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-use crate::ffi::{OsStr, OsString};
-use crate::marker::PhantomData;
-use crate::path::{self, PathBuf};
-use crate::sys::unsupported;
-use crate::{fmt, io};
-
-pub fn getcwd() -> io::Result<PathBuf> {
-    Ok(PathBuf::from("/"))
-}
-
-pub fn chdir(_: &path::Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub struct SplitPaths<'a>(!, PhantomData<&'a ()>);
-
-pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
-    panic!("unsupported")
-}
-
-impl<'a> Iterator for SplitPaths<'a> {
-    type Item = PathBuf;
-    fn next(&mut self) -> Option<PathBuf> {
-        self.0
-    }
-}
-
-#[derive(Debug)]
-pub struct JoinPathsError;
-
-pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
-where
-    I: Iterator<Item = T>,
-    T: AsRef<OsStr>,
-{
-    Err(JoinPathsError)
-}
-
-impl fmt::Display for JoinPathsError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        "not supported on hermit yet".fmt(f)
-    }
-}
-
-impl crate::error::Error for JoinPathsError {}
-
-pub fn current_exe() -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn temp_dir() -> PathBuf {
-    PathBuf::from("/tmp")
-}
-
-pub fn home_dir() -> Option<PathBuf> {
-    None
-}
diff --git a/library/std/src/sys/pal/motor/mod.rs b/library/std/src/sys/pal/motor/mod.rs
index a520375..705413c 100644
--- a/library/std/src/sys/pal/motor/mod.rs
+++ b/library/std/src/sys/pal/motor/mod.rs
@@ -1,7 +1,5 @@
 #![allow(unsafe_op_in_unsafe_fn)]
 
-pub mod os;
-
 pub use moto_rt::futex;
 
 use crate::io;
diff --git a/library/std/src/sys/pal/motor/os.rs b/library/std/src/sys/pal/motor/os.rs
deleted file mode 100644
index 0af5793..0000000
--- a/library/std/src/sys/pal/motor/os.rs
+++ /dev/null
@@ -1,64 +0,0 @@
-use super::map_motor_error;
-use crate::error::Error as StdError;
-use crate::ffi::{OsStr, OsString};
-use crate::marker::PhantomData;
-use crate::os::motor::ffi::OsStrExt;
-use crate::path::{self, PathBuf};
-use crate::{fmt, io};
-
-pub fn getcwd() -> io::Result<PathBuf> {
-    moto_rt::fs::getcwd().map(PathBuf::from).map_err(map_motor_error)
-}
-
-pub fn chdir(path: &path::Path) -> io::Result<()> {
-    moto_rt::fs::chdir(path.as_os_str().as_str()).map_err(map_motor_error)
-}
-
-pub struct SplitPaths<'a>(!, PhantomData<&'a ()>);
-
-pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
-    panic!("unsupported")
-}
-
-impl<'a> Iterator for SplitPaths<'a> {
-    type Item = PathBuf;
-    fn next(&mut self) -> Option<PathBuf> {
-        self.0
-    }
-}
-
-#[derive(Debug)]
-pub struct JoinPathsError;
-
-pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
-where
-    I: Iterator<Item = T>,
-    T: AsRef<OsStr>,
-{
-    Err(JoinPathsError)
-}
-
-impl fmt::Display for JoinPathsError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        "not supported on this platform yet".fmt(f)
-    }
-}
-
-impl StdError for JoinPathsError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "not supported on this platform yet"
-    }
-}
-
-pub fn current_exe() -> io::Result<PathBuf> {
-    moto_rt::process::current_exe().map(PathBuf::from).map_err(map_motor_error)
-}
-
-pub fn temp_dir() -> PathBuf {
-    PathBuf::from(moto_rt::fs::TEMP_DIR)
-}
-
-pub fn home_dir() -> Option<PathBuf> {
-    None
-}
diff --git a/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs
index aaf380d..c269431 100644
--- a/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs
+++ b/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs
@@ -8,7 +8,6 @@
 use crate::convert::TryInto;
 use crate::mem::{self, ManuallyDrop, MaybeUninit};
 use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut};
-use crate::pin::PinCoerceUnsized;
 use crate::ptr::{self, NonNull};
 use crate::slice::SliceIndex;
 use crate::{cmp, intrinsics, slice};
@@ -773,9 +772,6 @@ fn drop(&mut self) {
 #[unstable(feature = "sgx_platform", issue = "56975")]
 impl<T: CoerceUnsized<U>, U> CoerceUnsized<UserRef<U>> for UserRef<T> {}
 
-#[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")]
-unsafe impl<T: ?Sized> PinCoerceUnsized for UserRef<T> {}
-
 #[unstable(feature = "sgx_platform", issue = "56975")]
 impl<T, I> Index<I> for UserRef<[T]>
 where
diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs
index 1de3ca4..2b284cc 100644
--- a/library/std/src/sys/pal/sgx/mod.rs
+++ b/library/std/src/sys/pal/sgx/mod.rs
@@ -10,7 +10,6 @@
 
 pub mod abi;
 mod libunwind_integration;
-pub mod os;
 pub mod thread_parking;
 pub mod waitqueue;
 
diff --git a/library/std/src/sys/pal/sgx/os.rs b/library/std/src/sys/pal/sgx/os.rs
deleted file mode 100644
index 5b0af37..0000000
--- a/library/std/src/sys/pal/sgx/os.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-use crate::ffi::{OsStr, OsString};
-use crate::marker::PhantomData;
-use crate::path::{self, PathBuf};
-use crate::sys::{sgx_ineffective, unsupported};
-use crate::{fmt, io};
-
-pub fn getcwd() -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn chdir(_: &path::Path) -> io::Result<()> {
-    sgx_ineffective(())
-}
-
-pub struct SplitPaths<'a>(!, PhantomData<&'a ()>);
-
-pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
-    panic!("unsupported")
-}
-
-impl<'a> Iterator for SplitPaths<'a> {
-    type Item = PathBuf;
-    fn next(&mut self) -> Option<PathBuf> {
-        self.0
-    }
-}
-
-#[derive(Debug)]
-pub struct JoinPathsError;
-
-pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
-where
-    I: Iterator<Item = T>,
-    T: AsRef<OsStr>,
-{
-    Err(JoinPathsError)
-}
-
-impl fmt::Display for JoinPathsError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        "not supported in SGX yet".fmt(f)
-    }
-}
-
-impl crate::error::Error for JoinPathsError {}
-
-pub fn current_exe() -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn temp_dir() -> PathBuf {
-    panic!("no filesystem in SGX")
-}
-
-pub fn home_dir() -> Option<PathBuf> {
-    None
-}
diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs
index 1376af8..c3f9e47 100644
--- a/library/std/src/sys/pal/solid/mod.rs
+++ b/library/std/src/sys/pal/solid/mod.rs
@@ -19,7 +19,6 @@ pub mod itron {
 // `error` is `pub(crate)` so that it can be accessed by `itron/error.rs` as
 // `crate::sys::error`
 pub(crate) mod error;
-pub mod os;
 pub use self::itron::thread_parking;
 
 // SAFETY: must be called only once during runtime initialization.
diff --git a/library/std/src/sys/pal/solid/os.rs b/library/std/src/sys/pal/solid/os.rs
deleted file mode 100644
index 79bb91b..0000000
--- a/library/std/src/sys/pal/solid/os.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-use super::unsupported;
-use crate::ffi::{OsStr, OsString};
-use crate::path::{self, PathBuf};
-use crate::{fmt, io};
-
-pub fn getcwd() -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn chdir(_: &path::Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub struct SplitPaths<'a>(&'a !);
-
-pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
-    panic!("unsupported")
-}
-
-impl<'a> Iterator for SplitPaths<'a> {
-    type Item = PathBuf;
-    fn next(&mut self) -> Option<PathBuf> {
-        *self.0
-    }
-}
-
-#[derive(Debug)]
-pub struct JoinPathsError;
-
-pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
-where
-    I: Iterator<Item = T>,
-    T: AsRef<OsStr>,
-{
-    Err(JoinPathsError)
-}
-
-impl fmt::Display for JoinPathsError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        "not supported on this platform yet".fmt(f)
-    }
-}
-
-impl crate::error::Error for JoinPathsError {}
-
-pub fn current_exe() -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn temp_dir() -> PathBuf {
-    panic!("no standard temporary directory on this platform")
-}
-
-pub fn home_dir() -> Option<PathBuf> {
-    None
-}
diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs
index 7d2ecdb..5caed27 100644
--- a/library/std/src/sys/pal/teeos/mod.rs
+++ b/library/std/src/sys/pal/teeos/mod.rs
@@ -7,7 +7,6 @@
 #![allow(dead_code)]
 
 pub mod conf;
-pub mod os;
 #[path = "../unix/time.rs"]
 pub mod time;
 
diff --git a/library/std/src/sys/pal/teeos/os.rs b/library/std/src/sys/pal/teeos/os.rs
deleted file mode 100644
index c86fa55..0000000
--- a/library/std/src/sys/pal/teeos/os.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-//! Implementation of `std::os` functionality for teeos
-
-use core::marker::PhantomData;
-
-use super::unsupported;
-use crate::ffi::{OsStr, OsString};
-use crate::path::PathBuf;
-use crate::{fmt, io, path};
-
-// Everything below are stubs and copied from unsupported.rs
-
-pub fn getcwd() -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn chdir(_: &path::Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub struct SplitPaths<'a>(!, PhantomData<&'a ()>);
-
-pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
-    panic!("unsupported")
-}
-
-impl<'a> Iterator for SplitPaths<'a> {
-    type Item = PathBuf;
-    fn next(&mut self) -> Option<PathBuf> {
-        self.0
-    }
-}
-
-#[derive(Debug)]
-pub struct JoinPathsError;
-
-pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
-where
-    I: Iterator<Item = T>,
-    T: AsRef<OsStr>,
-{
-    Err(JoinPathsError)
-}
-
-impl fmt::Display for JoinPathsError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        "not supported on this platform yet".fmt(f)
-    }
-}
-
-impl crate::error::Error for JoinPathsError {}
-
-pub fn current_exe() -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn temp_dir() -> PathBuf {
-    panic!("no filesystem on this platform")
-}
-
-pub fn home_dir() -> Option<PathBuf> {
-    None
-}
diff --git a/library/std/src/sys/pal/trusty/mod.rs b/library/std/src/sys/pal/trusty/mod.rs
index b785c2d..ec2d938 100644
--- a/library/std/src/sys/pal/trusty/mod.rs
+++ b/library/std/src/sys/pal/trusty/mod.rs
@@ -3,7 +3,5 @@
 #[path = "../unsupported/common.rs"]
 #[deny(unsafe_op_in_unsafe_fn)]
 mod common;
-#[path = "../unsupported/os.rs"]
-pub mod os;
 
 pub use common::*;
diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs
index e4a8f50..67499d2 100644
--- a/library/std/src/sys/pal/uefi/mod.rs
+++ b/library/std/src/sys/pal/uefi/mod.rs
@@ -14,7 +14,6 @@
 #![forbid(unsafe_op_in_unsafe_fn)]
 
 pub mod helpers;
-pub mod os;
 pub mod system_time;
 
 #[cfg(test)]
diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs
index 9931b4d..0be150a 100644
--- a/library/std/src/sys/pal/unix/mod.rs
+++ b/library/std/src/sys/pal/unix/mod.rs
@@ -8,7 +8,6 @@
 pub mod futex;
 #[cfg(target_os = "linux")]
 pub mod linux;
-pub mod os;
 pub mod stack_overflow;
 pub mod sync;
 pub mod thread_parking;
diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs
index 632f619..5d53de7 100644
--- a/library/std/src/sys/pal/unix/stack_overflow.rs
+++ b/library/std/src/sys/pal/unix/stack_overflow.rs
@@ -429,6 +429,11 @@ unsafe fn install_main_guard() -> Option<Range<usize>> {
 
     #[forbid(unsafe_op_in_unsafe_fn)]
     unsafe fn install_main_guard_linux(page_size: usize) -> Option<Range<usize>> {
+        // See the corresponding conditional in init().
+        // Avoid stack_start_aligned, which makes slow syscalls to read /proc/self/maps
+        if cfg!(panic = "immediate-abort") {
+            return None;
+        }
         // Linux doesn't allocate the whole stack right away, and
         // the kernel has its own stack-guard mechanism to fault
         // when growing too close to an existing mapping. If we map
@@ -456,6 +461,10 @@ unsafe fn install_main_guard_linux_musl(_page_size: usize) -> Option<Range<usize
     #[forbid(unsafe_op_in_unsafe_fn)]
     #[cfg(target_os = "freebsd")]
     unsafe fn install_main_guard_freebsd(page_size: usize) -> Option<Range<usize>> {
+        // See the corresponding conditional in install_main_guard_linux().
+        if cfg!(panic = "immediate-abort") {
+            return None;
+        }
         // FreeBSD's stack autogrows, and optionally includes a guard page
         // at the bottom. If we try to remap the bottom of the stack
         // ourselves, FreeBSD's guard page moves upwards. So we'll just use
@@ -489,6 +498,10 @@ unsafe fn install_main_guard_freebsd(page_size: usize) -> Option<Range<usize>> {
 
     #[forbid(unsafe_op_in_unsafe_fn)]
     unsafe fn install_main_guard_bsds(page_size: usize) -> Option<Range<usize>> {
+        // See the corresponding conditional in install_main_guard_linux().
+        if cfg!(panic = "immediate-abort") {
+            return None;
+        }
         // OpenBSD stack already includes a guard page, and stack is
         // immutable.
         // NetBSD stack includes the guard page.
diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs
index 0f15781..c4b14ab 100644
--- a/library/std/src/sys/pal/unsupported/mod.rs
+++ b/library/std/src/sys/pal/unsupported/mod.rs
@@ -1,6 +1,4 @@
 #![deny(unsafe_op_in_unsafe_fn)]
 
-pub mod os;
-
 mod common;
 pub use common::*;
diff --git a/library/std/src/sys/pal/vexos/mod.rs b/library/std/src/sys/pal/vexos/mod.rs
index d1380ab..61bbe78 100644
--- a/library/std/src/sys/pal/vexos/mod.rs
+++ b/library/std/src/sys/pal/vexos/mod.rs
@@ -1,6 +1,3 @@
-#[path = "../unsupported/os.rs"]
-pub mod os;
-
 #[expect(dead_code)]
 #[path = "../unsupported/common.rs"]
 mod unsupported_common;
diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs
index 66d9107..6f60993 100644
--- a/library/std/src/sys/pal/wasi/mod.rs
+++ b/library/std/src/sys/pal/wasi/mod.rs
@@ -10,7 +10,6 @@
 #[allow(unused)]
 #[path = "../wasm/atomics/futex.rs"]
 pub mod futex;
-pub mod os;
 pub mod stack_overflow;
 #[path = "../unix/time.rs"]
 pub mod time;
diff --git a/library/std/src/sys/pal/wasi/os.rs b/library/std/src/sys/pal/wasi/os.rs
deleted file mode 100644
index b1c26ac..0000000
--- a/library/std/src/sys/pal/wasi/os.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-#![forbid(unsafe_op_in_unsafe_fn)]
-
-use crate::ffi::{CStr, OsStr, OsString};
-use crate::marker::PhantomData;
-use crate::os::wasi::prelude::*;
-use crate::path::{self, PathBuf};
-use crate::sys::helpers::run_path_with_cstr;
-use crate::sys::unsupported;
-use crate::{fmt, io};
-
-pub fn getcwd() -> io::Result<PathBuf> {
-    let mut buf = Vec::with_capacity(512);
-    loop {
-        unsafe {
-            let ptr = buf.as_mut_ptr() as *mut libc::c_char;
-            if !libc::getcwd(ptr, buf.capacity()).is_null() {
-                let len = CStr::from_ptr(buf.as_ptr() as *const libc::c_char).to_bytes().len();
-                buf.set_len(len);
-                buf.shrink_to_fit();
-                return Ok(PathBuf::from(OsString::from_vec(buf)));
-            } else {
-                let error = io::Error::last_os_error();
-                if error.raw_os_error() != Some(libc::ERANGE) {
-                    return Err(error);
-                }
-            }
-
-            // Trigger the internal buffer resizing logic of `Vec` by requiring
-            // more space than the current capacity.
-            let cap = buf.capacity();
-            buf.set_len(cap);
-            buf.reserve(1);
-        }
-    }
-}
-
-pub fn chdir(p: &path::Path) -> io::Result<()> {
-    let result = run_path_with_cstr(p, &|p| unsafe { Ok(libc::chdir(p.as_ptr())) })?;
-    match result == (0 as libc::c_int) {
-        true => Ok(()),
-        false => Err(io::Error::last_os_error()),
-    }
-}
-
-pub struct SplitPaths<'a>(!, PhantomData<&'a ()>);
-
-pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
-    panic!("unsupported")
-}
-
-impl<'a> Iterator for SplitPaths<'a> {
-    type Item = PathBuf;
-    fn next(&mut self) -> Option<PathBuf> {
-        self.0
-    }
-}
-
-#[derive(Debug)]
-pub struct JoinPathsError;
-
-pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
-where
-    I: Iterator<Item = T>,
-    T: AsRef<OsStr>,
-{
-    Err(JoinPathsError)
-}
-
-impl fmt::Display for JoinPathsError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        "not supported on wasm yet".fmt(f)
-    }
-}
-
-impl crate::error::Error for JoinPathsError {}
-
-pub fn current_exe() -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn temp_dir() -> PathBuf {
-    panic!("no filesystem on wasm")
-}
-
-pub fn home_dir() -> Option<PathBuf> {
-    None
-}
diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs
index 5f56edd..24a2ab8 100644
--- a/library/std/src/sys/pal/wasm/mod.rs
+++ b/library/std/src/sys/pal/wasm/mod.rs
@@ -16,9 +16,6 @@
 
 #![deny(unsafe_op_in_unsafe_fn)]
 
-#[path = "../unsupported/os.rs"]
-pub mod os;
-
 #[cfg(target_feature = "atomics")]
 #[path = "atomics/futex.rs"]
 pub mod futex;
diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs
index 0cd9152..b67ba37 100644
--- a/library/std/src/sys/pal/windows/mod.rs
+++ b/library/std/src/sys/pal/windows/mod.rs
@@ -18,7 +18,6 @@
 #[cfg(not(target_vendor = "win7"))]
 pub mod futex;
 pub mod handle;
-pub mod os;
 pub mod time;
 cfg_select! {
     // We don't care about printing nice error messages for panic=immediate-abort
diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs
index 9b22fb8..b5b3fd9 100644
--- a/library/std/src/sys/pal/xous/mod.rs
+++ b/library/std/src/sys/pal/xous/mod.rs
@@ -1,6 +1,5 @@
 #![forbid(unsafe_op_in_unsafe_fn)]
 
-pub mod os;
 pub mod params;
 
 #[path = "../unsupported/common.rs"]
diff --git a/library/std/src/sys/pal/xous/os.rs b/library/std/src/sys/pal/xous/os.rs
deleted file mode 100644
index fe8adde..0000000
--- a/library/std/src/sys/pal/xous/os.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-use super::unsupported;
-use crate::ffi::{OsStr, OsString};
-use crate::marker::PhantomData;
-use crate::path::{self, PathBuf};
-use crate::{fmt, io};
-
-pub fn getcwd() -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn chdir(_: &path::Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub struct SplitPaths<'a>(!, PhantomData<&'a ()>);
-
-pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
-    panic!("unsupported")
-}
-
-impl<'a> Iterator for SplitPaths<'a> {
-    type Item = PathBuf;
-    fn next(&mut self) -> Option<PathBuf> {
-        self.0
-    }
-}
-
-#[derive(Debug)]
-pub struct JoinPathsError;
-
-pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
-where
-    I: Iterator<Item = T>,
-    T: AsRef<OsStr>,
-{
-    Err(JoinPathsError)
-}
-
-impl fmt::Display for JoinPathsError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        "not supported on this platform yet".fmt(f)
-    }
-}
-
-impl crate::error::Error for JoinPathsError {}
-
-pub fn current_exe() -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn temp_dir() -> PathBuf {
-    panic!("no filesystem on this platform")
-}
-
-pub fn home_dir() -> Option<PathBuf> {
-    None
-}
diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs
index 1b18adb..1a64d3c 100644
--- a/library/std/src/sys/pal/zkvm/mod.rs
+++ b/library/std/src/sys/pal/zkvm/mod.rs
@@ -11,7 +11,6 @@
 pub const WORD_SIZE: usize = size_of::<u32>();
 
 pub mod abi;
-pub mod os;
 
 use crate::io as std_io;
 
diff --git a/library/std/src/sys/pal/zkvm/os.rs b/library/std/src/sys/pal/zkvm/os.rs
deleted file mode 100644
index fe8adde..0000000
--- a/library/std/src/sys/pal/zkvm/os.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-use super::unsupported;
-use crate::ffi::{OsStr, OsString};
-use crate::marker::PhantomData;
-use crate::path::{self, PathBuf};
-use crate::{fmt, io};
-
-pub fn getcwd() -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn chdir(_: &path::Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub struct SplitPaths<'a>(!, PhantomData<&'a ()>);
-
-pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
-    panic!("unsupported")
-}
-
-impl<'a> Iterator for SplitPaths<'a> {
-    type Item = PathBuf;
-    fn next(&mut self) -> Option<PathBuf> {
-        self.0
-    }
-}
-
-#[derive(Debug)]
-pub struct JoinPathsError;
-
-pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
-where
-    I: Iterator<Item = T>,
-    T: AsRef<OsStr>,
-{
-    Err(JoinPathsError)
-}
-
-impl fmt::Display for JoinPathsError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        "not supported on this platform yet".fmt(f)
-    }
-}
-
-impl crate::error::Error for JoinPathsError {}
-
-pub fn current_exe() -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn temp_dir() -> PathBuf {
-    panic!("no filesystem on this platform")
-}
-
-pub fn home_dir() -> Option<PathBuf> {
-    None
-}
diff --git a/library/std/src/sys/paths/hermit.rs b/library/std/src/sys/paths/hermit.rs
new file mode 100644
index 0000000..36f667d
--- /dev/null
+++ b/library/std/src/sys/paths/hermit.rs
@@ -0,0 +1,10 @@
+use crate::io;
+use crate::path::PathBuf;
+
+pub fn getcwd() -> io::Result<PathBuf> {
+    Ok(PathBuf::from("/"))
+}
+
+pub fn temp_dir() -> PathBuf {
+    PathBuf::from("/tmp")
+}
diff --git a/library/std/src/sys/paths/mod.rs b/library/std/src/sys/paths/mod.rs
new file mode 100644
index 0000000..8880a83
--- /dev/null
+++ b/library/std/src/sys/paths/mod.rs
@@ -0,0 +1,59 @@
+cfg_select! {
+    target_os = "hermit" => {
+        mod hermit;
+        #[expect(dead_code)]
+        mod unsupported;
+        mod imp {
+            pub use super::hermit::{getcwd, temp_dir};
+            pub use super::unsupported::{chdir, SplitPaths, split_paths, JoinPathsError, join_paths, current_exe, home_dir};
+        }
+    }
+    target_os = "motor" => {
+        mod motor;
+        #[expect(dead_code)]
+        mod unsupported;
+        mod imp {
+            pub use super::motor::{getcwd, chdir, current_exe, temp_dir};
+            pub use super::unsupported::{SplitPaths, split_paths, JoinPathsError, join_paths, home_dir};
+        }
+    }
+    all(target_vendor = "fortanix", target_env = "sgx") => {
+        mod sgx;
+        #[expect(dead_code)]
+        mod unsupported;
+        mod imp {
+            pub use super::sgx::chdir;
+            pub use super::unsupported::{getcwd, SplitPaths, split_paths, JoinPathsError, join_paths, current_exe, temp_dir, home_dir};
+        }
+    }
+    target_os = "uefi" => {
+        mod uefi;
+        use uefi as imp;
+    }
+    target_family = "unix" => {
+        mod unix;
+        use unix as imp;
+    }
+    target_os = "wasi" => {
+        mod wasi;
+        #[expect(dead_code)]
+        mod unsupported;
+        mod imp {
+            pub use super::wasi::{getcwd, chdir, temp_dir};
+            pub use super::unsupported::{current_exe, SplitPaths, split_paths, JoinPathsError, join_paths, home_dir};
+        }
+    }
+    target_os = "windows" => {
+        mod windows;
+        use windows as imp;
+    }
+    _ => {
+        mod unsupported;
+        use unsupported as imp;
+    }
+}
+
+pub use imp::{
+    JoinPathsError, SplitPaths, chdir, current_exe, getcwd, home_dir, join_paths, split_paths,
+    temp_dir,
+};
diff --git a/library/std/src/sys/paths/motor.rs b/library/std/src/sys/paths/motor.rs
new file mode 100644
index 0000000..33d746b
--- /dev/null
+++ b/library/std/src/sys/paths/motor.rs
@@ -0,0 +1,20 @@
+use crate::io;
+use crate::os::motor::ffi::OsStrExt;
+use crate::path::{self, PathBuf};
+use crate::sys::pal::map_motor_error;
+
+pub fn getcwd() -> io::Result<PathBuf> {
+    moto_rt::fs::getcwd().map(PathBuf::from).map_err(map_motor_error)
+}
+
+pub fn chdir(path: &path::Path) -> io::Result<()> {
+    moto_rt::fs::chdir(path.as_os_str().as_str()).map_err(map_motor_error)
+}
+
+pub fn current_exe() -> io::Result<PathBuf> {
+    moto_rt::process::current_exe().map(PathBuf::from).map_err(map_motor_error)
+}
+
+pub fn temp_dir() -> PathBuf {
+    PathBuf::from(moto_rt::fs::TEMP_DIR)
+}
diff --git a/library/std/src/sys/paths/sgx.rs b/library/std/src/sys/paths/sgx.rs
new file mode 100644
index 0000000..6a4cbe9
--- /dev/null
+++ b/library/std/src/sys/paths/sgx.rs
@@ -0,0 +1,7 @@
+use crate::io;
+use crate::path::Path;
+use crate::sys::pal::sgx_ineffective;
+
+pub fn chdir(_: &Path) -> io::Result<()> {
+    sgx_ineffective(())
+}
diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/paths/uefi.rs
similarity index 96%
rename from library/std/src/sys/pal/uefi/os.rs
rename to library/std/src/sys/paths/uefi.rs
index b25be43..7fddcfd 100644
--- a/library/std/src/sys/pal/uefi/os.rs
+++ b/library/std/src/sys/paths/uefi.rs
@@ -1,9 +1,9 @@
 use r_efi::efi::protocols::{device_path, loaded_image_device_path};
 
-use super::{helpers, unsupported_err};
 use crate::ffi::{OsStr, OsString};
 use crate::os::uefi::ffi::{OsStrExt, OsStringExt};
 use crate::path::{self, PathBuf};
+use crate::sys::pal::{helpers, unsupported_err};
 use crate::{fmt, io};
 
 const PATHS_SEP: u16 = b';' as u16;
@@ -115,7 +115,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
 }
 
 pub fn temp_dir() -> PathBuf {
-    panic!("no filesystem on this platform")
+    panic!("UEFI doesn't have a dedicated temp directory")
 }
 
 pub fn home_dir() -> Option<PathBuf> {
diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/paths/unix.rs
similarity index 98%
rename from library/std/src/sys/pal/unix/os.rs
rename to library/std/src/sys/paths/unix.rs
index f69614c..544d495 100644
--- a/library/std/src/sys/pal/unix/os.rs
+++ b/library/std/src/sys/paths/unix.rs
@@ -7,8 +7,8 @@
 use crate::ffi::{CStr, OsStr, OsString};
 use crate::os::unix::prelude::*;
 use crate::path::{self, PathBuf};
-use crate::sys::cvt;
 use crate::sys::helpers::run_path_with_cstr;
+use crate::sys::pal::cvt;
 use crate::{fmt, io, iter, mem, ptr, slice, str};
 
 const PATH_SEPARATOR: u8 = b':';
@@ -47,7 +47,7 @@ pub fn getcwd() -> io::Result<PathBuf> {
 
 #[cfg(target_os = "espidf")]
 pub fn chdir(_p: &path::Path) -> io::Result<()> {
-    super::unsupported::unsupported()
+    crate::sys::pal::unsupported::unsupported()
 }
 
 #[cfg(not(target_os = "espidf"))]
@@ -372,7 +372,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
 
 #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))]
 pub fn current_exe() -> io::Result<PathBuf> {
-    super::unsupported::unsupported()
+    crate::sys::pal::unsupported::unsupported()
 }
 
 #[cfg(target_os = "fuchsia")]
diff --git a/library/std/src/sys/pal/unsupported/os.rs b/library/std/src/sys/paths/unsupported.rs
similarity index 96%
rename from library/std/src/sys/pal/unsupported/os.rs
rename to library/std/src/sys/paths/unsupported.rs
index fe8adde..024830a 100644
--- a/library/std/src/sys/pal/unsupported/os.rs
+++ b/library/std/src/sys/paths/unsupported.rs
@@ -1,7 +1,7 @@
-use super::unsupported;
 use crate::ffi::{OsStr, OsString};
 use crate::marker::PhantomData;
 use crate::path::{self, PathBuf};
+use crate::sys::pal::unsupported;
 use crate::{fmt, io};
 
 pub fn getcwd() -> io::Result<PathBuf> {
diff --git a/library/std/src/sys/paths/wasi.rs b/library/std/src/sys/paths/wasi.rs
new file mode 100644
index 0000000..1e1f951
--- /dev/null
+++ b/library/std/src/sys/paths/wasi.rs
@@ -0,0 +1,45 @@
+#![forbid(unsafe_op_in_unsafe_fn)]
+
+use crate::ffi::{CStr, OsString};
+use crate::io;
+use crate::os::wasi::prelude::*;
+use crate::path::{self, PathBuf};
+use crate::sys::helpers::run_path_with_cstr;
+
+pub fn getcwd() -> io::Result<PathBuf> {
+    let mut buf = Vec::with_capacity(512);
+    loop {
+        unsafe {
+            let ptr = buf.as_mut_ptr() as *mut libc::c_char;
+            if !libc::getcwd(ptr, buf.capacity()).is_null() {
+                let len = CStr::from_ptr(buf.as_ptr() as *const libc::c_char).to_bytes().len();
+                buf.set_len(len);
+                buf.shrink_to_fit();
+                return Ok(PathBuf::from(OsString::from_vec(buf)));
+            } else {
+                let error = io::Error::last_os_error();
+                if error.raw_os_error() != Some(libc::ERANGE) {
+                    return Err(error);
+                }
+            }
+
+            // Trigger the internal buffer resizing logic of `Vec` by requiring
+            // more space than the current capacity.
+            let cap = buf.capacity();
+            buf.set_len(cap);
+            buf.reserve(1);
+        }
+    }
+}
+
+pub fn chdir(p: &path::Path) -> io::Result<()> {
+    let result = run_path_with_cstr(p, &|p| unsafe { Ok(libc::chdir(p.as_ptr())) })?;
+    match result == (0 as libc::c_int) {
+        true => Ok(()),
+        false => Err(io::Error::last_os_error()),
+    }
+}
+
+pub fn temp_dir() -> PathBuf {
+    panic!("not supported by WASI yet")
+}
diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/paths/windows.rs
similarity index 87%
rename from library/std/src/sys/pal/windows/os.rs
rename to library/std/src/sys/paths/windows.rs
index 30cad2a..cfdc938 100644
--- a/library/std/src/sys/pal/windows/os.rs
+++ b/library/std/src/sys/paths/windows.rs
@@ -2,17 +2,13 @@
 
 #![allow(nonstandard_style)]
 
-#[cfg(test)]
-mod tests;
-
-use super::api;
-#[cfg(not(target_vendor = "uwp"))]
-use super::api::WinError;
 use crate::ffi::{OsStr, OsString};
 use crate::os::windows::ffi::EncodeWide;
 use crate::os::windows::prelude::*;
 use crate::path::{self, PathBuf};
-use crate::sys::pal::{c, cvt};
+#[cfg(not(target_vendor = "uwp"))]
+use crate::sys::pal::api::WinError;
+use crate::sys::pal::{api, c, cvt, fill_utf16_buf, os2path};
 use crate::{fmt, io, ptr};
 
 pub struct SplitPaths<'a> {
@@ -56,11 +52,7 @@ fn next(&mut self) -> Option<PathBuf> {
             }
         }
 
-        if !must_yield && in_progress.is_empty() {
-            None
-        } else {
-            Some(super::os2path(&in_progress))
-        }
+        if !must_yield && in_progress.is_empty() { None } else { Some(os2path(&in_progress)) }
     }
 }
 
@@ -104,14 +96,11 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 impl crate::error::Error for JoinPathsError {}
 
 pub fn current_exe() -> io::Result<PathBuf> {
-    super::fill_utf16_buf(
-        |buf, sz| unsafe { c::GetModuleFileNameW(ptr::null_mut(), buf, sz) },
-        super::os2path,
-    )
+    fill_utf16_buf(|buf, sz| unsafe { c::GetModuleFileNameW(ptr::null_mut(), buf, sz) }, os2path)
 }
 
 pub fn getcwd() -> io::Result<PathBuf> {
-    super::fill_utf16_buf(|buf, sz| unsafe { c::GetCurrentDirectoryW(sz, buf) }, super::os2path)
+    fill_utf16_buf(|buf, sz| unsafe { c::GetCurrentDirectoryW(sz, buf) }, os2path)
 }
 
 pub fn chdir(p: &path::Path) -> io::Result<()> {
@@ -123,7 +112,7 @@ pub fn chdir(p: &path::Path) -> io::Result<()> {
 }
 
 pub fn temp_dir() -> PathBuf {
-    super::fill_utf16_buf(|buf, sz| unsafe { c::GetTempPath2W(sz, buf) }, super::os2path).unwrap()
+    fill_utf16_buf(|buf, sz| unsafe { c::GetTempPath2W(sz, buf) }, os2path).unwrap()
 }
 
 #[cfg(all(not(target_vendor = "uwp"), not(target_vendor = "win7")))]
@@ -132,7 +121,7 @@ fn home_dir_crt() -> Option<PathBuf> {
         // Defined in processthreadsapi.h.
         const CURRENT_PROCESS_TOKEN: usize = -4_isize as usize;
 
-        super::fill_utf16_buf(
+        fill_utf16_buf(
             |buf, mut sz| {
                 // GetUserProfileDirectoryW does not quite use the usual protocol for
                 // negotiating the buffer size, so we have to translate.
@@ -146,7 +135,7 @@ fn home_dir_crt() -> Option<PathBuf> {
                     _ => sz - 1, // sz includes the null terminator
                 }
             },
-            super::os2path,
+            os2path,
         )
         .ok()
     }
@@ -163,7 +152,7 @@ fn home_dir_crt() -> Option<PathBuf> {
             return None;
         }
         let _handle = Handle::from_raw_handle(token);
-        super::fill_utf16_buf(
+        fill_utf16_buf(
             |buf, mut sz| {
                 match c::GetUserProfileDirectoryW(token, buf, &mut sz) {
                     0 if api::get_last_error() != WinError::INSUFFICIENT_BUFFER => 0,
@@ -171,7 +160,7 @@ fn home_dir_crt() -> Option<PathBuf> {
                     _ => sz - 1, // sz includes the null terminator
                 }
             },
-            super::os2path,
+            os2path,
         )
         .ok()
     }
diff --git a/library/std/src/sys/thread_local/os.rs b/library/std/src/sys/thread_local/os.rs
index 3f06c9b..e1d9d80 100644
--- a/library/std/src/sys/thread_local/os.rs
+++ b/library/std/src/sys/thread_local/os.rs
@@ -62,25 +62,7 @@ fn __rust_std_internal_init_fn() -> $t { $init }
     // by translating it into a `cfg`ed block and recursing.
     // https://doc.rust-lang.org/reference/conditional-compilation.html#railroad-ConfigurationPredicate
 
-    (@align $final_align:ident, cfg_attr(true, $($cfg_rhs:tt)*) $(, $($attr_rest:tt)+)?) => {
-        #[cfg(true)]
-        {
-            $crate::thread::local_impl::thread_local_inner!(@align $final_align, $($cfg_rhs)*);
-        }
-
-        $($crate::thread::local_impl::thread_local_inner!(@align $final_align, $($attr_rest)+);)?
-    },
-
-    (@align $final_align:ident, cfg_attr(false, $($cfg_rhs:tt)*) $(, $($attr_rest:tt)+)?) => {
-        #[cfg(false)]
-        {
-            $crate::thread::local_impl::thread_local_inner!(@align $final_align, $($cfg_rhs)*);
-        }
-
-        $($crate::thread::local_impl::thread_local_inner!(@align $final_align, $($attr_rest)+);)?
-    },
-
-    (@align $final_align:ident, cfg_attr($cfg_pred:meta, $($cfg_rhs:tt)*) $(, $($attr_rest:tt)+)?) => {
+    (@align $final_align:ident, cfg_attr($cfg_pred:expr, $($cfg_rhs:tt)*) $(, $($attr_rest:tt)+)?) => {
         #[cfg($cfg_pred)]
         {
             $crate::thread::local_impl::thread_local_inner!(@align $final_align, $($cfg_rhs)*);
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index 1318d8d..5de0018 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -198,41 +198,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         );
     ),
 
-    // it's a nested `cfg_attr(true, ...)`; recurse into RHS
-    (
-        [$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*];
-        @processing_cfg_attr { pred: ($($predicate:tt)*), rhs: [cfg_attr(true, $($cfg_rhs:tt)*) $(, $($attr_rhs:tt)*)?] };
-        $($rest:tt)*
-    ) => (
-        $crate::thread::local_impl::thread_local_process_attrs!(
-            [] [];
-            @processing_cfg_attr { pred: (true), rhs: [$($cfg_rhs)*] };
-            [$($prev_align_attrs)*] [$($prev_other_attrs)*];
-            @processing_cfg_attr { pred: ($($predicate)*), rhs: [$($($attr_rhs)*)?] };
-            $($rest)*
-        );
-    ),
-
-    // it's a nested `cfg_attr(false, ...)`; recurse into RHS
-    (
-        [$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*];
-        @processing_cfg_attr { pred: ($($predicate:tt)*), rhs: [cfg_attr(false, $($cfg_rhs:tt)*) $(, $($attr_rhs:tt)*)?] };
-        $($rest:tt)*
-    ) => (
-        $crate::thread::local_impl::thread_local_process_attrs!(
-            [] [];
-            @processing_cfg_attr { pred: (false), rhs: [$($cfg_rhs)*] };
-            [$($prev_align_attrs)*] [$($prev_other_attrs)*];
-            @processing_cfg_attr { pred: ($($predicate)*), rhs: [$($($attr_rhs)*)?] };
-            $($rest)*
-        );
-    ),
-
-
     // it's a nested `cfg_attr(..., ...)`; recurse into RHS
     (
         [$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*];
-        @processing_cfg_attr { pred: ($($predicate:tt)*), rhs: [cfg_attr($cfg_lhs:meta, $($cfg_rhs:tt)*) $(, $($attr_rhs:tt)*)?] };
+        @processing_cfg_attr { pred: ($($predicate:tt)*), rhs: [cfg_attr($cfg_lhs:expr, $($cfg_rhs:tt)*) $(, $($attr_rhs:tt)*)?] };
         $($rest:tt)*
     ) => (
         $crate::thread::local_impl::thread_local_process_attrs!(
@@ -268,28 +237,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         );
     ),
 
-    // `cfg_attr(true, ...)` attribute; parse it
-    ([$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*]; #[cfg_attr(true, $($cfg_rhs:tt)*)] $($rest:tt)*) => (
-        $crate::thread::local_impl::thread_local_process_attrs!(
-            [] [];
-            @processing_cfg_attr { pred: (true), rhs: [$($cfg_rhs)*] };
-            [$($prev_align_attrs)*] [$($prev_other_attrs)*];
-            $($rest)*
-        );
-    ),
-
-    // `cfg_attr(false, ...)` attribute; parse it
-    ([$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*]; #[cfg_attr(false, $($cfg_rhs:tt)*)] $($rest:tt)*) => (
-        $crate::thread::local_impl::thread_local_process_attrs!(
-            [] [];
-            @processing_cfg_attr { pred: (false), rhs: [$($cfg_rhs)*] };
-            [$($prev_align_attrs)*] [$($prev_other_attrs)*];
-            $($rest)*
-        );
-    ),
-
     // `cfg_attr(..., ...)` attribute; parse it
-    ([$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*]; #[cfg_attr($cfg_pred:meta, $($cfg_rhs:tt)*)] $($rest:tt)*) => (
+    ([$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*]; #[cfg_attr($cfg_pred:expr, $($cfg_rhs:tt)*)] $($rest:tt)*) => (
         $crate::thread::local_impl::thread_local_process_attrs!(
             [] [];
             @processing_cfg_attr { pred: ($cfg_pred), rhs: [$($cfg_rhs)*] };
diff --git a/library/std/tests/sync/mpmc.rs b/library/std/tests/sync/mpmc.rs
index bf80ab9..db221ff 100644
--- a/library/std/tests/sync/mpmc.rs
+++ b/library/std/tests/sync/mpmc.rs
@@ -475,7 +475,6 @@ fn stress_recv_timeout_two_threads() {
     });
 
     let mut recv_count = 0;
-    let mut got_timeout = false;
     loop {
         match rx.recv_timeout(timeout) {
             Ok(n) => {
@@ -483,7 +482,6 @@ fn stress_recv_timeout_two_threads() {
                 recv_count += 1;
             }
             Err(RecvTimeoutError::Timeout) => {
-                got_timeout = true;
                 continue;
             }
             Err(RecvTimeoutError::Disconnected) => break,
@@ -491,7 +489,6 @@ fn stress_recv_timeout_two_threads() {
     }
 
     assert_eq!(recv_count, stress);
-    assert!(got_timeout);
 }
 
 #[test]
diff --git a/library/std/tests/sync/mpsc.rs b/library/std/tests/sync/mpsc.rs
index 9de4a71..4dc4b95 100644
--- a/library/std/tests/sync/mpsc.rs
+++ b/library/std/tests/sync/mpsc.rs
@@ -438,7 +438,6 @@ fn stress_recv_timeout_two_threads() {
     });
 
     let mut recv_count = 0;
-    let mut got_timeout = false;
     loop {
         match rx.recv_timeout(timeout) {
             Ok(n) => {
@@ -446,7 +445,6 @@ fn stress_recv_timeout_two_threads() {
                 recv_count += 1;
             }
             Err(RecvTimeoutError::Timeout) => {
-                got_timeout = true;
                 continue;
             }
             Err(RecvTimeoutError::Disconnected) => break,
@@ -454,7 +452,6 @@ fn stress_recv_timeout_two_threads() {
     }
 
     assert_eq!(recv_count, stress);
-    assert!(got_timeout);
 }
 
 #[test]
diff --git a/library/stdarch/crates/core_arch/src/mips/msa.rs b/library/stdarch/crates/core_arch/src/mips/msa.rs
index 563e121..6246433 100644
--- a/library/stdarch/crates/core_arch/src/mips/msa.rs
+++ b/library/stdarch/crates/core_arch/src/mips/msa.rs
@@ -9187,7 +9187,6 @@ mod tests {
         core_arch::{mips::msa::*, simd::*},
         mem,
     };
-    use std::{f32, f64};
     use stdarch_test::simd_test;
 
     #[simd_test(enable = "msa")]
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index f130381..6af11d9 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -883,6 +883,12 @@ fn rustc_features(&self, kind: Kind, target: TargetSelection, crates: &[String])
             features.push("check_only");
         }
 
+        if crates.iter().any(|c| c == "rustc_transmute") {
+            // for `x test rustc_transmute`, this feature isn't enabled automatically by a
+            // dependent crate.
+            features.push("rustc");
+        }
+
         // If debug logging is on, then we want the default for tracing:
         // https://github.com/tokio-rs/tracing/blob/3dd5c03d907afdf2c39444a29931833335171554/tracing/src/level_filters.rs#L26
         // which is everything (including debug/trace/etc.)
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 7c0f1d3..5909f29 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -509,7 +509,7 @@
   - name: dist-aarch64-apple
     env:
       SCRIPT: >-
-        ./x.py dist bootstrap
+        ./x.py dist bootstrap enzyme
         --include-default-paths
         --host=aarch64-apple-darwin
         --target=aarch64-apple-darwin
@@ -518,6 +518,7 @@
         --enable-sanitizers
         --enable-profiler
         --set rust.jemalloc
+        --set llvm.link-shared=true
         --set rust.lto=thin
         --set rust.codegen-units=1
       # Aarch64 tooling only needs to support macOS 11.0 and up as nothing else
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
index e88aa44..2463ede 160000
--- a/src/doc/embedded-book
+++ b/src/doc/embedded-book
@@ -1 +1 @@
-Subproject commit e88aa4403b4bf2071c8df9509160477e40179099
+Subproject commit 2463edeb8003c5743918b3739a9f6870b86396f5
diff --git a/src/doc/reference b/src/doc/reference
index c49e89c..7446bf9 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit c49e89cc8c7c2c43ca625a8d5b7ad9a53a9ce978
+Subproject commit 7446bf9697c95d155eef33c6a9d91fbd29a5e359
diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs
index 4038f11..a9b4d18 100644
--- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs
+++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs
@@ -15,7 +15,7 @@ struct Cli {
     /// Modify files that do not comply
     overwrite: bool,
     /// Applies to lines that are to be split
-    #[arg(long, default_value_t = 100)]
+    #[arg(long, default_value_t = 80)]
     line_length_limit: usize,
 }
 
diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version
index db94926..a51e46f 100644
--- a/src/doc/rustc-dev-guide/rust-version
+++ b/src/doc/rustc-dev-guide/rust-version
@@ -1 +1 @@
-eda4fc7733ee89e484d7120cafbd80dcb2fce66e
+562dee4820c458d823175268e41601d4c060588a
diff --git a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md
index 56fa49e..0b6bb0d 100644
--- a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md
+++ b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md
@@ -1,6 +1,5 @@
 # Updating LLVM
 
-<!-- date-check: Aug 2024 -->
 Rust supports building against multiple LLVM versions:
 
 * Tip-of-tree for the current LLVM development branch is usually supported within a few days.
@@ -91,7 +90,6 @@
 
 ## New LLVM Release Updates
 
-<!-- date-check: Jul 2023 -->
 
 Unlike bugfixes,
 updating to a new release of LLVM typically requires a lot more work.
@@ -172,12 +170,14 @@
    You'll change at least
    `src/llvm-project` and will likely also change [`llvm-wrapper`] as well.
 
-   <!-- date-check: mar 2025 -->
+   <!-- date-check: March 2026 -->
    > For prior art, here are some previous LLVM updates:
    > - [LLVM 17](https://github.com/rust-lang/rust/pull/115959)
    > - [LLVM 18](https://github.com/rust-lang/rust/pull/120055)
    > - [LLVM 19](https://github.com/rust-lang/rust/pull/127513)
    > - [LLVM 20](https://github.com/rust-lang/rust/pull/135763)
+   > - [LLVM 21](https://github.com/rust-lang/rust/pull/143684)
+   > - [LLVM 22](https://github.com/rust-lang/rust/pull/150722)
 
    Note that sometimes it's easiest to land [`llvm-wrapper`] compatibility as a PR
    before actually updating `src/llvm-project`.
diff --git a/src/doc/rustc-dev-guide/src/borrow-check/region-inference/member-constraints.md b/src/doc/rustc-dev-guide/src/borrow-check/region-inference/member-constraints.md
index 2804c97..21a56da 100644
--- a/src/doc/rustc-dev-guide/src/borrow-check/region-inference/member-constraints.md
+++ b/src/doc/rustc-dev-guide/src/borrow-check/region-inference/member-constraints.md
@@ -1,17 +1,18 @@
 # Member constraints
 
 A member constraint `'m member of ['c_1..'c_N]` expresses that the
-region `'m` must be *equal* to some **choice regions** `'c_i` (for
-some `i`). These constraints cannot be expressed by users, but they
-arise from `impl Trait` due to its lifetime capture rules. Consider a
-function such as the following:
+region `'m` must be *equal* to some **choice regions** `'c_i` (for some `i`).
+These constraints cannot be expressed by users, but they
+arise from `impl Trait` due to its lifetime capture rules.
+Consider a function such as the following:
 
 ```rust,ignore
 fn make(a: &'a u32, b: &'b u32) -> impl Trait<'a, 'b> { .. }
 ```
 
 Here, the true return type (often called the "hidden type") is only
-permitted to capture the lifetimes `'a` or `'b`. You can kind of see
+permitted to capture the lifetimes `'a` or `'b`.
+You can kind of see
 this more clearly by desugaring that `impl Trait` return type into its
 more explicit form:
 
@@ -23,7 +24,8 @@
 Here, the idea is that the hidden type must be some type that could
 have been written in place of the `impl Trait<'x, 'y>` -- but clearly
 such a type can only reference the regions `'x` or `'y` (or
-`'static`!), as those are the only names in scope. This limitation is
+`'static`!), as those are the only names in scope.
+This limitation is
 then translated into a restriction to only access `'a` or `'b` because
 we are returning `MakeReturn<'a, 'b>`, where `'x` and `'y` have been
 replaced with `'a` and `'b` respectively.
@@ -31,8 +33,8 @@
 ## Detailed example
 
 To help us explain member constraints in more detail, let's spell out
-the `make` example in a bit more detail. First off, let's assume that
-you have some dummy trait:
+the `make` example in a bit more detail.
+First off, let's assume that you have some dummy trait:
 
 ```rust,ignore
 trait Trait<'a, 'b> { }
@@ -49,8 +51,8 @@
 ```
 
 What happens in this case is that the return type will be `(&'0 u32, &'1 u32)`,
-where `'0` and `'1` are fresh region variables. We will have the following
-region constraints:
+where `'0` and `'1` are fresh region variables.
+We will have the following region constraints:
 
 ```txt
 '0 live at {L}
@@ -67,11 +69,11 @@
 `'1` might have slightly different liveness sets, but that's not very
 interesting to the point we are illustrating here).
 
-The `'a: '0` and `'b: '1` constraints arise from subtyping. When we
-construct the `(a, b)` value, it will be assigned type `(&'0 u32, &'1
+The `'a: '0` and `'b: '1` constraints arise from subtyping.
+When we construct the `(a, b)` value, it will be assigned type `(&'0 u32, &'1
 u32)` -- the region variables reflect that the lifetimes of these
-references could be made smaller. For this value to be created from
-`a` and `b`, however, we do require that:
+references could be made smaller.
+For this value to be created from `a` and `b`, however, we do require that:
 
 ```txt
 (&'a u32, &'b u32) <: (&'0 u32, &'1 u32)
@@ -82,35 +84,39 @@
 
 Note that if we ignore member constraints, the value of `'0` would be
 inferred to some subset of the function body (from the liveness
-constraints, which we did not write explicitly). It would never become
+constraints, which we did not write explicitly).
+It would never become
 `'a`, because there is no need for it too -- we have a constraint that
-`'a: '0`, but that just puts a "cap" on how *large* `'0` can grow to
-become. Since we compute the *minimal* value that we can, we are happy
-to leave `'0` as being just equal to the liveness set. This is where
-member constraints come in.
+`'a: '0`, but that just puts a "cap" on how *large* `'0` can grow to become.
+Since we compute the *minimal* value that we can, we are happy
+to leave `'0` as being just equal to the liveness set.
+This is where member constraints come in.
 
 ## Choices are always lifetime parameters
 
 At present, the "choice" regions from a member constraint are always lifetime
-parameters from the current function. As of <!-- date-check --> October 2021,
+parameters from the current function. As of <!-- date-check --> March 2026,
 this falls out from the placement of impl Trait, though in the future it may not
-be the case. We take some advantage of this fact, as it simplifies the current
-code. In particular, we don't have to consider a case like `'0 member of ['1,
+be the case.
+We take some advantage of this fact, as it simplifies the current code.
+In particular, we don't have to consider a case like `'0 member of ['1,
 'static]`, in which the value of both `'0` and `'1` are being inferred and hence
-changing. See [rust-lang/rust#61773][#61773] for more information.
+changing.
+See [rust-lang/rust#61773][#61773] for more information.
 
 [#61773]: https://github.com/rust-lang/rust/issues/61773
 
 ## Applying member constraints
 
-Member constraints are a bit more complex than other forms of
-constraints. This is because they have a "or" quality to them -- that
+Member constraints are a bit more complex than other forms of constraints.
+This is because they have a "or" quality to them -- that
 is, they describe multiple choices that we must select from. E.g., in
 our example constraint `'0 member of ['a, 'b, 'static]`, it might be
-that `'0` is equal to `'a`, `'b`, *or* `'static`. How can we pick the
-correct one?  What we currently do is to look for a *minimal choice*
--- if we find one, then we will grow `'0` to be equal to that minimal
-choice. To find that minimal choice, we take two factors into
+that `'0` is equal to `'a`, `'b`, *or* `'static`.
+How can we pick the correct one?
+What we currently do is to look for a *minimal choice*
+-- if we find one, then we will grow `'0` to be equal to that minimal choice.
+To find that minimal choice, we take two factors into
 consideration: lower and upper bounds.
 
 ### Lower bounds
@@ -121,30 +127,34 @@
 `'0` because we computed its minimal value (or at least, the lower
 bounds considering everything but member constraints).
 
-Let `LB` be the current value of `'0`. We know then that `'0: LB` must
-hold, whatever the final value of `'0` is. Therefore, we can rule out
+Let `LB` be the current value of `'0`.
+We know then that `'0: LB` must hold, whatever the final value of `'0` is.
+Therefore, we can rule out
 any choice `'choice` where `'choice: LB` does not hold.
 
-Unfortunately, in our example, this is not very helpful. The lower
-bound for `'0` will just be the liveness set `{L}`, and we know that
-all the lifetime parameters outlive that set. So we are left with the
-same set of choices here. (But in other examples, particularly those
+Unfortunately, in our example, this is not very helpful.
+The lower bound for `'0` will just be the liveness set `{L}`, and we know that
+all the lifetime parameters outlive that set.
+So we are left with the same set of choices here.
+(But in other examples, particularly those
 with different variance, lower bound constraints may be relevant.)
 
 ### Upper bounds
 
 The *upper bounds* are those lifetimes that *must outlive* `'0` --
 i.e., that `'0` must be *smaller* than. In our example, this would be
-`'a`, because we have the constraint that `'a: '0`. In more complex
-examples, the chain may be more indirect.
+`'a`, because we have the constraint that `'a: '0`.
+In more complex examples, the chain may be more indirect.
 
 We can use upper bounds to rule out members in a very similar way to
-lower bounds. If UB is some upper bound, then we know that `UB:
+lower bounds.
+If UB is some upper bound, then we know that `UB:
 '0` must hold, so we can rule out any choice `'choice` where `UB:
 'choice` does not hold.
 
 In our example, we would be able to reduce our choice set from `['a,
-'b, 'static]` to just `['a]`. This is because `'0` has an upper bound
+'b, 'static]` to just `['a]`.
+This is because `'0` has an upper bound
 of `'a`, and neither `'a: 'b` nor `'a: 'static` is known to hold.
 
 (For notes on how we collect upper bounds in the implementation, see
@@ -153,39 +163,45 @@
 ### Minimal choice
 
 After applying lower and upper bounds, we can still sometimes have
-multiple possibilities. For example, imagine a variant of our example
-using types with the opposite variance. In that case, we would have
-the constraint `'0: 'a` instead of `'a: '0`. Hence the current value
-of `'0` would be `{L, 'a}`. Using this as a lower bound, we would be
+multiple possibilities.
+For example, imagine a variant of our example
+using types with the opposite variance.
+In that case, we would have the constraint `'0: 'a` instead of `'a: '0`.
+Hence the current value of `'0` would be `{L, 'a}`.
+Using this as a lower bound, we would be
 able to narrow down the member choices to `['a, 'static]` because `'b:
-'a` is not known to hold (but `'a: 'a` and `'static: 'a` do hold). We
-would not have any upper bounds, so that would be our final set of choices.
+'a` is not known to hold (but `'a: 'a` and `'static: 'a` do hold).
+We would not have any upper bounds, so that would be our final set of choices.
 
 In that case, we apply the **minimal choice** rule -- basically, if
-one of our choices if smaller than the others, we can use that. In
-this case, we would opt for `'a` (and not `'static`).
+one of our choices if smaller than the others, we can use that.
+In this case, we would opt for `'a` (and not `'static`).
 
 This choice is consistent with the general 'flow' of region
 propagation, which always aims to compute a minimal value for the
-region being inferred. However, it is somewhat arbitrary.
+region being inferred.
+However, it is somewhat arbitrary.
 
 <a id="collecting"></a>
 
 ### Collecting upper bounds in the implementation
 
 In practice, computing upper bounds is a bit inconvenient, because our
-data structures are setup for the opposite. What we do is to compute
+data structures are setup for the opposite.
+What we do is to compute
 the **reverse SCC graph** (we do this lazily and cache the result) --
-that is, a graph where `'a: 'b` induces an edge `SCC('b) ->
-SCC('a)`. Like the normal SCC graph, this is a DAG. We can then do a
-depth-first search starting from `SCC('0)` in this graph. This will
-take us to all the SCCs that must outlive `'0`.
+that is, a graph where `'a: 'b` induces an edge `SCC('b) -> SCC('a)`.
+Like the normal SCC graph, this is a DAG.
+We can then do a depth-first search starting from `SCC('0)` in this graph.
+This will take us to all the SCCs that must outlive `'0`.
 
 One wrinkle is that, as we walk the "upper bound" SCCs, their values
-will not yet have been fully computed. However, we **have** already
+will not yet have been fully computed.
+However, we **have** already
 applied their liveness constraints, so we have some information about
-their value. In particular, for any regions representing lifetime
+their value.
+In particular, for any regions representing lifetime
 parameters, their value will contain themselves (i.e., the initial
-value for `'a` includes `'a` and the value for `'b` contains `'b`). So
-we can collect all of the lifetime parameters that are reachable,
+value for `'a` includes `'a` and the value for `'b` contains `'b`).
+So we can collect all of the lifetime parameters that are reachable,
 which is precisely what we are interested in.
diff --git a/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md b/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md
index 9a302f9..b5bb44c 100644
--- a/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md
+++ b/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md
@@ -10,7 +10,7 @@
 The explanations are written in Markdown (see the [CommonMark Spec] for
 specifics around syntax), and all of them are linked in the [`rustc_error_codes`] crate.
 Please read [RFC 1567] for details on how to format and write long error codes.
-As of <!-- date-check --> February 2023, there is an
+As of <!-- date-check --> March 2026, there is an
 effort[^new-explanations] to replace this largely outdated RFC with a new more flexible standard.
 
 Error explanations should expand on the error message and provide details about
diff --git a/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md b/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md
index 7b98bc6..cda975a 100644
--- a/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md
+++ b/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md
@@ -3,15 +3,14 @@
 This page documents some of the machinery around lint registration and how we
 run lints in the compiler.
 
-The [`LintStore`] is the central piece of infrastructure, around which
-everything rotates. The `LintStore` is held as part of the [`Session`], and it
+The [`LintStore`] is the central piece of infrastructure, around which everything rotates.
+The `LintStore` is held as part of the [`Session`], and it
 gets populated with the list of lints shortly after the `Session` is created.
 
 ## Lints vs. lint passes
 
-There are two parts to the linting mechanism within the compiler: lints and
-lint passes. Unfortunately, a lot of the documentation we have refers to both
-of these as just "lints."
+There are two parts to the linting mechanism within the compiler: lints and lint passes.
+Unfortunately, a lot of the documentation we have refers to both of these as just "lints."
 
 First, we have the lint declarations themselves,
 and this is where the name and default lint level and other metadata come from.
@@ -21,14 +20,14 @@
 as the macro is somewhat unwieldy to add new fields to,
 like all macros).
 
-As of <!-- date-check --> Aug 2022,
 we lint against direct declarations without the use of the macro.
 
 Lint declarations don't carry any "state" - they are merely global identifiers
-and descriptions of lints. We assert at runtime that they are not registered
-twice (by lint name).
+and descriptions of lints.
+We assert at runtime that they are not registered twice (by lint name).
 
-Lint passes are the meat of any lint. Notably, there is not a one-to-one
+Lint passes are the meat of any lint.
+Notably, there is not a one-to-one
 relationship between lints and lint passes; a lint might not have any lint pass
 that emits it, it could have many, or just one -- the compiler doesn't track
 whether a pass is in any way associated with a particular lint, and frequently
@@ -45,36 +44,33 @@
 There are three 'sources' of lints:
 
 * internal lints: lints only used by the rustc codebase
-* builtin lints: lints built into the compiler and not provided by some outside
-  source
-* `rustc_interface::Config`[`register_lints`]: lints passed into the compiler
-  during construction
+* builtin lints: lints built into the compiler and not provided by some outside source
+* `rustc_interface::Config`[`register_lints`]: lints passed into the compiler during construction
 
-Lints are registered via the [`LintStore::register_lint`] function. This should
-happen just once for any lint, or an ICE will occur.
+Lints are registered via the [`LintStore::register_lint`] function.
+This should happen just once for any lint, or an ICE will occur.
 
-Once the registration is complete, we "freeze" the lint store by placing it in
-an `Arc`.
+Once the registration is complete, we "freeze" the lint store by placing it in an `Arc`.
 
 Lint passes are registered separately into one of the categories
-(pre-expansion, early, late, late module). Passes are registered as a closure
+(pre-expansion, early, late, late module).
+Passes are registered as a closure
 -- i.e., `impl Fn() -> Box<dyn X>`, where `dyn X` is either an early or late
-lint pass trait object. When we run the lint passes, we run the closure and
-then invoke the lint pass methods. The lint pass methods take `&mut self` so
-they can keep track of state internally.
+lint pass trait object.
+When we run the lint passes, we run the closure and then invoke the lint pass methods.
+The lint pass methods take `&mut self` so they can keep track of state internally.
 
 #### Internal lints
 
-These are lints used just by the compiler or drivers like `clippy`. They can be
-found in [`rustc_lint::internal`].
+These are lints used just by the compiler or drivers like `clippy`.
+They can be found in [`rustc_lint::internal`].
 
 An example of such a lint is the check that lint passes are implemented using
-the `declare_lint_pass!` macro and not by hand. This is accomplished with the
-`LINT_PASS_IMPL_WITHOUT_MACRO` lint.
+the `declare_lint_pass!` macro and not by hand.
+This is accomplished with the `LINT_PASS_IMPL_WITHOUT_MACRO` lint.
 
 Registration of these lints happens in the [`rustc_lint::register_internals`]
-function which is called when constructing a new lint store inside
-[`rustc_lint::new_lint_store`].
+function which is called when constructing a new lint store inside [`rustc_lint::new_lint_store`].
 
 #### Builtin Lints
 
@@ -84,19 +80,18 @@
 and the latter provides the lint pass definitions (and implementations),
 but this is not always true.
 
-The builtin lint registration happens in
-the [`rustc_lint::register_builtins`] function.
+The builtin lint registration happens in the [`rustc_lint::register_builtins`] function.
 Just like with internal lints,
 this happens inside of [`rustc_lint::new_lint_store`].
 
 #### Driver lints
 
 These are the lints provided by drivers via the `rustc_interface::Config`
-[`register_lints`] field, which is a callback. Drivers should, if finding it
-already set, call the function currently set within the callback they add. The
-best way for drivers to get access to this is by overriding the
-`Callbacks::config` function which gives them direct access to the `Config`
-structure.
+[`register_lints`] field, which is a callback.
+Drivers should, if finding it
+already set, call the function currently set within the callback they add.
+The best way for drivers to get access to this is by overriding the
+`Callbacks::config` function which gives them direct access to the `Config` structure.
 
 ## Compiler lint passes are combined into one pass
 
@@ -106,8 +101,8 @@
 individual lint passes; this is because then we get the benefits of static over
 dynamic dispatch for each of the (often empty) trait methods.
 
-Ideally, we'd not have to do this, since it adds to the complexity of
-understanding the code. However, with the current type-erased lint store
+Ideally, we'd not have to do this, since it adds to the complexity of understanding the code.
+However, with the current type-erased lint store
 approach, it is beneficial to do so for performance reasons.
 
 [`LintStore`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html
diff --git a/src/doc/rustc-dev-guide/src/early-late-parameters.md b/src/doc/rustc-dev-guide/src/early-late-parameters.md
index 7651dee..d78d533 100644
--- a/src/doc/rustc-dev-guide/src/early-late-parameters.md
+++ b/src/doc/rustc-dev-guide/src/early-late-parameters.md
@@ -11,7 +11,8 @@
 
 ## What does it mean to be "early" bound or "late" bound
 
-Every function definition has a corresponding ZST that implements the `Fn*` traits known as a [function item type][function_item_type]. This part of the chapter will talk a little bit about the "desugaring" of function item types as it is useful context for explaining the difference between early bound and late bound generic parameters.
+Every function definition has a corresponding ZST that implements the `Fn*` traits known as a [function item type][function_item_type].
+This part of the chapter will talk a little bit about the "desugaring" of function item types as it is useful context for explaining the difference between early bound and late bound generic parameters.
 
 Let's start with a very trivial example involving no generic parameters:
 
@@ -36,7 +37,7 @@
 
 A slightly more complicated example would involve introducing generic parameters to the function:
 ```rust
-fn foo<T: Sized>(a: T) -> T { 
+fn foo<T: Sized>(a: T) -> T {
     # a
     /* snip */
 }
@@ -51,7 +52,8 @@
 }
 ```
 
-Note that the function item type `FooFnItem` is generic over some type parameter `T` as defined on the function `foo`. However, not all generic parameters defined on functions are also defined on the function item type as demonstrated here:
+Note that the function item type `FooFnItem` is generic over some type parameter `T` as defined on the function `foo`.
+However, not all generic parameters defined on functions are also defined on the function item type as demonstrated here:
 ```rust
 fn foo<'a, T: Sized>(a: &'a T) -> &'a T {
     # a
@@ -71,12 +73,13 @@
 The lifetime parameter `'a` from the function `foo` is not present on the function item type `FooFnItem` and is instead introduced on the builtin impl solely for use in representing the argument types.
 
 Generic parameters not all being defined on the function item type means that there are two steps where generic arguments are provided when calling a function.
-1. Naming the function (e.g. `let a = foo;`) the arguments for `FooFnItem` are provided. 
+1. Naming the function (e.g. `let a = foo;`) the arguments for `FooFnItem` are provided.
 2. Calling the function (e.g. `a(&10);`) any parameters defined on the builtin impl are provided.
 
-This two-step system is where the early vs late naming scheme comes from, early bound parameters are provided in the *earliest* step (naming the function), whereas late bound parameters are provided in the *latest* step (calling the function). 
+This two-step system is where the early vs late naming scheme comes from, early bound parameters are provided in the *earliest* step (naming the function), whereas late bound parameters are provided in the *latest* step (calling the function).
 
-Looking at the desugaring from the previous example we can tell that `T` is an early bound type parameter and `'a` is a late bound lifetime parameter as `T` is present on the function item type but `'a` is not. See this example of calling `foo` annotated with where each generic parameter has an argument provided:
+Looking at the desugaring from the previous example we can tell that `T` is an early bound type parameter and `'a` is a late bound lifetime parameter as `T` is present on the function item type but `'a` is not.
+See this example of calling `foo` annotated with where each generic parameter has an argument provided:
 ```rust
 fn foo<'a, T: Sized>(a: &'a T) -> &'a T {
     # a
@@ -96,15 +99,17 @@
 
 ## Differences between early and late bound parameters
 
-### Higher ranked function pointers and trait bounds 
+### Higher ranked function pointers and trait bounds
 
-A generic parameter being late bound allows for more flexible usage of the function item. For example if we have some function `foo` with an early bound lifetime parameter and some function `bar` with a late bound lifetime parameter `'a` we would have the following builtin `Fn` impls:
+A generic parameter being late bound allows for more flexible usage of the function item.
+For example, if we have some function `foo` with an early bound lifetime parameter and some function `bar` with a late bound lifetime parameter `'a`, we would have the following builtin `Fn` impls:
 ```rust,ignore
 impl<'a> Fn<(&'a String,)> for FooFnItem<'a> { /* ... */ }
 impl<'a> Fn<(&'a String,)> for BarFnItem { /* ... */ }
 ```
 
-The `bar` function has a strictly more flexible signature as the function item type can be called with a borrow with *any* lifetime, whereas the `foo` function item type would only be callable with a borrow with the same lifetime on the function item type. We can show this by simply trying to call `foo`'s function item type multiple times with different lifetimes:
+The `bar` function has a strictly more flexible signature as the function item type can be called with a borrow with *any* lifetime, whereas the `foo` function item type would only be callable with a borrow with the same lifetime on the function item type.
+We can show this by simply trying to call `foo`'s function item type multiple times with different lifetimes:
 
 ```rust
 // The `'a: 'a` bound forces this lifetime to be early bound.
@@ -125,9 +130,12 @@
 f(&String::new());
 ```
 
-In this example we call `foo`'s function item type twice, each time with a borrow of a temporary. These two borrows could not possible have lifetimes that overlap as the temporaries are only alive during the function call, not after. The lifetime parameter on `foo` being early bound requires all callers of `f` to provide a borrow with the same lifetime, as this is not possible the borrow checker errors.
+In this example, we call `foo`'s function item type twice, each time with a borrow of a temporary.
+These two borrows could not possibly have lifetimes that overlap as the temporaries are only alive during the function call, not after.
+The lifetime parameter on `foo` being early bound requires all callers of `f` to provide a borrow with the same lifetime, as this is not possible the borrow checker errors.
 
-If the lifetime parameter on `foo` was late bound this would be able to compile as each caller could provide a different lifetime argument for its borrow. See the following example which demonstrates this using the `bar` function defined above:
+If the lifetime parameter on `foo` was late bound, this would be able to compile as each caller could provide a different lifetime argument for its borrow.
+See the following example, which demonstrates this using the `bar` function defined above:
 
 ```rust
 # fn foo<'a: 'a>(b: &'a String) -> &'a String { b }
@@ -143,7 +151,8 @@
 b(&String::new());
 ```
 
-This is reflected in the ability to coerce function item types to higher ranked function pointers and prove higher ranked `Fn` trait bounds. We can demonstrate this with the following example:
+This is reflected in the ability to coerce function item types to higher ranked function pointers and prove higher ranked `Fn` trait bounds.
+We can demonstrate this with the following example:
 ```rust
 // The `'a: 'a` bound forces this lifetime to be early bound.
 fn foo<'a: 'a>(b: &'a String) -> &'a String { b }
@@ -163,14 +172,15 @@
 fn higher_ranked_fn_ptr() {
     let bar_fn_item = bar;
     let fn_ptr: for<'a> fn(&'a String) -> &'a String = bar_fn_item;
-    
+
     let foo_fn_item = foo::<'_>;
     // errors
     let fn_ptr: for<'a> fn(&'a String) -> &'a String = foo_fn_item;
 }
 ```
 
-In both of these cases the borrow checker errors as it does not consider `foo_fn_item` to be callable with a borrow of any lifetime. This is due to the fact that the lifetime parameter on `foo` is early bound, causing `foo_fn_item` to have a type of `FooFnItem<'_>` which (as demonstrated by the desugared `Fn` impl) is only callable with a borrow of the same lifetime `'_`.
+In both of these cases, the borrow checker errors as it does not consider `foo_fn_item` to be callable with a borrow of any lifetime.
+This is due to the fact that the lifetime parameter on `foo` is early bound, causing `foo_fn_item` to have a type of `FooFnItem<'_>` which (as demonstrated by the desugared `Fn` impl) is only callable with a borrow of the same lifetime `'_`.
 
 ### Turbofishing in the presence of late bound parameters
 
@@ -188,15 +198,17 @@
 let f /* : FooFnItem<????> */ = foo::<'static>;
 ```
 
-The above example errors as the lifetime parameter `'a` is late bound and so cannot be instantiated as part of the "naming a function" step. If we make the lifetime parameter early bound we will see this code start to compile:
+The above example errors as the lifetime parameter `'a` is late bound and so cannot be instantiated as part of the "naming a function" step.
+If we make the lifetime parameter early bound we will see this code start to compile:
 ```rust
 fn foo<'a: 'a>(b: &'a u32) -> &'a u32 { b }
 
 let f /* : FooFnItem<'static> */ = foo::<'static>;
 ```
 
-What the current implementation of the compiler aims to do is error when specifying lifetime arguments to a function that has both early *and* late bound lifetime parameters. In practice, due to excessive breakage, some cases are actually only future compatibility warnings ([#42868](https://github.com/rust-lang/rust/issues/42868)):
-- When the amount of lifetime arguments is the same as the number of early bound lifetime parameters a FCW is emitted instead of an error
+What the current implementation of the compiler aims to do is error when specifying lifetime arguments to a function that has both early *and* late bound lifetime parameters.
+In practice, due to excessive breakage, some cases are actually only future compatibility warnings ([#42868](https://github.com/rust-lang/rust/issues/42868)):
+- When the amount of lifetime arguments is the same as the number of early bound lifetime parameters, a FCW is emitted instead of an error
 - An error is always downgraded to a FCW when using method call syntax
 
 To demonstrate this we can write out the different kinds of functions and give them both a late and early bound lifetime:
@@ -287,7 +299,8 @@
 free_function::<'static, 'static, 'static>(&(), &());
 ```
 
-Even when specifying enough lifetime arguments for both the late and early bound lifetime parameter, these arguments are not actually used to annotate the lifetime provided to late bound parameters. We can demonstrate this by turbofishing `'static` to a function while providing a non-static borrow:
+Even when specifying enough lifetime arguments for both the late and early bound lifetime parameter, these arguments are not actually used to annotate the lifetime provided to late bound parameters.
+We can demonstrate this by turbofishing `'static` to a function while providing a non-static borrow:
 ```rust
 struct Foo;
 
@@ -302,7 +315,8 @@
 
 ### Liveness of types with late bound parameters
 
-When checking type outlives bounds involving function item types we take into account early bound parameters. For example:
+When checking type outlives bounds involving function item types we take into account early bound parameters.
+For example:
 
 ```rust
 fn foo<T>(_: T) {}
@@ -315,9 +329,11 @@
 }
 ```
 
-As the type parameter `T` is early bound, the desugaring of the function item type for `foo` would look something like `struct FooFnItem<T>`. Then in order for `FooFnItem<T>: 'static` to hold we must also require `T: 'static` to hold as otherwise we would wind up with soundness bugs.
+As the type parameter `T` is early bound, the desugaring of the function item type for `foo` would look something like `struct FooFnItem<T>`.
+Then, in order for `FooFnItem<T>: 'static` to hold, we must also require `T: 'static` to hold as otherwise we would wind up with soundness bugs.
 
-Unfortunately, due to bugs in the compiler, we do not take into account early bound *lifetimes*, which is the cause of the open soundness bug [#84366](https://github.com/rust-lang/rust/issues/84366). This means that it's impossible to demonstrate a "difference" between early/late bound parameters for liveness/type outlives bounds as the only kind of generic parameters that are able to be late bound are lifetimes which are handled incorrectly.
+Unfortunately, due to bugs in the compiler, we do not take into account early bound *lifetimes*, which is the cause of the open soundness bug [#84366](https://github.com/rust-lang/rust/issues/84366).
+This means that it's impossible to demonstrate a "difference" between early/late bound parameters for liveness/type outlives bounds as the only kind of generic parameters that are able to be late bound are lifetimes which are handled incorrectly.
 
 Regardless, in theory the code example below *should* demonstrate such a difference once [#84366](https://github.com/rust-lang/rust/issues/84366) is fixed:
 ```rust
@@ -341,17 +357,20 @@
 
 ### Must be a lifetime parameter
 
-Type and Const parameters are not able to be late bound as we do not have a way to support types such as `dyn for<T> Fn(Box<T>)` or `for<T> fn(Box<T>)`. Calling such types requires being able to monomorphize the underlying function which is not possible with indirection through dynamic dispatch.
+Type and Const parameters are not able to be late bound as we do not have a way to support types such as `dyn for<T> Fn(Box<T>)` or `for<T> fn(Box<T>)`.
+Calling such types requires being able to monomorphize the underlying function which is not possible with indirection through dynamic dispatch.
 
 ### Must not be used in a where clause
 
-Currently when a generic parameter is used in a where clause it must be early bound. For example:
+Currently when a generic parameter is used in a where clause it must be early bound.
+For example:
 ```rust
 # trait Trait<'a> {}
 fn foo<'a, T: Trait<'a>>(_: &'a String, _: T) {}
 ```
 
-In this example the lifetime parameter `'a` is considered to be early bound as it appears in the where clause `T: Trait<'a>`. This is true even for "trivial" where clauses such as `'a: 'a` or those implied by wellformedness of function arguments, for example:
+In this example the lifetime parameter `'a` is considered to be early bound as it appears in the where clause `T: Trait<'a>`.
+This is true even for "trivial" where clauses such as `'a: 'a` or those implied by wellformedness of function arguments, for example:
 ```rust
 fn foo<'a: 'a>(_: &'a String) {}
 fn bar<'a, T: 'a>(_: &'a T) {}
@@ -375,9 +394,12 @@
 
 At *some point* during type checking an error should be emitted for this code as `String` does not implement `Trait` for any lifetime.
 
-If the lifetime `'a` were late bound then this becomes difficult to check. When naming `foo` we do not know what lifetime should be used as part of the `T: Trait<'a>` trait bound as it has not yet been instantiated. When coercing the function item type to a function pointer we have no way of tracking the `String: Trait<'a>` trait bound that must be proven when calling the function. 
+If the lifetime `'a` were late bound then this becomes difficult to check.
+When naming `foo` we do not know what lifetime should be used as part of the `T: Trait<'a>` trait bound as it has not yet been instantiated.
+When coercing the function item type to a function pointer we have no way of tracking the `String: Trait<'a>` trait bound that must be proven when calling the function.
 
-If the lifetime `'a` is early bound (which it is in the current implementation in rustc), then the trait bound can be checked when naming the function `foo`. Requiring parameters used in where clauses to be early bound gives a natural place to check where clauses defined on the function.
+If the lifetime `'a` is early bound (which it is in the current implementation in rustc), then the trait bound can be checked when naming the function `foo`.
+Requiring parameters used in where clauses to be early bound gives a natural place to check where clauses defined on the function.
 
 Finally, we do not require lifetimes to be early bound if they are used in *implied bounds*, for example:
 ```rust
@@ -388,11 +410,13 @@
 f(&String::new());
 ```
 
-This code compiles, demonstrating that the lifetime parameter is late bound, even though `'a` is used in the type `&'a T` which implicitly requires `T: 'a` to hold. Implied bounds can be treated specially as any types introducing implied bounds are in the signature of the function pointer type, which means that when calling the function we know to prove `T: 'a`.
+This code compiles, demonstrating that the lifetime parameter is late bound, even though `'a` is used in the type `&'a T` which implicitly requires `T: 'a` to hold.
+Implied bounds can be treated specially as any types introducing implied bounds are in the signature of the function pointer type, which means that when calling the function we know to prove `T: 'a`.
 
 ### Must be constrained by argument types
 
-It is important that builtin impls on function item types do not wind up with unconstrained generic parameters as this can lead to unsoundness. This is the same kind of restriction as applies to user written impls, for example the following code results in an error:
+It is important that builtin impls on function item types do not wind up with unconstrained generic parameters as this can lead to unsoundness.
+This is the same kind of restriction as applies to user written impls, for example the following code results in an error:
 ```rust
 trait Trait {
     type Assoc;
diff --git a/src/doc/rustc-dev-guide/src/parallel-rustc.md b/src/doc/rustc-dev-guide/src/parallel-rustc.md
index f83aaa6..c4e0663 100644
--- a/src/doc/rustc-dev-guide/src/parallel-rustc.md
+++ b/src/doc/rustc-dev-guide/src/parallel-rustc.md
@@ -11,7 +11,8 @@
 As of <!-- date-check --> November 2024, most of the rust compiler is now
 parallelized.
 
-- The codegen part is executed concurrently by default. You can use the `-C
+- The codegen part is executed concurrently by default.
+  You can use the `-C
   codegen-units=n` option to control the number of concurrent tasks.
 - The parts after HIR lowering to codegen such as type checking, borrowing
   checking, and mir optimization are parallelized in the nightly version.
@@ -31,17 +32,19 @@
 ## Code generation
 
 During monomorphization the compiler splits up all the code to
-be generated into smaller chunks called _codegen units_. These are then generated by
-independent instances of LLVM running in parallel. At the end, the linker
-is run to combine all the codegen units together into one binary. This process
-occurs in the [`rustc_codegen_ssa::base`] module.
+be generated into smaller chunks called _codegen units_.
+These are then generated by independent instances of LLVM running in parallel.
+At the end, the linker
+is run to combine all the codegen units together into one binary.
+This process occurs in the [`rustc_codegen_ssa::base`] module.
 
 [`rustc_codegen_ssa::base`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/base/index.html
 
 ## Data structures
 
 The underlying thread-safe data-structures used in the parallel compiler
-can be found in the [`rustc_data_structures::sync`] module. These data structures 
+can be found in the [`rustc_data_structures::sync`] module.
+These data structures
 are implemented differently depending on whether `parallel-compiler` is true.
 
 | data structure                   | parallel                                            | non-parallel |
@@ -61,21 +64,25 @@
   or the authoring of persistent documentation covering the specific of the
   invariants, the atomicity, and the lock orderings.
 
-- On the other hand, we still need to figure out what other invariants 
+- On the other hand, we still need to figure out what other invariants
   during compilation might not hold in parallel compilation.
 
 [`rustc_data_structures::sync`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/sync/index.html
 
 ### WorkerLocal
 
-[`WorkerLocal`] is a special data structure implemented for parallel compilers. It
-holds worker-locals values for each thread in a thread pool. You can only
+[`WorkerLocal`] is a special data structure implemented for parallel compilers.
+It holds worker-locals values for each thread in a thread pool.
+You can only
 access the worker local value through the `Deref` `impl` on the thread pool it
-was constructed on. It panics otherwise. 
+was constructed on.
+It panics otherwise.
 
 `WorkerLocal` is used to implement the `Arena` allocator in the parallel
-environment, which is critical in parallel queries. Its implementation is
-located in the [`rustc_data_structures::sync::worker_local`] module. However,
+environment, which is critical in parallel queries.
+Its implementation is
+located in the [`rustc_data_structures::sync::worker_local`] module.
+However,
 in the non-parallel compiler, it is implemented as `(OneThread<T>)`, whose `T`
 can be accessed directly through `Deref::deref`.
 
@@ -85,10 +92,11 @@
 ## Parallel iterator
 
 The parallel iterators provided by the [`rayon`] crate are easy ways to
-implement parallelism. In the current implementation of the parallel compiler
-we use a custom [fork][rustc-rayon] of `rayon` to run tasks in parallel.
+implement parallelism.
+In the current implementation of the parallel compiler,
+we use [a custom fork of `rayon`][rustc-rayon] to run tasks in parallel.
 
-Some iterator functions are implemented to run loops in parallel 
+Some iterator functions are implemented to run loops in parallel
 when `parallel-compiler` is true.
 
 | Function(Omit `Send` and `Sync`)                             | Introduction                                                 | Owning Module              |
@@ -142,15 +150,17 @@
   start evaluating.
 - If there *is* another query invocation for the same key in progress, we
   release the lock, and just block the thread until the other invocation has
-  computed the result we are waiting for. **Cycle error detection** in the parallel 
-  compiler requires more complex logic than in single-threaded mode. When 
-  worker threads in parallel queries stop making progress due to interdependence, 
-  the compiler uses an extra thread *(named deadlock handler)* to detect, remove and 
+  computed the result we are waiting for.
+  **Cycle error detection** in the parallel
+  compiler requires more complex logic than in single-threaded mode.
+  When
+  worker threads in parallel queries stop making progress due to interdependence,
+  the compiler uses an extra thread *(named deadlock handler)* to detect, remove and
   report the cycle error.
 
 The parallel query feature still has implementation to do, most of which is
-related to the previous `Data Structures` and `Parallel Iterators`. See [this
-open feature tracking issue][tracking].
+related to the previous `Data Structures` and `Parallel Iterators`.
+See [this open feature tracking issue][tracking].
 
 ## Rustdoc
 
diff --git a/src/doc/rustc-dev-guide/src/queries/incremental-compilation-in-detail.md b/src/doc/rustc-dev-guide/src/queries/incremental-compilation-in-detail.md
index 9882846..014d1a0 100644
--- a/src/doc/rustc-dev-guide/src/queries/incremental-compilation-in-detail.md
+++ b/src/doc/rustc-dev-guide/src/queries/incremental-compilation-in-detail.md
@@ -418,6 +418,13 @@
 
 ## Query modifiers
 
+> FIXME: Make [`rustc_middle::query::modifiers`] the home for query modifier documentation,
+> and migrate all other useful modifier docs there after verifying that they are still accurate.
+
+[`rustc_middle::query::modifiers`]:
+    https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/query/modifiers/index.html
+
+
 The query system allows for applying [modifiers][mod] to queries.
 These modifiers affect certain aspects of how the system treats the query with
 respect to incremental compilation:
@@ -437,6 +444,9 @@
       as an optimization because the system can skip recording dependencies in
       the first place.
 
+ - `no_force` - Never "force" the dep nodes for this query, even if the query's
+   key type is recoverable.
+
  - `no_hash` - Applying `no_hash` to a query tells the system to not compute
    the fingerprint of the query's result.
    This has two consequences:
@@ -475,13 +485,6 @@
    For example, it makes no sense to store values from upstream
    crates in the cache because they are already available in the upstream crate's metadata.
 
- - `anon` - This attribute makes the system use "anonymous" dep-nodes for the given query.
-   An anonymous dep-node is not identified by the corresponding query key.
-   Instead, its ID is computed from the IDs of its dependencies.
-   This allows the red-green system to do its change detection even if there is no
-   query key available for a given dep-node -- something which is needed for
-   handling trait selection because it is not based on queries.
-
 [mod]: ../query.html#adding-a-new-kind-of-query
 
 
diff --git a/src/doc/rustc-dev-guide/src/solve/candidate-preference.md b/src/doc/rustc-dev-guide/src/solve/candidate-preference.md
index 4615234..7fc3926 100644
--- a/src/doc/rustc-dev-guide/src/solve/candidate-preference.md
+++ b/src/doc/rustc-dev-guide/src/solve/candidate-preference.md
@@ -1,16 +1,23 @@
 # Candidate preference
 
-There are multiple ways to prove `Trait` and `NormalizesTo` goals. Each such option is called a [`Candidate`]. If there are multiple applicable candidates, we prefer some candidates over others. We store the relevant information in their [`CandidateSource`].
+There are multiple ways to prove `Trait` and `NormalizesTo` goals.
+Each such option is called a [`Candidate`].
+If there are multiple applicable candidates, we prefer some candidates over others.
+We store the relevant information in their [`CandidateSource`].
 
-This preference may result in incorrect inference or region constraints and would therefore be unsound during coherence. Because of this, we simply try to merge all candidates in coherence.
+This preference may result in incorrect inference or region constraints and would therefore be unsound during coherence.
+Because of this, we simply try to merge all candidates in coherence.
 
 ## `Trait` goals
 
-Trait goals merge their applicable candidates in [`fn merge_trait_candidates`]. This document provides additional details and references to explain *why* we've got the current preference rules.
+Trait goals merge their applicable candidates in [`fn merge_trait_candidates`].
+This document provides additional details and references to explain *why* we've got the current preference rules.
 
 ### `CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))`
 
-Trivial builtin impls are builtin impls which are known to be always applicable for well-formed types. This means that if one exists, using another candidate should never have fewer constraints. We currently only consider `Sized` - and `MetaSized` - impls to be trivial.
+Trivial builtin impls are builtin impls which are known to be always applicable for well-formed types.
+This means that if one exists, using another candidate should never have fewer constraints.
+We currently only consider `Sized` - and `MetaSized` - impls to be trivial.
 
 This is necessary to prevent a lifetime error for the following pattern
 
@@ -25,7 +32,7 @@
 {
     // Elaborating the `&'a str: Trait<T>` where-bound results in a
     // `&'a str: Sized` where-bound. We do not want to prefer this
-    // over the builtin impl. 
+    // over the builtin impl.
     is_sized(x);
 }
 ```
@@ -50,7 +57,8 @@
 ### `CandidateSource::ParamEnv`
 
 Once there's at least one *non-global* `ParamEnv` candidate, we prefer *all* `ParamEnv` candidates over other candidate kinds.
-A where-bound is global if it is not higher-ranked and doesn't contain any generic parameters. It may contain `'static`.
+A where-bound is global if it is not higher-ranked and doesn't contain any generic parameters.
+It may contain `'static`.
 
 We try to apply where-bounds over other candidates as users tends to have the most control over them, so they can most easily
 adjust them in case our candidate preference is incorrect.
@@ -68,7 +76,8 @@
 }
 ```
 
-We also need this as shadowed impls can result in currently ambiguous solver cycles: [trait-system-refactor-initiative#76]. Without preference we'd be forced to fail with ambiguity
+We also need this as shadowed impls can result in currently ambiguous solver cycles: [trait-system-refactor-initiative#76].
+Without preference, we'd be forced to fail with ambiguity
 errors if the where-bound results in region constraints to avoid incompleteness.
 ```rust
 trait Super {
@@ -89,13 +98,15 @@
 fn overflow<T: Trait>() {
     // We can use the elaborated `Super<SuperAssoc = Self::TraitAssoc>` where-bound
     // to prove the where-bound of the `T: Trait` implementation. This currently results in
-    // overflow. 
+    // overflow.
     let x: <T as Trait>::TraitAssoc;
 }
 ```
 
-This preference causes a lot of issues. See [#24066]. Most of the
-issues are caused by preferring where-bounds over impls even if the where-bound guides type inference:
+This preference causes a lot of issues.
+See [#24066].
+Most of the
+issues are caused by preferring where-bounds over impls even, if the where-bound guides type inference:
 ```rust
 trait Trait<T> {
     fn call_me(&self, x: T) {}
@@ -167,7 +178,10 @@
 
 #### Why no preference for global where-bounds
 
-Global where-bounds are either fully implied by an impl or unsatisfiable. If they are unsatisfiable, we don't really care what happens. If a where-bound is fully implied then using the impl to prove the trait goal cannot result in additional constraints. For trait goals this is only useful for where-bounds which use `'static`:
+Global where-bounds are either fully implied by an impl or unsatisfiable.
+If they are unsatisfiable, we don't really care what happens.
+If a where-bound is fully implied, then using the impl to prove the trait goal cannot result in additional constraints.
+For trait goals, this is only useful for where-bounds which use `'static`:
 
 ```rust
 trait A {
@@ -181,13 +195,15 @@
     x.test();
 }
 ```
-More importantly, by using impls here we prevent global where-bounds from shadowing impls when normalizing associated types. There are no known issues from preferring impls over global where-bounds.
+More importantly, by using impls here, we prevent global where-bounds from shadowing impls when normalizing associated types.
+There are no known issues from preferring impls over global where-bounds.
 
 #### Why still consider global where-bounds
 
 Given that we just use impls even if there exists a global where-bounds, you may ask why we don't just ignore these global where-bounds entirely: we use them to weaken the inference guidance from non-global where-bounds.
 
-Without a global where-bound, we currently prefer non-global where bounds even though there would be an applicable impl as well. By adding a non-global where-bound, this unnecessary inference guidance is disabled, allowing the following to compile:
+Without a global where-bound, we currently prefer non-global where bounds even though there would be an applicable impl as well.
+By adding a non-global where-bound, this unnecessary inference guidance is disabled, allowing the following to compile:
 ```rust
 fn check<Color>(color: Color)
 where
@@ -209,7 +225,9 @@
 
 ### `CandidateSource::AliasBound`
 
-We prefer alias-bound candidates over impls. We currently use this preference to guide type inference, causing the following to compile. I personally don't think this preference is desirable 🤷
+We prefer alias-bound candidates over impls.
+We currently use this preference to guide type inference, causing the following to compile.
+I personally don't think this preference is desirable 🤷
 ```rust
 pub trait Dyn {
     type Word: Into<u64>;
@@ -254,7 +272,9 @@
 
 ### `CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_))`
 
-We prefer builtin trait object impls over user-written impls. This is **unsound** and should be remoed in the future. See [#57893](https://github.com/rust-lang/rust/issues/57893) and [#141347](https://github.com/rust-lang/rust/pull/141347) for more details.
+We prefer builtin trait object impls over user-written impls.
+This is **unsound** and should be remoed in the future.
+See [#57893] and [#141347] for more details.
 
 ## `NormalizesTo` goals
 
@@ -336,7 +356,7 @@
 #### We prefer "orphaned" where-bounds
 
 We add "orphaned" `Projection` clauses into the `ParamEnv` when normalizing item bounds of GATs and RPITIT in `fn check_type_bounds`.
-We need to prefer these `ParamEnv` candidates over impls and other where-bounds. 
+We need to prefer these `ParamEnv` candidates over impls and other where-bounds.
 ```rust
 #![feature(associated_type_defaults)]
 trait Foo {
@@ -355,7 +375,8 @@
 
 #### We prefer global where-bounds over impls
 
-This is necessary for the following to compile. I don't know whether anything relies on it in practice 🤷
+This is necessary for the following to compile.
+I don't know whether anything relies on it in practice 🤷
 ```rust
 trait Id {
     type This;
@@ -423,7 +444,8 @@
 
 #### RPITIT `type_of` cycles
 
-We currently have to avoid impl candidates if there are where-bounds to avoid query cycles for RPITIT, see [#139762]. It feels desirable to me to stop relying on auto-trait leakage of during RPITIT computation to remove this issue, see [#139788].
+We currently have to avoid impl candidates if there are where-bounds to avoid query cycles for RPITIT, see [#139762].
+It feels desirable to me to stop relying on auto-trait leakage of during RPITIT computation to remove this issue, see [#139788].
 
 ```rust
 use std::future::Future;
@@ -454,6 +476,31 @@
 }
 ```
 
+<!-- date-check: Mar 2026 -->
+#### Trait definition cannot use associated types from always applicable impls
+
+The `T: Trait` assumption in the trait definition prevents it from normalizing
+`<Self as Trait>::Assoc` to `T` by using the blanket impl.
+This feels like a somewhat desirable constraint, if not incredibly so.
+
+```rust
+trait Eq<T> {}
+impl<T> Eq<T> for T {}
+struct IsEqual<T: Eq<U>, U>(T, U);
+
+trait Trait: Sized {
+    type Assoc;
+    fn foo() -> IsEqual<Self, Self::Assoc> {
+        //~^ ERROR the trait bound `Self: Eq<<Self as Trait>::Assoc>` is not satisfied
+        todo!()
+    }
+}
+
+impl<T> Trait for T {
+    type Assoc = T;
+}
+```
+
 [`Candidate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_next_trait_solver/solve/assembly/struct.Candidate.html
 [`CandidateSource`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_next_trait_solver/solve/enum.CandidateSource.html
 [`fn merge_trait_candidates`]: https://github.com/rust-lang/rust/blob/e3ee7f7aea5b45af3b42b5e4713da43876a65ac9/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs#L1342-L1424
@@ -462,4 +509,6 @@
 [#24066]: https://github.com/rust-lang/rust/issues/24066
 [#133044]: https://github.com/rust-lang/rust/issues/133044
 [#139762]: https://github.com/rust-lang/rust/pull/139762
-[#139788]: https://github.com/rust-lang/rust/issues/139788
\ No newline at end of file
+[#139788]: https://github.com/rust-lang/rust/issues/139788
+[#57893]: https://github.com/rust-lang/rust/issues/57893
+[#141347]: https://github.com/rust-lang/rust/pull/141347
diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md
index 5161194..5581b7e 100644
--- a/src/doc/rustc-dev-guide/src/tests/ci.md
+++ b/src/doc/rustc-dev-guide/src/tests/ci.md
@@ -109,11 +109,13 @@
 At any given time, at most a single `auto` build is being executed.
 Find out more in [Merging PRs serially with bors](#merging-prs-serially-with-bors).
 
-Normally, when an auto job fails, the whole CI workflow immediately ends. However, it can be useful to
+Normally, when an auto job fails, the whole CI workflow immediately ends.
+However, it can be useful to
 create auto jobs that are "non-blocking", or optional, to test them on CI for some time before blocking
-merges on them. This can be useful if those jobs can be flaky.
+merges on them.
+This can be useful if those jobs can be flaky.
 
-To do that, prefix such a job with `optional-`, and set `continue_on_error: true` for it in [`jobs.yml`]. 
+To do that, prefix such a job with `optional-`, and set `continue_on_error: true` for it in [`jobs.yml`].
 
 [platform tiers]: https://forge.rust-lang.org/release/platform-support.html#rust-platform-support
 [auto]: https://github.com/rust-lang/rust/tree/automation/bors/auto
diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md
index 1502e69..1e5822d 100644
--- a/src/doc/rustc/src/linker-plugin-lto.md
+++ b/src/doc/rustc/src/linker-plugin-lto.md
@@ -194,7 +194,7 @@
 INSTALL_TOOLCHAIN = ["rustup", "toolchain", "install", "--profile", "minimal"]
 subprocess.run(INSTALL_TOOLCHAIN + ["nightly"])
 
-LOWER_BOUND = 87
+LOWER_BOUND = 91
 NIGHTLY_VERSION = minor_version(subprocess.run(
     ["rustc", "+nightly", "--version"],
     capture_output=True,
@@ -256,6 +256,6 @@
 | 1.78 - 1.81  |      18       |
 | 1.82 - 1.86  |      19       |
 | 1.87 - 1.90  |      20       |
-| 1.91 - 1.93  |      21       |
+| 1.91 - 1.94  |      21       |
 
 Note that the compatibility policy for this feature might change in the future.
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index 1771d13..eb070c2 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -22,6 +22,8 @@
   * [AddressSanitizer](#addresssanitizer) a fast memory error detector.
   * [HWAddressSanitizer](#hwaddresssanitizer) a memory error detector similar to
     AddressSanitizer, but based on partial hardware assistance.
+  * [KernelHWAddressSanitizer](#kernelhwaddresssanitizer) variant of
+    HWAddressSanitizer that is designed for bare metal environments.
   * [LeakSanitizer](#leaksanitizer) a run-time memory leak detector.
   * [MemorySanitizer](#memorysanitizer) a detector of uninitialized reads.
   * [RealtimeSanitizer](#realtimesanitizer) a detector of calls to function with
@@ -622,6 +624,16 @@
 SUMMARY: HWAddressSanitizer: tag-mismatch (/.../main+0x54a94)
 ```
 
+# KernelHWAddressSanitizer
+
+KernelHWAddressSanitizer is the kernel version of [HWAddressSanitizer](#hwaddresssanitizer),
+which achieves the same purpose but is designed for bare-metal environments.
+
+HWAddressSanitizer is supported on the `aarch64*-unknown-none` and
+`aarch64*-unknown-none-softfloat` targets.
+
+See the [Clang HWAddressSanitizer documentation][clang-hwasan] for more details.
+
 # KernelControlFlowIntegrity
 
 The LLVM Kernel Control Flow Integrity (CFI) support to the Rust compiler
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 13a9c78..f543394 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2776,7 +2776,12 @@ fn get_name(
         // These kinds of item either don't need a `name` or accept a `None` one so we handle them
         // before.
         match item.kind {
-            ItemKind::Impl(ref impl_) => return clean_impl(impl_, item.owner_id.def_id, cx),
+            ItemKind::Impl(ref impl_) => {
+                // If `renamed` is `Some()` for an `impl`, it means it's been inlined because we use
+                // it as a marker to indicate that this is an inlined impl and that we should
+                // generate an impl placeholder and not a "real" impl item.
+                return clean_impl(impl_, item.owner_id.def_id, cx, renamed.is_some());
+            }
             ItemKind::Use(path, kind) => {
                 return clean_use_statement(
                     item,
@@ -2909,10 +2914,27 @@ fn clean_impl<'tcx>(
     impl_: &hir::Impl<'tcx>,
     def_id: LocalDefId,
     cx: &mut DocContext<'tcx>,
+    // If true, this is an inlined impl and it will be handled later on in the code.
+    // In here, we will generate a placeholder for it in order to be able to compute its
+    // `doc_cfg` info.
+    is_inlined: bool,
 ) -> Vec<Item> {
     let tcx = cx.tcx;
     let mut ret = Vec::new();
-    let trait_ = impl_.of_trait.map(|t| clean_trait_ref(&t.trait_ref, cx));
+    let trait_ = match impl_.of_trait {
+        Some(t) => {
+            if is_inlined {
+                return vec![Item::from_def_id_and_parts(
+                    def_id.to_def_id(),
+                    None,
+                    PlaceholderImplItem,
+                    cx,
+                )];
+            }
+            Some(clean_trait_ref(&t.trait_ref, cx))
+        }
+        None => None,
+    };
     let items = impl_
         .items
         .iter()
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 431e9ff..ad70fc1 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -885,6 +885,9 @@ pub(crate) enum ItemKind {
     TraitItem(Box<Trait>),
     TraitAliasItem(TraitAlias),
     ImplItem(Box<Impl>),
+    /// This variant is used only as a placeholder for trait impls in order to correctly compute
+    /// `doc_cfg` as trait impls are added to `clean::Crate` after we went through the whole tree.
+    PlaceholderImplItem,
     /// A required method in a trait declaration meaning it's only a function signature.
     RequiredMethodItem(Box<Function>, Defaultness),
     /// A method in a trait impl or a provided method in a trait declaration.
@@ -964,7 +967,8 @@ pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
             | AssocTypeItem(..)
             | StrippedItem(_)
             | KeywordItem
-            | AttributeItem => [].iter(),
+            | AttributeItem
+            | PlaceholderImplItem => [].iter(),
         }
     }
 }
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index c970fdb..8b9db46 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -97,7 +97,8 @@ fn fold_inner_recur(&mut self, kind: ItemKind) -> ItemKind {
             | RequiredAssocTypeItem(..)
             | AssocTypeItem(..)
             | KeywordItem
-            | AttributeItem => kind,
+            | AttributeItem
+            | PlaceholderImplItem => kind,
         }
     }
 
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 5a97d8e..35071f4 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -389,6 +389,8 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
                 // So would rather leave them to an expert,
                 // as at least the list is better than `_ => {}`.
             }
+
+            clean::PlaceholderImplItem => return None,
         }
 
         // Maintain the parent stack.
diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs
index 6830c1e..eb3492e 100644
--- a/src/librustdoc/formats/item_type.rs
+++ b/src/librustdoc/formats/item_type.rs
@@ -122,7 +122,7 @@ fn from(item: &'a clean::Item) -> ItemType {
             clean::StaticItem(..) => ItemType::Static,
             clean::ConstantItem(..) => ItemType::Constant,
             clean::TraitItem(..) => ItemType::Trait,
-            clean::ImplItem(..) => ItemType::Impl,
+            clean::ImplItem(..) | clean::PlaceholderImplItem => ItemType::Impl,
             clean::RequiredMethodItem(..) => ItemType::TyMethod,
             clean::MethodItem(..) => ItemType::Method,
             clean::StructFieldItem(..) => ItemType::StructField,
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index bc9ad16..5d1f477 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -353,6 +353,8 @@ fn from_clean_item(item: &clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum
             name: name.as_ref().unwrap().to_string(),
             rename: src.map(|x| x.to_string()),
         },
+        // All placeholder impl items should have been removed in the stripper passes.
+        PlaceholderImplItem => unreachable!(),
     }
 }
 
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 77b3a2e..ac5e780 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -203,6 +203,10 @@ fn visit_item(&mut self, i: &clean::Item) {
                 // don't count items in stripped modules
                 return;
             }
+            clean::PlaceholderImplItem => {
+                // The "real" impl items are handled below.
+                return;
+            }
             // docs on `use` and `extern crate` statements are not displayed, so they're not
             // worth counting
             clean::ImportItem(..) | clean::ExternCrateItem { .. } => {}
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index a1578ab..ff7535f 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -80,6 +80,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
                 | clean::ImplAssocConstItem(..)
                 | clean::RequiredAssocTypeItem(..)
                 | clean::ImplItem(_)
+                | clean::PlaceholderImplItem
         )
     {
         return false;
diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs
index 54da158..f73db25 100644
--- a/src/librustdoc/passes/propagate_doc_cfg.rs
+++ b/src/librustdoc/passes/propagate_doc_cfg.rs
@@ -1,10 +1,11 @@
 //! Propagates [`#[doc(cfg(...))]`](https://github.com/rust-lang/rust/issues/43781) to child items.
 
+use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::Attribute;
 use rustc_hir::attrs::{AttributeKind, DocAttribute};
 
 use crate::clean::inline::{load_attrs, merge_attrs};
-use crate::clean::{CfgInfo, Crate, Item, ItemKind};
+use crate::clean::{CfgInfo, Crate, Item, ItemId, ItemKind};
 use crate::core::DocContext;
 use crate::fold::DocFolder;
 use crate::passes::Pass;
@@ -17,7 +18,8 @@
 
 pub(crate) fn propagate_doc_cfg(cr: Crate, cx: &mut DocContext<'_>) -> Crate {
     if cx.tcx.features().doc_cfg() {
-        CfgPropagator { cx, cfg_info: CfgInfo::default() }.fold_crate(cr)
+        CfgPropagator { cx, cfg_info: CfgInfo::default(), impl_cfg_info: FxHashMap::default() }
+            .fold_crate(cr)
     } else {
         cr
     }
@@ -26,6 +28,10 @@ pub(crate) fn propagate_doc_cfg(cr: Crate, cx: &mut DocContext<'_>) -> Crate {
 struct CfgPropagator<'a, 'tcx> {
     cx: &'a mut DocContext<'tcx>,
     cfg_info: CfgInfo,
+
+    /// To ensure the `doc_cfg` feature works with how `rustdoc` handles impls, we need to store
+    /// the `cfg` info of `impl`s placeholder to use them later on the "real" impl item.
+    impl_cfg_info: FxHashMap<ItemId, CfgInfo>,
 }
 
 /// This function goes through the attributes list (`new_attrs`) and extract the `cfg` tokens from
@@ -78,7 +84,22 @@ impl DocFolder for CfgPropagator<'_, '_> {
     fn fold_item(&mut self, mut item: Item) -> Option<Item> {
         let old_cfg_info = self.cfg_info.clone();
 
-        self.merge_with_parent_attributes(&mut item);
+        // If we have an impl, we check if it has an associated `cfg` "context", and if so we will
+        // use that context instead of the actual (wrong) one.
+        if let ItemKind::ImplItem(_) = item.kind
+            && let Some(cfg_info) = self.impl_cfg_info.remove(&item.item_id)
+        {
+            self.cfg_info = cfg_info;
+        }
+
+        if let ItemKind::PlaceholderImplItem = item.kind {
+            // If we have a placeholder impl, we store the current `cfg` "context" to be used
+            // on the actual impl later on (the impls are generated after we go through the whole
+            // AST so they're stored in the `krate` object at the end).
+            self.impl_cfg_info.insert(item.item_id, self.cfg_info.clone());
+        } else {
+            self.merge_with_parent_attributes(&mut item);
+        }
 
         let result = self.fold_item_recur(item);
         self.cfg_info = old_cfg_info;
diff --git a/src/librustdoc/passes/propagate_stability.rs b/src/librustdoc/passes/propagate_stability.rs
index 5139ca3..c8691fd 100644
--- a/src/librustdoc/passes/propagate_stability.rs
+++ b/src/librustdoc/passes/propagate_stability.rs
@@ -107,7 +107,8 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                     | ItemKind::AssocTypeItem(..)
                     | ItemKind::PrimitiveItem(..)
                     | ItemKind::KeywordItem
-                    | ItemKind::AttributeItem => own_stability,
+                    | ItemKind::AttributeItem
+                    | ItemKind::PlaceholderImplItem => own_stability,
 
                     ItemKind::StrippedItem(..) => unreachable!(),
                 }
diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs
index 99d2252..bf4e842 100644
--- a/src/librustdoc/passes/stripper.rs
+++ b/src/librustdoc/passes/stripper.rs
@@ -120,6 +120,10 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
 
             clean::ImplItem(..) => {}
 
+            // Since the `doc_cfg` propagation was handled before the current pass, we can (and
+            // should) remove all placeholder impl items.
+            clean::PlaceholderImplItem => return None,
+
             // tymethods etc. have no control over privacy
             clean::RequiredMethodItem(..)
             | clean::RequiredAssocConstItem(..)
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index cc78dec..63b869c 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -3,7 +3,7 @@
 use std::fs;
 use std::path::PathBuf;
 
-use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_errors::DiagCtxtHandle;
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
@@ -15,7 +15,7 @@
 use rustc_session::getopts;
 use rustc_span::def_id::{CrateNum, DefPathHash, LOCAL_CRATE};
 use rustc_span::edition::Edition;
-use rustc_span::{BytePos, FileName, SourceFile};
+use rustc_span::{BytePos, FileName, SourceFile, Span};
 use tracing::{debug, trace, warn};
 
 use crate::html::render::Context;
@@ -114,6 +114,7 @@ struct FindCalls<'a, 'tcx> {
     target_crates: Vec<CrateNum>,
     calls: &'a mut AllCallLocations,
     bin_crate: bool,
+    call_ident_spans: FxHashSet<Span>,
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for FindCalls<'a, 'tcx>
@@ -165,6 +166,10 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
             }
         };
 
+        if !self.call_ident_spans.insert(ident_span) {
+            return;
+        }
+
         // If this span comes from a macro expansion, then the source code may not actually show
         // a use of the given item, so it would be a poor example. Hence, we skip all uses in
         // macros.
@@ -300,7 +305,13 @@ pub(crate) fn run(
 
         // Run call-finder on all items
         let mut calls = FxIndexMap::default();
-        let mut finder = FindCalls { calls: &mut calls, cx, target_crates, bin_crate };
+        let mut finder = FindCalls {
+            calls: &mut calls,
+            cx,
+            target_crates,
+            bin_crate,
+            call_ident_spans: FxHashSet::default(),
+        };
         tcx.hir_visit_all_item_likes_in_crate(&mut finder);
 
         // The visitor might have found a type error, which we need to
diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs
index 9f6bf00..9cf7d6b 100644
--- a/src/librustdoc/visit.rs
+++ b/src/librustdoc/visit.rs
@@ -50,7 +50,8 @@ fn visit_inner_recur(&mut self, kind: &'a ItemKind) {
             | RequiredAssocTypeItem(..)
             | AssocTypeItem(..)
             | KeywordItem
-            | AttributeItem => {}
+            | AttributeItem
+            | PlaceholderImplItem => {}
         }
     }
 
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index fd6ea21..906289b 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -373,6 +373,19 @@ fn reexport_public_and_not_hidden(
     }
 
     #[inline]
+    fn add_impl_to_current_mod(&mut self, item: &'tcx hir::Item<'_>, impl_: hir::Impl<'_>) {
+        self.add_to_current_mod(
+            item,
+            // The symbol here is used as a "sentinel" value and has no meaning in
+            // itself. It just tells that this is an inlined impl and that it should not
+            // be cleaned as a normal `ImplItem` but instead as a `PlaceholderImplItem`.
+            // It's to ensure that `doc_cfg` inheritance works as expected.
+            if impl_.of_trait.is_none() { None } else { Some(rustc_span::symbol::kw::Impl) },
+            None,
+        );
+    }
+
+    #[inline]
     fn add_to_current_mod(
         &mut self,
         item: &'tcx hir::Item<'_>,
@@ -426,12 +439,8 @@ fn visit_item_inner(
             // }
             // Bar::bar();
             // ```
-            if let hir::ItemKind::Impl(impl_) = item.kind &&
-                // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
-                // them up regardless of where they're located.
-                impl_.of_trait.is_none()
-            {
-                self.add_to_current_mod(item, None, None);
+            if let hir::ItemKind::Impl(impl_) = item.kind {
+                self.add_impl_to_current_mod(item, impl_);
             }
             return;
         }
@@ -530,10 +539,10 @@ fn visit_item_inner(
                 }
             }
             hir::ItemKind::Impl(impl_) => {
-                // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
+                // Don't duplicate impls when inlining, we'll pick
                 // them up regardless of where they're located.
-                if !self.inlining && impl_.of_trait.is_none() {
-                    self.add_to_current_mod(item, None, None);
+                if !self.inlining {
+                    self.add_impl_to_current_mod(item, impl_);
                 }
             }
         }
diff --git a/src/llvm-project b/src/llvm-project
index 41f177e..0591836 160000
--- a/src/llvm-project
+++ b/src/llvm-project
@@ -1 +1 @@
-Subproject commit 41f177ed26a5252a30ea6090a4da66ce0a96bf44
+Subproject commit 05918363362b439b9b0bced3daa14badd75da790
diff --git a/src/tools/cargo b/src/tools/cargo
index cbb9bb8..e84cb63 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit cbb9bb8bd0fb272b1be0d63a010701ecb3d1d6d3
+Subproject commit e84cb639edfea2c42efd563b72a9be0cc5de6523
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 7c798a3..45bfb65 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -6,7 +6,103 @@
 
 ## Unreleased / Beta / In Rust Nightly
 
-[92b4b68...master](https://github.com/rust-lang/rust-clippy/compare/92b4b68...master)
+[500e0ff...master](https://github.com/rust-lang/rust-clippy/compare/500e0ff...master)
+
+## Rust 1.94
+
+Current stable, released 2026-03-05
+
+[View all 94 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2025-11-29T21%3A01%3A29Z..2026-01-08T20%3A33%3A22Z+base%3Amaster)
+
+### New Lints
+
+* Added [`same_length_and_capacity`] to `pedantic`
+  [#15656](https://github.com/rust-lang/rust-clippy/pull/15656)
+* Added [`manual_ilog2`] to `pedantic`
+  [#15865](https://github.com/rust-lang/rust-clippy/pull/15865)
+* Added [`needless_type_cast`] to `nursery`
+  [#16139](https://github.com/rust-lang/rust-clippy/pull/16139)
+* Added [`ptr_offset_by_literal`] to `pedantic`
+  [#15606](https://github.com/rust-lang/rust-clippy/pull/15606)
+* Added [`decimal_bitwise_operands`] to `pedantic`
+  [#15215](https://github.com/rust-lang/rust-clippy/pull/15215)
+
+### Moves and Deprecations
+
+* Moved [`multiple_bound_locations`] from `suspicious` to `style`
+  [#16302](https://github.com/rust-lang/rust-clippy/pull/16302)
+* Moved [`collapsible_else_if`] from `style` to `pedantic`
+  [#16211](https://github.com/rust-lang/rust-clippy/pull/16211)
+* Moved [`needless_type_cast`] from `pedantic` to `nursery`
+  [#16246](https://github.com/rust-lang/rust-clippy/pull/16246)
+
+### Enhancements
+
+* [`never_loop`] do not consider `return` as preventing the iterator from looping; lint diverging
+  iterator reduction closures like `for_each` and `fold`
+  [#16364](https://github.com/rust-lang/rust-clippy/pull/16364)
+* [`single_range_in_vec_init`] don't apply the suggestion automatically
+  [#16365](https://github.com/rust-lang/rust-clippy/pull/16365)
+* [`useless_conversion`] refine `.into_iter()` suggestions to stop at final target type
+  [#16238](https://github.com/rust-lang/rust-clippy/pull/16238)
+* Multiple lints fix wrongly unmangled macros
+  [#16337](https://github.com/rust-lang/rust-clippy/pull/16337)
+* [`large_stack_arrays`] do not warn for libtest harness
+  [#16347](https://github.com/rust-lang/rust-clippy/pull/16347)
+* [`derive_ord_xor_partial_ord`] allow `expect` on `impl` block
+  [#16303](https://github.com/rust-lang/rust-clippy/pull/16303)
+* [`match_bool`] restrict to 2 arms
+  [#16333](https://github.com/rust-lang/rust-clippy/pull/16333)
+* [`multiple_inherent_impl`] fix false negatives for generic impl blocks
+  [#16284](https://github.com/rust-lang/rust-clippy/pull/16284)
+* [`unnecessary_fold`] warn about semantics change and lint `Add::add`/`Mul::mul` folds
+  [#16324](https://github.com/rust-lang/rust-clippy/pull/16324)
+* [`transmuting_null`] check const blocks and const integer casts
+  [#16260](https://github.com/rust-lang/rust-clippy/pull/16260)
+* [`needless_pass_by_ref_mut`] preserve user-provided lifetime information
+  [#16273](https://github.com/rust-lang/rust-clippy/pull/16273)
+* [`while_let_on_iterator`] use reborrow for non-`Sized` trait references
+  [#16100](https://github.com/rust-lang/rust-clippy/pull/16100)
+* [`collapsible_else_if`] prevent emitting when arms only `if {..} else {..}`
+  [#16286](https://github.com/rust-lang/rust-clippy/pull/16286)
+* [`multiple_unsafe_ops_per_block`] count only towards innermost unsafe block
+  [#16117](https://github.com/rust-lang/rust-clippy/pull/16117)
+* [`manual_saturating_arithmetic`] lint `x.checked_sub(y).unwrap_or_default()`
+  [#15845](https://github.com/rust-lang/rust-clippy/pull/15845)
+* [`transmute_ptr_to_ref`] handle pointer in struct
+  [#15948](https://github.com/rust-lang/rust-clippy/pull/15948)
+* [`disallowed_methods`] skip compiler-generated code
+  [#16186](https://github.com/rust-lang/rust-clippy/pull/16186)
+* [`missing_enforced_import_renames`] do not enforce for "as _"
+  [#16352](https://github.com/rust-lang/rust-clippy/pull/16352)
+
+### False Positive Fixes
+
+* [`double_parens`] fix FP on macro repetition patterns
+  [#16301](https://github.com/rust-lang/rust-clippy/pull/16301)
+* [`assertions_on_constants`] fix false positive when there is non-constant value in condition expr
+  [#16297](https://github.com/rust-lang/rust-clippy/pull/16297)
+* [`use_self`] fix FP on type in const generics
+  [#16172](https://github.com/rust-lang/rust-clippy/pull/16172)
+* [`set_contains_or_insert`] fix FP when set is mutated before `insert`
+  [#16009](https://github.com/rust-lang/rust-clippy/pull/16009)
+* [`if_then_some_else_none`] fix FP when then block contains `await`
+  [#16178](https://github.com/rust-lang/rust-clippy/pull/16178)
+* [`match_like_matches_macro`] fix FP with guards containing `if let`
+  [#15876](https://github.com/rust-lang/rust-clippy/pull/15876)
+* [`tuple_array_conversions`] fix FP when binded vars are used before conversion
+  [#16197](https://github.com/rust-lang/rust-clippy/pull/16197)
+* [`map_entry`] fix FP when it would cause `MutexGuard` to be held across await
+  [#16199](https://github.com/rust-lang/rust-clippy/pull/16199)
+* [`panicking_unwrap`] fix FP on field access with implicit deref
+  [#16196](https://github.com/rust-lang/rust-clippy/pull/16196)
+* [`large_stack_frames`] fix FP on compiler generated targets
+  [#15101](https://github.com/rust-lang/rust-clippy/pull/15101)
+
+### ICE Fixes
+
+* [`needless_type_cast`] do not ICE on struct constructor
+  [#16245](https://github.com/rust-lang/rust-clippy/pull/16245)
 
 ### New Lints
 
@@ -6705,6 +6801,7 @@
 [`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or
 [`manual_option_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_option_as_slice
 [`manual_pattern_char_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_pattern_char_comparison
+[`manual_pop_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_pop_if
 [`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains
 [`manual_range_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_patterns
 [`manual_rem_euclid`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid
diff --git a/src/tools/clippy/clippy.toml b/src/tools/clippy/clippy.toml
index 4aa0a42..6f9db8d 100644
--- a/src/tools/clippy/clippy.toml
+++ b/src/tools/clippy/clippy.toml
@@ -5,11 +5,11 @@
 lint-commented-code = true
 
 [[disallowed-methods]]
-path = "rustc_lint::context::LintContext::lint"
+path = "rustc_lint::context::LintContext::opt_span_lint"
 reason = "this function does not add a link to our documentation; please use the `clippy_utils::diagnostics::span_lint*` functions instead"
 
 [[disallowed-methods]]
-path = "rustc_lint::context::LintContext::span_lint"
+path = "rustc_lint::context::LintContext::emit_span_lint"
 reason = "this function does not add a link to our documentation; please use the `clippy_utils::diagnostics::span_lint*` functions instead"
 
 [[disallowed-methods]]
diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs
index 359bf17..99709ed 100644
--- a/src/tools/clippy/clippy_dev/src/lib.rs
+++ b/src/tools/clippy/clippy_dev/src/lib.rs
@@ -5,8 +5,7 @@
     os_str_slice,
     os_string_truncate,
     pattern,
-    rustc_private,
-    slice_split_once
+    rustc_private
 )]
 #![warn(
     trivial_casts,
diff --git a/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs b/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
index b98a20a..8b45473 100644
--- a/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
+++ b/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
@@ -1,5 +1,4 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::HasSession;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{higher, is_else_clause, is_in_const_context, span_contains_comment};
 use rustc_ast::LitKind;
@@ -60,7 +59,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
             && !is_in_const_context(cx)
         {
             let ty = cx.typeck_results().expr_ty(then);
-            let mut applicability = if span_contains_comment(cx.sess().source_map(), expr.span) {
+            let mut applicability = if span_contains_comment(cx, expr.span) {
                 Applicability::MaybeIncorrect
             } else {
                 Applicability::MachineApplicable
diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs
index 75761de..151f9c9 100644
--- a/src/tools/clippy/clippy_lints/src/casts/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs
@@ -691,7 +691,7 @@
     /// const SIZE: usize = 15;
     /// let arr: [u8; SIZE] = [0; SIZE];
     /// ```
-    #[clippy::version = "1.93.0"]
+    #[clippy::version = "1.94.0"]
     pub NEEDLESS_TYPE_CAST,
     nursery,
     "binding defined with one type but always cast to another"
diff --git a/src/tools/clippy/clippy_lints/src/collapsible_if.rs b/src/tools/clippy/clippy_lints/src/collapsible_if.rs
index a76027c..3850c55 100644
--- a/src/tools/clippy/clippy_lints/src/collapsible_if.rs
+++ b/src/tools/clippy/clippy_lints/src/collapsible_if.rs
@@ -1,7 +1,7 @@
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::msrvs::Msrv;
-use clippy_utils::source::{IntoSpan as _, SpanRangeExt, snippet, snippet_block_with_applicability};
+use clippy_utils::source::{HasSession, IntoSpan as _, SpanRangeExt, snippet, snippet_block_with_applicability};
 use clippy_utils::{can_use_if_let_chains, span_contains_non_whitespace, sym, tokenize_with_text};
 use rustc_ast::{BinOpKind, MetaItemInner};
 use rustc_errors::Applicability;
@@ -9,7 +9,6 @@
 use rustc_lexer::TokenKind;
 use rustc_lint::{LateContext, LateLintPass, Level};
 use rustc_session::impl_lint_pass;
-use rustc_span::source_map::SourceMap;
 use rustc_span::{BytePos, Span, Symbol};
 
 declare_clippy_lint! {
@@ -111,10 +110,8 @@ fn check_collapsible_else_if(&self, cx: &LateContext<'_>, then_span: Span, else_
                     let up_to_else = then_span.between(else_block.span);
                     let else_before_if = else_.span.shrink_to_lo().with_hi(else_if_cond.span.lo() - BytePos(1));
                     if self.lint_commented_code
-                        && let Some(else_keyword_span) =
-                            span_extract_keyword(cx.tcx.sess.source_map(), up_to_else, "else")
-                        && let Some(else_if_keyword_span) =
-                            span_extract_keyword(cx.tcx.sess.source_map(), else_before_if, "if")
+                        && let Some(else_keyword_span) = span_extract_keyword(cx, up_to_else, "else")
+                        && let Some(else_if_keyword_span) = span_extract_keyword(cx, else_before_if, "if")
                     {
                         let else_keyword_span = else_keyword_span.with_leading_whitespace(cx).into_span();
                         let else_open_bracket = else_block.span.split_at(1).0.with_leading_whitespace(cx).into_span();
@@ -139,7 +136,7 @@ fn check_collapsible_else_if(&self, cx: &LateContext<'_>, then_span: Span, else_
                     }
 
                     // Peel off any parentheses.
-                    let (_, else_block_span, _) = peel_parens(cx.tcx.sess.source_map(), else_.span);
+                    let (_, else_block_span, _) = peel_parens(cx, else_.span);
 
                     // Prevent "elseif"
                     // Check that the "else" is followed by whitespace
@@ -187,7 +184,7 @@ fn check_collapsible_if_if(&self, cx: &LateContext<'_>, expr: &Expr<'_>, check:
                             .with_leading_whitespace(cx)
                             .into_span()
                     };
-                    let (paren_start, inner_if_span, paren_end) = peel_parens(cx.tcx.sess.source_map(), inner.span);
+                    let (paren_start, inner_if_span, paren_end) = peel_parens(cx, inner.span);
                     let inner_if = inner_if_span.split_at(2).0;
                     let mut sugg = vec![
                         // Remove the outer then block `{`
@@ -320,33 +317,36 @@ pub(super) fn parens_around(expr: &Expr<'_>) -> Vec<(Span, String)> {
     }
 }
 
-fn span_extract_keyword(sm: &SourceMap, span: Span, keyword: &str) -> Option<Span> {
-    let snippet = sm.span_to_snippet(span).ok()?;
-    tokenize_with_text(&snippet)
-        .filter(|(t, s, _)| matches!(t, TokenKind::Ident if *s == keyword))
-        .map(|(_, _, inner)| {
-            span.split_at(u32::try_from(inner.start).unwrap())
-                .1
-                .split_at(u32::try_from(inner.end - inner.start).unwrap())
-                .0
-        })
-        .next()
+fn span_extract_keyword(cx: &impl HasSession, span: Span, keyword: &str) -> Option<Span> {
+    span.with_source_text(cx, |snippet| {
+        tokenize_with_text(snippet)
+            .filter(|(t, s, _)| matches!(t, TokenKind::Ident if *s == keyword))
+            .map(|(_, _, inner)| {
+                span.split_at(u32::try_from(inner.start).unwrap())
+                    .1
+                    .split_at(u32::try_from(inner.end - inner.start).unwrap())
+                    .0
+            })
+            .next()
+    })
+    .flatten()
 }
 
 /// Peel the parentheses from an `if` expression, e.g. `((if true {} else {}))`.
-pub(super) fn peel_parens(sm: &SourceMap, mut span: Span) -> (Span, Span, Span) {
+pub(super) fn peel_parens(cx: &impl HasSession, mut span: Span) -> (Span, Span, Span) {
     use crate::rustc_span::Pos;
 
     let start = span.shrink_to_lo();
     let end = span.shrink_to_hi();
 
-    let snippet = sm.span_to_snippet(span).unwrap();
-    if let Some((trim_start, _, trim_end)) = peel_parens_str(&snippet) {
-        let mut data = span.data();
-        data.lo = data.lo + BytePos::from_usize(trim_start);
-        data.hi = data.hi - BytePos::from_usize(trim_end);
-        span = data.span();
-    }
+    span.with_source_text(cx, |snippet| {
+        if let Some((trim_start, _, trim_end)) = peel_parens_str(snippet) {
+            let mut data = span.data();
+            data.lo = data.lo + BytePos::from_usize(trim_start);
+            data.hi = data.hi - BytePos::from_usize(trim_end);
+            span = data.span();
+        }
+    });
 
     (start.with_hi(span.lo()), span, end.with_lo(span.hi()))
 }
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index e16b194..441b907 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -312,6 +312,7 @@
     crate::manual_main_separator_str::MANUAL_MAIN_SEPARATOR_STR_INFO,
     crate::manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE_INFO,
     crate::manual_option_as_slice::MANUAL_OPTION_AS_SLICE_INFO,
+    crate::manual_pop_if::MANUAL_POP_IF_INFO,
     crate::manual_range_patterns::MANUAL_RANGE_PATTERNS_INFO,
     crate::manual_rem_euclid::MANUAL_REM_EUCLID_INFO,
     crate::manual_retain::MANUAL_RETAIN_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic/custom_abs.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic/custom_abs.rs
index 6578cf2..f476aba 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic/custom_abs.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic/custom_abs.rs
@@ -6,8 +6,7 @@
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
 use rustc_lint::LateContext;
-use rustc_span::SyntaxContext;
-use rustc_span::Spanned;
+use rustc_span::{Spanned, SyntaxContext};
 
 use super::SUBOPTIMAL_FLOPS;
 
diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
index 04c6571..7c1b3ef 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -24,7 +24,7 @@
 
 pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
     let attrs = cx.tcx.hir_attrs(item.hir_id());
-    let attr = find_attr!(cx.tcx.hir_attrs(item.hir_id()), MustUse { span, reason } => (span, reason));
+    let attr = find_attr!(cx.tcx, item.hir_id(), MustUse { span, reason } => (span, reason));
     if let hir::ItemKind::Fn {
         ref sig,
         body: ref body_id,
@@ -65,7 +65,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
         let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
         let attrs = cx.tcx.hir_attrs(item.hir_id());
-        let attr = find_attr!(cx.tcx.hir_attrs(item.hir_id()), MustUse { span, reason } => (span, reason));
+        let attr = find_attr!(cx.tcx, item.hir_id(), MustUse { span, reason } => (span, reason));
         if let Some((attr_span, reason)) = attr {
             check_needless_must_use(
                 cx,
@@ -98,7 +98,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
 
         let attrs = cx.tcx.hir_attrs(item.hir_id());
-        let attr = find_attr!(cx.tcx.hir_attrs(item.hir_id()), MustUse { span, reason } => (span, reason));
+        let attr = find_attr!(cx.tcx, item.hir_id(), MustUse { span, reason } => (span, reason));
         if let Some((attr_span, reason)) = attr {
             check_needless_must_use(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
index ad81810..1ae8198 100644
--- a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
+++ b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
@@ -269,5 +269,5 @@ fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &'tcx hir::Ty<'tcx, Ambig
 fn is_under_cfg_attribute(cx: &LateContext<'_>, hir_id: HirId) -> bool {
     cx.tcx
         .hir_parent_id_iter(hir_id)
-        .any(|id| find_attr!(cx.tcx.hir_attrs(id), CfgTrace(..) | CfgAttrTrace))
+        .any(|id| find_attr!(cx.tcx, id, CfgTrace(..) | CfgAttrTrace))
 }
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 4d67c15..719484b 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -210,6 +210,7 @@
 mod manual_main_separator_str;
 mod manual_non_exhaustive;
 mod manual_option_as_slice;
+mod manual_pop_if;
 mod manual_range_patterns;
 mod manual_rem_euclid;
 mod manual_retain;
@@ -863,6 +864,7 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co
         Box::new(move |tcx| Box::new(duration_suboptimal_units::DurationSuboptimalUnits::new(tcx, conf))),
         Box::new(move |_| Box::new(manual_take::ManualTake::new(conf))),
         Box::new(|_| Box::new(manual_checked_ops::ManualCheckedOps)),
+        Box::new(move |_| Box::new(manual_pop_if::ManualPopIf::new(conf))),
         // add late passes here, used by `cargo dev new_lint`
     ];
     store.late_passes.extend(late_lints);
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
index 96de118..2c89afc 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
@@ -3,7 +3,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::res::MaybeResPath;
-use clippy_utils::source::{HasSession, indent_of, reindent_multiline, snippet_with_applicability};
+use clippy_utils::source::{indent_of, reindent_multiline, snippet_with_applicability};
 use clippy_utils::visitors::is_local_used;
 use clippy_utils::{higher, is_refutable, peel_blocks_with_stmt, span_contains_comment};
 use rustc_errors::Applicability;
@@ -50,7 +50,7 @@ pub(super) fn check<'tcx>(
             format!("unnecessary `if let` since only the `{if_let_type}` variant of the iterator element is used");
 
         // Prepare the help message
-        let mut applicability = if span_contains_comment(cx.sess().source_map(), body.span) {
+        let mut applicability = if span_contains_comment(cx, body.span) {
             Applicability::MaybeIncorrect
         } else {
             Applicability::MachineApplicable
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_slice_fill.rs b/src/tools/clippy/clippy_lints/src/loops/manual_slice_fill.rs
index 5d09f75..ffc6f71 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_slice_fill.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_slice_fill.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::eager_or_lazy::switch_to_eager_eval;
 use clippy_utils::msrvs::{self, Msrv};
-use clippy_utils::source::{HasSession, snippet_with_applicability};
+use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{implements_trait, is_slice_like};
 use clippy_utils::visitors::is_local_used;
 use clippy_utils::{higher, peel_blocks_with_stmt, span_contains_comment};
@@ -93,7 +93,7 @@ fn sugg<'tcx>(
     slice_span: rustc_span::Span,
     assignval_span: rustc_span::Span,
 ) {
-    let mut app = if span_contains_comment(cx.sess().source_map(), body.span) {
+    let mut app = if span_contains_comment(cx, body.span) {
         Applicability::MaybeIncorrect // Comments may be informational.
     } else {
         Applicability::MachineApplicable
diff --git a/src/tools/clippy/clippy_lints/src/manual_abs_diff.rs b/src/tools/clippy/clippy_lints/src/manual_abs_diff.rs
index e388651..400cfcd 100644
--- a/src/tools/clippy/clippy_lints/src/manual_abs_diff.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_abs_diff.rs
@@ -3,7 +3,6 @@
 use clippy_utils::higher::If;
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::res::MaybeDef;
-use clippy_utils::source::HasSession as _;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::peel_and_count_ty_refs;
 use clippy_utils::{eq_expr_value, peel_blocks, span_contains_comment, sym};
@@ -76,10 +75,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
                         (a, b) = (b, a);
                     }
                     let applicability = {
-                        let source_map = cx.sess().source_map();
-                        if span_contains_comment(source_map, if_expr.then.span)
-                            || span_contains_comment(source_map, r#else.span)
-                        {
+                        if span_contains_comment(cx, if_expr.then.span) || span_contains_comment(cx, r#else.span) {
                             Applicability::MaybeIncorrect
                         } else {
                             Applicability::MachineApplicable
diff --git a/src/tools/clippy/clippy_lints/src/manual_assert.rs b/src/tools/clippy/clippy_lints/src/manual_assert.rs
index c34e0d3..c771331 100644
--- a/src/tools/clippy/clippy_lints/src/manual_assert.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_assert.rs
@@ -58,7 +58,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
                 "only a `panic!` in `if`-then statement",
                 |diag| {
                     let mut applicability = Applicability::MachineApplicable;
-                    let mut comments = span_extract_comment(cx.sess().source_map(), expr.span);
+                    let mut comments = span_extract_comment(cx, expr.span);
                     if !comments.is_empty() {
                         comments += "\n";
                     }
diff --git a/src/tools/clippy/clippy_lints/src/manual_ilog2.rs b/src/tools/clippy/clippy_lints/src/manual_ilog2.rs
index 7c397bd..2c368f1 100644
--- a/src/tools/clippy/clippy_lints/src/manual_ilog2.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_ilog2.rs
@@ -31,7 +31,7 @@
     /// let log = x.ilog2();
     /// let log = x.ilog2();
     /// ```
-    #[clippy::version = "1.93.0"]
+    #[clippy::version = "1.94.0"]
     pub MANUAL_ILOG2,
     pedantic,
     "manually reimplementing `ilog2`"
diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
index 9ababe8..703c913 100644
--- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
@@ -92,7 +92,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
                         .then_some((v.def_id, v.span))
                 });
                 if let Ok((id, span)) = iter.exactly_one()
-                    && !find_attr!(cx.tcx.hir_attrs(item.hir_id()), NonExhaustive(..))
+                    && !find_attr!(cx.tcx, item.hir_id(), NonExhaustive(..))
                 {
                     self.potential_enums.push((item.owner_id.def_id, id, item.span, span));
                 }
@@ -113,7 +113,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
                         "this seems like a manual implementation of the non-exhaustive pattern",
                         |diag| {
                             if let Some(non_exhaustive_span) =
-                                find_attr!(cx.tcx.hir_attrs(item.hir_id()), NonExhaustive(span) => *span)
+                                find_attr!(cx.tcx, item.hir_id(), NonExhaustive(span) => *span)
                             {
                                 diag.span_note(non_exhaustive_span, "the struct is already non-exhaustive");
                             } else {
diff --git a/src/tools/clippy/clippy_lints/src/manual_pop_if.rs b/src/tools/clippy/clippy_lints/src/manual_pop_if.rs
new file mode 100644
index 0000000..6662a34
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/manual_pop_if.rs
@@ -0,0 +1,434 @@
+use clippy_config::Conf;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::msrvs::{self, Msrv};
+use clippy_utils::res::MaybeDef;
+use clippy_utils::source::snippet_with_context;
+use clippy_utils::visitors::is_local_used;
+use clippy_utils::{eq_expr_value, is_else_clause, is_lang_item_or_ctor, peel_blocks_with_stmt, sym};
+use rustc_ast::LitKind;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind, LangItem, PatKind, RustcVersion, StmtKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::impl_lint_pass;
+use rustc_span::{Span, Symbol};
+use std::fmt;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for code to be replaced by `pop_if` methods.
+    ///
+    /// ### Why is this bad?
+    /// Using `pop_if` is more concise and idiomatic.
+    ///
+    /// ### Known issues
+    /// Currently, the lint does not handle the case where the
+    /// `if` condition is part of an `else if` branch.
+    ///
+    /// The lint also does not handle the case where
+    /// the popped value is assigned and used.
+    ///
+    /// ### Examples
+    /// ```no_run
+    /// # use std::collections::VecDeque;
+    /// # let mut vec = vec![1, 2, 3, 4, 5];
+    /// # let mut deque: VecDeque<i32> = VecDeque::from([1, 2, 3, 4, 5]);
+    /// if vec.last().is_some_and(|x| *x > 5) {
+    ///     vec.pop().unwrap();
+    /// }
+    /// if deque.back().is_some_and(|x| *x > 5) {
+    ///     deque.pop_back().unwrap();
+    /// }
+    /// if deque.front().is_some_and(|x| *x > 5) {
+    ///     deque.pop_front().unwrap();
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// # use std::collections::VecDeque;
+    /// # let mut vec = vec![1, 2, 3, 4, 5];
+    /// # let mut deque: VecDeque<i32> = VecDeque::from([1, 2, 3, 4, 5]);
+    /// vec.pop_if(|x| *x > 5);
+    /// deque.pop_back_if(|x| *x > 5);
+    /// deque.pop_front_if(|x| *x > 5);
+    /// ```
+    #[clippy::version = "1.95.0"]
+    pub MANUAL_POP_IF,
+    complexity,
+    "manual implementation of `pop_if` methods"
+}
+
+impl_lint_pass!(ManualPopIf => [MANUAL_POP_IF]);
+
+pub struct ManualPopIf {
+    msrv: Msrv,
+}
+
+impl ManualPopIf {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self { msrv: conf.msrv }
+    }
+}
+
+#[allow(clippy::enum_variant_names)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum ManualPopIfKind {
+    Vec,
+    VecDequeBack,
+    VecDequeFront,
+}
+
+impl ManualPopIfKind {
+    fn check_method(self) -> Symbol {
+        match self {
+            ManualPopIfKind::Vec => sym::last,
+            ManualPopIfKind::VecDequeBack => sym::back,
+            ManualPopIfKind::VecDequeFront => sym::front,
+        }
+    }
+
+    fn pop_method(self) -> Symbol {
+        match self {
+            ManualPopIfKind::Vec => sym::pop,
+            ManualPopIfKind::VecDequeBack => sym::pop_back,
+            ManualPopIfKind::VecDequeFront => sym::pop_front,
+        }
+    }
+
+    fn pop_if_method(self) -> Symbol {
+        match self {
+            ManualPopIfKind::Vec => sym::pop_if,
+            ManualPopIfKind::VecDequeBack => sym::pop_back_if,
+            ManualPopIfKind::VecDequeFront => sym::pop_front_if,
+        }
+    }
+
+    fn is_diag_item(self, cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+        let ty = cx.typeck_results().expr_ty(expr).peel_refs();
+        match self {
+            ManualPopIfKind::Vec => ty.is_diag_item(cx, sym::Vec),
+            ManualPopIfKind::VecDequeBack | ManualPopIfKind::VecDequeFront => ty.is_diag_item(cx, sym::VecDeque),
+        }
+    }
+
+    fn msrv(self) -> RustcVersion {
+        match self {
+            ManualPopIfKind::Vec => msrvs::VEC_POP_IF,
+            ManualPopIfKind::VecDequeBack => msrvs::VEC_DEQUE_POP_BACK_IF,
+            ManualPopIfKind::VecDequeFront => msrvs::VEC_DEQUE_POP_FRONT_IF,
+        }
+    }
+}
+
+impl fmt::Display for ManualPopIfKind {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            ManualPopIfKind::Vec => write!(f, "`Vec::pop_if`"),
+            ManualPopIfKind::VecDequeBack => write!(f, "`VecDeque::pop_back_if`"),
+            ManualPopIfKind::VecDequeFront => write!(f, "`VecDeque::pop_front_if`"),
+        }
+    }
+}
+
+struct ManualPopIfPattern<'tcx> {
+    kind: ManualPopIfKind,
+
+    /// The collection (`vec` in `vec.last()`)
+    collection_expr: &'tcx Expr<'tcx>,
+
+    /// The closure (`*x > 5` in `|x| *x > 5`)
+    predicate: &'tcx Expr<'tcx>,
+
+    /// Parameter name for the closure (`x` in `|x| *x > 5`)
+    param_name: Symbol,
+
+    /// Span of the if expression (including the `if` keyword)
+    if_span: Span,
+}
+
+impl ManualPopIfPattern<'_> {
+    fn emit_lint(&self, cx: &LateContext<'_>) {
+        let mut app = Applicability::MachineApplicable;
+        let ctxt = self.if_span.ctxt();
+        let collection_snippet = snippet_with_context(cx, self.collection_expr.span, ctxt, "..", &mut app).0;
+        let predicate_snippet = snippet_with_context(cx, self.predicate.span, ctxt, "..", &mut app).0;
+        let param_name = self.param_name;
+        let pop_if_method = self.kind.pop_if_method();
+
+        let suggestion = format!("{collection_snippet}.{pop_if_method}(|{param_name}| {predicate_snippet});");
+
+        span_lint_and_sugg(
+            cx,
+            MANUAL_POP_IF,
+            self.if_span,
+            format!("manual implementation of {}", self.kind),
+            "try",
+            suggestion,
+            app,
+        );
+    }
+}
+
+fn pop_value_is_used(then_block: &Expr<'_>) -> bool {
+    let ExprKind::Block(block, _) = then_block.kind else {
+        return true;
+    };
+
+    if block.expr.is_some() {
+        return true;
+    }
+
+    match block.stmts {
+        [stmt] => !matches!(stmt.kind, StmtKind::Semi(_) | StmtKind::Item(_)),
+        [.., last] => matches!(last.kind, StmtKind::Expr(_)),
+        [] => false,
+    }
+}
+
+/// Checks for the pattern:
+/// ```ignore
+/// if vec.last().is_some_and(|x| *x > 5) {
+///     vec.pop().unwrap();
+/// }
+/// ```
+fn check_is_some_and_pattern<'tcx>(
+    cx: &LateContext<'tcx>,
+    cond: &'tcx Expr<'_>,
+    then_block: &'tcx Expr<'_>,
+    if_expr_span: Span,
+    kind: ManualPopIfKind,
+) -> Option<ManualPopIfPattern<'tcx>> {
+    if pop_value_is_used(then_block) {
+        return None;
+    }
+
+    let check_method = kind.check_method();
+    let pop_method = kind.pop_method();
+
+    if let ExprKind::MethodCall(path, receiver, [closure_arg], _) = cond.kind
+        && path.ident.name == sym::is_some_and
+        && let ExprKind::MethodCall(check_path, collection_expr, [], _) = receiver.kind
+        && check_path.ident.name == check_method
+        && kind.is_diag_item(cx, collection_expr)
+        && let ExprKind::Closure(closure) = closure_arg.kind
+        && let body = cx.tcx.hir_body(closure.body)
+        && let Some((pop_collection, _pop_span)) = check_pop_unwrap(then_block, pop_method)
+        && eq_expr_value(cx, collection_expr, pop_collection)
+        && let Some(param) = body.params.first()
+        && let Some(ident) = param.pat.simple_ident()
+    {
+        return Some(ManualPopIfPattern {
+            kind,
+            collection_expr,
+            predicate: body.value,
+            param_name: ident.name,
+            if_span: if_expr_span,
+        });
+    }
+
+    None
+}
+
+/// Checks for the pattern:
+/// ```ignore
+/// if let Some(x) = vec.last() {
+///     if *x > 5 {
+///         vec.pop().unwrap();
+///     }
+/// }
+/// ```
+fn check_if_let_pattern<'tcx>(
+    cx: &LateContext<'tcx>,
+    cond: &'tcx Expr<'_>,
+    then_block: &'tcx Expr<'_>,
+    if_expr_span: Span,
+    kind: ManualPopIfKind,
+) -> Option<ManualPopIfPattern<'tcx>> {
+    let check_method = kind.check_method();
+    let pop_method = kind.pop_method();
+
+    if let ExprKind::Let(let_expr) = cond.kind
+        && let PatKind::TupleStruct(qpath, [binding_pat], _) = let_expr.pat.kind
+    {
+        let res = cx.qpath_res(&qpath, let_expr.pat.hir_id);
+
+        if let Some(def_id) = res.opt_def_id()
+            && is_lang_item_or_ctor(cx, def_id, LangItem::OptionSome)
+            && let PatKind::Binding(_, binding_id, binding_name, _) = binding_pat.kind
+            && let ExprKind::MethodCall(path, collection_expr, [], _) = let_expr.init.kind
+            && path.ident.name == check_method
+            && kind.is_diag_item(cx, collection_expr)
+            && let ExprKind::Block(block, _) = then_block.kind
+        {
+            // The inner if can be either a statement or a block expression
+            let inner_if = match (block.stmts, block.expr) {
+                ([stmt], _) => match stmt.kind {
+                    StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr,
+                    _ => return None,
+                },
+                ([], Some(expr)) => expr,
+                _ => return None,
+            };
+
+            if let ExprKind::If(inner_cond, inner_then, None) = inner_if.kind
+                && is_local_used(cx, inner_cond, binding_id)
+                && !pop_value_is_used(inner_then)
+                && let Some((pop_collection, _pop_span)) = check_pop_unwrap(inner_then, pop_method)
+                && eq_expr_value(cx, collection_expr, pop_collection)
+            {
+                return Some(ManualPopIfPattern {
+                    kind,
+                    collection_expr,
+                    predicate: inner_cond,
+                    param_name: binding_name.name,
+                    if_span: if_expr_span,
+                });
+            }
+        }
+    }
+
+    None
+}
+
+/// Checks for the pattern:
+/// ```ignore
+/// if let Some(x) = vec.last() && *x > 5 {
+///     vec.pop().unwrap();
+/// }
+/// ```
+fn check_let_chain_pattern<'tcx>(
+    cx: &LateContext<'tcx>,
+    cond: &'tcx Expr<'_>,
+    then_block: &'tcx Expr<'_>,
+    if_expr_span: Span,
+    kind: ManualPopIfKind,
+) -> Option<ManualPopIfPattern<'tcx>> {
+    if pop_value_is_used(then_block) {
+        return None;
+    }
+
+    let check_method = kind.check_method();
+    let pop_method = kind.pop_method();
+
+    if let ExprKind::Binary(op, left, right) = cond.kind
+        && op.node == rustc_ast::BinOpKind::And
+        && let ExprKind::Let(let_expr) = left.kind
+        && let PatKind::TupleStruct(qpath, [binding_pat], _) = let_expr.pat.kind
+    {
+        let res = cx.qpath_res(&qpath, let_expr.pat.hir_id);
+
+        if let Some(def_id) = res.opt_def_id()
+            && is_lang_item_or_ctor(cx, def_id, LangItem::OptionSome)
+            && let PatKind::Binding(_, binding_id, binding_name, _) = binding_pat.kind
+            && let ExprKind::MethodCall(path, collection_expr, [], _) = let_expr.init.kind
+            && path.ident.name == check_method
+            && kind.is_diag_item(cx, collection_expr)
+            && is_local_used(cx, right, binding_id)
+            && !pop_value_is_used(then_block)
+            && let Some((pop_collection, _pop_span)) = check_pop_unwrap(then_block, pop_method)
+            && eq_expr_value(cx, collection_expr, pop_collection)
+        {
+            return Some(ManualPopIfPattern {
+                kind,
+                collection_expr,
+                predicate: right,
+                param_name: binding_name.name,
+                if_span: if_expr_span,
+            });
+        }
+    }
+
+    None
+}
+
+/// Checks for the pattern:
+/// ```ignore
+/// if vec.last().map(|x| *x > 5).unwrap_or(false) {
+///     vec.pop().unwrap();
+/// }
+/// ```
+fn check_map_unwrap_or_pattern<'tcx>(
+    cx: &LateContext<'tcx>,
+    cond: &'tcx Expr<'_>,
+    then_block: &'tcx Expr<'_>,
+    if_expr_span: Span,
+    kind: ManualPopIfKind,
+) -> Option<ManualPopIfPattern<'tcx>> {
+    if pop_value_is_used(then_block) {
+        return None;
+    }
+
+    let check_method = kind.check_method();
+    let pop_method = kind.pop_method();
+
+    if let ExprKind::MethodCall(unwrap_path, receiver, [default_arg], _) = cond.kind
+        && unwrap_path.ident.name == sym::unwrap_or
+        && matches!(default_arg.kind, ExprKind::Lit(lit) if matches!(lit.node, LitKind::Bool(false)))
+        && let ExprKind::MethodCall(map_path, map_receiver, [closure_arg], _) = receiver.kind
+        && map_path.ident.name == sym::map
+        && let ExprKind::MethodCall(check_path, collection_expr, [], _) = map_receiver.kind
+        && check_path.ident.name == check_method
+        && kind.is_diag_item(cx, collection_expr)
+        && let ExprKind::Closure(closure) = closure_arg.kind
+        && let body = cx.tcx.hir_body(closure.body)
+        && cx.typeck_results().expr_ty(body.value).is_bool()
+        && let Some((pop_collection, _pop_span)) = check_pop_unwrap(then_block, pop_method)
+        && eq_expr_value(cx, collection_expr, pop_collection)
+        && let Some(param) = body.params.first()
+        && let Some(ident) = param.pat.simple_ident()
+    {
+        return Some(ManualPopIfPattern {
+            kind,
+            collection_expr,
+            predicate: body.value,
+            param_name: ident.name,
+            if_span: if_expr_span,
+        });
+    }
+
+    None
+}
+
+/// Checks for `collection.<pop_method>().unwrap()` or `collection.<pop_method>().expect(..)`
+/// and returns the collection and the span of the peeled expr
+fn check_pop_unwrap<'tcx>(expr: &'tcx Expr<'_>, pop_method: Symbol) -> Option<(&'tcx Expr<'tcx>, Span)> {
+    let inner_expr = peel_blocks_with_stmt(expr);
+
+    if let ExprKind::MethodCall(unwrap_path, receiver, _, _) = inner_expr.kind
+        && matches!(unwrap_path.ident.name, sym::unwrap | sym::expect)
+        && let ExprKind::MethodCall(pop_path, collection_expr, [], _) = receiver.kind
+        && pop_path.ident.name == pop_method
+    {
+        return Some((collection_expr, inner_expr.span));
+    }
+
+    None
+}
+
+impl<'tcx> LateLintPass<'tcx> for ManualPopIf {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        let ExprKind::If(cond, then_block, None) = expr.kind else {
+            return;
+        };
+
+        // Do not lint if we are in an else-if branch.
+        if is_else_clause(cx.tcx, expr) {
+            return;
+        }
+
+        for kind in [
+            ManualPopIfKind::Vec,
+            ManualPopIfKind::VecDequeBack,
+            ManualPopIfKind::VecDequeFront,
+        ] {
+            if let Some(pattern) = check_is_some_and_pattern(cx, cond, then_block, expr.span, kind)
+                .or_else(|| check_if_let_pattern(cx, cond, then_block, expr.span, kind))
+                .or_else(|| check_let_chain_pattern(cx, cond, then_block, expr.span, kind))
+                .or_else(|| check_map_unwrap_or_pattern(cx, cond, then_block, expr.span, kind))
+                && self.msrv.meets(cx, kind.msrv())
+            {
+                pattern.emit_lint(cx);
+                return;
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
index c95a72d..de5f83b 100644
--- a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
@@ -154,7 +154,7 @@ fn check_arm<'tcx>(
                 } else {
                     outer_pat.span.shrink_to_hi()
                 };
-                let (paren_start, inner_if_span, paren_end) = peel_parens(cx.tcx.sess.source_map(), inner_expr.span);
+                let (paren_start, inner_if_span, paren_end) = peel_parens(cx, inner_expr.span);
                 let inner_if = inner_if_span.split_at(2).0;
                 let mut sugg = vec![
                     (inner.then.span.shrink_to_lo(), "=> ".to_string()),
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs b/src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs
index 1fc8bb9..abbf600 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs
@@ -9,7 +9,7 @@
 use rustc_hir::LangItem::ResultErr;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Arm, Expr, ExprKind, Pat, PatExpr, PatExprKind, PatKind, Path, QPath};
-use rustc_lint::{LateContext, LintContext};
+use rustc_lint::LateContext;
 use rustc_middle::ty::Ty;
 use rustc_span::symbol::Ident;
 
@@ -130,7 +130,7 @@ fn is_none(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 /// `err`, depending on `is_ok`.
 fn apply_lint(cx: &LateContext<'_>, expr: &Expr<'_>, scrutinee: &Expr<'_>, is_ok: bool) {
     let method = if is_ok { "ok" } else { "err" };
-    let mut app = if span_contains_comment(cx.sess().source_map(), expr.span) {
+    let mut app = if span_contains_comment(cx, expr.span) {
         Applicability::MaybeIncorrect
     } else {
         Applicability::MachineApplicable
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
index 421c606..e3a112d 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
@@ -5,7 +5,7 @@
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, Pat, PatExpr, PatExprKind, PatKind, QPath};
-use rustc_lint::{LateContext, LintContext};
+use rustc_lint::LateContext;
 use rustc_middle::ty::{GenericArgKind, Ty};
 use rustc_span::sym;
 
@@ -101,7 +101,7 @@ fn handle(
         && local_id == binding_id
     {
         // Machine applicable only if there are no comments present
-        let mut applicability = if span_contains_comment(cx.sess().source_map(), expr.span) {
+        let mut applicability = if span_contains_comment(cx, expr.span) {
             Applicability::MaybeIncorrect
         } else {
             Applicability::MachineApplicable
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
index 3a16c2e..7b3ad25 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
@@ -8,7 +8,7 @@
 use rustc_ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, Pat, PatKind, QPath};
-use rustc_lint::{LateContext, LintContext};
+use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_span::Spanned;
 
@@ -22,7 +22,7 @@ pub(crate) fn check_if_let<'tcx>(
     then_expr: &'tcx Expr<'_>,
     else_expr: &'tcx Expr<'_>,
 ) {
-    if !span_contains_comment(cx.sess().source_map(), expr.span)
+    if !span_contains_comment(cx, expr.span)
         && cx.typeck_results().expr_ty(expr).is_bool()
         && let Some(b0) = find_bool_lit(then_expr)
         && let Some(b1) = find_bool_lit(else_expr)
@@ -71,7 +71,7 @@ pub(super) fn check_match<'tcx>(
 ) -> bool {
     if let Some((last_arm, arms_without_last)) = arms.split_last()
         && let Some((first_arm, middle_arms)) = arms_without_last.split_first()
-        && !span_contains_comment(cx.sess().source_map(), e.span)
+        && !span_contains_comment(cx, e.span)
         && cx.typeck_results().expr_ty(e).is_bool()
         && let Some(b0) = find_bool_lit(first_arm.body)
         && let Some(b1) = find_bool_lit(last_arm.body)
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
index 5b0de80..a8312a0 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
@@ -12,7 +12,7 @@
 use rustc_hir::{Arm, Expr, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatExpr, PatExprKind, PatKind, RangeEnd};
 use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_lint::{LateContext, LintContext};
-use rustc_middle::ty;
+use rustc_middle::ty::{self, TypeckResults};
 use rustc_span::{ByteSymbol, ErrorGuaranteed, Span, Symbol};
 
 use super::MATCH_SAME_ARMS;
@@ -61,7 +61,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
 
         let check_eq_with_pat = |expr_a: &Expr<'_>, expr_b: &Expr<'_>| {
             let mut local_map: HirIdMap<HirId> = HirIdMap::default();
-            let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| {
+            let eq_fallback = |a_typeck_results: &TypeckResults<'tcx>,
+                               a: &Expr<'_>,
+                               b_typeck_results: &TypeckResults<'tcx>,
+                               b: &Expr<'_>| {
                 if let Some(a_id) = a.res_local_id()
                     && let Some(b_id) = b.res_local_id()
                     && let entry = match local_map.entry(a_id) {
@@ -71,7 +74,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
                     }
                     // the names technically don't have to match; this makes the lint more conservative
                     && cx.tcx.hir_name(a_id) == cx.tcx.hir_name(b_id)
-                    && cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b)
+                    && a_typeck_results.expr_ty(a) == b_typeck_results.expr_ty(b)
                     && pat_contains_local(lhs.pat, a_id)
                     && pat_contains_local(rhs.pat, b_id)
                 {
diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs
index dc8c06f..717c47b 100644
--- a/src/tools/clippy/clippy_lints/src/matches/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs
@@ -1093,12 +1093,11 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                     }
 
                     redundant_pattern_match::check_match(cx, expr, ex, arms);
-                    let source_map = cx.tcx.sess.source_map();
-                    let mut match_comments = span_extract_comments(source_map, expr.span);
+                    let mut match_comments = span_extract_comments(cx, expr.span);
                     // We remove comments from inside arms block.
                     if !match_comments.is_empty() {
                         for arm in arms {
-                            for comment in span_extract_comments(source_map, arm.body.span) {
+                            for comment in span_extract_comments(cx, arm.body.span) {
                                 if let Some(index) = match_comments
                                     .iter()
                                     .enumerate()
diff --git a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
index 23a0046..2296704 100644
--- a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
@@ -7,8 +7,7 @@
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem};
 use rustc_lint::LateContext;
-use rustc_span::Span;
-use rustc_span::Spanned;
+use rustc_span::{Span, Spanned};
 
 use super::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS;
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
index 7b10c37..d2e593f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
@@ -9,6 +9,7 @@
 use rustc_hir::def::Res;
 use rustc_hir::{Closure, Expr, ExprKind, PatKind, PathSegment, QPath, UnOp};
 use rustc_lint::LateContext;
+use rustc_middle::ty::TypeckResults;
 use rustc_middle::ty::adjustment::Adjust;
 use rustc_span::Span;
 use rustc_span::symbol::{Ident, Symbol};
@@ -136,7 +137,9 @@ pub fn check_map_call(
                     // .map(|y| y[.acceptable_method()].unwrap())
                     && let simple_equal = (receiver.res_local_id() == Some(filter_param_id)
                         && map_arg_peeled.res_local_id() == Some(map_param_id))
-                    && let eq_fallback = (|a: &Expr<'_>, b: &Expr<'_>| {
+                    && let eq_fallback =
+                    (|a_typeck_results: &TypeckResults<'tcx>, a: &Expr<'_>,
+                     b_typeck_results: &TypeckResults<'tcx>, b: &Expr<'_>| {
                         // in `filter(|x| ..)`, replace `*x` with `x`
                         let a_path = if !is_filter_param_ref
                             && let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind
@@ -144,7 +147,7 @@ pub fn check_map_call(
                         // let the filter closure arg and the map closure arg be equal
                         a_path.res_local_id() == Some(filter_param_id)
                             && b.res_local_id() == Some(map_param_id)
-                            && cx.typeck_results().expr_ty_adjusted(a) == cx.typeck_results().expr_ty_adjusted(b)
+                            && a_typeck_results.expr_ty_adjusted(a) == b_typeck_results.expr_ty_adjusted(b)
                     })
                     && (simple_equal
                         || SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(receiver, map_arg_peeled))
diff --git a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
index 4577be3..cfda39e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
@@ -39,7 +39,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_
 fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool {
     cx.tcx
         .hir_parent_id_iter(id)
-        .any(|id| find_attr!(cx.tcx.hir_attrs(id), CfgTrace(..)))
+        .any(|id| find_attr!(cx.tcx, id, CfgTrace(..)))
 }
 
 /// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
index aaface3..3aa6661 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
@@ -1,7 +1,7 @@
 use clippy_utils::res::{MaybeDef, MaybeTypeckRes};
 use clippy_utils::ty::get_iterator_item_ty;
 use hir::ExprKind;
-use rustc_lint::{LateContext, LintContext};
+use rustc_lint::LateContext;
 
 use super::{ITER_FILTER_IS_OK, ITER_FILTER_IS_SOME};
 
@@ -144,7 +144,7 @@ fn expression_type(
 ) -> Option<FilterType> {
     if !cx.ty_based_def(expr).opt_parent(cx).is_diag_item(cx, sym::Iterator)
         || parent_is_map(cx, expr)
-        || span_contains_comment(cx.sess().source_map(), filter_span.with_hi(expr.span.hi()))
+        || span_contains_comment(cx, filter_span.with_hi(expr.span.hi()))
     {
         return None;
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
index e4ae14b..0973395 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
@@ -19,7 +19,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, map_
         let closure_snippet = snippet_with_applicability(cx, map_arg.span, "..", &mut applicability);
         let span = expr.span.with_lo(map_span.lo());
         // If the methods are separated with comments, we don't apply suggestion automatically.
-        if span_contains_comment(cx.tcx.sess.source_map(), span) {
+        if span_contains_comment(cx, span) {
             applicability = Applicability::Unspecified;
         }
         span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 0ed166f..b647dbd 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -134,9 +134,8 @@
 mod unnecessary_lazy_eval;
 mod unnecessary_literal_unwrap;
 mod unnecessary_map_or;
+mod unnecessary_map_or_else;
 mod unnecessary_min_or_max;
-mod unnecessary_option_map_or_else;
-mod unnecessary_result_map_or_else;
 mod unnecessary_sort_by;
 mod unnecessary_to_owned;
 mod unwrap_expect_used;
@@ -3030,7 +3029,7 @@
     ///     ptr.sub(8);
     /// }
     /// ```
-    #[clippy::version = "1.92.0"]
+    #[clippy::version = "1.94.0"]
     pub PTR_OFFSET_BY_LITERAL,
     pedantic,
     "unneeded pointer offset"
@@ -4347,6 +4346,7 @@
 }
 
 declare_clippy_lint! {
+    /// ### What it does
     /// Checks for usage of `.map_or_else()` "map closure" for `Option` type.
     ///
     /// ### Why is this bad?
@@ -5449,8 +5449,7 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                 },
                 (sym::map_or_else, [def, map]) => {
                     result_map_or_else_none::check(cx, expr, recv, def, map);
-                    unnecessary_option_map_or_else::check(cx, expr, recv, def, map);
-                    unnecessary_result_map_or_else::check(cx, expr, recv, def, map);
+                    unnecessary_map_or_else::check(cx, expr, recv, def, map, call_span);
                 },
                 (sym::next, []) => {
                     if let Some((name2, recv2, args2, _, _)) = method_call(recv) {
diff --git a/src/tools/clippy/clippy_lints/src/methods/open_options.rs b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
index 042558d..36dd4e9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/open_options.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
@@ -7,8 +7,7 @@
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::Ty;
-use rustc_span::Span;
-use rustc_span::Spanned;
+use rustc_span::{Span, Spanned};
 
 use super::{NONSENSICAL_OPEN_OPTIONS, SUSPICIOUS_OPEN_OPTIONS};
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
index 98b7834..cbb7da3 100644
--- a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
@@ -2,8 +2,7 @@
 use rustc_ast::LitKind;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
-use rustc_span::Symbol;
-use rustc_span::Spanned;
+use rustc_span::{Spanned, Symbol};
 
 use super::SUSPICIOUS_SPLITN;
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or_else.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or_else.rs
new file mode 100644
index 0000000..7c1c31d
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or_else.rs
@@ -0,0 +1,39 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::is_expr_identity_function;
+use clippy_utils::res::MaybeDef;
+use clippy_utils::source::snippet_with_applicability;
+use rustc_errors::Applicability;
+use rustc_hir::Expr;
+use rustc_lint::LateContext;
+use rustc_span::Span;
+use rustc_span::symbol::sym;
+
+use super::{UNNECESSARY_OPTION_MAP_OR_ELSE, UNNECESSARY_RESULT_MAP_OR_ELSE};
+
+/// lint use of `_.map_or_else(|err| err, |n| n)` for `Result`s and `Option`s.
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    expr: &Expr<'_>,
+    recv: &Expr<'_>,
+    def_arg: &Expr<'_>,
+    map_arg: &Expr<'_>,
+    call_span: Span,
+) {
+    let (symbol, lint) = match cx.typeck_results().expr_ty(recv).opt_diag_name(cx) {
+        Some(x @ sym::Result) => (x, UNNECESSARY_RESULT_MAP_OR_ELSE),
+        Some(x @ sym::Option) => (x, UNNECESSARY_OPTION_MAP_OR_ELSE),
+        _ => return,
+    };
+
+    if is_expr_identity_function(cx, map_arg) {
+        let msg = format!("unused \"map closure\" when calling `{symbol}::map_or_else` value");
+
+        span_lint_and_then(cx, lint, expr.span, msg, |diag| {
+            let mut applicability = Applicability::MachineApplicable;
+            let err_snippet = snippet_with_applicability(cx, def_arg.span, "..", &mut applicability);
+            let sugg = format!("unwrap_or_else({err_snippet})");
+
+            diag.span_suggestion_verbose(call_span, "consider using `unwrap_or_else`", sugg, applicability);
+        });
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_option_map_or_else.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_option_map_or_else.rs
deleted file mode 100644
index 265619e..0000000
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_option_map_or_else.rs
+++ /dev/null
@@ -1,111 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::res::MaybeDef;
-use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{expr_or_init, find_binding_init, peel_blocks};
-use rustc_errors::Applicability;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{Body, BodyId, Closure, Expr, ExprKind, HirId, QPath};
-use rustc_lint::LateContext;
-use rustc_span::symbol::sym;
-
-use super::UNNECESSARY_OPTION_MAP_OR_ELSE;
-use super::utils::get_last_chain_binding_hir_id;
-
-fn emit_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def_arg: &Expr<'_>) {
-    let msg = "unused \"map closure\" when calling `Option::map_or_else` value";
-    let mut applicability = Applicability::MachineApplicable;
-    let self_snippet = snippet_with_applicability(cx, recv.span, "_", &mut applicability);
-    let err_snippet = snippet_with_applicability(cx, def_arg.span, "..", &mut applicability);
-    span_lint_and_sugg(
-        cx,
-        UNNECESSARY_OPTION_MAP_OR_ELSE,
-        expr.span,
-        msg,
-        "consider using `unwrap_or_else`",
-        format!("{self_snippet}.unwrap_or_else({err_snippet})"),
-        Applicability::MachineApplicable,
-    );
-}
-
-fn handle_qpath(
-    cx: &LateContext<'_>,
-    expr: &Expr<'_>,
-    recv: &Expr<'_>,
-    def_arg: &Expr<'_>,
-    expected_hir_id: HirId,
-    qpath: QPath<'_>,
-) {
-    if let QPath::Resolved(_, path) = qpath
-        && let Res::Local(hir_id) = path.res
-        && expected_hir_id == hir_id
-    {
-        emit_lint(cx, expr, recv, def_arg);
-    }
-}
-
-fn handle_closure(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def_arg: &Expr<'_>, body_id: BodyId) {
-    let body = cx.tcx.hir_body(body_id);
-    handle_fn_body(cx, expr, recv, def_arg, body);
-}
-
-fn handle_fn_body(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def_arg: &Expr<'_>, body: &Body<'_>) {
-    if let Some(first_param) = body.params.first() {
-        let body_expr = peel_blocks(body.value);
-        match body_expr.kind {
-            ExprKind::Path(qpath) => {
-                handle_qpath(cx, expr, recv, def_arg, first_param.pat.hir_id, qpath);
-            },
-            // If this is a block (that wasn't peeled off), then it means there are statements.
-            ExprKind::Block(block, _) => {
-                if let Some(block_expr) = block.expr
-                        // First we ensure that this is a "binding chain" (each statement is a binding
-                        // of the previous one) and that it is a binding of the closure argument.
-                        && let Some(last_chain_binding_id) =
-                            get_last_chain_binding_hir_id(first_param.pat.hir_id, block.stmts)
-                        && let ExprKind::Path(qpath) = block_expr.kind
-                {
-                    handle_qpath(cx, expr, recv, def_arg, last_chain_binding_id, qpath);
-                }
-            },
-            _ => {},
-        }
-    }
-}
-
-/// lint use of `_.map_or_else(|err| err, |n| n)` for `Option`s.
-pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def_arg: &Expr<'_>, map_arg: &Expr<'_>) {
-    // lint if the caller of `map_or_else()` is an `Option`
-    if !cx.typeck_results().expr_ty(recv).is_diag_item(cx, sym::Option) {
-        return;
-    }
-    match map_arg.kind {
-        // If the second argument is a closure, we can check its body.
-        ExprKind::Closure(&Closure { body, .. }) => {
-            handle_closure(cx, expr, recv, def_arg, body);
-        },
-        ExprKind::Path(qpath) => {
-            let res = cx.qpath_res(&qpath, map_arg.hir_id);
-            match res {
-                // Case 1: Local variable (could be a closure)
-                Res::Local(hir_id) => {
-                    if let Some(init_expr) = find_binding_init(cx, hir_id) {
-                        let origin = expr_or_init(cx, init_expr);
-                        if let ExprKind::Closure(&Closure { body, .. }) = origin.kind {
-                            handle_closure(cx, expr, recv, def_arg, body);
-                        }
-                    }
-                },
-                // Case 2: Function definition
-                Res::Def(DefKind::Fn, def_id) => {
-                    if let Some(local_def_id) = def_id.as_local()
-                        && let Some(body) = cx.tcx.hir_maybe_body_owned_by(local_def_id)
-                    {
-                        handle_fn_body(cx, expr, recv, def_arg, body);
-                    }
-                },
-                _ => (),
-            }
-        },
-        _ => (),
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs
deleted file mode 100644
index 1f6bb60..0000000
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs
+++ /dev/null
@@ -1,80 +0,0 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::peel_blocks;
-use clippy_utils::res::MaybeDef;
-use clippy_utils::source::snippet;
-use rustc_errors::Applicability;
-use rustc_hir as hir;
-use rustc_hir::{Closure, Expr, ExprKind, HirId, QPath};
-use rustc_lint::LateContext;
-use rustc_span::symbol::sym;
-
-use super::UNNECESSARY_RESULT_MAP_OR_ELSE;
-use super::utils::get_last_chain_binding_hir_id;
-
-fn emit_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def_arg: &Expr<'_>) {
-    let msg = "unused \"map closure\" when calling `Result::map_or_else` value";
-    let self_snippet = snippet(cx, recv.span, "..");
-    let err_snippet = snippet(cx, def_arg.span, "..");
-    span_lint_and_sugg(
-        cx,
-        UNNECESSARY_RESULT_MAP_OR_ELSE,
-        expr.span,
-        msg,
-        "consider using `unwrap_or_else`",
-        format!("{self_snippet}.unwrap_or_else({err_snippet})"),
-        Applicability::MachineApplicable,
-    );
-}
-
-fn handle_qpath(
-    cx: &LateContext<'_>,
-    expr: &Expr<'_>,
-    recv: &Expr<'_>,
-    def_arg: &Expr<'_>,
-    expected_hir_id: HirId,
-    qpath: QPath<'_>,
-) {
-    if let QPath::Resolved(_, path) = qpath
-        && let hir::def::Res::Local(hir_id) = path.res
-        && expected_hir_id == hir_id
-    {
-        emit_lint(cx, expr, recv, def_arg);
-    }
-}
-
-/// lint use of `_.map_or_else(|err| err, |n| n)` for `Result`s.
-pub(super) fn check<'tcx>(
-    cx: &LateContext<'tcx>,
-    expr: &'tcx Expr<'_>,
-    recv: &'tcx Expr<'_>,
-    def_arg: &'tcx Expr<'_>,
-    map_arg: &'tcx Expr<'_>,
-) {
-    // lint if the caller of `map_or_else()` is a `Result`
-    if cx.typeck_results().expr_ty(recv).is_diag_item(cx, sym::Result)
-        && let ExprKind::Closure(&Closure { body, .. }) = map_arg.kind
-        && let body = cx.tcx.hir_body(body)
-        && let Some(first_param) = body.params.first()
-    {
-        let body_expr = peel_blocks(body.value);
-
-        match body_expr.kind {
-            ExprKind::Path(qpath) => {
-                handle_qpath(cx, expr, recv, def_arg, first_param.pat.hir_id, qpath);
-            },
-            // If this is a block (that wasn't peeled off), then it means there are statements.
-            ExprKind::Block(block, _) => {
-                if let Some(block_expr) = block.expr
-                    // First we ensure that this is a "binding chain" (each statement is a binding
-                    // of the previous one) and that it is a binding of the closure argument.
-                    && let Some(last_chain_binding_id) =
-                        get_last_chain_binding_hir_id(first_param.pat.hir_id, block.stmts)
-                    && let ExprKind::Path(qpath) = block_expr.kind
-                {
-                    handle_qpath(cx, expr, recv, def_arg, last_chain_binding_id, qpath);
-                }
-            },
-            _ => {},
-        }
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs
index 387b6f8..a0ad1fe 100644
--- a/src/tools/clippy/clippy_lints/src/needless_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs
@@ -108,7 +108,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
                 then,
                 r#else: Some(else_expr),
             }) = higher::If::hir(e)
-            && !span_contains_comment(cx.tcx.sess.source_map(), e.span)
+            && !span_contains_comment(cx, e.span)
         {
             let reduce = |ret, not| {
                 let mut applicability = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs
index 567443b..b4519d6 100644
--- a/src/tools/clippy/clippy_lints/src/operators/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs
@@ -221,7 +221,7 @@
     /// ```rust,no_run
     /// let a = 0b1110 & 0b0110;
     /// ```
-    #[clippy::version = "1.93.0"]
+    #[clippy::version = "1.94.0"]
     pub DECIMAL_BITWISE_OPERANDS,
     pedantic,
     "use binary, hex, or octal literals for bitwise operations"
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index e79ce91..dfd7834a 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -143,7 +143,7 @@ fn init_expr_can_use_question_mark(cx: &LateContext<'_>, init_expr: &Expr<'_>) -
         && init_expr_can_use_question_mark(cx, init_expr)
         && let Some(ret) = find_let_else_ret_expression(els)
         && let Some(inner_pat) = pat_and_expr_can_be_question_mark(cx, pat, ret)
-        && !span_contains_comment(cx.tcx.sess.source_map(), els.span)
+        && !span_contains_comment(cx, els.span)
         && !span_contains_cfg(cx, els.span)
     {
         let mut applicability = Applicability::MaybeIncorrect;
@@ -501,7 +501,8 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
 
         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 parent = cx.tcx.parent_hir_node(expr.hir_id);
+        let requires_semi = matches!(parent, Node::Stmt(_)) || cx.typeck_results().expr_ty(expr).is_unit();
         let method_call_str = match by_ref {
             ByRef::Yes(_, Mutability::Mut) => ".as_mut()",
             ByRef::Yes(_, Mutability::Not) => ".as_ref()",
@@ -512,7 +513,7 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
             "{receiver_str}{method_call_str}?{}",
             if requires_semi { ";" } else { "" }
         );
-        if is_else_clause(cx.tcx, expr) {
+        if is_else_clause(cx.tcx, expr) || (requires_semi && !matches!(parent, Node::Stmt(_) | Node::Block(_))) {
             sugg = format!("{{ {sugg} }}");
         }
 
diff --git a/src/tools/clippy/clippy_lints/src/same_length_and_capacity.rs b/src/tools/clippy/clippy_lints/src/same_length_and_capacity.rs
index b200fd1f..ebf649c 100644
--- a/src/tools/clippy/clippy_lints/src/same_length_and_capacity.rs
+++ b/src/tools/clippy/clippy_lints/src/same_length_and_capacity.rs
@@ -65,7 +65,7 @@
     /// // This time, leverage the previously saved capacity:
     /// let reconstructed = unsafe { Vec::from_raw_parts(ptr, len, cap) };
     /// ```
-    #[clippy::version = "1.93.0"]
+    #[clippy::version = "1.94.0"]
     pub SAME_LENGTH_AND_CAPACITY,
     pedantic,
     "`from_raw_parts` with same length and capacity"
diff --git a/src/tools/clippy/clippy_lints/src/semicolon_block.rs b/src/tools/clippy/clippy_lints/src/semicolon_block.rs
index 7c68762..e806123 100644
--- a/src/tools/clippy/clippy_lints/src/semicolon_block.rs
+++ b/src/tools/clippy/clippy_lints/src/semicolon_block.rs
@@ -170,7 +170,7 @@ fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) {
             StmtKind::Semi(Expr {
                 kind: ExprKind::Block(block, _),
                 ..
-            }) if !block.span.from_expansion() => {
+            }) if !block.span.from_expansion() && !block.targeted_by_break => {
                 let attrs = cx.tcx.hir_attrs(stmt.hir_id);
                 if !attrs.is_empty() && !cx.tcx.features().stmt_expr_attributes() {
                     return;
diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
index 8524497..c99f2e2 100644
--- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
+++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
@@ -208,7 +208,7 @@ fn emit_lint(cx: &LateContext<'_>, slow_fill: &Expr<'_>, vec_alloc: &VecAllocati
             .with_lo(vec_alloc.allocation_expr.span.source_callsite().lo());
 
         // If there is no comment in `span_to_replace`, Clippy can automatically fix the code.
-        let app = if span_contains_comment(cx.tcx.sess.source_map(), span_to_replace) {
+        let app = if span_contains_comment(cx, span_to_replace) {
             Applicability::Unspecified
         } else {
             Applicability::MachineApplicable
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
index 44e35b8..ac2d374 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
@@ -7,9 +7,8 @@
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::Span;
-use rustc_span::Spanned;
 use rustc_span::symbol::Ident;
+use rustc_span::{Span, Spanned};
 
 declare_clippy_lint! {
     /// ### What it does
diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
index 60775d1..2bf1d8b 100644
--- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -826,7 +826,9 @@ fn text_has_safety_comment(
             // Don't lint if the safety comment is part of a codeblock in a doc comment.
             // It may or may not be required, and we can't very easily check it (and we shouldn't, since
             // the safety comment isn't referring to the node we're currently checking)
-            if line.trim_start_matches("///").trim_start().starts_with("```") {
+            if let Some(doc) = line.strip_prefix("///").or_else(|| line.strip_prefix("//!"))
+                && doc.trim_start().starts_with("```")
+            {
                 in_codeblock = !in_codeblock;
             }
 
diff --git a/src/tools/clippy/clippy_lints/src/useless_vec.rs b/src/tools/clippy/clippy_lints/src/useless_vec.rs
index 28c339c..7b61222 100644
--- a/src/tools/clippy/clippy_lints/src/useless_vec.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_vec.rs
@@ -251,7 +251,7 @@ fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
                     let help_msg = format!("you can use {} directly", suggest_ty.desc());
                     // If the `vec!` macro contains comment, better not make the suggestion machine applicable as it
                     // would remove them.
-                    let applicability = if span_contains_comment(cx.tcx.sess.source_map(), span) {
+                    let applicability = if span_contains_comment(cx, span) {
                         Applicability::Unspecified
                     } else {
                         Applicability::MachineApplicable
diff --git a/src/tools/clippy/clippy_lints/src/write/empty_string.rs b/src/tools/clippy/clippy_lints/src/write/empty_string.rs
index 1291f24..fa2ad4b 100644
--- a/src/tools/clippy/clippy_lints/src/write/empty_string.rs
+++ b/src/tools/clippy/clippy_lints/src/write/empty_string.rs
@@ -22,7 +22,7 @@ pub(super) fn check(cx: &LateContext<'_>, format_args: &FormatArgs, macro_call:
             macro_call.span,
             format!("empty string literal in `{name}!`"),
             |diag| {
-                if span_extract_comments(cx.sess().source_map(), macro_call.span).is_empty() {
+                if span_extract_comments(cx, macro_call.span).is_empty() {
                     let closing_paren = cx.sess().source_map().span_extend_to_prev_char_before(
                         macro_call.span.shrink_to_hi(),
                         ')',
diff --git a/src/tools/clippy/clippy_test_deps/Cargo.lock b/src/tools/clippy/clippy_test_deps/Cargo.lock
index b22cf9d..63e41e8a 100644
--- a/src/tools/clippy/clippy_test_deps/Cargo.lock
+++ b/src/tools/clippy/clippy_test_deps/Cargo.lock
@@ -55,9 +55,9 @@
 
 [[package]]
 name = "bytes"
-version = "1.10.1"
+version = "1.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
+checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
 
 [[package]]
 name = "cfg-if"
diff --git a/src/tools/clippy/clippy_utils/README.md b/src/tools/clippy/clippy_utils/README.md
index d7e4013..b5e2e0f 100644
--- a/src/tools/clippy/clippy_utils/README.md
+++ b/src/tools/clippy/clippy_utils/README.md
@@ -8,7 +8,7 @@
 
 <!-- begin autogenerated nightly -->
 ```
-nightly-2026-03-05
+nightly-2026-03-21
 ```
 <!-- end autogenerated nightly -->
 
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
index 50cfb0e..9a463d1 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -280,7 +280,7 @@ pub fn eq_arm(l: &Arm, r: &Arm) -> bool {
     l.is_placeholder == r.is_placeholder
         && eq_pat(&l.pat, &r.pat)
         && eq_expr_opt(l.body.as_deref(), r.body.as_deref())
-        && eq_expr_opt(l.guard.as_deref(), r.guard.as_deref())
+        && eq_expr_opt(l.guard.as_deref().map(|g| &g.cond), r.guard.as_deref().map(|g| &g.cond))
         && over(&l.attrs, &r.attrs, eq_attr)
 }
 
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 1a75bdff..51db6b6 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -841,12 +841,18 @@ fn fetch_path(&self, qpath: &QPath<'_>, id: HirId) -> Option<ConstValue> {
                     && ty.span.ctxt() == self.ctxt.get()
                     && ty_name.ident.span.ctxt() == self.ctxt.get()
                     && matches!(ty_path.res, Res::PrimTy(_))
-                    && let Some((DefKind::AssocConst { .. }, did)) = self.typeck.type_dependent_def(id) =>
+                    && let Some((DefKind::AssocConst { .. }, did)) = self.typeck.type_dependent_def(id)
+                    && self.tcx.inherent_impl_of_assoc(did).is_some() =>
             {
                 did
             },
-            _ if let Res::Def(DefKind::Const { .. } | DefKind::AssocConst { .. }, did) =
-                self.typeck.qpath_res(qpath, id) =>
+            // TODO: revisit when feature `min_generic_const_args` is stabilized. In the meantime,
+            // `TyCtxt::const_eval_resolve()` will trigger an ICE when evaluating the body of the
+            // `type const` definition.
+            _ if let Res::Def(
+                DefKind::Const { is_type_const: false } | DefKind::AssocConst { is_type_const: false },
+                did,
+            ) = self.typeck.qpath_res(qpath, id) =>
             {
                 self.source.set(ConstantSource::NonLocal);
                 did
diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs
index 88dd3d9..f3c4ae3 100644
--- a/src/tools/clippy/clippy_utils/src/diagnostics.rs
+++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs
@@ -8,7 +8,7 @@
 //! Thank you!
 //! ~The `INTERNAL_METADATA_COLLECTOR` lint
 
-use rustc_errors::{Applicability, Diag, Diagnostic, DiagCtxtHandle, DiagMessage, Level, MultiSpan};
+use rustc_errors::{Applicability, Diag, DiagCtxtHandle, DiagMessage, Diagnostic, Level, MultiSpan};
 #[cfg(debug_assertions)]
 use rustc_errors::{EmissionGuarantee, SubstitutionPart, Suggestions};
 use rustc_hir::HirId;
@@ -252,15 +252,19 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
 
     let sp = sp.into();
     #[expect(clippy::disallowed_methods)]
-    cx.emit_span_lint(lint, sp.clone(), ClippyDiag(|diag: &mut Diag<'_, ()>| {
-        diag.primary_message(msg);
-        diag.span(sp);
-        f(diag);
-        docs_link(diag, lint);
+    cx.emit_span_lint(
+        lint,
+        sp.clone(),
+        ClippyDiag(|diag: &mut Diag<'_, ()>| {
+            diag.primary_message(msg);
+            diag.span(sp);
+            f(diag);
+            docs_link(diag, lint);
 
-        #[cfg(debug_assertions)]
-        validate_diag(diag);
-    }));
+            #[cfg(debug_assertions)]
+            validate_diag(diag);
+        }),
+    );
 }
 
 /// Like [`span_lint`], but emits the lint at the node identified by the given `HirId`.
@@ -326,14 +330,19 @@ pub fn span_lint_hir_and_then(
     f: impl FnOnce(&mut Diag<'_, ()>),
 ) {
     #[expect(clippy::disallowed_methods)]
-    cx.tcx.emit_node_span_lint(lint, hir_id, sp, rustc_errors::DiagDecorator(|diag| {
-        diag.primary_message(msg);
-        f(diag);
-        docs_link(diag, lint);
+    cx.tcx.emit_node_span_lint(
+        lint,
+        hir_id,
+        sp,
+        rustc_errors::DiagDecorator(|diag| {
+            diag.primary_message(msg);
+            f(diag);
+            docs_link(diag, lint);
 
-        #[cfg(debug_assertions)]
-        validate_diag(diag);
-    }));
+            #[cfg(debug_assertions)]
+            validate_diag(diag);
+        }),
+    );
 }
 
 /// Add a span lint with a suggestion on how to fix it.
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 4e9c64d..a4d8fd2 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -26,7 +26,8 @@
 
 /// Callback that is called when two expressions are not equal in the sense of `SpanlessEq`, but
 /// other conditions would make them equal.
-type SpanlessEqCallback<'a> = dyn FnMut(&Expr<'_>, &Expr<'_>) -> bool + 'a;
+type SpanlessEqCallback<'a, 'tcx> =
+    dyn FnMut(&TypeckResults<'tcx>, &Expr<'_>, &TypeckResults<'tcx>, &Expr<'_>) -> bool + 'a;
 
 /// Determines how paths are hashed and compared for equality.
 #[derive(Copy, Clone, Debug, Default)]
@@ -59,7 +60,7 @@ pub struct SpanlessEq<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
     maybe_typeck_results: Option<(&'tcx TypeckResults<'tcx>, &'tcx TypeckResults<'tcx>)>,
     allow_side_effects: bool,
-    expr_fallback: Option<Box<SpanlessEqCallback<'a>>>,
+    expr_fallback: Option<Box<SpanlessEqCallback<'a, 'tcx>>>,
     path_check: PathCheck,
 }
 
@@ -94,7 +95,10 @@ pub fn paths_by_resolution(self) -> Self {
     }
 
     #[must_use]
-    pub fn expr_fallback(self, expr_fallback: impl FnMut(&Expr<'_>, &Expr<'_>) -> bool + 'a) -> Self {
+    pub fn expr_fallback(
+        self,
+        expr_fallback: impl FnMut(&TypeckResults<'tcx>, &Expr<'_>, &TypeckResults<'tcx>, &Expr<'_>) -> bool + 'a,
+    ) -> Self {
         Self {
             expr_fallback: Some(Box::new(expr_fallback)),
             ..self
@@ -639,7 +643,15 @@ pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool {
             ) => false,
         };
         (is_eq && (!self.should_ignore(left) || !self.should_ignore(right)))
-            || self.inner.expr_fallback.as_mut().is_some_and(|f| f(left, right))
+            || self
+                .inner
+                .maybe_typeck_results
+                .is_some_and(|(left_typeck_results, right_typeck_results)| {
+                    self.inner
+                        .expr_fallback
+                        .as_mut()
+                        .is_some_and(|f| f(left_typeck_results, left, right_typeck_results, right))
+                })
     }
 
     fn eq_exprs(&mut self, left: &[Expr<'_>], right: &[Expr<'_>]) -> bool {
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 1e73e43..8f028ba 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1710,7 +1710,7 @@ pub fn has_attr(attrs: &[hir::Attribute], symbol: Symbol) -> bool {
 }
 
 pub fn has_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
-    find_attr!(cx.tcx.hir_attrs(hir_id), Repr { .. })
+    find_attr!(cx.tcx, hir_id, Repr { .. })
 }
 
 pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool {
@@ -1838,13 +1838,38 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
 /// * `|[x, y]| [x, y]`
 /// * `|Foo(bar, baz)| Foo(bar, baz)`
 /// * `|Foo { bar, baz }| Foo { bar, baz }`
+/// * `|x| { let y = x; ...; let z = y; z }`
+/// * `|x| { let y = x; ...; let z = y; return z }`
 ///
 /// Consider calling [`is_expr_untyped_identity_function`] or [`is_expr_identity_function`] instead.
-fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
+fn is_body_identity_function<'hir>(cx: &LateContext<'_>, func: &Body<'hir>) -> bool {
     let [param] = func.params else {
         return false;
     };
 
+    let mut param_pat = param.pat;
+
+    // Given a sequence of `Stmt`s of the form `let p = e` where `e` is an expr identical to the
+    // current `param_pat`, advance the current `param_pat` to `p`.
+    //
+    // Note: This is similar to `clippy_utils::get_last_chain_binding_hir_id`, but it works
+    // directly over a `Pattern` rather than a `HirId`. And it checks for compatibility via
+    // `is_expr_identity_of_pat` rather than `HirId` equality
+    let mut advance_param_pat_over_stmts = |stmts: &[Stmt<'hir>]| {
+        for stmt in stmts {
+            if let StmtKind::Let(local) = stmt.kind
+                && let Some(init) = local.init
+                && is_expr_identity_of_pat(cx, param_pat, init, true)
+            {
+                param_pat = local.pat;
+            } else {
+                return false;
+            }
+        }
+
+        true
+    };
+
     let mut expr = func.value;
     loop {
         match expr.kind {
@@ -1873,7 +1898,30 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
                     return false;
                 }
             },
-            _ => return is_expr_identity_of_pat(cx, param.pat, expr, true),
+            ExprKind::Block(
+                &Block {
+                    stmts, expr: Some(e), ..
+                },
+                _,
+            ) => {
+                if !advance_param_pat_over_stmts(stmts) {
+                    return false;
+                }
+
+                expr = e;
+            },
+            ExprKind::Block(&Block { stmts, expr: None, .. }, _) => {
+                if let Some((last_stmt, stmts)) = stmts.split_last()
+                    && advance_param_pat_over_stmts(stmts)
+                    && let StmtKind::Semi(e) | StmtKind::Expr(e) = last_stmt.kind
+                    && let ExprKind::Ret(Some(ret_val)) = e.kind
+                {
+                    expr = ret_val;
+                } else {
+                    return false;
+                }
+            },
+            _ => return is_expr_identity_of_pat(cx, param_pat, expr, true),
         }
     }
 }
@@ -2362,7 +2410,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl FnOnce(&
                     && let TyKind::Path(QPath::Resolved(_, path)) = ty.kind
                     // We could also check for the type name `test::TestDescAndFn`
                     && let Res::Def(DefKind::Struct, _) = path.res
-                    && find_attr!(tcx.hir_attrs(item.hir_id()), RustcTestMarker(..))
+                    && find_attr!(tcx, item.hir_id(), RustcTestMarker(..))
                 {
                     names.push(ident.name);
                 }
@@ -2420,7 +2468,7 @@ pub fn is_test_function(tcx: TyCtxt<'_>, fn_def_id: LocalDefId) -> bool {
 /// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent
 /// use [`is_in_cfg_test`]
 pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool {
-    if let Some(cfgs) = find_attr!(tcx.hir_attrs(id), CfgTrace(cfgs) => cfgs)
+    if let Some(cfgs) = find_attr!(tcx, id, CfgTrace(cfgs) => cfgs)
         && cfgs
             .iter()
             .any(|(cfg, _)| matches!(cfg, CfgEntry::NameValue { name: sym::test, .. }))
@@ -2762,16 +2810,15 @@ pub fn tokenize_with_text(s: &str) -> impl Iterator<Item = (TokenKind, &str, Inn
 
 /// Checks whether a given span has any comment token
 /// This checks for all types of comment: line "//", block "/**", doc "///" "//!"
-pub fn span_contains_comment(sm: &SourceMap, span: Span) -> bool {
-    let Ok(snippet) = sm.span_to_snippet(span) else {
-        return false;
-    };
-    return tokenize(&snippet, FrontmatterAllowed::No).any(|token| {
-        matches!(
-            token.kind,
-            TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }
-        )
-    });
+pub fn span_contains_comment(cx: &impl source::HasSession, span: Span) -> bool {
+    span.check_source_text(cx, |snippet| {
+        tokenize(snippet, FrontmatterAllowed::No).any(|token| {
+            matches!(
+                token.kind,
+                TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }
+            )
+        })
+    })
 }
 
 /// Checks whether a given span has any significant token. A significant token is a non-whitespace
@@ -2779,30 +2826,32 @@ pub fn span_contains_comment(sm: &SourceMap, span: Span) -> bool {
 /// This is useful to determine if there are any actual code tokens in the span that are omitted in
 /// the late pass, such as platform-specific code.
 pub fn span_contains_non_whitespace(cx: &impl source::HasSession, span: Span, skip_comments: bool) -> bool {
-    matches!(span.get_source_text(cx), Some(snippet) if tokenize_with_text(&snippet).any(|(token, _, _)|
-        match token {
+    span.check_source_text(cx, |snippet| {
+        tokenize_with_text(snippet).any(|(token, _, _)| match token {
             TokenKind::Whitespace => false,
             TokenKind::BlockComment { .. } | TokenKind::LineComment { .. } => !skip_comments,
             _ => true,
-        }
-    ))
+        })
+    })
 }
 /// Returns all the comments a given span contains
 ///
 /// Comments are returned wrapped with their relevant delimiters
-pub fn span_extract_comment(sm: &SourceMap, span: Span) -> String {
-    span_extract_comments(sm, span).join("\n")
+pub fn span_extract_comment(cx: &impl source::HasSession, span: Span) -> String {
+    span_extract_comments(cx, span).join("\n")
 }
 
 /// Returns all the comments a given span contains.
 ///
 /// Comments are returned wrapped with their relevant delimiters.
-pub fn span_extract_comments(sm: &SourceMap, span: Span) -> Vec<String> {
-    let snippet = sm.span_to_snippet(span).unwrap_or_default();
-    tokenize_with_text(&snippet)
-        .filter(|(t, ..)| matches!(t, TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }))
-        .map(|(_, s, _)| s.to_string())
-        .collect::<Vec<_>>()
+pub fn span_extract_comments(cx: &impl source::HasSession, span: Span) -> Vec<String> {
+    span.with_source_text(cx, |snippet| {
+        tokenize_with_text(snippet)
+            .filter(|(t, ..)| matches!(t, TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }))
+            .map(|(_, s, _)| s.to_string())
+            .collect::<Vec<_>>()
+    })
+    .unwrap_or_default()
 }
 
 pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs
index 5aa457b..ecadc33 100644
--- a/src/tools/clippy/clippy_utils/src/msrvs.rs
+++ b/src/tools/clippy/clippy_utils/src/msrvs.rs
@@ -23,9 +23,11 @@ macro_rules! msrv_aliases {
 
 // names may refer to stabilized feature flags or library items
 msrv_aliases! {
+    1,93,0 { VEC_DEQUE_POP_BACK_IF, VEC_DEQUE_POP_FRONT_IF }
     1,91,0 { DURATION_FROM_MINUTES_HOURS }
     1,88,0 { LET_CHAINS }
     1,87,0 { OS_STR_DISPLAY, INT_MIDPOINT, CONST_CHAR_IS_DIGIT, UNSIGNED_IS_MULTIPLE_OF, INTEGER_SIGN_CAST }
+    1,86,0 { VEC_POP_IF }
     1,85,0 { UINT_FLOAT_MIDPOINT, CONST_SIZE_OF_VAL }
     1,84,0 { CONST_OPTION_AS_SLICE, MANUAL_DANGLING_PTR }
     1,83,0 { CONST_EXTERN_FN, CONST_FLOAT_BITS_CONV, CONST_FLOAT_CLASSIFY, CONST_MUT_REFS, CONST_UNWRAP }
diff --git a/src/tools/clippy/clippy_utils/src/sym.rs b/src/tools/clippy/clippy_utils/src/sym.rs
index d6ba678..bb67e43 100644
--- a/src/tools/clippy/clippy_utils/src/sym.rs
+++ b/src/tools/clippy/clippy_utils/src/sym.rs
@@ -140,6 +140,7 @@ macro_rules! generate {
     as_str,
     assert_failed,
     author,
+    back,
     binaryheap_iter,
     bool_then,
     borrow,
@@ -295,6 +296,7 @@ macro_rules! generate {
     from_str_method,
     from_str_radix,
     from_weeks,
+    front,
     fs,
     fs_create_dir,
     fuse,
@@ -464,6 +466,12 @@ macro_rules! generate {
     peekable,
     permissions_from_mode,
     pin_macro,
+    pop,
+    pop_back,
+    pop_back_if,
+    pop_front,
+    pop_front_if,
+    pop_if,
     position,
     pow,
     powf,
diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs
index af51477..1ac417a 100644
--- a/src/tools/clippy/clippy_utils/src/ty/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs
@@ -29,8 +29,7 @@
 use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
 use rustc_trait_selection::traits::{Obligation, ObligationCause};
 use std::collections::hash_map::Entry;
-use std::debug_assert_matches;
-use std::{iter, mem};
+use std::{debug_assert_matches, iter, mem};
 
 use crate::paths::{PathNS, lookup_path_str};
 use crate::res::{MaybeDef, MaybeQPath};
diff --git a/src/tools/clippy/rust-toolchain.toml b/src/tools/clippy/rust-toolchain.toml
index c9bb94c..1f8bcde 100644
--- a/src/tools/clippy/rust-toolchain.toml
+++ b/src/tools/clippy/rust-toolchain.toml
@@ -1,6 +1,6 @@
 [toolchain]
 # begin autogenerated nightly
-channel = "nightly-2026-03-05"
+channel = "nightly-2026-03-21"
 # end autogenerated nightly
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
 profile = "minimal"
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 cd69a12..efb57e6 100644
--- a/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs
+++ b/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs
@@ -12,17 +12,26 @@
 use rustc_middle::ty::TyCtxt;
 
 pub fn a(cx: impl LintContext, lint: &'static Lint, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
-    cx.span_lint(lint, span, |lint| {
+    cx.emit_span_lint(
         //~^ disallowed_methods
-        lint.primary_message(msg);
-    });
+        lint,
+        span,
+        DiagDecorator(|lint| {
+            lint.primary_message(msg);
+        }),
+    );
 }
 
 pub fn b(tcx: TyCtxt<'_>, lint: &'static Lint, hir_id: HirId, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
-    tcx.emit_node_span_lint(lint, hir_id, span, DiagDecorator(|lint| {
+    tcx.emit_node_span_lint(
         //~^ disallowed_methods
-        lint.primary_message(msg);
-    }));
+        lint,
+        hir_id,
+        span,
+        DiagDecorator(|lint| {
+            lint.primary_message(msg);
+        }),
+    );
 }
 
 fn main() {}
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 e9d53c6..8631ddb 100644
--- a/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
+++ b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
@@ -1,8 +1,8 @@
-error: use of a disallowed method `rustc_lint::context::LintContext::span_lint`
+error: use of a disallowed method `rustc_lint::context::LintContext::emit_span_lint`
   --> tests/ui-internal/disallow_span_lint.rs:15:8
    |
-LL |     cx.span_lint(lint, span, |lint| {
-   |        ^^^^^^^^^
+LL |     cx.emit_span_lint(
+   |        ^^^^^^^^^^^^^^
    |
    = note: this function does not add a link to our documentation; please use the `clippy_utils::diagnostics::span_lint*` functions instead
 note: the lint level is defined here
@@ -11,11 +11,11 @@
 LL | #![deny(clippy::disallowed_methods)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::node_span_lint`
-  --> tests/ui-internal/disallow_span_lint.rs:22:9
+error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::emit_node_span_lint`
+  --> tests/ui-internal/disallow_span_lint.rs:26:9
    |
-LL |     tcx.node_span_lint(lint, hir_id, span, |lint| {
-   |         ^^^^^^^^^^^^^^
+LL |     tcx.emit_node_span_lint(
+   |         ^^^^^^^^^^^^^^^^^^^
    |
    = note: this function does not add a link to our documentation; please use the `clippy_utils::diagnostics::span_lint_hir*` functions instead
 
diff --git a/src/tools/clippy/tests/ui/crashes/mgca-16691.rs b/src/tools/clippy/tests/ui/crashes/mgca-16691.rs
new file mode 100644
index 0000000..b703924
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/mgca-16691.rs
@@ -0,0 +1,16 @@
+//@ check-pass
+#![allow(incomplete_features)]
+#![feature(min_generic_const_args)]
+
+trait Trait {
+    type const N: usize;
+    fn process();
+}
+
+impl Trait for () {
+    type const N: usize = 3;
+    fn process() {
+        const N: usize = <()>::N;
+        _ = 0..Self::N;
+    }
+}
diff --git a/src/tools/clippy/tests/ui/eta.fixed b/src/tools/clippy/tests/ui/eta.fixed
index 41e5bbe..36300aa 100644
--- a/src/tools/clippy/tests/ui/eta.fixed
+++ b/src/tools/clippy/tests/ui/eta.fixed
@@ -13,7 +13,8 @@
     clippy::uninlined_format_args,
     clippy::useless_vec,
     clippy::unnecessary_map_on_constructor,
-    clippy::needless_lifetimes
+    clippy::needless_lifetimes,
+    clippy::unnecessary_option_map_or_else
 )]
 
 use std::path::{Path, PathBuf};
diff --git a/src/tools/clippy/tests/ui/eta.rs b/src/tools/clippy/tests/ui/eta.rs
index de0d3fb..63b4418 100644
--- a/src/tools/clippy/tests/ui/eta.rs
+++ b/src/tools/clippy/tests/ui/eta.rs
@@ -13,7 +13,8 @@
     clippy::uninlined_format_args,
     clippy::useless_vec,
     clippy::unnecessary_map_on_constructor,
-    clippy::needless_lifetimes
+    clippy::needless_lifetimes,
+    clippy::unnecessary_option_map_or_else
 )]
 
 use std::path::{Path, PathBuf};
diff --git a/src/tools/clippy/tests/ui/eta.stderr b/src/tools/clippy/tests/ui/eta.stderr
index c19947c..b570389 100644
--- a/src/tools/clippy/tests/ui/eta.stderr
+++ b/src/tools/clippy/tests/ui/eta.stderr
@@ -1,5 +1,5 @@
 error: redundant closure
-  --> tests/ui/eta.rs:34:27
+  --> tests/ui/eta.rs:35:27
    |
 LL |     let a = Some(1u8).map(|a| foo(a));
    |                           ^^^^^^^^^^ help: replace the closure with the function itself: `foo`
@@ -8,31 +8,31 @@
    = help: to override `-D warnings` add `#[allow(clippy::redundant_closure)]`
 
 error: redundant closure
-  --> tests/ui/eta.rs:39:40
+  --> tests/ui/eta.rs:40:40
    |
 LL |     let _: Option<Vec<u8>> = true.then(|| vec![]); // special case vec!
    |                                        ^^^^^^^^^ help: replace the closure with `Vec::new`: `std::vec::Vec::new`
 
 error: redundant closure
-  --> tests/ui/eta.rs:42:35
+  --> tests/ui/eta.rs:43:35
    |
 LL |     let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted?
    |                                   ^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo2`
 
 error: redundant closure
-  --> tests/ui/eta.rs:45:26
+  --> tests/ui/eta.rs:46:26
    |
 LL |     all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted
    |                          ^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `below`
 
 error: redundant closure
-  --> tests/ui/eta.rs:54:27
+  --> tests/ui/eta.rs:55:27
    |
 LL |     let e = Some(1u8).map(|a| generic(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic`
 
 error: redundant closure
-  --> tests/ui/eta.rs:107:51
+  --> tests/ui/eta.rs:108:51
    |
 LL |     let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo());
    |                                                   ^^^^^^^^^^^ help: replace the closure with the method itself: `TestStruct::foo`
@@ -41,229 +41,229 @@
    = help: to override `-D warnings` add `#[allow(clippy::redundant_closure_for_method_calls)]`
 
 error: redundant closure
-  --> tests/ui/eta.rs:109:51
+  --> tests/ui/eta.rs:110:51
    |
 LL |     let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo());
    |                                                   ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `TestTrait::trait_foo`
 
 error: redundant closure
-  --> tests/ui/eta.rs:112:42
+  --> tests/ui/eta.rs:113:42
    |
 LL |     let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear());
    |                                          ^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::vec::Vec::clear`
 
 error: redundant closure
-  --> tests/ui/eta.rs:117:29
+  --> tests/ui/eta.rs:118:29
    |
 LL |     let e = Some("str").map(|s| s.to_string());
    |                             ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::string::ToString::to_string`
 
 error: redundant closure
-  --> tests/ui/eta.rs:119:27
+  --> tests/ui/eta.rs:120:27
    |
 LL |     let e = Some('a').map(|s| s.to_uppercase());
    |                           ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_uppercase`
 
 error: redundant closure
-  --> tests/ui/eta.rs:122:65
+  --> tests/ui/eta.rs:123:65
    |
 LL |     let e: std::vec::Vec<char> = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect();
    |                                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_ascii_uppercase`
 
 error: redundant closure
-  --> tests/ui/eta.rs:139:23
+  --> tests/ui/eta.rs:140:23
    |
 LL |         let _ = x.map(|x| x.parse::<i16>());
    |                       ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `str::parse::<i16>`
 
 error: redundant closure
-  --> tests/ui/eta.rs:192:22
+  --> tests/ui/eta.rs:193:22
    |
 LL |     requires_fn_once(|| x());
    |                      ^^^^^^ help: replace the closure with the function itself: `x`
 
 error: redundant closure
-  --> tests/ui/eta.rs:200:27
+  --> tests/ui/eta.rs:201:27
    |
 LL |     let a = Some(1u8).map(|a| foo_ptr(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr`
 
 error: redundant closure
-  --> tests/ui/eta.rs:206:27
+  --> tests/ui/eta.rs:207:27
    |
 LL |     let a = Some(1u8).map(|a| closure(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure`
 
 error: redundant closure
-  --> tests/ui/eta.rs:239:28
+  --> tests/ui/eta.rs:240:28
    |
 LL |     x.into_iter().for_each(|x| add_to_res(x));
    |                            ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res`
 
 error: redundant closure
-  --> tests/ui/eta.rs:241:28
+  --> tests/ui/eta.rs:242:28
    |
 LL |     y.into_iter().for_each(|x| add_to_res(x));
    |                            ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res`
 
 error: redundant closure
-  --> tests/ui/eta.rs:243:28
+  --> tests/ui/eta.rs:244:28
    |
 LL |     z.into_iter().for_each(|x| add_to_res(x));
    |                            ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `add_to_res`
 
 error: redundant closure
-  --> tests/ui/eta.rs:251:21
+  --> tests/ui/eta.rs:252:21
    |
 LL |         Some(1).map(|n| closure(n));
    |                     ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut closure`
 
 error: redundant closure
-  --> tests/ui/eta.rs:256:21
+  --> tests/ui/eta.rs:257:21
    |
 LL |         Some(1).map(|n| in_loop(n));
    |                     ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `in_loop`
 
 error: redundant closure
-  --> tests/ui/eta.rs:350:18
+  --> tests/ui/eta.rs:351:18
    |
 LL |     takes_fn_mut(|| f());
    |                  ^^^^^^ help: replace the closure with the function itself: `&mut f`
 
 error: redundant closure
-  --> tests/ui/eta.rs:354:19
+  --> tests/ui/eta.rs:355:19
    |
 LL |     takes_fn_once(|| f());
    |                   ^^^^^^ help: replace the closure with the function itself: `&mut f`
 
 error: redundant closure
-  --> tests/ui/eta.rs:359:26
+  --> tests/ui/eta.rs:360:26
    |
 LL |     move || takes_fn_mut(|| f_used_once())
    |                          ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut f_used_once`
 
 error: redundant closure
-  --> tests/ui/eta.rs:372:19
+  --> tests/ui/eta.rs:373:19
    |
 LL |     array_opt.map(|a| a.as_slice());
    |                   ^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8; 3]>::as_slice`
 
 error: redundant closure
-  --> tests/ui/eta.rs:376:19
+  --> tests/ui/eta.rs:377:19
    |
 LL |     slice_opt.map(|s| s.len());
    |                   ^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8]>::len`
 
 error: redundant closure
-  --> tests/ui/eta.rs:380:17
+  --> tests/ui/eta.rs:381:17
    |
 LL |     ptr_opt.map(|p| p.is_null());
    |                 ^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<*const usize>::is_null`
 
 error: redundant closure
-  --> tests/ui/eta.rs:385:17
+  --> tests/ui/eta.rs:386:17
    |
 LL |     dyn_opt.map(|d| d.method_on_dyn());
    |                 ^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<dyn TestTrait>::method_on_dyn`
 
 error: redundant closure
-  --> tests/ui/eta.rs:446:19
+  --> tests/ui/eta.rs:447:19
    |
 LL |     let _ = f(&0, |x, y| f2(x, y));
    |                   ^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `f2`
 
 error: redundant closure
-  --> tests/ui/eta.rs:475:22
+  --> tests/ui/eta.rs:476:22
    |
 LL |             test.map(|t| t.method())
    |                      ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `Test::method`
 
 error: redundant closure
-  --> tests/ui/eta.rs:480:22
+  --> tests/ui/eta.rs:481:22
    |
 LL |             test.map(|t| t.method())
    |                      ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `super::Outer::method`
 
 error: redundant closure
-  --> tests/ui/eta.rs:494:18
+  --> tests/ui/eta.rs:495:18
    |
 LL |         test.map(|t| t.method())
    |                  ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `test_mod::Test::method`
 
 error: redundant closure
-  --> tests/ui/eta.rs:502:30
+  --> tests/ui/eta.rs:503:30
    |
 LL |                     test.map(|t| t.method())
    |                              ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `crate::issue_10854::d::Test::method`
 
 error: redundant closure
-  --> tests/ui/eta.rs:522:38
+  --> tests/ui/eta.rs:523:38
    |
 LL |         let x = Box::new(|| None.map(|x| f(x)));
    |                                      ^^^^^^^^ help: replace the closure with the function itself: `&f`
 
 error: redundant closure
-  --> tests/ui/eta.rs:527:38
+  --> tests/ui/eta.rs:528:38
    |
 LL |         let x = Box::new(|| None.map(|x| f(x)));
    |                                      ^^^^^^^^ help: replace the closure with the function itself: `f`
 
 error: redundant closure
-  --> tests/ui/eta.rs:545:35
+  --> tests/ui/eta.rs:546:35
    |
 LL |         let _field = bind.or_else(|| get_default()).unwrap();
    |                                   ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `get_default`
 
 error: redundant closure
-  --> tests/ui/eta.rs:592:16
+  --> tests/ui/eta.rs:593:16
    |
 LL |     accepts_fn(|| f());
    |                ^^^^^^ help: replace the closure with the function itself: `**f`
 
 error: redundant closure
-  --> tests/ui/eta.rs:596:16
+  --> tests/ui/eta.rs:597:16
    |
 LL |     accepts_fn(|| g());
    |                ^^^^^^ help: replace the closure with the function itself: `g`
 
 error: redundant closure
-  --> tests/ui/eta.rs:609:16
+  --> tests/ui/eta.rs:610:16
    |
 LL |     accepts_fn(|| b());
    |                ^^^^^^ help: replace the closure with the function itself: `***b`
 
 error: redundant closure
-  --> tests/ui/eta.rs:633:14
+  --> tests/ui/eta.rs:634:14
    |
 LL |         .map(|n| MyError::A(n))
    |              ^^^^^^^^^^^^^^^^^ help: replace the closure with the tuple variant itself: `MyError::A`
 
 error: redundant closure
-  --> tests/ui/eta.rs:630:14
+  --> tests/ui/eta.rs:631:14
    |
 LL |         .map(|n| S(n))
    |              ^^^^^^^^ help: replace the closure with the tuple struct itself: `S`
 
 error: redundant closure
-  --> tests/ui/eta.rs:627:14
+  --> tests/ui/eta.rs:628:14
    |
 LL |         .map(|n| g(n))
    |              ^^^^^^^^ help: replace the closure with the function itself: `g`
 
 error: redundant closure
-  --> tests/ui/eta.rs:624:14
+  --> tests/ui/eta.rs:625:14
    |
 LL |         .map(|n| f(n))
    |              ^^^^^^^^ help: replace the closure with the function itself: `f`
 
 error: redundant closure
-  --> tests/ui/eta.rs:651:31
+  --> tests/ui/eta.rs:652:31
    |
 LL |         array.iter().for_each(|item| item.method());
    |                               ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `Self::method`
 
 error: redundant closure
-  --> tests/ui/eta.rs:661:38
+  --> tests/ui/eta.rs:662:38
    |
 LL |     (0..10).flat_map(|x| (0..10).map(|y| closure(y))).count();
    |                                      ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&*closure`
diff --git a/src/tools/clippy/tests/ui/manual_pop_if.fixed b/src/tools/clippy/tests/ui/manual_pop_if.fixed
new file mode 100644
index 0000000..6e30786
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_pop_if.fixed
@@ -0,0 +1,247 @@
+#![warn(clippy::manual_pop_if)]
+#![allow(clippy::collapsible_if, clippy::redundant_closure)]
+
+use std::collections::VecDeque;
+use std::marker::PhantomData;
+
+// FakeVec has the same methods as Vec but isn't actually a Vec
+struct FakeVec<T>(PhantomData<T>);
+
+impl<T> FakeVec<T> {
+    fn last(&self) -> Option<&T> {
+        None
+    }
+
+    fn pop(&mut self) -> Option<T> {
+        None
+    }
+}
+
+fn is_some_and_pattern_positive(mut vec: Vec<i32>, mut deque: VecDeque<i32>) {
+    vec.pop_if(|x| *x > 2);
+
+    vec.pop_if(|x| *x > 2);
+
+    deque.pop_back_if(|x| *x > 2);
+
+    deque.pop_front_if(|x| *x > 2);
+}
+
+fn is_some_and_pattern_negative(mut vec: Vec<i32>, mut deque: VecDeque<i32>) {
+    // Do not lint, different vectors
+    let mut vec2 = vec![0];
+    if vec.last().is_some_and(|x| *x > 2) {
+        vec2.pop().unwrap();
+    }
+
+    // Do not lint, non-Vec type
+    let mut fake_vec: FakeVec<i32> = FakeVec(PhantomData);
+    if fake_vec.last().is_some_and(|x| *x > 2) {
+        fake_vec.pop().unwrap();
+    }
+
+    // Do not lint, else-if branch
+    if false {
+        // something
+    } else if vec.last().is_some_and(|x| *x > 2) {
+        vec.pop().unwrap();
+    }
+
+    // Do not lint, value used in let binding
+    if vec.last().is_some_and(|x| *x > 2) {
+        let _value = vec.pop().unwrap();
+        println!("Popped: {}", _value);
+    }
+
+    // Do not lint, value used in expression
+    if vec.last().is_some_and(|x| *x > 2) {
+        println!("Popped: {}", vec.pop().unwrap());
+    }
+
+    // Do not lint, else block
+    let _result = if vec.last().is_some_and(|x| *x > 2) {
+        vec.pop().unwrap()
+    } else {
+        0
+    };
+}
+
+fn if_let_pattern_positive(mut vec: Vec<i32>, mut deque: VecDeque<i32>) {
+    vec.pop_if(|x| *x > 2);
+
+    vec.pop_if(|x| *x > 2);
+
+    deque.pop_back_if(|x| *x > 2);
+
+    deque.pop_front_if(|x| *x > 2);
+}
+
+fn if_let_pattern_negative(mut vec: Vec<i32>) {
+    // Do not lint, different vectors
+    let mut vec2 = vec![0];
+    if let Some(x) = vec.last() {
+        if *x > 2 {
+            vec2.pop().unwrap();
+        }
+    }
+
+    // Do not lint, intervening statements
+    if let Some(x) = vec.last() {
+        println!("Checking {}", x);
+        if *x > 2 {
+            vec.pop().unwrap();
+        }
+    }
+
+    // Do not lint, bound variable not used in condition
+    if let Some(_x) = vec.last() {
+        if vec.len() > 2 {
+            vec.pop().unwrap();
+        }
+    }
+
+    // Do not lint, value used in let binding
+    if let Some(x) = vec.last() {
+        if *x > 2 {
+            let _val = vec.pop().unwrap();
+        }
+    }
+
+    // Do not lint, else block
+    let _result = if let Some(x) = vec.last() {
+        if *x > 2 { vec.pop().unwrap() } else { 0 }
+    } else {
+        0
+    };
+}
+
+fn let_chain_pattern_positive(mut vec: Vec<i32>, mut deque: VecDeque<i32>) {
+    vec.pop_if(|x| *x > 2);
+
+    vec.pop_if(|x| *x > 2);
+
+    deque.pop_back_if(|x| *x > 2);
+
+    deque.pop_front_if(|x| *x > 2);
+}
+
+fn let_chain_pattern_negative(mut vec: Vec<i32>) {
+    // Do not lint, different vectors
+    let mut vec2 = vec![0];
+    if let Some(x) = vec.last()
+        && *x > 2
+    {
+        vec2.pop().unwrap();
+    }
+
+    // Do not lint, bound variable not used in condition
+    if let Some(_x) = vec.last()
+        && vec.len() > 2
+    {
+        vec.pop().unwrap();
+    }
+
+    // Do not lint, value used in let binding
+    if let Some(x) = vec.last()
+        && *x > 2
+    {
+        let _val = vec.pop().unwrap();
+    }
+
+    // Do not lint, value used in expression
+    if let Some(x) = vec.last()
+        && *x > 2
+    {
+        println!("Popped: {}", vec.pop().unwrap());
+    }
+
+    // Do not lint, else block
+    let _result = if let Some(x) = vec.last()
+        && *x > 2
+    {
+        vec.pop().unwrap()
+    } else {
+        0
+    };
+}
+
+fn map_unwrap_or_pattern_positive(mut vec: Vec<i32>, mut deque: VecDeque<i32>) {
+    vec.pop_if(|x| *x > 2);
+
+    vec.pop_if(|x| *x > 2);
+
+    deque.pop_back_if(|x| *x > 2);
+
+    deque.pop_front_if(|x| *x > 2);
+}
+
+fn map_unwrap_or_pattern_negative(mut vec: Vec<i32>) {
+    // Do not lint, unwrap_or(true) instead of false
+    if vec.last().map(|x| *x > 2).unwrap_or(true) {
+        vec.pop().unwrap();
+    }
+
+    // Do not lint, different vectors
+    let mut vec2 = vec![0];
+    if vec.last().map(|x| *x > 2).unwrap_or(false) {
+        vec2.pop().unwrap();
+    }
+
+    // Do not lint, non-Vec type
+    let mut fake_vec: FakeVec<i32> = FakeVec(PhantomData);
+    if fake_vec.last().map(|x| *x > 2).unwrap_or(false) {
+        fake_vec.pop().unwrap();
+    }
+
+    // Do not lint, map returns non-boolean
+    if vec.last().map(|x| x + 1).unwrap_or(0) > 2 {
+        vec.pop().unwrap();
+    }
+
+    // Do not lint, value used in let binding
+    if vec.last().map(|x| *x > 2).unwrap_or(false) {
+        let _val = vec.pop().unwrap();
+    }
+
+    // Do not lint, else block
+    let _result = if vec.last().map(|x| *x > 2).unwrap_or(false) {
+        vec.pop().unwrap()
+    } else {
+        0
+    };
+}
+
+// this makes sure we do not expand vec![] in the suggestion
+fn handle_macro_in_closure(mut vec: Vec<Vec<i32>>) {
+    vec.pop_if(|e| *e == vec![1]);
+}
+
+#[clippy::msrv = "1.85.0"]
+fn msrv_too_low_vec(mut vec: Vec<i32>) {
+    if vec.last().is_some_and(|x| *x > 2) {
+        vec.pop().unwrap();
+    }
+}
+
+#[clippy::msrv = "1.92.0"]
+fn msrv_too_low_vecdeque(mut deque: VecDeque<i32>) {
+    if deque.back().is_some_and(|x| *x > 2) {
+        deque.pop_back().unwrap();
+    }
+
+    if deque.front().is_some_and(|x| *x > 2) {
+        deque.pop_front().unwrap();
+    }
+}
+
+#[clippy::msrv = "1.86.0"]
+fn msrv_high_enough_vec(mut vec: Vec<i32>) {
+    vec.pop_if(|x| *x > 2);
+}
+
+#[clippy::msrv = "1.93.0"]
+fn msrv_high_enough_vecdeque(mut deque: VecDeque<i32>) {
+    deque.pop_back_if(|x| *x > 2);
+
+    deque.pop_front_if(|x| *x > 2);
+}
diff --git a/src/tools/clippy/tests/ui/manual_pop_if.rs b/src/tools/clippy/tests/ui/manual_pop_if.rs
new file mode 100644
index 0000000..a2f679d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_pop_if.rs
@@ -0,0 +1,319 @@
+#![warn(clippy::manual_pop_if)]
+#![allow(clippy::collapsible_if, clippy::redundant_closure)]
+
+use std::collections::VecDeque;
+use std::marker::PhantomData;
+
+// FakeVec has the same methods as Vec but isn't actually a Vec
+struct FakeVec<T>(PhantomData<T>);
+
+impl<T> FakeVec<T> {
+    fn last(&self) -> Option<&T> {
+        None
+    }
+
+    fn pop(&mut self) -> Option<T> {
+        None
+    }
+}
+
+fn is_some_and_pattern_positive(mut vec: Vec<i32>, mut deque: VecDeque<i32>) {
+    if vec.last().is_some_and(|x| *x > 2) {
+        //~^ manual_pop_if
+        vec.pop().unwrap();
+    }
+
+    if vec.last().is_some_and(|x| *x > 2) {
+        //~^ manual_pop_if
+        vec.pop().expect("element");
+    }
+
+    if deque.back().is_some_and(|x| *x > 2) {
+        //~^ manual_pop_if
+        deque.pop_back().unwrap();
+    }
+
+    if deque.front().is_some_and(|x| *x > 2) {
+        //~^ manual_pop_if
+        deque.pop_front().unwrap();
+    }
+}
+
+fn is_some_and_pattern_negative(mut vec: Vec<i32>, mut deque: VecDeque<i32>) {
+    // Do not lint, different vectors
+    let mut vec2 = vec![0];
+    if vec.last().is_some_and(|x| *x > 2) {
+        vec2.pop().unwrap();
+    }
+
+    // Do not lint, non-Vec type
+    let mut fake_vec: FakeVec<i32> = FakeVec(PhantomData);
+    if fake_vec.last().is_some_and(|x| *x > 2) {
+        fake_vec.pop().unwrap();
+    }
+
+    // Do not lint, else-if branch
+    if false {
+        // something
+    } else if vec.last().is_some_and(|x| *x > 2) {
+        vec.pop().unwrap();
+    }
+
+    // Do not lint, value used in let binding
+    if vec.last().is_some_and(|x| *x > 2) {
+        let _value = vec.pop().unwrap();
+        println!("Popped: {}", _value);
+    }
+
+    // Do not lint, value used in expression
+    if vec.last().is_some_and(|x| *x > 2) {
+        println!("Popped: {}", vec.pop().unwrap());
+    }
+
+    // Do not lint, else block
+    let _result = if vec.last().is_some_and(|x| *x > 2) {
+        vec.pop().unwrap()
+    } else {
+        0
+    };
+}
+
+fn if_let_pattern_positive(mut vec: Vec<i32>, mut deque: VecDeque<i32>) {
+    if let Some(x) = vec.last() {
+        //~^ manual_pop_if
+        if *x > 2 {
+            vec.pop().unwrap();
+        }
+    }
+
+    if let Some(x) = vec.last() {
+        //~^ manual_pop_if
+        if *x > 2 {
+            vec.pop().expect("element");
+        }
+    }
+
+    if let Some(x) = deque.back() {
+        //~^ manual_pop_if
+        if *x > 2 {
+            deque.pop_back().unwrap();
+        }
+    }
+
+    if let Some(x) = deque.front() {
+        //~^ manual_pop_if
+        if *x > 2 {
+            deque.pop_front().unwrap();
+        }
+    }
+}
+
+fn if_let_pattern_negative(mut vec: Vec<i32>) {
+    // Do not lint, different vectors
+    let mut vec2 = vec![0];
+    if let Some(x) = vec.last() {
+        if *x > 2 {
+            vec2.pop().unwrap();
+        }
+    }
+
+    // Do not lint, intervening statements
+    if let Some(x) = vec.last() {
+        println!("Checking {}", x);
+        if *x > 2 {
+            vec.pop().unwrap();
+        }
+    }
+
+    // Do not lint, bound variable not used in condition
+    if let Some(_x) = vec.last() {
+        if vec.len() > 2 {
+            vec.pop().unwrap();
+        }
+    }
+
+    // Do not lint, value used in let binding
+    if let Some(x) = vec.last() {
+        if *x > 2 {
+            let _val = vec.pop().unwrap();
+        }
+    }
+
+    // Do not lint, else block
+    let _result = if let Some(x) = vec.last() {
+        if *x > 2 { vec.pop().unwrap() } else { 0 }
+    } else {
+        0
+    };
+}
+
+fn let_chain_pattern_positive(mut vec: Vec<i32>, mut deque: VecDeque<i32>) {
+    if let Some(x) = vec.last() //~ manual_pop_if
+        && *x > 2
+    {
+        vec.pop().unwrap();
+    }
+
+    if let Some(x) = vec.last() //~ manual_pop_if
+        && *x > 2
+    {
+        vec.pop().expect("element");
+    }
+
+    if let Some(x) = deque.back() //~ manual_pop_if
+        && *x > 2
+    {
+        deque.pop_back().unwrap();
+    }
+
+    if let Some(x) = deque.front() //~ manual_pop_if
+        && *x > 2
+    {
+        deque.pop_front().unwrap();
+    }
+}
+
+fn let_chain_pattern_negative(mut vec: Vec<i32>) {
+    // Do not lint, different vectors
+    let mut vec2 = vec![0];
+    if let Some(x) = vec.last()
+        && *x > 2
+    {
+        vec2.pop().unwrap();
+    }
+
+    // Do not lint, bound variable not used in condition
+    if let Some(_x) = vec.last()
+        && vec.len() > 2
+    {
+        vec.pop().unwrap();
+    }
+
+    // Do not lint, value used in let binding
+    if let Some(x) = vec.last()
+        && *x > 2
+    {
+        let _val = vec.pop().unwrap();
+    }
+
+    // Do not lint, value used in expression
+    if let Some(x) = vec.last()
+        && *x > 2
+    {
+        println!("Popped: {}", vec.pop().unwrap());
+    }
+
+    // Do not lint, else block
+    let _result = if let Some(x) = vec.last()
+        && *x > 2
+    {
+        vec.pop().unwrap()
+    } else {
+        0
+    };
+}
+
+fn map_unwrap_or_pattern_positive(mut vec: Vec<i32>, mut deque: VecDeque<i32>) {
+    if vec.last().map(|x| *x > 2).unwrap_or(false) {
+        //~^ manual_pop_if
+        vec.pop().unwrap();
+    }
+
+    if vec.last().map(|x| *x > 2).unwrap_or(false) {
+        //~^ manual_pop_if
+        vec.pop().expect("element");
+    }
+
+    if deque.back().map(|x| *x > 2).unwrap_or(false) {
+        //~^ manual_pop_if
+        deque.pop_back().unwrap();
+    }
+
+    if deque.front().map(|x| *x > 2).unwrap_or(false) {
+        //~^ manual_pop_if
+        deque.pop_front().unwrap();
+    }
+}
+
+fn map_unwrap_or_pattern_negative(mut vec: Vec<i32>) {
+    // Do not lint, unwrap_or(true) instead of false
+    if vec.last().map(|x| *x > 2).unwrap_or(true) {
+        vec.pop().unwrap();
+    }
+
+    // Do not lint, different vectors
+    let mut vec2 = vec![0];
+    if vec.last().map(|x| *x > 2).unwrap_or(false) {
+        vec2.pop().unwrap();
+    }
+
+    // Do not lint, non-Vec type
+    let mut fake_vec: FakeVec<i32> = FakeVec(PhantomData);
+    if fake_vec.last().map(|x| *x > 2).unwrap_or(false) {
+        fake_vec.pop().unwrap();
+    }
+
+    // Do not lint, map returns non-boolean
+    if vec.last().map(|x| x + 1).unwrap_or(0) > 2 {
+        vec.pop().unwrap();
+    }
+
+    // Do not lint, value used in let binding
+    if vec.last().map(|x| *x > 2).unwrap_or(false) {
+        let _val = vec.pop().unwrap();
+    }
+
+    // Do not lint, else block
+    let _result = if vec.last().map(|x| *x > 2).unwrap_or(false) {
+        vec.pop().unwrap()
+    } else {
+        0
+    };
+}
+
+// this makes sure we do not expand vec![] in the suggestion
+fn handle_macro_in_closure(mut vec: Vec<Vec<i32>>) {
+    if vec.last().is_some_and(|e| *e == vec![1]) {
+        //~^ manual_pop_if
+        vec.pop().unwrap();
+    }
+}
+
+#[clippy::msrv = "1.85.0"]
+fn msrv_too_low_vec(mut vec: Vec<i32>) {
+    if vec.last().is_some_and(|x| *x > 2) {
+        vec.pop().unwrap();
+    }
+}
+
+#[clippy::msrv = "1.92.0"]
+fn msrv_too_low_vecdeque(mut deque: VecDeque<i32>) {
+    if deque.back().is_some_and(|x| *x > 2) {
+        deque.pop_back().unwrap();
+    }
+
+    if deque.front().is_some_and(|x| *x > 2) {
+        deque.pop_front().unwrap();
+    }
+}
+
+#[clippy::msrv = "1.86.0"]
+fn msrv_high_enough_vec(mut vec: Vec<i32>) {
+    if vec.last().is_some_and(|x| *x > 2) {
+        //~^ manual_pop_if
+        vec.pop().unwrap();
+    }
+}
+
+#[clippy::msrv = "1.93.0"]
+fn msrv_high_enough_vecdeque(mut deque: VecDeque<i32>) {
+    if deque.back().is_some_and(|x| *x > 2) {
+        //~^ manual_pop_if
+        deque.pop_back().unwrap();
+    }
+
+    if deque.front().is_some_and(|x| *x > 2) {
+        //~^ manual_pop_if
+        deque.pop_front().unwrap();
+    }
+}
diff --git a/src/tools/clippy/tests/ui/manual_pop_if.stderr b/src/tools/clippy/tests/ui/manual_pop_if.stderr
new file mode 100644
index 0000000..d57e20d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_pop_if.stderr
@@ -0,0 +1,197 @@
+error: manual implementation of `Vec::pop_if`
+  --> tests/ui/manual_pop_if.rs:21:5
+   |
+LL | /     if vec.last().is_some_and(|x| *x > 2) {
+LL | |
+LL | |         vec.pop().unwrap();
+LL | |     }
+   | |_____^ help: try: `vec.pop_if(|x| *x > 2);`
+   |
+   = note: `-D clippy::manual-pop-if` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::manual_pop_if)]`
+
+error: manual implementation of `Vec::pop_if`
+  --> tests/ui/manual_pop_if.rs:26:5
+   |
+LL | /     if vec.last().is_some_and(|x| *x > 2) {
+LL | |
+LL | |         vec.pop().expect("element");
+LL | |     }
+   | |_____^ help: try: `vec.pop_if(|x| *x > 2);`
+
+error: manual implementation of `VecDeque::pop_back_if`
+  --> tests/ui/manual_pop_if.rs:31:5
+   |
+LL | /     if deque.back().is_some_and(|x| *x > 2) {
+LL | |
+LL | |         deque.pop_back().unwrap();
+LL | |     }
+   | |_____^ help: try: `deque.pop_back_if(|x| *x > 2);`
+
+error: manual implementation of `VecDeque::pop_front_if`
+  --> tests/ui/manual_pop_if.rs:36:5
+   |
+LL | /     if deque.front().is_some_and(|x| *x > 2) {
+LL | |
+LL | |         deque.pop_front().unwrap();
+LL | |     }
+   | |_____^ help: try: `deque.pop_front_if(|x| *x > 2);`
+
+error: manual implementation of `Vec::pop_if`
+  --> tests/ui/manual_pop_if.rs:82:5
+   |
+LL | /     if let Some(x) = vec.last() {
+LL | |
+LL | |         if *x > 2 {
+LL | |             vec.pop().unwrap();
+LL | |         }
+LL | |     }
+   | |_____^ help: try: `vec.pop_if(|x| *x > 2);`
+
+error: manual implementation of `Vec::pop_if`
+  --> tests/ui/manual_pop_if.rs:89:5
+   |
+LL | /     if let Some(x) = vec.last() {
+LL | |
+LL | |         if *x > 2 {
+LL | |             vec.pop().expect("element");
+LL | |         }
+LL | |     }
+   | |_____^ help: try: `vec.pop_if(|x| *x > 2);`
+
+error: manual implementation of `VecDeque::pop_back_if`
+  --> tests/ui/manual_pop_if.rs:96:5
+   |
+LL | /     if let Some(x) = deque.back() {
+LL | |
+LL | |         if *x > 2 {
+LL | |             deque.pop_back().unwrap();
+LL | |         }
+LL | |     }
+   | |_____^ help: try: `deque.pop_back_if(|x| *x > 2);`
+
+error: manual implementation of `VecDeque::pop_front_if`
+  --> tests/ui/manual_pop_if.rs:103:5
+   |
+LL | /     if let Some(x) = deque.front() {
+LL | |
+LL | |         if *x > 2 {
+LL | |             deque.pop_front().unwrap();
+LL | |         }
+LL | |     }
+   | |_____^ help: try: `deque.pop_front_if(|x| *x > 2);`
+
+error: manual implementation of `Vec::pop_if`
+  --> tests/ui/manual_pop_if.rs:151:5
+   |
+LL | /     if let Some(x) = vec.last()
+LL | |         && *x > 2
+LL | |     {
+LL | |         vec.pop().unwrap();
+LL | |     }
+   | |_____^ help: try: `vec.pop_if(|x| *x > 2);`
+
+error: manual implementation of `Vec::pop_if`
+  --> tests/ui/manual_pop_if.rs:157:5
+   |
+LL | /     if let Some(x) = vec.last()
+LL | |         && *x > 2
+LL | |     {
+LL | |         vec.pop().expect("element");
+LL | |     }
+   | |_____^ help: try: `vec.pop_if(|x| *x > 2);`
+
+error: manual implementation of `VecDeque::pop_back_if`
+  --> tests/ui/manual_pop_if.rs:163:5
+   |
+LL | /     if let Some(x) = deque.back()
+LL | |         && *x > 2
+LL | |     {
+LL | |         deque.pop_back().unwrap();
+LL | |     }
+   | |_____^ help: try: `deque.pop_back_if(|x| *x > 2);`
+
+error: manual implementation of `VecDeque::pop_front_if`
+  --> tests/ui/manual_pop_if.rs:169:5
+   |
+LL | /     if let Some(x) = deque.front()
+LL | |         && *x > 2
+LL | |     {
+LL | |         deque.pop_front().unwrap();
+LL | |     }
+   | |_____^ help: try: `deque.pop_front_if(|x| *x > 2);`
+
+error: manual implementation of `Vec::pop_if`
+  --> tests/ui/manual_pop_if.rs:217:5
+   |
+LL | /     if vec.last().map(|x| *x > 2).unwrap_or(false) {
+LL | |
+LL | |         vec.pop().unwrap();
+LL | |     }
+   | |_____^ help: try: `vec.pop_if(|x| *x > 2);`
+
+error: manual implementation of `Vec::pop_if`
+  --> tests/ui/manual_pop_if.rs:222:5
+   |
+LL | /     if vec.last().map(|x| *x > 2).unwrap_or(false) {
+LL | |
+LL | |         vec.pop().expect("element");
+LL | |     }
+   | |_____^ help: try: `vec.pop_if(|x| *x > 2);`
+
+error: manual implementation of `VecDeque::pop_back_if`
+  --> tests/ui/manual_pop_if.rs:227:5
+   |
+LL | /     if deque.back().map(|x| *x > 2).unwrap_or(false) {
+LL | |
+LL | |         deque.pop_back().unwrap();
+LL | |     }
+   | |_____^ help: try: `deque.pop_back_if(|x| *x > 2);`
+
+error: manual implementation of `VecDeque::pop_front_if`
+  --> tests/ui/manual_pop_if.rs:232:5
+   |
+LL | /     if deque.front().map(|x| *x > 2).unwrap_or(false) {
+LL | |
+LL | |         deque.pop_front().unwrap();
+LL | |     }
+   | |_____^ help: try: `deque.pop_front_if(|x| *x > 2);`
+
+error: manual implementation of `Vec::pop_if`
+  --> tests/ui/manual_pop_if.rs:276:5
+   |
+LL | /     if vec.last().is_some_and(|e| *e == vec![1]) {
+LL | |
+LL | |         vec.pop().unwrap();
+LL | |     }
+   | |_____^ help: try: `vec.pop_if(|e| *e == vec![1]);`
+
+error: manual implementation of `Vec::pop_if`
+  --> tests/ui/manual_pop_if.rs:302:5
+   |
+LL | /     if vec.last().is_some_and(|x| *x > 2) {
+LL | |
+LL | |         vec.pop().unwrap();
+LL | |     }
+   | |_____^ help: try: `vec.pop_if(|x| *x > 2);`
+
+error: manual implementation of `VecDeque::pop_back_if`
+  --> tests/ui/manual_pop_if.rs:310:5
+   |
+LL | /     if deque.back().is_some_and(|x| *x > 2) {
+LL | |
+LL | |         deque.pop_back().unwrap();
+LL | |     }
+   | |_____^ help: try: `deque.pop_back_if(|x| *x > 2);`
+
+error: manual implementation of `VecDeque::pop_front_if`
+  --> tests/ui/manual_pop_if.rs:315:5
+   |
+LL | /     if deque.front().is_some_and(|x| *x > 2) {
+LL | |
+LL | |         deque.pop_front().unwrap();
+LL | |     }
+   | |_____^ help: try: `deque.pop_front_if(|x| *x > 2);`
+
+error: aborting due to 20 previous errors
+
diff --git a/src/tools/clippy/tests/ui/match_same_arms.fixed b/src/tools/clippy/tests/ui/match_same_arms.fixed
index 31684a5..b0ab833 100644
--- a/src/tools/clippy/tests/ui/match_same_arms.fixed
+++ b/src/tools/clippy/tests/ui/match_same_arms.fixed
@@ -140,3 +140,35 @@
         _ => false,
     };
 }
+
+fn issue16678() {
+    // ICE in Rust 1.94.0
+    match true {
+        true => {
+            fn wrapper(_arg: ()) {
+                _arg;
+            }
+        },
+        false => {
+            fn wrapper(_arg: ()) {
+                _arg;
+            }
+        },
+    }
+}
+
+fn issue16698() {
+    trait Foo {
+        const X: u8;
+    }
+    impl Foo for u8 {
+        const X: u8 = 2;
+    }
+    impl Foo for i8 {
+        const X: u8 = 2;
+    }
+    match true {
+        false => u8::X,
+        true => i8::X,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/match_same_arms.rs b/src/tools/clippy/tests/ui/match_same_arms.rs
index 39bee01..9c78991 100644
--- a/src/tools/clippy/tests/ui/match_same_arms.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms.rs
@@ -149,3 +149,35 @@ fn main() {
         _ => false,
     };
 }
+
+fn issue16678() {
+    // ICE in Rust 1.94.0
+    match true {
+        true => {
+            fn wrapper(_arg: ()) {
+                _arg;
+            }
+        },
+        false => {
+            fn wrapper(_arg: ()) {
+                _arg;
+            }
+        },
+    }
+}
+
+fn issue16698() {
+    trait Foo {
+        const X: u8;
+    }
+    impl Foo for u8 {
+        const X: u8 = 2;
+    }
+    impl Foo for i8 {
+        const X: u8 = 2;
+    }
+    match true {
+        false => u8::X,
+        true => i8::X,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/question_mark.fixed b/src/tools/clippy/tests/ui/question_mark.fixed
index 102517d..e209da5 100644
--- a/src/tools/clippy/tests/ui/question_mark.fixed
+++ b/src/tools/clippy/tests/ui/question_mark.fixed
@@ -524,3 +524,16 @@
 
     Some(0)
 }
+
+fn issue16654() -> Result<(), i32> {
+    let result = func_returning_result();
+
+    #[allow(clippy::collapsible_if)]
+    if true {
+        result?;
+    }
+
+    _ = [{ result?; }];
+
+    Ok(())
+}
diff --git a/src/tools/clippy/tests/ui/question_mark.rs b/src/tools/clippy/tests/ui/question_mark.rs
index cfea127..579b514 100644
--- a/src/tools/clippy/tests/ui/question_mark.rs
+++ b/src/tools/clippy/tests/ui/question_mark.rs
@@ -649,3 +649,22 @@ fn issue16429(b: i32) -> Option<i32> {
 
     Some(0)
 }
+
+fn issue16654() -> Result<(), i32> {
+    let result = func_returning_result();
+
+    #[allow(clippy::collapsible_if)]
+    if true {
+        if let Err(err) = result {
+            //~^ question_mark
+            return Err(err);
+        }
+    }
+
+    _ = [if let Err(err) = result {
+        //~^ question_mark
+        return Err(err);
+    }];
+
+    Ok(())
+}
diff --git a/src/tools/clippy/tests/ui/question_mark.stderr b/src/tools/clippy/tests/ui/question_mark.stderr
index c243f12..1d7f665 100644
--- a/src/tools/clippy/tests/ui/question_mark.stderr
+++ b/src/tools/clippy/tests/ui/question_mark.stderr
@@ -362,5 +362,24 @@
 LL | |     };
    | |_____^ help: replace it with: `{ a? }`
 
-error: aborting due to 38 previous errors
+error: this block may be rewritten with the `?` operator
+  --> tests/ui/question_mark.rs:658:9
+   |
+LL | /         if let Err(err) = result {
+LL | |
+LL | |             return Err(err);
+LL | |         }
+   | |_________^ help: replace it with: `result?;`
+
+error: this block may be rewritten with the `?` operator
+  --> tests/ui/question_mark.rs:664:10
+   |
+LL |       _ = [if let Err(err) = result {
+   |  __________^
+LL | |
+LL | |         return Err(err);
+LL | |     }];
+   | |_____^ help: replace it with: `{ result?; }`
+
+error: aborting due to 40 previous errors
 
diff --git a/src/tools/clippy/tests/ui/semicolon_inside_block.fixed b/src/tools/clippy/tests/ui/semicolon_inside_block.fixed
index 468f0a5..c717488 100644
--- a/src/tools/clippy/tests/ui/semicolon_inside_block.fixed
+++ b/src/tools/clippy/tests/ui/semicolon_inside_block.fixed
@@ -7,6 +7,7 @@
     clippy::double_parens
 )]
 #![warn(clippy::semicolon_inside_block)]
+#![feature(try_blocks)]
 
 macro_rules! m {
     (()) => {
@@ -106,3 +107,11 @@
     #[rustfmt::skip]
     {0; 0};
 }
+
+fn issue_try_blocks() {
+    // try blocks should NOT trigger semicolon_inside_block:
+    // moving `;` inside changes the return type (e.g. `Option<i32>` -> `Option<()>`)
+    // which in turn changes the type constraints on `?` operators inside the block,
+    // causing type errors.
+    try { Some(1)? };
+}
diff --git a/src/tools/clippy/tests/ui/semicolon_inside_block.rs b/src/tools/clippy/tests/ui/semicolon_inside_block.rs
index 101374a..25be9be 100644
--- a/src/tools/clippy/tests/ui/semicolon_inside_block.rs
+++ b/src/tools/clippy/tests/ui/semicolon_inside_block.rs
@@ -7,6 +7,7 @@
     clippy::double_parens
 )]
 #![warn(clippy::semicolon_inside_block)]
+#![feature(try_blocks)]
 
 macro_rules! m {
     (()) => {
@@ -106,3 +107,11 @@ pub fn issue15388() {
     #[rustfmt::skip]
     {0; 0};
 }
+
+fn issue_try_blocks() {
+    // try blocks should NOT trigger semicolon_inside_block:
+    // moving `;` inside changes the return type (e.g. `Option<i32>` -> `Option<()>`)
+    // which in turn changes the type constraints on `?` operators inside the block,
+    // causing type errors.
+    try { Some(1)? };
+}
diff --git a/src/tools/clippy/tests/ui/semicolon_inside_block.stderr b/src/tools/clippy/tests/ui/semicolon_inside_block.stderr
index 2046dd1..e165903 100644
--- a/src/tools/clippy/tests/ui/semicolon_inside_block.stderr
+++ b/src/tools/clippy/tests/ui/semicolon_inside_block.stderr
@@ -1,5 +1,5 @@
 error: consider moving the `;` inside the block for consistent formatting
-  --> tests/ui/semicolon_inside_block.rs:39:5
+  --> tests/ui/semicolon_inside_block.rs:40:5
    |
 LL |     { unit_fn_block() };
    |     ^^^^^^^^^^^^^^^^^^^^
@@ -13,7 +13,7 @@
    |
 
 error: consider moving the `;` inside the block for consistent formatting
-  --> tests/ui/semicolon_inside_block.rs:41:5
+  --> tests/ui/semicolon_inside_block.rs:42:5
    |
 LL |     unsafe { unit_fn_block() };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -25,7 +25,7 @@
    |
 
 error: consider moving the `;` inside the block for consistent formatting
-  --> tests/ui/semicolon_inside_block.rs:50:5
+  --> tests/ui/semicolon_inside_block.rs:51:5
    |
 LL | /     {
 LL | |
@@ -41,7 +41,7 @@
    |
 
 error: consider moving the `;` inside the block for consistent formatting
-  --> tests/ui/semicolon_inside_block.rs:64:5
+  --> tests/ui/semicolon_inside_block.rs:65:5
    |
 LL |     { m!(()) };
    |     ^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/unnecessary_option_map_or_else.fixed b/src/tools/clippy/tests/ui/unnecessary_option_map_or_else.fixed
index 9974ee2..8d25efb 100644
--- a/src/tools/clippy/tests/ui/unnecessary_option_map_or_else.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_option_map_or_else.fixed
@@ -3,13 +3,10 @@
     clippy::let_and_return,
     clippy::let_unit_value,
     clippy::unnecessary_lazy_evaluations,
-    clippy::unnecessary_literal_unwrap
+    clippy::unnecessary_literal_unwrap,
+    clippy::needless_return
 )]
 
-const fn identity<T>(x: T) -> T {
-    x
-}
-
 const fn double_it(x: i32) -> i32 {
     x * 2
 }
@@ -18,31 +15,42 @@
     // Expected errors
     // Basic scenario
     let option = Some(());
-    option.unwrap_or_else(|| ()); //~ ERROR: unused "map closure" when calling
+    option.unwrap_or_else(|| ()); //~ unnecessary_option_map_or_else
 
     // Type ascription
     let option = Some(());
-    option.unwrap_or_else(|| ()); //~ ERROR: unused "map closure" when calling
+    option.unwrap_or_else(|| ()); //~ unnecessary_option_map_or_else
 
     // Auto-deref
     let string = String::new();
     let option = Some(&string);
-    let _: &str = option.unwrap_or_else(|| &string); //~ ERROR: unused "map closure" when calling
+    let _: &str = option.map_or_else(|| &string, |x| x);
+    // This should in theory lint with a smarter check
 
     // Temporary variable
     let option = Some(());
     option.unwrap_or_else(|| ());
 
-    // Identity
+    // Temporary variable with pattern
+    let option = Some(((), ()));
+    option.unwrap_or_else(|| ((), ()));
+
+    // std::convert::identity
     let string = String::new();
     let option = Some(&string);
-    let _: &str = option.unwrap_or_else(|| &string); //~ ERROR: unused "map closure" when calling
+    let _: &str = option.unwrap_or_else(|| &string); //~ unnecessary_option_map_or_else
 
-    // Closure bound to a variable
-    let do_nothing = |x: String| x;
-    let string = String::new();
-    let option = Some(string.clone());
-    let _: String = option.unwrap_or_else(|| string); //~ ERROR: unused "map closure" when calling
+    let x: Option<((), ())> = Some(((), ()));
+    x.unwrap_or_else(|| ((), ()));
+    //~^ unnecessary_option_map_or_else
+
+    // Returned temporary variable.
+    let x: Option<()> = Some(());
+    x.unwrap_or_else(|| ());
+
+    // Returned temporary variable with pattern
+    let x: Option<((), ())> = Some(((), ()));
+    x.unwrap_or_else(|| ((), ()));
 
     // Correct usages
     let option = Some(());
diff --git a/src/tools/clippy/tests/ui/unnecessary_option_map_or_else.rs b/src/tools/clippy/tests/ui/unnecessary_option_map_or_else.rs
index 9b53f3fc..42d4ad6 100644
--- a/src/tools/clippy/tests/ui/unnecessary_option_map_or_else.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_option_map_or_else.rs
@@ -3,13 +3,10 @@
     clippy::let_and_return,
     clippy::let_unit_value,
     clippy::unnecessary_lazy_evaluations,
-    clippy::unnecessary_literal_unwrap
+    clippy::unnecessary_literal_unwrap,
+    clippy::needless_return
 )]
 
-const fn identity<T>(x: T) -> T {
-    x
-}
-
 const fn double_it(x: i32) -> i32 {
     x * 2
 }
@@ -18,21 +15,22 @@ fn main() {
     // Expected errors
     // Basic scenario
     let option = Some(());
-    option.map_or_else(|| (), |x| x); //~ ERROR: unused "map closure" when calling
+    option.map_or_else(|| (), |x| x); //~ unnecessary_option_map_or_else
 
     // Type ascription
     let option = Some(());
-    option.map_or_else(|| (), |x: ()| x); //~ ERROR: unused "map closure" when calling
+    option.map_or_else(|| (), |x: ()| x); //~ unnecessary_option_map_or_else
 
     // Auto-deref
     let string = String::new();
     let option = Some(&string);
-    let _: &str = option.map_or_else(|| &string, |x| x); //~ ERROR: unused "map closure" when calling
+    let _: &str = option.map_or_else(|| &string, |x| x);
+    // This should in theory lint with a smarter check
 
     // Temporary variable
     let option = Some(());
     option.map_or_else(
-        //~^ ERROR: unused "map closure" when calling
+        //~^ unnecessary_option_map_or_else
         || (),
         |x| {
             let tmp = x;
@@ -40,16 +38,50 @@ fn main() {
         },
     );
 
-    // Identity
+    // Temporary variable with pattern
+    let option = Some(((), ()));
+    option.map_or_else(
+        //~^ unnecessary_option_map_or_else
+        || ((), ()),
+        |x| {
+            let tmp = x;
+            let (a, b) = tmp;
+            (a, b)
+        },
+    );
+
+    // std::convert::identity
     let string = String::new();
     let option = Some(&string);
-    let _: &str = option.map_or_else(|| &string, identity); //~ ERROR: unused "map closure" when calling
+    let _: &str = option.map_or_else(|| &string, std::convert::identity); //~ unnecessary_option_map_or_else
 
-    // Closure bound to a variable
-    let do_nothing = |x: String| x;
-    let string = String::new();
-    let option = Some(string.clone());
-    let _: String = option.map_or_else(|| string, do_nothing); //~ ERROR: unused "map closure" when calling
+    let x: Option<((), ())> = Some(((), ()));
+    x.map_or_else(|| ((), ()), |(a, b)| (a, b));
+    //~^ unnecessary_option_map_or_else
+
+    // Returned temporary variable.
+    let x: Option<()> = Some(());
+    x.map_or_else(
+        //~^ unnecessary_option_map_or_else
+        || (),
+        |n| {
+            let tmp = n;
+            let tmp2 = tmp;
+            return tmp2;
+        },
+    );
+
+    // Returned temporary variable with pattern
+    let x: Option<((), ())> = Some(((), ()));
+    x.map_or_else(
+        //~^ unnecessary_option_map_or_else
+        || ((), ()),
+        |n| {
+            let tmp = n;
+            let (a, b) = tmp;
+            return (a, b);
+        },
+    );
 
     // Correct usages
     let option = Some(());
diff --git a/src/tools/clippy/tests/ui/unnecessary_option_map_or_else.stderr b/src/tools/clippy/tests/ui/unnecessary_option_map_or_else.stderr
index d90875e..3b579eb 100644
--- a/src/tools/clippy/tests/ui/unnecessary_option_map_or_else.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_option_map_or_else.stderr
@@ -1,26 +1,31 @@
 error: unused "map closure" when calling `Option::map_or_else` value
-  --> tests/ui/unnecessary_option_map_or_else.rs:21:5
+  --> tests/ui/unnecessary_option_map_or_else.rs:18:5
    |
 LL |     option.map_or_else(|| (), |x| x);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `unwrap_or_else`: `option.unwrap_or_else(|| ())`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::unnecessary-option-map-or-else` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_option_map_or_else)]`
+help: consider using `unwrap_or_else`
+   |
+LL -     option.map_or_else(|| (), |x| x);
+LL +     option.unwrap_or_else(|| ());
+   |
 
 error: unused "map closure" when calling `Option::map_or_else` value
-  --> tests/ui/unnecessary_option_map_or_else.rs:25:5
+  --> tests/ui/unnecessary_option_map_or_else.rs:22:5
    |
 LL |     option.map_or_else(|| (), |x: ()| x);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `unwrap_or_else`: `option.unwrap_or_else(|| ())`
-
-error: unused "map closure" when calling `Option::map_or_else` value
-  --> tests/ui/unnecessary_option_map_or_else.rs:30:19
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-LL |     let _: &str = option.map_or_else(|| &string, |x| x);
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `unwrap_or_else`: `option.unwrap_or_else(|| &string)`
+help: consider using `unwrap_or_else`
+   |
+LL -     option.map_or_else(|| (), |x: ()| x);
+LL +     option.unwrap_or_else(|| ());
+   |
 
 error: unused "map closure" when calling `Option::map_or_else` value
-  --> tests/ui/unnecessary_option_map_or_else.rs:34:5
+  --> tests/ui/unnecessary_option_map_or_else.rs:32:5
    |
 LL | /     option.map_or_else(
 LL | |
@@ -29,19 +34,122 @@
 ...  |
 LL | |         },
 LL | |     );
-   | |_____^ help: consider using `unwrap_or_else`: `option.unwrap_or_else(|| ())`
+   | |_____^
+   |
+help: consider using `unwrap_or_else`
+   |
+LL -     option.map_or_else(
+LL -
+LL -         || (),
+LL -         |x| {
+LL -             let tmp = x;
+LL -             tmp
+LL -         },
+LL -     );
+LL +     option.unwrap_or_else(|| ());
+   |
 
 error: unused "map closure" when calling `Option::map_or_else` value
-  --> tests/ui/unnecessary_option_map_or_else.rs:46:19
+  --> tests/ui/unnecessary_option_map_or_else.rs:43:5
    |
-LL |     let _: &str = option.map_or_else(|| &string, identity);
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `unwrap_or_else`: `option.unwrap_or_else(|| &string)`
+LL | /     option.map_or_else(
+LL | |
+LL | |         || ((), ()),
+LL | |         |x| {
+...  |
+LL | |         },
+LL | |     );
+   | |_____^
+   |
+help: consider using `unwrap_or_else`
+   |
+LL -     option.map_or_else(
+LL -
+LL -         || ((), ()),
+LL -         |x| {
+LL -             let tmp = x;
+LL -             let (a, b) = tmp;
+LL -             (a, b)
+LL -         },
+LL -     );
+LL +     option.unwrap_or_else(|| ((), ()));
+   |
 
 error: unused "map closure" when calling `Option::map_or_else` value
-  --> tests/ui/unnecessary_option_map_or_else.rs:52:21
+  --> tests/ui/unnecessary_option_map_or_else.rs:56:19
    |
-LL |     let _: String = option.map_or_else(|| string, do_nothing);
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `unwrap_or_else`: `option.unwrap_or_else(|| string)`
+LL |     let _: &str = option.map_or_else(|| &string, std::convert::identity);
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider using `unwrap_or_else`
+   |
+LL -     let _: &str = option.map_or_else(|| &string, std::convert::identity);
+LL +     let _: &str = option.unwrap_or_else(|| &string);
+   |
 
-error: aborting due to 6 previous errors
+error: unused "map closure" when calling `Option::map_or_else` value
+  --> tests/ui/unnecessary_option_map_or_else.rs:59:5
+   |
+LL |     x.map_or_else(|| ((), ()), |(a, b)| (a, b));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider using `unwrap_or_else`
+   |
+LL -     x.map_or_else(|| ((), ()), |(a, b)| (a, b));
+LL +     x.unwrap_or_else(|| ((), ()));
+   |
+
+error: unused "map closure" when calling `Option::map_or_else` value
+  --> tests/ui/unnecessary_option_map_or_else.rs:64:5
+   |
+LL | /     x.map_or_else(
+LL | |
+LL | |         || (),
+LL | |         |n| {
+...  |
+LL | |         },
+LL | |     );
+   | |_____^
+   |
+help: consider using `unwrap_or_else`
+   |
+LL -     x.map_or_else(
+LL -
+LL -         || (),
+LL -         |n| {
+LL -             let tmp = n;
+LL -             let tmp2 = tmp;
+LL -             return tmp2;
+LL -         },
+LL -     );
+LL +     x.unwrap_or_else(|| ());
+   |
+
+error: unused "map closure" when calling `Option::map_or_else` value
+  --> tests/ui/unnecessary_option_map_or_else.rs:76:5
+   |
+LL | /     x.map_or_else(
+LL | |
+LL | |         || ((), ()),
+LL | |         |n| {
+...  |
+LL | |         },
+LL | |     );
+   | |_____^
+   |
+help: consider using `unwrap_or_else`
+   |
+LL -     x.map_or_else(
+LL -
+LL -         || ((), ()),
+LL -         |n| {
+LL -             let tmp = n;
+LL -             let (a, b) = tmp;
+LL -             return (a, b);
+LL -         },
+LL -     );
+LL +     x.unwrap_or_else(|| ((), ()));
+   |
+
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.fixed b/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.fixed
index 5d7e3fa..5554251 100644
--- a/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.fixed
@@ -1,5 +1,10 @@
 #![warn(clippy::unnecessary_result_map_or_else)]
-#![allow(clippy::unnecessary_literal_unwrap, clippy::let_and_return, clippy::let_unit_value)]
+#![allow(
+    clippy::unnecessary_literal_unwrap,
+    clippy::let_and_return,
+    clippy::let_unit_value,
+    clippy::needless_return
+)]
 
 fn main() {
     let x: Result<(), ()> = Ok(());
@@ -14,13 +19,17 @@
     // Auto-deref.
     let y = String::new();
     let x: Result<&String, &String> = Ok(&y);
-    let y: &str = x.unwrap_or_else(|err| err);
-    //~^ unnecessary_result_map_or_else
+    let y: &str = x.map_or_else(|err| err, |n| n);
+    // This should lint with a smarter check
 
     // Temporary variable.
     let x: Result<(), ()> = Ok(());
     x.unwrap_or_else(|err| err);
 
+    // Temporary variable with pattern
+    let x: Result<((), ()), ((), ())> = Ok(((), ()));
+    x.unwrap_or_else(|err| err);
+
     // Should not warn.
     let x: Result<usize, usize> = Ok(0);
     x.map_or_else(|err| err, |n| n + 1);
@@ -61,4 +70,16 @@
             y
         },
     );
+
+    let x: Result<((), ()), ((), ())> = Ok(((), ()));
+    x.unwrap_or_else(|err| err);
+    //~^ unnecessary_result_map_or_else
+
+    // Returned temporary variable.
+    let x: Result<(), ()> = Ok(());
+    x.unwrap_or_else(|err| err);
+
+    // Returned temporary variable with pattern
+    let x: Result<((), ()), ((), ())> = Ok(((), ()));
+    x.unwrap_or_else(|err| err);
 }
diff --git a/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.rs b/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.rs
index d2bab0f..21a4826 100644
--- a/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.rs
@@ -1,5 +1,10 @@
 #![warn(clippy::unnecessary_result_map_or_else)]
-#![allow(clippy::unnecessary_literal_unwrap, clippy::let_and_return, clippy::let_unit_value)]
+#![allow(
+    clippy::unnecessary_literal_unwrap,
+    clippy::let_and_return,
+    clippy::let_unit_value,
+    clippy::needless_return
+)]
 
 fn main() {
     let x: Result<(), ()> = Ok(());
@@ -15,7 +20,7 @@ fn main() {
     let y = String::new();
     let x: Result<&String, &String> = Ok(&y);
     let y: &str = x.map_or_else(|err| err, |n| n);
-    //~^ unnecessary_result_map_or_else
+    // This should lint with a smarter check
 
     // Temporary variable.
     let x: Result<(), ()> = Ok(());
@@ -29,6 +34,18 @@ fn main() {
         },
     );
 
+    // Temporary variable with pattern
+    let x: Result<((), ()), ((), ())> = Ok(((), ()));
+    x.map_or_else(
+        //~^ unnecessary_result_map_or_else
+        |err| err,
+        |n| {
+            let tmp = n;
+            let (a, b) = tmp;
+            (a, b)
+        },
+    );
+
     // Should not warn.
     let x: Result<usize, usize> = Ok(0);
     x.map_or_else(|err| err, |n| n + 1);
@@ -69,4 +86,32 @@ fn main() {
             y
         },
     );
+
+    let x: Result<((), ()), ((), ())> = Ok(((), ()));
+    x.map_or_else(|err| err, |(a, b)| (a, b));
+    //~^ unnecessary_result_map_or_else
+
+    // Returned temporary variable.
+    let x: Result<(), ()> = Ok(());
+    x.map_or_else(
+        //~^ unnecessary_result_map_or_else
+        |err| err,
+        |n| {
+            let tmp = n;
+            let tmp2 = tmp;
+            return tmp2;
+        },
+    );
+
+    // Returned temporary variable with pattern
+    let x: Result<((), ()), ((), ())> = Ok(((), ()));
+    x.map_or_else(
+        //~^ unnecessary_result_map_or_else
+        |err| err,
+        |n| {
+            let tmp = n;
+            let (a, b) = tmp;
+            return (a, b);
+        },
+    );
 }
diff --git a/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.stderr b/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.stderr
index e6afa50..f769991 100644
--- a/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.stderr
@@ -1,26 +1,31 @@
 error: unused "map closure" when calling `Result::map_or_else` value
-  --> tests/ui/unnecessary_result_map_or_else.rs:6:5
+  --> tests/ui/unnecessary_result_map_or_else.rs:11:5
    |
 LL |     x.map_or_else(|err| err, |n| n);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `unwrap_or_else`: `x.unwrap_or_else(|err| err)`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::unnecessary-result-map-or-else` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_result_map_or_else)]`
+help: consider using `unwrap_or_else`
+   |
+LL -     x.map_or_else(|err| err, |n| n);
+LL +     x.unwrap_or_else(|err| err);
+   |
 
 error: unused "map closure" when calling `Result::map_or_else` value
-  --> tests/ui/unnecessary_result_map_or_else.rs:11:5
+  --> tests/ui/unnecessary_result_map_or_else.rs:16:5
    |
 LL |     x.map_or_else(|err: ()| err, |n: ()| n);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `unwrap_or_else`: `x.unwrap_or_else(|err: ()| err)`
-
-error: unused "map closure" when calling `Result::map_or_else` value
-  --> tests/ui/unnecessary_result_map_or_else.rs:17:19
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-LL |     let y: &str = x.map_or_else(|err| err, |n| n);
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `unwrap_or_else`: `x.unwrap_or_else(|err| err)`
+help: consider using `unwrap_or_else`
+   |
+LL -     x.map_or_else(|err: ()| err, |n: ()| n);
+LL +     x.unwrap_or_else(|err: ()| err);
+   |
 
 error: unused "map closure" when calling `Result::map_or_else` value
-  --> tests/ui/unnecessary_result_map_or_else.rs:22:5
+  --> tests/ui/unnecessary_result_map_or_else.rs:27:5
    |
 LL | /     x.map_or_else(
 LL | |
@@ -29,7 +34,111 @@
 ...  |
 LL | |         },
 LL | |     );
-   | |_____^ help: consider using `unwrap_or_else`: `x.unwrap_or_else(|err| err)`
+   | |_____^
+   |
+help: consider using `unwrap_or_else`
+   |
+LL -     x.map_or_else(
+LL -
+LL -         |err| err,
+LL -         |n| {
+LL -             let tmp = n;
+LL -             let tmp2 = tmp;
+LL -             tmp2
+LL -         },
+LL -     );
+LL +     x.unwrap_or_else(|err| err);
+   |
 
-error: aborting due to 4 previous errors
+error: unused "map closure" when calling `Result::map_or_else` value
+  --> tests/ui/unnecessary_result_map_or_else.rs:39:5
+   |
+LL | /     x.map_or_else(
+LL | |
+LL | |         |err| err,
+LL | |         |n| {
+...  |
+LL | |         },
+LL | |     );
+   | |_____^
+   |
+help: consider using `unwrap_or_else`
+   |
+LL -     x.map_or_else(
+LL -
+LL -         |err| err,
+LL -         |n| {
+LL -             let tmp = n;
+LL -             let (a, b) = tmp;
+LL -             (a, b)
+LL -         },
+LL -     );
+LL +     x.unwrap_or_else(|err| err);
+   |
+
+error: unused "map closure" when calling `Result::map_or_else` value
+  --> tests/ui/unnecessary_result_map_or_else.rs:91:5
+   |
+LL |     x.map_or_else(|err| err, |(a, b)| (a, b));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider using `unwrap_or_else`
+   |
+LL -     x.map_or_else(|err| err, |(a, b)| (a, b));
+LL +     x.unwrap_or_else(|err| err);
+   |
+
+error: unused "map closure" when calling `Result::map_or_else` value
+  --> tests/ui/unnecessary_result_map_or_else.rs:96:5
+   |
+LL | /     x.map_or_else(
+LL | |
+LL | |         |err| err,
+LL | |         |n| {
+...  |
+LL | |         },
+LL | |     );
+   | |_____^
+   |
+help: consider using `unwrap_or_else`
+   |
+LL -     x.map_or_else(
+LL -
+LL -         |err| err,
+LL -         |n| {
+LL -             let tmp = n;
+LL -             let tmp2 = tmp;
+LL -             return tmp2;
+LL -         },
+LL -     );
+LL +     x.unwrap_or_else(|err| err);
+   |
+
+error: unused "map closure" when calling `Result::map_or_else` value
+  --> tests/ui/unnecessary_result_map_or_else.rs:108:5
+   |
+LL | /     x.map_or_else(
+LL | |
+LL | |         |err| err,
+LL | |         |n| {
+...  |
+LL | |         },
+LL | |     );
+   | |_____^
+   |
+help: consider using `unwrap_or_else`
+   |
+LL -     x.map_or_else(
+LL -
+LL -         |err| err,
+LL -         |n| {
+LL -             let tmp = n;
+LL -             let (a, b) = tmp;
+LL -             return (a, b);
+LL -         },
+LL -     );
+LL +     x.unwrap_or_else(|err| err);
+   |
+
+error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_safety_comment.rs b/src/tools/clippy/tests/ui/unnecessary_safety_comment.rs
index d82a7b9..75e8315 100644
--- a/src/tools/clippy/tests/ui/unnecessary_safety_comment.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_safety_comment.rs
@@ -100,3 +100,13 @@ pub fn point_to_five() -> *const u8 {
 }
 
 fn main() {}
+
+mod issue16553 {
+    //! ```
+    //! // SAFETY: All is well.
+    //! unsafe {
+    //!    foo()
+    //! }
+    //! ```
+    mod blah {}
+}
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed b/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed
index 2c79446..852c4dd 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns2.fixed
@@ -23,6 +23,6 @@
     //~^ unnested_or_patterns
     if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {}
     //~^ unnested_or_patterns
-    if let box box (0 | 2 | 4) = Box::new(Box::new(0)) {}
+    if let box (box (0 | 2 | 4)) = Box::new(Box::new(0)) {}
     //~^ unnested_or_patterns
 }
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns2.stderr b/src/tools/clippy/tests/ui/unnested_or_patterns2.stderr
index 3fc8fa1..3deef33 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns2.stderr
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns2.stderr
@@ -93,7 +93,7 @@
 help: nest the patterns
    |
 LL -     if let box box 0 | box (box 2 | box 4) = Box::new(Box::new(0)) {}
-LL +     if let box box (0 | 2 | 4) = Box::new(Box::new(0)) {}
+LL +     if let box (box (0 | 2 | 4)) = Box::new(Box::new(0)) {}
    |
 
 error: aborting due to 8 previous errors
diff --git a/src/tools/clippy/util/gh-pages/index_template.html b/src/tools/clippy/util/gh-pages/index_template.html
index 91a5c12..26ca901 100644
--- a/src/tools/clippy/util/gh-pages/index_template.html
+++ b/src/tools/clippy/util/gh-pages/index_template.html
@@ -174,13 +174,13 @@
                     <h2 class="lint-title"> {# #}
                         <div class="panel-title-name" id="lint-{{lint.id}}"> {# #}
                             {{lint.id ~}}
-                            <a href="#{{lint.id}}" class="anchor label label-default">&para;</a> {#+ #}
-                            <a href="" class="copy-to-clipboard anchor label label-default"> {# #}
+                            <a href="#{{lint.id}}" class="anchor label">&para;</a> {#+ #}
+                            <a href="" class="copy-to-clipboard anchor label"> {# #}
                                 &#128203; {# #}
                             </a> {# #}
                         </div> {# #}
 
-                        <span class="label label-default lint-group group-{{lint.group}}">{{lint.group}}</span> {#+ #}
+                        <span class="label lint-group group-{{lint.group}}">{{lint.group}}</span> {#+ #}
 
                         <span class="label lint-level level-{{lint.level}}">{{lint.level}}</span> {#+ #}
 
@@ -194,24 +194,20 @@
                         {# Applicability #}
                         <div> {# #}
                             Applicability: {#+ #}
-                            <span class="label label-default applicability">{{ lint.applicability_str() }}</span> {# #}
+                            <span class="label applicability">{{ lint.applicability_str() }}</span> {# #}
                             <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/enum.Applicability.html#variants">(?)</a> {# #}
                         </div>
                         {# Clippy version #}
                         <div> {# #}
                             {% if lint.group == "deprecated" %}Deprecated{% else %} Added{% endif +%} in: {#+ #}
-                            <span class="label label-default label-version">{{lint.version}}</span> {# #}
+                            <span class="label label-version">{{lint.version}}</span> {# #}
                         </div>
                         {# Open related issues #}
-                        <div> {# #}
-                            <a href="https://github.com/rust-lang/rust-clippy/issues?q=is%3Aissue+{{lint.id}}">Related Issues</a> {# #}
-                        </div>
+                        <a href="https://github.com/rust-lang/rust-clippy/issues?q=is%3Aissue+{{lint.id}}">Related Issues</a>
 
                         {# Jump to source #}
                         {% if let Some(id_location) = lint.id_location %}
-                            <div> {# #}
-                                <a href="https://github.com/rust-lang/rust-clippy/blob/master/{{id_location}}">View Source</a> {# #}
-                            </div>
+                            <a href="https://github.com/rust-lang/rust-clippy/blob/master/{{id_location}}">View Source</a>
                         {% endif %}
                     </div> {# #}
                 </div> {# #}
diff --git a/src/tools/clippy/util/gh-pages/style.css b/src/tools/clippy/util/gh-pages/style.css
index ce478a3..4f1935b 100644
--- a/src/tools/clippy/util/gh-pages/style.css
+++ b/src/tools/clippy/util/gh-pages/style.css
@@ -1,5 +1,6 @@
 body {
     --icon-filter: initial;
+    --label-background: #777;
 }
 
 body.ayu {
@@ -230,7 +231,10 @@
 
 .panel-title-name { flex: 1; min-width: 400px;}
 
-.panel-title-name .anchor { display: none; }
+.panel-title-name .anchor {
+    display: none;
+    background-color: var(--label-background);
+}
 article:hover .panel-title-name .anchor { display: inline;}
 
 .search-control {
@@ -397,10 +401,6 @@
     text-decoration: none;
 }
 
-.label-default {
-    background-color: #777;
-}
-
 .lint-level {
     min-width: 4em;
 }
@@ -420,6 +420,7 @@
 
 .lint-group {
     min-width: 8em;
+    background-color: var(--label-background);
 }
 .group-deprecated {
     opacity: 0.5;
@@ -459,7 +460,7 @@
         display: flex;
         flex-flow: column;
     }
-    .lint-additional-info > div + div {
+    .lint-additional-info > * + * {
         border-top: 1px solid var(--theme-popup-border);
     }
 }
@@ -468,12 +469,12 @@
         display: flex;
         flex-flow: row;
     }
-    .lint-additional-info > div + div {
+    .lint-additional-info > * + * {
         border-left: 1px solid var(--theme-popup-border);
     }
 }
 
-.lint-additional-info > div {
+.lint-additional-info > * {
     display: inline-flex;
     min-width: 200px;
     flex-grow: 1;
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index bc94a81..7cac7f5 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -168,6 +168,7 @@ pub enum Sanitizer {
     Dataflow,
     Kcfi,
     KernelAddress,
+    KernelHwaddress,
     Leak,
     Memory,
     Memtag,
diff --git a/src/tools/compiletest/src/directives/directive_names.rs b/src/tools/compiletest/src/directives/directive_names.rs
index 9af881b..5421a97 100644
--- a/src/tools/compiletest/src/directives/directive_names.rs
+++ b/src/tools/compiletest/src/directives/directive_names.rs
@@ -179,6 +179,7 @@
     "needs-sanitizer-hwaddress",
     "needs-sanitizer-kasan",
     "needs-sanitizer-kcfi",
+    "needs-sanitizer-khwasan",
     "needs-sanitizer-leak",
     "needs-sanitizer-memory",
     "needs-sanitizer-memtag",
@@ -213,6 +214,7 @@
     "only-apple",
     "only-arm",
     "only-arm64ec",
+    "only-armv7-unknown-linux-gnueabihf",
     "only-avr",
     "only-beta",
     "only-bpf",
diff --git a/src/tools/compiletest/src/directives/needs.rs b/src/tools/compiletest/src/directives/needs.rs
index 168d5e9..e9f3d6c 100644
--- a/src/tools/compiletest/src/directives/needs.rs
+++ b/src/tools/compiletest/src/directives/needs.rs
@@ -47,6 +47,11 @@ pub(super) fn handle_needs(
             ignore_reason: "ignored on targets without kernel address sanitizer",
         },
         Need {
+            name: "needs-sanitizer-khwasan",
+            condition: cache.sanitizer_khwasan,
+            ignore_reason: "ignored on targets without kernel hardware-assisted address sanitizer",
+        },
+        Need {
             name: "needs-sanitizer-leak",
             condition: cache.sanitizer_leak,
             ignore_reason: "ignored on targets without leak sanitizer",
@@ -332,6 +337,7 @@ pub(super) struct CachedNeedsConditions {
     sanitizer_dataflow: bool,
     sanitizer_kcfi: bool,
     sanitizer_kasan: bool,
+    sanitizer_khwasan: bool,
     sanitizer_leak: bool,
     sanitizer_memory: bool,
     sanitizer_thread: bool,
@@ -359,6 +365,7 @@ pub(super) fn load(config: &Config) -> Self {
             sanitizer_dataflow: sanitizers.contains(&Sanitizer::Dataflow),
             sanitizer_kcfi: sanitizers.contains(&Sanitizer::Kcfi),
             sanitizer_kasan: sanitizers.contains(&Sanitizer::KernelAddress),
+            sanitizer_khwasan: sanitizers.contains(&Sanitizer::KernelHwaddress),
             sanitizer_leak: sanitizers.contains(&Sanitizer::Leak),
             sanitizer_memory: sanitizers.contains(&Sanitizer::Memory),
             sanitizer_thread: sanitizers.contains(&Sanitizer::Thread),
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index b584d14..da4ec44 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1919,8 +1919,9 @@ fn make_compile_args(
             compiler.args(&["-A", "unused", "-W", "unused_attributes"]);
         }
 
-        // Allow tests to use internal features.
+        // Allow tests to use internal and incomplete features.
         compiler.args(&["-A", "internal_features"]);
+        compiler.args(&["-A", "incomplete_features"]);
 
         // Allow tests to have unused parens and braces.
         // Add #![deny(unused_parens, unused_braces)] to the test file if you want to
diff --git a/src/tools/enzyme b/src/tools/enzyme
index 0b86a67..3244024 160000
--- a/src/tools/enzyme
+++ b/src/tools/enzyme
@@ -1 +1 @@
-Subproject commit 0b86a6759e5f250d6691a94a4a779a44d846e25b
+Subproject commit 324402444ac48874d8ebd3ac767330bdc7cb1c06
diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock
index 2d332ae..630a4b5 100644
--- a/src/tools/miri/Cargo.lock
+++ b/src/tools/miri/Cargo.lock
@@ -779,9 +779,9 @@
 
 [[package]]
 name = "libc"
-version = "0.2.177"
+version = "0.2.182"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
+checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
 
 [[package]]
 name = "libffi"
@@ -923,11 +923,12 @@
 
 [[package]]
 name = "mio"
-version = "1.1.0"
+version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873"
+checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
 dependencies = [
  "libc",
+ "log",
  "wasi",
  "windows-sys 0.61.2",
 ]
@@ -950,6 +951,7 @@
  "libffi",
  "libloading",
  "measureme",
+ "mio",
  "nix",
  "rand",
  "regex",
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index 6238784..3255885 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -28,6 +28,7 @@
 directories = "6"
 bitflags = "2.6"
 serde_json = { version = "1.0", optional = true }
+mio = { version = "1.1.1", features = ["os-poll", "net"] }
 
 [target.'cfg(unix)'.dependencies]
 libc = "0.2"
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index 4808e53..f51cd96 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -476,8 +476,9 @@
   but reports to the program that it did actually write. This is useful when you
   are not interested in the actual program's output, but only want to see Miri's
   errors and warnings.
-* `-Zmiri-recursive-validation` is a *highly experimental* flag that makes validity checking
-  recurse below references.
+* `-Zmiri-recursive-validation` is a *highly experimental* flag that makes validity checking recurse
+  *one level* below references. The in-memory value is treated as-if it was inside a
+  `MaybeDangling`, i.e., nested references do not even have to be dereferenceable.
 * `-Zmiri-preemption-rate` configures the probability that at the end of a basic block, the active
   thread will be preempted. The default is `0.01` (i.e., 1%). Setting this to `0` disables
   preemption. Note that even without preemption, the schedule is still non-deterministic:
@@ -641,6 +642,7 @@
 * [`winit` registering a global constructor with the wrong ABI on Windows](https://github.com/rust-windowing/winit/issues/4435)
 * [`VecDeque::splice` confusing physical and logical indices](https://github.com/rust-lang/rust/issues/151758)
 * [Data race in `oneshot` channel](https://github.com/faern/oneshot/issues/69)
+* [Memory leak in serde-yaml-bw](https://github.com/bourumir-wyngs/serde-yaml-bw/issues/197)
 
 Violations of [Stacked Borrows] found that are likely bugs (but Stacked Borrows is currently just an experiment):
 
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 998ecc0..e281dad 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-d1ee5e59a964a419b84b760812a35075034f4861
+fd0c901b00ee1e08a250039cdb90258603497e20
diff --git a/src/tools/miri/src/concurrency/blocking_io.rs b/src/tools/miri/src/concurrency/blocking_io.rs
new file mode 100644
index 0000000..221d049
--- /dev/null
+++ b/src/tools/miri/src/concurrency/blocking_io.rs
@@ -0,0 +1,148 @@
+use std::io;
+use std::time::Duration;
+
+use mio::event::Source;
+use mio::{Events, Interest, Poll, Token};
+use rustc_data_structures::fx::FxHashMap;
+
+use crate::*;
+
+/// Capacity of the event queue which can be polled at a time.
+/// Since we don't expect many simultaneous blocking I/O events
+/// this value can be set rather low.
+const IO_EVENT_CAPACITY: usize = 16;
+
+/// Trait for values that contain a mio [`Source`].
+pub trait WithSource {
+    /// Invoke `f` on the source inside `self`.
+    fn with_source(&self, f: &mut dyn FnMut(&mut dyn Source) -> io::Result<()>) -> io::Result<()>;
+}
+
+/// Manager for managing blocking host I/O in a non-blocking manner.
+/// We use [`Poll`] to poll for new I/O events from the OS for sources
+/// registered using this manager.
+///
+/// Since blocking host I/O is inherently non-deterministic, no method on this
+/// manager should be called when isolation is enabled. The only exception is
+/// the [`BlockingIoManager::new`] function to create the manager. Everywhere else,
+/// we assert that isolation is disabled!
+pub struct BlockingIoManager {
+    /// Poll instance to monitor I/O events from the OS.
+    /// This is only [`None`] when Miri is run with isolation enabled.
+    poll: Option<Poll>,
+    /// Buffer used to store the ready I/O events when calling [`Poll::poll`].
+    /// This is not part of the state and only stored to avoid allocating a
+    /// new buffer for every poll.
+    events: Events,
+    /// Map between threads which are currently blocked and the
+    /// underlying I/O source.
+    sources: FxHashMap<ThreadId, Box<dyn WithSource>>,
+}
+
+impl BlockingIoManager {
+    /// Create a new blocking I/O manager instance based on the availability
+    /// of communication with the host.
+    pub fn new(communicate: bool) -> Result<Self, io::Error> {
+        let manager = Self {
+            poll: communicate.then_some(Poll::new()?),
+            events: Events::with_capacity(IO_EVENT_CAPACITY),
+            sources: FxHashMap::default(),
+        };
+        Ok(manager)
+    }
+
+    /// Poll for new I/O events from the OS or wait until the timeout expired.
+    ///
+    /// - If the timeout is [`Some`] and contains [`Duration::ZERO`], the poll doesn't block and just
+    ///   reads all events since the last poll.
+    /// - If the timeout is [`Some`] and contains a non-zero duration, it blocks at most for the
+    ///   specified duration.
+    /// - If the timeout is [`None`] the poll blocks indefinitely until an event occurs.
+    ///
+    /// Returns all threads that are ready because they received an I/O event.
+    pub fn poll(&mut self, timeout: Option<Duration>) -> Result<Vec<ThreadId>, io::Error> {
+        let poll =
+            self.poll.as_mut().expect("Blocking I/O should not be called with isolation enabled");
+
+        // Poll for new I/O events from OS and store them in the events buffer.
+        poll.poll(&mut self.events, timeout)?;
+
+        let ready = self
+            .events
+            .iter()
+            .map(|event| {
+                let token = event.token();
+                ThreadId::new_unchecked(token.0.try_into().unwrap())
+            })
+            .collect::<Vec<_>>();
+
+        // Deregister all ready sources as we only want to receive one event per thread.
+        ready.iter().for_each(|thread_id| self.deregister(*thread_id));
+
+        Ok(ready)
+    }
+
+    /// Register a blocking I/O source for a thread together with it's poll interests.
+    ///
+    /// The source will be deregistered automatically once an event for it is received.
+    ///
+    /// As the OS can always produce spurious wake-ups, it's the callers responsibility to
+    /// verify the requested I/O interests are really ready and to register again if they're not.
+    pub fn register(&mut self, source: Box<dyn WithSource>, thread: ThreadId, interests: Interest) {
+        let poll =
+            self.poll.as_ref().expect("Blocking I/O should not be called with isolation enabled");
+
+        let token = Token(thread.to_u32().to_usize());
+
+        // Treat errors from registering as fatal. On UNIX hosts this can only
+        // fail due to system resource errors (e.g. ENOMEM or ENOSPC).
+        source
+            .with_source(&mut |source| source.register(poll.registry(), token, interests))
+            .unwrap();
+        self.sources
+            .try_insert(thread, source)
+            .unwrap_or_else(|_| panic!("A thread cannot be registered twice at the same time"));
+    }
+
+    /// Deregister the event source for a thread. Returns the kind of I/O the thread was
+    /// blocked on.
+    fn deregister(&mut self, thread: ThreadId) {
+        let poll =
+            self.poll.as_ref().expect("Blocking I/O should not be called with isolation enabled");
+
+        let Some(source) = self.sources.remove(&thread) else {
+            panic!("Attempt to deregister a token which isn't registered")
+        };
+
+        // Treat errors from deregistering as fatal. On UNIX hosts this can only
+        // fail due to system resource errors (e.g. ENOMEM or ENOSPC).
+        source.with_source(&mut |source| source.deregister(poll.registry())).unwrap();
+    }
+}
+
+impl<'tcx> EvalContextExt<'tcx> for MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> {
+    /// Block the current thread until some interests on an I/O source
+    /// are fulfilled or the optional timeout exceeded.
+    /// The callback will be invoked when the thread gets unblocked.
+    ///
+    /// There can be spurious wake-ups by the OS and thus it's the callers
+    /// responsibility to verify that the requested I/O interests are
+    /// really ready and to block again if they're not.
+    #[inline]
+    fn block_thread_for_io(
+        &mut self,
+        source: impl WithSource + 'static,
+        interests: Interest,
+        timeout: Option<(TimeoutClock, TimeoutAnchor, Duration)>,
+        callback: DynUnblockCallback<'tcx>,
+    ) {
+        let this = self.eval_context_mut();
+        this.machine.blocking_io.register(
+            Box::new(source),
+            this.machine.threads.active_thread(),
+            interests,
+        );
+        this.block_thread(BlockReason::IO, timeout, callback);
+    }
+}
diff --git a/src/tools/miri/src/concurrency/mod.rs b/src/tools/miri/src/concurrency/mod.rs
index 421f243..815ce91 100644
--- a/src/tools/miri/src/concurrency/mod.rs
+++ b/src/tools/miri/src/concurrency/mod.rs
@@ -1,3 +1,4 @@
+pub mod blocking_io;
 pub mod cpu_affinity;
 pub mod data_race;
 mod data_race_handler;
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index 9d829bf..d6d6449 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -1,9 +1,9 @@
 //! Implements threads.
 
-use std::mem;
 use std::sync::atomic::Ordering::Relaxed;
 use std::task::Poll;
 use std::time::{Duration, SystemTime};
+use std::{io, mem};
 
 use rand::seq::IteratorRandom;
 use rustc_abi::ExternAbi;
@@ -25,10 +25,11 @@
 enum SchedulingAction {
     /// Execute step on the active thread.
     ExecuteStep,
-    /// Execute a timeout callback.
-    ExecuteTimeoutCallback,
-    /// Wait for a bit, until there is a timeout to be called.
-    Sleep(Duration),
+    /// Wait for a bit, but at most as long as the duration specified.
+    /// We wake up early if an I/O event happened.
+    /// If the duration is [`None`], we sleep indefinitely. This is
+    /// only allowed when isolation is disabled and there are threads waiting for I/O!
+    SleepAndWaitForIo(Option<Duration>),
 }
 
 /// What to do with TLS allocations from terminated threads
@@ -111,6 +112,8 @@ pub enum BlockReason {
     Eventfd,
     /// Blocked on unnamed_socket.
     UnnamedSocket,
+    /// Blocked on an IO operation.
+    IO,
     /// Blocked for any reason related to GenMC, such as `assume` statements (GenMC mode only).
     /// Will be implicitly unblocked when GenMC schedules this thread again.
     Genmc,
@@ -765,9 +768,7 @@ fn schedule(&mut self) -> InterpResult<'tcx, SchedulingAction> {
         }
 
         // We are not in GenMC mode, so we control the scheduling.
-        let thread_manager = &mut this.machine.threads;
-        let clock = &this.machine.monotonic_clock;
-        let rng = this.machine.rng.get_mut();
+        let thread_manager = &this.machine.threads;
         // This thread and the program can keep going.
         if thread_manager.threads[thread_manager.active_thread].state.is_enabled()
             && !thread_manager.yield_active_thread
@@ -775,16 +776,37 @@ fn schedule(&mut self) -> InterpResult<'tcx, SchedulingAction> {
             // The currently active thread is still enabled, just continue with it.
             return interp_ok(SchedulingAction::ExecuteStep);
         }
-        // The active thread yielded or got terminated. Let's see if there are any timeouts to take
-        // care of. We do this *before* running any other thread, to ensure that timeouts "in the
-        // past" fire before any other thread can take an action. This ensures that for
+
+        // The active thread yielded or got terminated. Let's see if there are any I/O events
+        // or timeouts to take care of.
+
+        if this.machine.communicate() {
+            // When isolation is disabled we need to check for events for
+            // threads which are blocked on host I/O.
+            // We do this before running any other threads such that the threads
+            // which received events are available for scheduling afterwards.
+
+            // Perform a non-blocking poll for newly available I/O events from the OS.
+            this.poll_and_unblock(Some(Duration::ZERO))?;
+        }
+
+        let thread_manager = &this.machine.threads;
+        let clock = &this.machine.monotonic_clock;
+
+        // We also check timeouts before running any other thread, to ensure that timeouts
+        // "in the past" fire before any other thread can take an action. This ensures that for
         // `pthread_cond_timedwait`, "an error is returned if [...] the absolute time specified by
         // abstime has already been passed at the time of the call".
         // <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html>
         let potential_sleep_time = thread_manager.next_callback_wait_time(clock);
         if potential_sleep_time == Some(Duration::ZERO) {
-            return interp_ok(SchedulingAction::ExecuteTimeoutCallback);
+            // The timeout exceeded for some thread so we unblock the thread and execute its timeout callback.
+            this.run_timeout_callback()?;
         }
+
+        let thread_manager = &mut this.machine.threads;
+        let rng = this.machine.rng.get_mut();
+
         // No callbacks immediately scheduled, pick a regular thread to execute.
         // The active thread blocked or yielded. So we go search for another enabled thread.
         // We build the list of threads by starting with the threads after the current one, followed by
@@ -832,7 +854,16 @@ fn schedule(&mut self) -> InterpResult<'tcx, SchedulingAction> {
             // All threads are currently blocked, but we have unexecuted
             // timeout_callbacks, which may unblock some of the threads. Hence,
             // sleep until the first callback.
-            interp_ok(SchedulingAction::Sleep(sleep_time))
+            interp_ok(SchedulingAction::SleepAndWaitForIo(Some(sleep_time)))
+        } else if thread_manager
+            .threads
+            .iter()
+            .any(|thread| thread.state.is_blocked_on(BlockReason::IO))
+        {
+            // At least one thread is blocked on host I/O but doesn't
+            // have a timeout set. Hence, we sleep indefinitely in the
+            // hope that eventually an I/O event for this thread happens.
+            interp_ok(SchedulingAction::SleepAndWaitForIo(None))
         } else {
             throw_machine_stop!(TerminationInfo::GlobalDeadlock);
         }
@@ -1300,13 +1331,38 @@ fn run_threads(&mut self) -> InterpResult<'tcx, !> {
                         }
                     }
                 }
-                SchedulingAction::ExecuteTimeoutCallback => {
-                    this.run_timeout_callback()?;
-                }
-                SchedulingAction::Sleep(duration) => {
-                    this.machine.monotonic_clock.sleep(duration);
+                SchedulingAction::SleepAndWaitForIo(duration) => {
+                    if this.machine.communicate() {
+                        // When we're running with isolation disabled, instead of
+                        // strictly sleeping the duration we allow waking up
+                        // early for I/O events from the OS.
+
+                        this.poll_and_unblock(duration)?;
+                    } else {
+                        let duration = duration.expect(
+                            "Infinite sleep should not be triggered when isolation is enabled",
+                        );
+                        this.machine.monotonic_clock.sleep(duration);
+                    }
                 }
             }
         }
     }
+
+    /// Poll for I/O events until either an I/O event happened or the timeout expired.
+    /// The different timeout values are described in [`BlockingIoManager::poll`].
+    fn poll_and_unblock(&mut self, timeout: Option<Duration>) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+
+        let ready = match this.machine.blocking_io.poll(timeout) {
+            Ok(ready) => ready,
+            // We can ignore errors originating from interrupts; that's just a spurious wakeup.
+            Err(e) if e.kind() == io::ErrorKind::Interrupted => return interp_ok(()),
+            // For other errors we panic. On Linux and BSD hosts this should only be
+            // reachable when a system resource error (e.g. ENOMEM or ENOSPC) occurred.
+            Err(e) => panic!("{e}"),
+        };
+
+        ready.into_iter().try_for_each(|thread_id| this.unblock_thread(thread_id, BlockReason::IO))
+    }
 }
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 787a710..9d93edc 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -141,13 +141,6 @@ pub enum NonHaltingDiagnostic {
         effective_failure_ordering: AtomicReadOrd,
     },
     FileInProcOpened,
-    SocketListenUnsupportedBacklog {
-        details: bool,
-        /// Unsupported backlog value provided the by the program.
-        provided: i32,
-        /// Supported backlog value by Miri.
-        supported: i32,
-    },
 }
 
 /// Level of Miri specific diagnostics
@@ -650,8 +643,6 @@ pub fn emit_diagnostic(&self, e: NonHaltingDiagnostic) {
             | WeakMemoryOutdatedLoad { .. } =>
                 ("tracking was triggered here".to_string(), DiagLevel::Note),
             FileInProcOpened => ("open a file in `/proc`".to_string(), DiagLevel::Warning),
-            SocketListenUnsupportedBacklog { .. } =>
-                ("call to `listen` with unsupported backlog value".to_string(), DiagLevel::Warning),
         };
 
         let title = match &e {
@@ -700,17 +691,12 @@ pub fn emit_diagnostic(&self, e: NonHaltingDiagnostic) {
                 format!("GenMC currently does not model the failure ordering for `compare_exchange`. {was_upgraded_msg}. Miri with GenMC might miss bugs related to this memory access.")
             }
             FileInProcOpened => format!("files in `/proc` can bypass the Abstract Machine and might not work properly in Miri"),
-            SocketListenUnsupportedBacklog { provided, supported, .. } => format!("called `listen` on socket with backlog value of {provided} but only {supported} is supported"),
         };
 
         let notes = match &e {
             ProgressReport { block_count } => {
                 vec![note!("so far, {block_count} basic blocks have been executed")]
             }
-            SocketListenUnsupportedBacklog { details: true, supported, .. } =>
-                vec![note!(
-                    "the given value will be ignored and a backlog of {supported} will be used instead"
-                )],
             _ => vec![],
         };
 
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 2f6c807..f41e3c2 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -16,6 +16,7 @@
 #![feature(never_type)]
 #![feature(try_blocks)]
 #![feature(io_error_more)]
+#![feature(io_error_inprogress)]
 #![feature(variant_count)]
 #![feature(yeet_expr)]
 #![feature(pointer_is_aligned_to)]
@@ -132,6 +133,7 @@ pub mod native_lib {
     BorTag, BorrowTrackerMethod, EvalContextExt as _, TreeBorrowsParams,
 };
 pub use crate::clock::{Instant, MonotonicClock};
+pub use crate::concurrency::blocking_io::{BlockingIoManager, EvalContextExt as _, WithSource};
 pub use crate::concurrency::cpu_affinity::MAX_CPUS;
 pub use crate::concurrency::data_race::{
     AtomicFenceOrd, AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd, EvalContextExt as _,
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index ab38828..d8224f1 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -537,6 +537,9 @@ pub struct MiriMachine<'tcx> {
     /// The set of threads.
     pub(crate) threads: ThreadManager<'tcx>,
 
+    /// Handles blocking I/O and polling for completion.
+    pub(crate) blocking_io: BlockingIoManager,
+
     /// Stores which thread is eligible to run on which CPUs.
     /// This has no effect at all, it is just tracked to produce the correct result
     /// in `sched_getaffinity`
@@ -732,6 +735,8 @@ pub(crate) fn new(
             thread_cpu_affinity
                 .insert(threads.active_thread(), CpuAffinityMask::new(&layout_cx, config.num_cpus));
         }
+        let blocking_io = BlockingIoManager::new(config.isolated_op == IsolatedOp::Allow)
+            .expect("Couldn't create poll instance");
         let alloc_addresses =
             RefCell::new(alloc_addresses::GlobalStateInner::new(config, stack_addr, tcx));
         MiriMachine {
@@ -754,6 +759,7 @@ pub(crate) fn new(
             layouts,
             threads,
             thread_cpu_affinity,
+            blocking_io,
             static_roots: Vec::new(),
             profiler,
             string_cache: Default::default(),
@@ -1010,6 +1016,7 @@ fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
             data_race,
             alloc_addresses,
             fds,
+            blocking_io:_,
             epoll_interests:_,
             tcx: _,
             isolated_op: _,
diff --git a/src/tools/miri/src/provenance_gc.rs b/src/tools/miri/src/provenance_gc.rs
index 66b0adb..f2c750a 100644
--- a/src/tools/miri/src/provenance_gc.rs
+++ b/src/tools/miri/src/provenance_gc.rs
@@ -19,7 +19,7 @@ fn visit_provenance(&self, _visit: &mut VisitWith<'_>) {}
         )+
     }
 }
-no_provenance!(i8 i16 i32 i64 isize u8 u16 u32 u64 usize ThreadId);
+no_provenance!(i8 i16 i32 i64 isize u8 u16 u32 u64 usize bool ThreadId);
 
 impl<T: VisitProvenance> VisitProvenance for Option<T> {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
diff --git a/src/tools/miri/src/shims/io_error.rs b/src/tools/miri/src/shims/io_error.rs
index 91ae448..bb76198 100644
--- a/src/tools/miri/src/shims/io_error.rs
+++ b/src/tools/miri/src/shims/io_error.rs
@@ -56,7 +56,7 @@ fn from(value: Scalar) -> Self {
 }
 
 // This mapping should match `decode_error_kind` in
-// <https://github.com/rust-lang/rust/blob/HEAD/library/std/src/sys/pal/unix/mod.rs>.
+// <https://github.com/rust-lang/rust/blob/HEAD/library/std/src/sys/io/error/unix.rs>.
 const UNIX_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = {
     use std::io::ErrorKind::*;
     &[
@@ -94,6 +94,7 @@ fn from(value: Scalar) -> Self {
         ("ETIMEDOUT", TimedOut),
         ("ETXTBSY", ExecutableFileBusy),
         ("EXDEV", CrossesDevices),
+        ("EINPROGRESS", InProgress),
         // The following have two valid options. We have both for the forwards mapping; only the
         // first one will be used for the backwards mapping.
         ("EPERM", PermissionDenied),
@@ -103,7 +104,7 @@ fn from(value: Scalar) -> Self {
     ]
 };
 // This mapping should match `decode_error_kind` in
-// <https://github.com/rust-lang/rust/blob/HEAD/library/std/src/sys/pal/windows/mod.rs>.
+// <https://github.com/rust-lang/rust/blob/HEAD/library/std/src/sys/io/error/windows.rs>.
 const WINDOWS_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = {
     use std::io::ErrorKind::*;
     // It's common for multiple error codes to map to the same io::ErrorKind. We have all for the
diff --git a/src/tools/miri/src/shims/unix/env.rs b/src/tools/miri/src/shims/unix/env.rs
index 41bf70c..488d82f 100644
--- a/src/tools/miri/src/shims/unix/env.rs
+++ b/src/tools/miri/src/shims/unix/env.rs
@@ -272,6 +272,53 @@ fn unix_gettid(&mut self, link_name: &str) -> InterpResult<'tcx, Scalar> {
         interp_ok(Scalar::from_u32(this.get_current_tid()))
     }
 
+    /// `fields_size`, if present, says how large each field of the struct is.
+    fn uname(
+        &mut self,
+        uname: &OpTy<'tcx>,
+        fields_size: Option<&OpTy<'tcx>>,
+    ) -> InterpResult<'tcx, Scalar> {
+        let this = self.eval_context_mut();
+        this.assert_target_os_is_unix("uname");
+
+        let uname_ptr = this.read_pointer(uname)?;
+        let fields_size = match fields_size {
+            None => None,
+            Some(size) => Some(this.read_scalar(size)?.to_i32()?),
+        };
+
+        if this.ptr_is_null(uname_ptr)? {
+            return this.set_last_error_and_return_i32(LibcError("EFAULT"));
+        }
+
+        let uname = this.deref_pointer_as(uname, this.libc_ty_layout("utsname"))?;
+        let arch = this.machine.tcx.sess.target.arch.desc_symbol();
+        // Values required by POSIX.
+        let mut values = vec![
+            ("sysname", "Miri"),
+            ("nodename", "Miri"),
+            ("release", env!("CARGO_PKG_VERSION")),
+            ("version", concat!("Miri ", env!("CARGO_PKG_VERSION"))),
+            ("machine", arch.as_str()),
+        ];
+        if matches!(this.machine.tcx.sess.target.os, Os::Linux | Os::Android) {
+            values.push(("domainname", "(none)"));
+        }
+
+        for (name, value) in values {
+            let field = this.project_field_named(&uname, name)?;
+            let size = field.layout().layout.size().bytes();
+            if fields_size.is_some_and(|fields_size| u64::try_from(fields_size) != Ok(size)) {
+                throw_unsup_format!(
+                    "the fields size passed to `uname` does not match the type in the libc crate"
+                );
+            }
+            let (written, _) = this.write_c_str(value.as_bytes(), field.ptr(), size)?;
+            assert!(written); // All values should fit.
+        }
+        interp_ok(Scalar::from_i32(0))
+    }
+
     /// The Apple-specific `int pthread_threadid_np(pthread_t thread, uint64_t *thread_id)`, which
     /// allows querying the ID for arbitrary threads, identified by their pthread_t.
     ///
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index 9a24cbc..f2e16e7 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -174,6 +174,21 @@ fn emulate_foreign_item_inner(
                 let result = this.getpid()?;
                 this.write_scalar(result, dest)?;
             }
+            "uname" => {
+                // Not all Unixes have the `uname` symbol, e.g. FreeBSD does not.
+                this.check_target_os(
+                    &[Os::Linux, Os::Android, Os::MacOs, Os::Solaris, Os::Illumos],
+                    link_name,
+                )?;
+                let [uname] = this.check_shim_sig(
+                    shim_sig!(extern "C" fn(*mut _) -> i32),
+                    link_name,
+                    abi,
+                    args,
+                )?;
+                let result = this.uname(uname, None)?;
+                this.write_scalar(result, dest)?;
+            }
             "sysconf" => {
                 let [val] = this.check_shim_sig(
                     shim_sig!(extern "C" fn(i32) -> isize),
@@ -570,6 +585,33 @@ fn emulate_foreign_item_inner(
                 let result = this.listen(socket, backlog)?;
                 this.write_scalar(result, dest)?;
             }
+            "accept" => {
+                let [socket, address, address_len] = this.check_shim_sig(
+                    shim_sig!(extern "C" fn(i32, *mut _, *mut _) -> i32),
+                    link_name,
+                    abi,
+                    args,
+                )?;
+                this.accept4(socket, address, address_len, /* flags */ None, dest)?;
+            }
+            "accept4" => {
+                let [socket, address, address_len, flags] = this.check_shim_sig(
+                    shim_sig!(extern "C" fn(i32, *mut _, *mut _, i32) -> i32),
+                    link_name,
+                    abi,
+                    args,
+                )?;
+                this.accept4(socket, address, address_len, Some(flags), dest)?;
+            }
+            "connect" => {
+                let [socket, address, address_len] = this.check_shim_sig(
+                    shim_sig!(extern "C" fn(i32, *const _, libc::socklen_t) -> i32),
+                    link_name,
+                    abi,
+                    args,
+                )?;
+                this.connect(socket, address, address_len, dest)?;
+            }
             "setsockopt" => {
                 let [socket, level, option_name, option_value, option_len] = this.check_shim_sig(
                     shim_sig!(extern "C" fn(i32, i32, i32, *const _, libc::socklen_t) -> i32),
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 f64ee3b..de08f4c 100644
--- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
@@ -165,6 +165,19 @@ fn emulate_foreign_item_inner(
                 let errno_place = this.last_error_place()?;
                 this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
             }
+            "__xuname" => {
+                // FreeBSD uses __xuname under the hood to implement uname, see:
+                // https://github.com/freebsd/freebsd-src/blob/3542d60fb8042474f66fbf2d779ed8c5a80d0f78/sys/sys/utsname.h#L64
+                // https://github.com/freebsd/freebsd-src/blob/3542d60fb8042474f66fbf2d779ed8c5a80d0f78/lib/libc/gen/uname.c#L44
+                let [size, uname] = this.check_shim_sig(
+                    shim_sig!(extern "C" fn(i32, *mut _) -> i32),
+                    link_name,
+                    abi,
+                    args,
+                )?;
+                let result = this.uname(uname, Some(size))?;
+                this.write_scalar(result, dest)?;
+            }
 
             // Incomplete shims that we "stub out" just to get pre-main initialization code to work.
             // These shims are enabled only when the caller is in the standard library.
diff --git a/src/tools/miri/src/shims/unix/linux_like/syscall.rs b/src/tools/miri/src/shims/unix/linux_like/syscall.rs
index 106e6c4..875fd09 100644
--- a/src/tools/miri/src/shims/unix/linux_like/syscall.rs
+++ b/src/tools/miri/src/shims/unix/linux_like/syscall.rs
@@ -7,6 +7,7 @@
 use crate::shims::unix::env::EvalContextExt;
 use crate::shims::unix::linux_like::eventfd::EvalContextExt as _;
 use crate::shims::unix::linux_like::sync::futex;
+use crate::shims::unix::socket::EvalContextExt as _;
 use crate::*;
 
 pub fn syscall<'tcx>(
@@ -26,6 +27,7 @@ pub fn syscall<'tcx>(
     let sys_futex = ecx.eval_libc("SYS_futex").to_target_usize(ecx)?;
     let sys_eventfd2 = ecx.eval_libc("SYS_eventfd2").to_target_usize(ecx)?;
     let sys_gettid = ecx.eval_libc("SYS_gettid").to_target_usize(ecx)?;
+    let sys_accept4 = ecx.eval_libc("SYS_accept4").to_target_usize(ecx)?;
 
     match ecx.read_target_usize(op)? {
         // `libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)`
@@ -59,6 +61,12 @@ pub fn syscall<'tcx>(
             let result = ecx.unix_gettid("SYS_gettid")?;
             ecx.write_int(result.to_u32()?, dest)?;
         }
+        num if num == sys_accept4 => {
+            // Used on Android.
+            let [socket, address, address_len, flags] =
+                check_min_vararg_count("syscall(SYS_accept4, ...)", varargs)?;
+            ecx.accept4(socket, address, address_len, Some(flags), dest)?;
+        }
         num => {
             throw_unsup_format!("syscall: unsupported syscall number {num}");
         }
diff --git a/src/tools/miri/src/shims/unix/socket.rs b/src/tools/miri/src/shims/unix/socket.rs
index af645f8..f9b3ca4 100644
--- a/src/tools/miri/src/shims/unix/socket.rs
+++ b/src/tools/miri/src/shims/unix/socket.rs
@@ -1,19 +1,18 @@
 use std::cell::{Cell, RefCell};
-use std::iter;
-use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, TcpListener};
+use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
+use std::{io, iter};
 
+use mio::Interest;
+use mio::event::Source;
+use mio::net::{TcpListener, TcpStream};
 use rustc_abi::Size;
 use rustc_const_eval::interpret::{InterpResult, interp_ok};
 use rustc_middle::throw_unsup_format;
 use rustc_target::spec::Os;
 
-use crate::diagnostics::SpanDedupDiagnostic;
-use crate::shims::files::{FdId, FileDescription};
+use crate::shims::files::{FdId, FileDescription, FileDescriptionRef};
 use crate::{OpTy, Scalar, *};
 
-/// Backlog value passed to the `listen` syscall by the standard library
-const SUPPORTED_LISTEN_BACKLOG: i32 = 128;
-
 #[derive(Debug, PartialEq)]
 enum SocketFamily {
     // IPv4 internet protocols
@@ -22,6 +21,22 @@ enum SocketFamily {
     IPv6,
 }
 
+enum SocketIoError {
+    /// The socket is not yet ready. Either EINPROGRESS or ENOTCONNECTED occurred.
+    NotReady,
+    /// Any other kind of I/O error.
+    Other(io::Error),
+}
+
+impl From<io::Error> for SocketIoError {
+    fn from(value: io::Error) -> Self {
+        match value.kind() {
+            io::ErrorKind::InProgress | io::ErrorKind::NotConnected => Self::NotReady,
+            _ => Self::Other(value),
+        }
+    }
+}
+
 #[derive(Debug)]
 enum SocketState {
     /// No syscall after `socket` has been made.
@@ -32,6 +47,69 @@ enum SocketState {
     /// The `listen` syscall has been called on the socket.
     /// This is only reachable from the [`SocketState::Bound`] state.
     Listening(TcpListener),
+    /// The `connect` syscall has been called and we weren't yet able
+    /// to ensure the connection is established. This is only reachable
+    /// from the [`SocketState::Initial`] state.
+    Connecting(TcpStream),
+    /// The `connect` syscall has been called on the socket and
+    /// we ensured that the connection is established, or
+    /// the socket was created by the `accept` syscall.
+    /// For a socket created using the `connect` syscall, this is
+    /// only reachable from the [`SocketState::Connecting`] state.
+    Connected(TcpStream),
+}
+
+impl SocketState {
+    /// If the socket is currently in [`SocketState::Connecting`], try to ensure
+    /// that the connection is established by first checking that [`TcpStream::take_error`]
+    /// doesn't return an error and then by checking that [`TcpStream::peer_addr`]
+    /// returns the address of the connected peer.
+    ///
+    /// If the connection is established or the socket is in any other state,
+    /// [`Ok`] is returned.
+    ///
+    /// **Important**: On Windows hosts this function can only be used to ensure a socket is connected
+    /// _after_ a [`Interest::WRITABLE`] event was received.
+    pub fn try_set_connected(&mut self) -> Result<(), SocketIoError> {
+        // Further explanation of the limitation on Windows hosts:
+        // Windows treats sockets which are connecting as connected until either the connection timeout hits
+        // or an error occurs. Thus, the [`TcpStream::peer_addr`] method returns [`Ok`] with the provided peer
+        // address even when the connection might not yet be established.
+
+        let SocketState::Connecting(stream) = self else { return Ok(()) };
+
+        if let Ok(Some(e)) = stream.take_error() {
+            // There was an error whilst connecting.
+            let e = SocketIoError::from(e);
+            // We won't get EINPROGRESS or ENOTCONNECTED here
+            // so we need to reset the state.
+            assert!(matches!(e, SocketIoError::Other(_)));
+            // Go back to initial state as the only way of getting into the
+            // `Connecting` state is from the `Initial` state.
+            *self = SocketState::Initial;
+            return Err(e);
+        }
+
+        if let Err(e) = stream.peer_addr() {
+            let e = SocketIoError::from(e);
+            if let SocketIoError::Other(_) = &e {
+                // All other errors are fatal for a socket and thus the state needs to be reset.
+                *self = SocketState::Initial;
+            }
+            return Err(e);
+        };
+
+        // We just read the peer address without an error so we can be
+        // sure that the connection is established.
+
+        // Temporarily use dummy state to take ownership of the stream.
+        let SocketState::Connecting(stream) = std::mem::replace(self, SocketState::Initial) else {
+            // At the start of the function we ensured that we're currently connecting.
+            unreachable!()
+        };
+        *self = SocketState::Connected(stream);
+        Ok(())
+    }
 }
 
 #[derive(Debug)]
@@ -132,7 +210,7 @@ fn socket(
         } else {
             throw_unsup_format!(
                 "socket: domain {:#x} is unsupported, only AF_INET and \
-                                AF_INET6 are allowed.",
+                AF_INET6 are allowed.",
                 domain
             );
         };
@@ -140,14 +218,14 @@ fn socket(
         if flags != this.eval_libc_i32("SOCK_STREAM") {
             throw_unsup_format!(
                 "socket: type {:#x} is unsupported, only SOCK_STREAM, \
-                                SOCK_CLOEXEC and SOCK_NONBLOCK are allowed",
+                SOCK_CLOEXEC and SOCK_NONBLOCK are allowed",
                 flags
             );
         }
         if protocol != 0 {
             throw_unsup_format!(
                 "socket: socket protocol {protocol} is unsupported, \
-                                only 0 is allowed"
+                only 0 is allowed"
             );
         }
 
@@ -177,12 +255,12 @@ fn bind(
 
         // Get the file handle
         let Some(fd) = this.machine.fds.get(socket) else {
-            return interp_ok(this.eval_libc("EBADF"));
+            return this.set_last_error_and_return_i32(LibcError("EBADF"));
         };
 
         let Some(socket) = fd.downcast::<Socket>() else {
             // Man page specifies to return ENOTSOCK if `fd` is not a socket.
-            return interp_ok(this.eval_libc("ENOTSOCK"));
+            return this.set_last_error_and_return_i32(LibcError("ENOTSOCK"));
         };
 
         assert!(this.machine.communicate(), "cannot have `Socket` with isolation enabled!");
@@ -200,7 +278,7 @@ fn bind(
                     // Attempted to bind an address from a family that doesn't match
                     // the family of the socket.
                     let err = if matches!(this.tcx.sess.target.os, Os::Linux | Os::Android) {
-                        // Linux man page states that `EINVAL` is used when there is an addres family mismatch.
+                        // Linux man page states that `EINVAL` is used when there is an address family mismatch.
                         // See <https://man7.org/linux/man-pages/man2/bind.2.html>
                         LibcError("EINVAL")
                     } else {
@@ -214,10 +292,15 @@ fn bind(
 
                 *state = SocketState::Bound(address);
             }
+            SocketState::Connecting(_) | SocketState::Connected(_) =>
+                throw_unsup_format!(
+                    "bind: socket is already connected and binding a
+                    connected socket is unsupported"
+                ),
             SocketState::Bound(_) | SocketState::Listening(_) =>
                 throw_unsup_format!(
                     "bind: socket is already bound and binding a socket \
-                                    multiple times is unsupported"
+                    multiple times is unsupported"
                 ),
         }
 
@@ -228,37 +311,24 @@ fn listen(&mut self, socket: &OpTy<'tcx>, backlog: &OpTy<'tcx>) -> InterpResult<
         let this = self.eval_context_mut();
 
         let socket = this.read_scalar(socket)?.to_i32()?;
-        let backlog = this.read_scalar(backlog)?.to_i32()?;
+        // Since the backlog value is just a performance hint we can ignore it.
+        let _backlog = this.read_scalar(backlog)?.to_i32()?;
 
         // Get the file handle
         let Some(fd) = this.machine.fds.get(socket) else {
-            return interp_ok(this.eval_libc("EBADF"));
+            return this.set_last_error_and_return_i32(LibcError("EBADF"));
         };
 
         let Some(socket) = fd.downcast::<Socket>() else {
             // Man page specifies to return ENOTSOCK if `fd` is not a socket.
-            return interp_ok(this.eval_libc("ENOTSOCK"));
+            return this.set_last_error_and_return_i32(LibcError("ENOTSOCK"));
         };
 
         assert!(this.machine.communicate(), "cannot have `Socket` with isolation enabled!");
 
-        // Only allow the same backlog value as the standard library uses since the standard library
-        // doesn't provide a way to set a custom value.
-        if backlog != SUPPORTED_LISTEN_BACKLOG {
-            // The first time this happens at a particular location, print a warning.
-            static DEDUP: SpanDedupDiagnostic = SpanDedupDiagnostic::new();
-            this.dedup_diagnostic(&DEDUP, |first| {
-                NonHaltingDiagnostic::SocketListenUnsupportedBacklog {
-                    details: first,
-                    provided: backlog,
-                    supported: SUPPORTED_LISTEN_BACKLOG,
-                }
-            });
-        }
-
         let mut state = socket.state.borrow_mut();
 
-        match &*state {
+        match *state {
             SocketState::Bound(socket_addr) =>
                 match TcpListener::bind(socket_addr) {
                     Ok(listener) => *state = SocketState::Listening(listener),
@@ -272,11 +342,160 @@ fn listen(&mut self, socket: &OpTy<'tcx>, backlog: &OpTy<'tcx>) -> InterpResult<
             SocketState::Listening(_) => {
                 throw_unsup_format!("listen: listening on a socket multiple times is unsupported")
             }
+            SocketState::Connecting(_) | SocketState::Connected(_) => {
+                throw_unsup_format!("listen: listening on a connected socket is unsupported")
+            }
         }
 
         interp_ok(Scalar::from_i32(0))
     }
 
+    /// For more information on the arguments see the accept manpage:
+    /// <https://linux.die.net/man/2/accept4>
+    fn accept4(
+        &mut self,
+        socket: &OpTy<'tcx>,
+        address: &OpTy<'tcx>,
+        address_len: &OpTy<'tcx>,
+        flags: Option<&OpTy<'tcx>>,
+        // Location where the output scalar is written to.
+        dest: &MPlaceTy<'tcx>,
+    ) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+
+        let socket = this.read_scalar(socket)?.to_i32()?;
+        let address_ptr = this.read_pointer(address)?;
+        let address_len_ptr = this.read_pointer(address_len)?;
+        let mut flags =
+            if let Some(flags) = flags { this.read_scalar(flags)?.to_i32()? } else { 0 };
+
+        // Get the file handle
+        let Some(fd) = this.machine.fds.get(socket) else {
+            return this.set_last_error_and_return(LibcError("EBADF"), dest);
+        };
+
+        let Some(socket) = fd.downcast::<Socket>() else {
+            // Man page specifies to return ENOTSOCK if `fd` is not a socket.
+            return this.set_last_error_and_return(LibcError("ENOTSOCK"), dest);
+        };
+
+        assert!(this.machine.communicate(), "cannot have `Socket` with isolation enabled!");
+
+        if !matches!(*socket.state.borrow(), SocketState::Listening(_)) {
+            throw_unsup_format!(
+                "accept4: accepting incoming connections is only allowed when socket is listening"
+            )
+        };
+
+        let mut is_client_sock_nonblock = false;
+
+        // Interpret the flag. Every flag we recognize is "subtracted" from `flags`, so
+        // if there is anything left at the end, that's an unsupported flag.
+        if matches!(
+            this.tcx.sess.target.os,
+            Os::Linux | Os::Android | Os::FreeBsd | Os::Solaris | Os::Illumos
+        ) {
+            // SOCK_NONBLOCK and SOCK_CLOEXEC only exist on Linux, Android, FreeBSD,
+            // Solaris, and Illumos targets
+            let sock_nonblock = this.eval_libc_i32("SOCK_NONBLOCK");
+            let sock_cloexec = this.eval_libc_i32("SOCK_CLOEXEC");
+            if flags & sock_nonblock == sock_nonblock {
+                is_client_sock_nonblock = true;
+                flags &= !sock_nonblock;
+            }
+            if flags & sock_cloexec == sock_cloexec {
+                // We don't support `exec` so we can ignore this.
+                flags &= !sock_cloexec;
+            }
+        }
+
+        if flags != 0 {
+            throw_unsup_format!(
+                "accept4: flag {flags:#x} is unsupported, only SOCK_CLOEXEC \
+                and SOCK_NONBLOCK are allowed",
+            );
+        }
+
+        if socket.is_non_block.get() {
+            throw_unsup_format!("accept4: non-blocking accept is unsupported")
+        }
+
+        // The socket is in blocking mode and thus the accept call should block
+        // until an incoming connection is ready.
+        this.block_for_accept(
+            address_ptr,
+            address_len_ptr,
+            is_client_sock_nonblock,
+            socket,
+            dest.clone(),
+        );
+        interp_ok(())
+    }
+
+    fn connect(
+        &mut self,
+        socket: &OpTy<'tcx>,
+        address: &OpTy<'tcx>,
+        address_len: &OpTy<'tcx>,
+        // Location where the output scalar is written to.
+        dest: &MPlaceTy<'tcx>,
+    ) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+
+        let socket = this.read_scalar(socket)?.to_i32()?;
+        let address = match this.socket_address(address, address_len, "connect")? {
+            Ok(address) => address,
+            Err(e) => return this.set_last_error_and_return(e, dest),
+        };
+
+        // Get the file handle
+        let Some(fd) = this.machine.fds.get(socket) else {
+            return this.set_last_error_and_return(LibcError("EBADF"), dest);
+        };
+
+        let Some(socket) = fd.downcast::<Socket>() else {
+            // Man page specifies to return ENOTSOCK if `fd` is not a socket
+            return this.set_last_error_and_return(LibcError("ENOTSOCK"), dest);
+        };
+
+        assert!(this.machine.communicate(), "cannot have `Socket` with isolation enabled!");
+
+        match &*socket.state.borrow() {
+            SocketState::Initial => { /* fall-through to below */ }
+            // The socket is already in a connecting state.
+            SocketState::Connecting(_) =>
+                return this.set_last_error_and_return(LibcError("EALREADY"), dest),
+            // We don't return EISCONN for already connected sockets, for which we're
+            // sure that the connection is established, since TCP sockets are usually
+            // allowed to be connected multiple times.
+            _ =>
+                throw_unsup_format!(
+                    "connect: connecting is only supported for sockets which are neither \
+                    bound, listening nor already connected"
+                ),
+        }
+
+        // Mio returns a potentially unconnected stream.
+        // We can be ensured that the connection is established when
+        // [`TcpStream::take_err`] and [`TcpStream::peer_addr`] both
+        // don't return errors.
+        // For non-blocking sockets we need to check that for every
+        // [`Interest::WRITEABLE`] event on the stream.
+        match TcpStream::connect(address) {
+            Ok(stream) => *socket.state.borrow_mut() = SocketState::Connecting(stream),
+            Err(e) => return this.set_last_error_and_return(e, dest),
+        };
+
+        if socket.is_non_block.get() {
+            throw_unsup_format!("connect: non-blocking connect is unsupported");
+        }
+
+        // The socket is in blocking mode and thus the connect call should block
+        // until the connection with the server is established.
+        this.block_for_connect(socket, dest.clone());
+        interp_ok(())
+    }
+
     fn setsockopt(
         &mut self,
         socket: &OpTy<'tcx>,
@@ -295,12 +514,12 @@ fn setsockopt(
 
         // Get the file handle
         let Some(fd) = this.machine.fds.get(socket) else {
-            return interp_ok(this.eval_libc("EBADF"));
+            return this.set_last_error_and_return_i32(LibcError("EBADF"));
         };
 
         let Some(_socket) = fd.downcast::<Socket>() else {
             // Man page specifies to return ENOTSOCK if `fd` is not a socket.
-            return interp_ok(this.eval_libc("ENOTSOCK"));
+            return this.set_last_error_and_return_i32(LibcError("ENOTSOCK"));
         };
 
         if level == this.eval_libc_i32("SOL_SOCKET") {
@@ -380,7 +599,7 @@ fn getsockname(
                     // random port will be and thus this is unsupported.
                     throw_unsup_format!(
                         "getsockname: when the port is 0, getting the socket address before \
-                                        calling `listen` or `connect` is unsupported"
+                        calling `listen` or `connect` is unsupported"
                     )
                 }
 
@@ -511,7 +730,7 @@ fn socket_address(
             // thus also no address family of another type should be supported.
             throw_unsup_format!(
                 "{foreign_name}: address family {family:#x} is unsupported, \
-                                only AF_INET and AF_INET6 are allowed"
+                only AF_INET and AF_INET6 are allowed"
             );
         };
 
@@ -672,4 +891,126 @@ fn write_socket_address(
 
         interp_ok(Ok(()))
     }
+
+    /// Block the thread until there's an incoming connection or an error occurred.
+    ///
+    /// This recursively calls itself should the operation still block for some reason.
+    fn block_for_accept(
+        &mut self,
+        address_ptr: Pointer,
+        address_len_ptr: Pointer,
+        is_client_sock_nonblock: bool,
+        socket: FileDescriptionRef<Socket>,
+        dest: MPlaceTy<'tcx>,
+    ) {
+        let this = self.eval_context_mut();
+        this.block_thread_for_io(
+            socket.clone(),
+            Interest::READABLE,
+            None,
+            callback!(@capture<'tcx> {
+                address_ptr: Pointer,
+                address_len_ptr: Pointer,
+                is_client_sock_nonblock: bool,
+                socket: FileDescriptionRef<Socket>,
+                dest: MPlaceTy<'tcx>,
+            } |this, kind: UnblockKind| {
+                assert_eq!(kind, UnblockKind::Ready);
+
+                let state = socket.state.borrow();
+
+                let SocketState::Listening(listener) = &*state else {
+                    // We checked that the socket is in listening state before blocking
+                    // and since there is no outgoing transition from that state this
+                    // should be unreachable.
+                    unreachable!()
+                };
+
+                let (stream, addr) = match listener.accept() {
+                    Ok(peer) => peer,
+                    Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
+                        // We need to block the thread again as it would still block.
+                        drop(state);
+                        this.block_for_accept(address_ptr, address_len_ptr, is_client_sock_nonblock, socket, dest);
+                        return interp_ok(())
+                    },
+                    Err(e) => return this.set_last_error_and_return(e, &dest),
+                };
+
+                let family = match addr {
+                    SocketAddr::V4(_) => SocketFamily::IPv4,
+                    SocketAddr::V6(_) => SocketFamily::IPv6,
+                };
+
+                if address_ptr != Pointer::null() {
+                    // We only attempt a write if the address pointer is not a null pointer.
+                    // If the address pointer is a null pointer the user isn't interested in the
+                    // address and we don't need to write anything.
+                    if let Err(e) = this.write_socket_address(&addr, address_ptr, address_len_ptr, "accept4")? {
+                      return this.set_last_error_and_return(e, &dest);
+                    };
+                }
+
+                let fd = this.machine.fds.new_ref(Socket {
+                    family,
+                    state: RefCell::new(SocketState::Connected(stream)),
+                    is_non_block: Cell::new(is_client_sock_nonblock),
+                });
+                let sockfd = this.machine.fds.insert(fd);
+                // We need to create the scalar using the destination size since
+                // `syscall(SYS_accept4, ...)` returns a long which doesn't match
+                // the int returned from the `accept`/`accept4` syscalls.
+                // See <https://man7.org/linux/man-pages/man2/syscall.2.html>.
+                this.write_scalar(Scalar::from_int(sockfd, dest.layout.size), &dest)
+            }),
+        );
+    }
+
+    /// Block the thread until the stream is connected or an error occurred.
+    fn block_for_connect(&mut self, socket: FileDescriptionRef<Socket>, dest: MPlaceTy<'tcx>) {
+        let this = self.eval_context_mut();
+        this.block_thread_for_io(
+            socket.clone(),
+            Interest::WRITABLE,
+            None,
+            callback!(@capture<'tcx> {
+                socket: FileDescriptionRef<Socket>,
+                dest: MPlaceTy<'tcx>,
+            } |this, kind: UnblockKind| {
+                assert_eq!(kind, UnblockKind::Ready);
+
+                let mut state = socket.state.borrow_mut();
+
+                // We received a "writable" event so `try_set_connected` is safe to call.
+                match state.try_set_connected() {
+                    Ok(_) => this.write_scalar(Scalar::from_i32(0), &dest),
+                     Err(SocketIoError::NotReady) => {
+                        // We need to block the thread again as the connection is still not yet ready.
+                        drop(state);
+                        this.block_for_connect(socket, dest);
+                        return interp_ok(())
+                    },
+                    Err(SocketIoError::Other(e)) => return this.set_last_error_and_return(e, &dest)
+                }
+            }),
+        );
+    }
+}
+
+impl VisitProvenance for FileDescriptionRef<Socket> {
+    // A socket doesn't contain any references to machine memory
+    // and thus we don't need to propagate the visit.
+    fn visit_provenance(&self, _visit: &mut VisitWith<'_>) {}
+}
+
+impl WithSource for FileDescriptionRef<Socket> {
+    fn with_source(&self, f: &mut dyn FnMut(&mut dyn Source) -> io::Result<()>) -> io::Result<()> {
+        let mut state = self.state.borrow_mut();
+        match &mut *state {
+            SocketState::Listening(listener) => f(listener),
+            SocketState::Connecting(stream) | SocketState::Connected(stream) => f(stream),
+            // We never try adding a socket which is not backed by a real socket to the poll registry.
+            _ => unreachable!(),
+        }
+    }
 }
diff --git a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs
index 9dbfc6d..d4ebdea 100644
--- a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs
@@ -133,6 +133,15 @@ fn emulate_foreign_item_inner(
                 let result = this.bind(socket, address, address_len)?;
                 this.write_scalar(result, dest)?;
             }
+            "__xnet_connect" => {
+                let [socket, address, address_len] = this.check_shim_sig(
+                    shim_sig!(extern "C" fn(i32, *const _, libc::socklen_t) -> i32),
+                    link_name,
+                    abi,
+                    args,
+                )?;
+                this.connect(socket, address, address_len, dest)?;
+            }
 
             // Miscellaneous
             "___errno" => {
diff --git a/src/tools/miri/src/shims/x86/avx512.rs b/src/tools/miri/src/shims/x86/avx512.rs
index 23538f0..8e1d22d 100644
--- a/src/tools/miri/src/shims/x86/avx512.rs
+++ b/src/tools/miri/src/shims/x86/avx512.rs
@@ -191,9 +191,9 @@ fn vpdpbusd<'tcx>(
     // fn vpdpbusd(src: i32x16, a: u8x64, b: i8x64) -> i32x16;
     // fn vpdpbusd256(src: i32x8, a: u8x32, b: i8x32) -> i32x8;
     // fn vpdpbusd128(src: i32x4, a: u8x16, b: i8x16) -> i32x4;
-    assert_eq!(dest_len, src_len);
-    assert_eq!(dest_len * 4, a_len);
-    assert_eq!(a_len, b_len);
+    assert_eq!(src_len, dest_len);
+    assert_eq!(a_len, dest_len.strict_mul(4));
+    assert_eq!(b_len, a_len);
 
     for i in 0..dest_len {
         let src = ecx.read_scalar(&ecx.project_index(&src, i)?)?.to_i32()?;
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.rs
index 6fec650..0245376 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.rs
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.rs
@@ -5,6 +5,7 @@
 use std::{mem, ptr};
 
 extern "C" fn thread_start() -> *mut libc::c_void {
+    //~^ERROR: calling a function with more arguments than it expected
     panic!()
 }
 
@@ -16,7 +17,6 @@ fn main() {
             mem::transmute(thread_start);
         assert_eq!(
             libc::pthread_create(&mut native, ptr::null(), thread_start, ptr::null_mut()),
-            //~^ERROR: calling a function with more arguments than it expected
             0
         );
         assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0);
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.stderr
index 979a1a8..e3509a2 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.stderr
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.stderr
@@ -1,14 +1,17 @@
 error: Undefined Behavior: calling a function with more arguments than it expected
   --> tests/fail-dep/concurrency/libc_pthread_create_too_few_args.rs:LL:CC
    |
-LL |             libc::pthread_create(&mut native, ptr::null(), thread_start, ptr::null_mut()),
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred due to this code
+LL | extern "C" fn thread_start() -> *mut libc::c_void {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: this is on thread `unnamed-ID`
-   = note: this error occurred while pushing a call frame onto an empty stack
-   = note: the span indicates which code caused the function to be called, but may not be the literal call site
+note: the current function got called indirectly due to this code
+  --> tests/fail-dep/concurrency/libc_pthread_create_too_few_args.rs:LL:CC
+   |
+LL |             libc::pthread_create(&mut native, ptr::null(), thread_start, ptr::null_mut()),
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.rs
index cb55b0f..28fdb1d 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.rs
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.rs
@@ -5,6 +5,7 @@
 use std::{mem, ptr};
 
 extern "C" fn thread_start(_null: *mut libc::c_void, _x: i32) -> *mut libc::c_void {
+    //~^ERROR: calling a function with fewer arguments than it requires
     panic!()
 }
 
@@ -16,7 +17,6 @@ fn main() {
             mem::transmute(thread_start);
         assert_eq!(
             libc::pthread_create(&mut native, ptr::null(), thread_start, ptr::null_mut()),
-            //~^ERROR: calling a function with fewer arguments than it requires
             0
         );
         assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0);
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.stderr
index e8ad65a..d6504f6 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.stderr
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.stderr
@@ -1,14 +1,17 @@
 error: Undefined Behavior: calling a function with fewer arguments than it requires
   --> tests/fail-dep/concurrency/libc_pthread_create_too_many_args.rs:LL:CC
    |
-LL |             libc::pthread_create(&mut native, ptr::null(), thread_start, ptr::null_mut()),
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred due to this code
+LL | extern "C" fn thread_start(_null: *mut libc::c_void, _x: i32) -> *mut libc::c_void {
+   |                                                      ^^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: this is on thread `unnamed-ID`
-   = note: this error occurred while pushing a call frame onto an empty stack
-   = note: the span indicates which code caused the function to be called, but may not be the literal call site
+note: the current function got called indirectly due to this code
+  --> tests/fail-dep/concurrency/libc_pthread_create_too_many_args.rs:LL:CC
+   |
+LL |             libc::pthread_create(&mut native, ptr::null(), thread_start, ptr::null_mut()),
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.stderr b/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.stderr
index 9d5e119..214b626 100644
--- a/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.stderr
+++ b/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at [3]: encountered uninitialized memory, but expected an integer
+error: Undefined Behavior: constructing invalid value of type [u8; 4]: at [3], encountered uninitialized memory, but expected an integer
   --> tests/fail-dep/libc/libc-read-and-uninit-premature-eof.rs:LL:CC
    |
 LL |         buf.assume_init();
diff --git a/src/tools/miri/tests/fail/branchless-select-i128-pointer.rs b/src/tools/miri/tests/fail/branchless-select-i128-pointer.rs
index 7147813..b425916 100644
--- a/src/tools/miri/tests/fail/branchless-select-i128-pointer.rs
+++ b/src/tools/miri/tests/fail/branchless-select-i128-pointer.rs
@@ -14,7 +14,7 @@ fn main() {
         // However, it drops provenance when transmuting to TwoPtrs, so this is UB.
         let val = unsafe {
             transmute::<_, &str>(
-                //~^ ERROR: constructing invalid value: encountered a dangling reference
+                //~^ ERROR: encountered a dangling reference
                 !mask & transmute::<_, TwoPtrs>("false !")
                     | mask & transmute::<_, TwoPtrs>("true !"),
             )
diff --git a/src/tools/miri/tests/fail/branchless-select-i128-pointer.stderr b/src/tools/miri/tests/fail/branchless-select-i128-pointer.stderr
index abcaf90..83dc2dd 100644
--- a/src/tools/miri/tests/fail/branchless-select-i128-pointer.stderr
+++ b/src/tools/miri/tests/fail/branchless-select-i128-pointer.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
+error: Undefined Behavior: constructing invalid value of type &str: encountered a dangling reference ($HEX[noalloc] has no provenance)
   --> tests/fail/branchless-select-i128-pointer.rs:LL:CC
    |
 LL | /             transmute::<_, &str>(
diff --git a/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_box.stderr b/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_box.stderr
index 0ae38c3..6467131 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_box.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_box.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a dangling box (0x18[noalloc] has no provenance)
+error: Undefined Behavior: constructing invalid value of type std::boxed::Box<i32>: encountered a dangling box (0x18[noalloc] has no provenance)
   --> tests/fail/dangling_pointers/deref_dangling_box.rs:LL:CC
    |
 LL |     let _val = unsafe { addr_of_mut!(**outer) };
diff --git a/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_ref.stderr b/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_ref.stderr
index c10dc19..5520947 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_ref.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/deref_dangling_ref.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a dangling reference (0x18[noalloc] has no provenance)
+error: Undefined Behavior: constructing invalid value of type &mut i32: encountered a dangling reference (0x18[noalloc] has no provenance)
   --> tests/fail/dangling_pointers/deref_dangling_ref.rs:LL:CC
    |
 LL |     let _val = unsafe { addr_of_mut!(**outer) };
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr b/src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr
index 74102f7..df82e08 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
+error: Undefined Behavior: constructing invalid value of type &SliceWithHead: encountered a dangling reference (going beyond the bounds of its allocation)
   --> tests/fail/dangling_pointers/dyn_size.rs:LL:CC
    |
 LL |     let _ptr = unsafe { &*ptr };
diff --git a/src/tools/miri/tests/fail/dyn-upcast-nop-wrong-trait.stderr b/src/tools/miri/tests/fail/dyn-upcast-nop-wrong-trait.stderr
index 65ad97f..86a695f 100644
--- a/src/tools/miri/tests/fail/dyn-upcast-nop-wrong-trait.stderr
+++ b/src/tools/miri/tests/fail/dyn-upcast-nop-wrong-trait.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: wrong trait in wide pointer vtable: expected `std::fmt::Debug + std::marker::Send + std::marker::Sync`, but encountered `std::fmt::Display`
+error: Undefined Behavior: constructing invalid value of type *const dyn std::fmt::Debug + std::marker::Send + std::marker::Sync: wrong trait in wide pointer vtable: expected `std::fmt::Debug + std::marker::Send + std::marker::Sync`, but encountered `std::fmt::Display`
   --> tests/fail/dyn-upcast-nop-wrong-trait.rs:LL:CC
    |
 LL |     let ptr: *const (dyn fmt::Debug + Send + Sync) = unsafe { std::mem::transmute(ptr) };
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs
index b6cda60..1fb597f 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs
@@ -21,8 +21,6 @@ fn main() {
             // This specifically uses a type with scalar representation to tempt Miri to use the
             // efficient way of storing local variables (outside adressable memory).
             Call(_unit = callee(Move(non_copy), Move(non_copy)), ReturnTo(after_call), UnwindContinue())
-            //~[stack]^ ERROR: not granting access
-            //~[tree]| ERROR: /read access .* forbidden/
         }
         after_call = {
             Return()
@@ -32,6 +30,8 @@ fn main() {
 
 #[expect(unused_variables, unused_assignments)]
 fn callee(x: S, mut y: S) {
+    //~[stack]^ ERROR: not granting access
+    //~[tree]| ERROR: /read access .* forbidden/
     // With the setup above, if `x` and `y` are both moved,
     // then writing to `y` will change the value stored in `x`!
     y.0 = 0;
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.stack.stderr
index a86c68c..14df4eb 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.stack.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected
   --> tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
    |
-LL |             Call(_unit = callee(Move(non_copy), Move(non_copy)), ReturnTo(after_call), UnwindContinue())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
+LL | fn callee(x: S, mut y: S) {
+   |                 ^^^^^ Undefined Behavior occurred here
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
@@ -14,8 +14,13 @@
 help: <TAG> is this argument
   --> tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
    |
-LL |     y.0 = 0;
-   |     ^^^^^^^
+LL | fn callee(x: S, mut y: S) {
+   |           ^
+   = note: stack backtrace:
+           0: callee
+               at tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
+           1: main
+               at tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.tree.stderr
index d62adee..7012c4f 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.tree.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: read access through <TAG> (root of the allocation) at ALLOC[0x0] is forbidden
   --> tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
    |
-LL |             Call(_unit = callee(Move(non_copy), Move(non_copy)), ReturnTo(after_call), UnwindContinue())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
+LL | fn callee(x: S, mut y: S) {
+   |                 ^^^^^ Undefined Behavior occurred here
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information
@@ -17,14 +17,19 @@
 help: the protected tag <TAG> was created here, in the initial state Reserved
   --> tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
    |
-LL |     y.0 = 0;
-   |     ^^^^^^^
+LL | fn callee(x: S, mut y: S) {
+   |           ^
 help: the protected tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4]
   --> tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
    |
-LL |     y.0 = 0;
-   |     ^^^^^^^
+LL | fn callee(x: S, mut y: S) {
+   |           ^
    = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference
+   = note: stack backtrace:
+           0: callee
+               at tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
+           1: main
+               at tests/fail/function_calls/arg_inplace_locals_alias.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs
index 3cb8ee2..b3d43ca 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs
@@ -20,8 +20,6 @@ fn main() {
             // This specifically uses a type with scalar representation to tempt Miri to use the
             // efficient way of storing local variables (outside adressable memory).
             Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue())
-            //~[stack]^ ERROR: not granting access
-            //~[tree]| ERROR: /reborrow .* forbidden/
         }
         after_call = {
             Return()
@@ -30,5 +28,7 @@ fn main() {
 }
 
 fn callee(x: S) -> S {
+    //~[stack]^ ERROR: not granting access
+    //~[tree]| ERROR: /reborrow .* forbidden/
     x
 }
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.stack.stderr
index 491d01c..21fcfb9 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.stack.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected
   --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
    |
-LL |             Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
+LL | fn callee(x: S) -> S {
+   |                    ^ Undefined Behavior occurred here
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
@@ -14,8 +14,13 @@
 help: <TAG> is this argument
   --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
    |
-LL |     x
-   |     ^
+LL | fn callee(x: S) -> S {
+   |           ^
+   = note: stack backtrace:
+           0: callee
+               at tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+           1: main
+               at tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr
index 3c1038d..e4d4e87 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: reborrow through <TAG> (root of the allocation) at ALLOC[0x0] is forbidden
   --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
    |
-LL |             Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
+LL | fn callee(x: S) -> S {
+   |                    ^ Undefined Behavior occurred here
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information
@@ -17,14 +17,19 @@
 help: the protected tag <TAG> was created here, in the initial state Reserved
   --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
    |
-LL |     x
-   |     ^
+LL | fn callee(x: S) -> S {
+   |           ^
 help: the protected tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4]
   --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
    |
-LL |     x
-   |     ^
+LL | fn callee(x: S) -> S {
+   |           ^
    = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference
+   = note: stack backtrace:
+           0: callee
+               at tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+           1: main
+               at tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr
index 952f227..c754acd 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr
@@ -19,8 +19,8 @@
 help: <TAG> is this argument
   --> tests/fail/function_calls/arg_inplace_mutate.rs:LL:CC
    |
-LL |     unsafe { ptr.write(S(0)) };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn callee(x: S, ptr: *mut S) {
+   |           ^
    = note: stack backtrace:
            0: callee
                at tests/fail/function_calls/arg_inplace_mutate.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr
index 095dc7e..c210d5c 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr
@@ -22,13 +22,13 @@
 help: the protected tag <TAG> was created here, in the initial state Reserved
   --> tests/fail/function_calls/arg_inplace_mutate.rs:LL:CC
    |
-LL |     unsafe { ptr.write(S(0)) };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn callee(x: S, ptr: *mut S) {
+   |           ^
 help: the protected tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4]
   --> tests/fail/function_calls/arg_inplace_mutate.rs:LL:CC
    |
-LL |     unsafe { ptr.write(S(0)) };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn callee(x: S, ptr: *mut S) {
+   |           ^
    = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference
    = note: stack backtrace:
            0: callee
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr
index d625d1d..b7eb3c5 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr
@@ -19,8 +19,8 @@
 help: <TAG> is this argument
   --> tests/fail/function_calls/arg_inplace_observe_during.rs:LL:CC
    |
-LL |     x.0 = 0;
-   |     ^^^^^^^
+LL | fn change_arg(mut x: S, ptr: *mut S) {
+   |               ^^^^^
    = note: stack backtrace:
            0: change_arg
                at tests/fail/function_calls/arg_inplace_observe_during.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr
index a01c040..e79cf08 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr
@@ -22,13 +22,13 @@
 help: the protected tag <TAG> was created here, in the initial state Reserved
   --> tests/fail/function_calls/arg_inplace_observe_during.rs:LL:CC
    |
-LL |     x.0 = 0;
-   |     ^^^^^^^
+LL | fn change_arg(mut x: S, ptr: *mut S) {
+   |               ^^^^^
 help: the protected tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4]
   --> tests/fail/function_calls/arg_inplace_observe_during.rs:LL:CC
    |
-LL |     x.0 = 0;
-   |     ^^^^^^^
+LL | fn change_arg(mut x: S, ptr: *mut S) {
+   |               ^^^^^
    = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference
    = note: stack backtrace:
            0: change_arg
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_wrong_arguments.rs b/src/tools/miri/tests/fail/function_calls/exported_symbol_wrong_arguments.rs
index a108944..81fa672 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_wrong_arguments.rs
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_wrong_arguments.rs
@@ -1,9 +1,9 @@
 #[no_mangle]
-fn foo() {}
+fn foo() {} //~ ERROR: calling a function with more arguments than it expected
 
 fn main() {
     extern "Rust" {
         fn foo(_: i32);
     }
-    unsafe { foo(1) } //~ ERROR: calling a function with more arguments than it expected
+    unsafe { foo(1) }
 }
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_wrong_arguments.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_wrong_arguments.stderr
index 75c060e..4c481e8 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_wrong_arguments.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_wrong_arguments.stderr
@@ -1,11 +1,16 @@
 error: Undefined Behavior: calling a function with more arguments than it expected
   --> tests/fail/function_calls/exported_symbol_wrong_arguments.rs:LL:CC
    |
-LL |     unsafe { foo(1) }
-   |              ^^^^^^ Undefined Behavior occurred here
+LL | fn foo() {}
+   | ^^^^^^^^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: stack backtrace:
+           0: foo
+               at tests/fail/function_calls/exported_symbol_wrong_arguments.rs:LL:CC
+           1: main
+               at tests/fail/function_calls/exported_symbol_wrong_arguments.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr
index 73c562c..5cf0fd4 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr
@@ -19,8 +19,8 @@
 help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique in-place function argument/return passing protection
   --> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC
    |
-LL |     unsafe { ptr.read() };
-   |     ^^^^^^^^^^^^^^^^^^^^^
+LL | fn myfun(ptr: *mut i32) -> i32 {
+   |                            ^^^
    = note: stack backtrace:
            0: myfun
                at tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr
index 0dc1378..cc5f4a8 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.tree.stderr
@@ -22,13 +22,13 @@
 help: the protected tag <TAG> was created here, in the initial state Reserved
   --> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC
    |
-LL |     unsafe { ptr.read() };
-   |     ^^^^^^^^^^^^^^^^^^^^^
+LL | fn myfun(ptr: *mut i32) -> i32 {
+   |                            ^^^
 help: the protected tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4]
   --> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC
    |
-LL |     unsafe { ptr.read() };
-   |     ^^^^^^^^^^^^^^^^^^^^^
+LL | fn myfun(ptr: *mut i32) -> i32 {
+   |                            ^^^
    = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference
    = note: stack backtrace:
            0: myfun
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr
index 6654ddc..133aa8c 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr
@@ -19,8 +19,8 @@
 help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique in-place function argument/return passing protection
   --> tests/fail/function_calls/return_pointer_aliasing_write.rs:LL:CC
    |
-LL |     unsafe { ptr.write(0) };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn myfun(ptr: *mut i32) -> i32 {
+   |                            ^^^
    = note: stack backtrace:
            0: myfun
                at tests/fail/function_calls/return_pointer_aliasing_write.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr
index 6472dfd..fb87eea 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.tree.stderr
@@ -22,13 +22,13 @@
 help: the protected tag <TAG> was created here, in the initial state Reserved
   --> tests/fail/function_calls/return_pointer_aliasing_write.rs:LL:CC
    |
-LL |     unsafe { ptr.write(0) };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn myfun(ptr: *mut i32) -> i32 {
+   |                            ^^^
 help: the protected tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4]
   --> tests/fail/function_calls/return_pointer_aliasing_write.rs:LL:CC
    |
-LL |     unsafe { ptr.write(0) };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn myfun(ptr: *mut i32) -> i32 {
+   |                            ^^^
    = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference
    = note: stack backtrace:
            0: myfun
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr
index 79f4d2c..07ed6d1 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr
@@ -19,8 +19,8 @@
 help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique in-place function argument/return passing protection
   --> tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs:LL:CC
    |
-LL |     become myfun2(ptr)
-   |     ^^^^^^^^^^^^^^^^^^
+LL | fn myfun(ptr: *mut i32) -> i32 {
+   |                            ^^^
    = note: stack backtrace:
            0: myfun2
                at tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr
index 82b898d..e3c5d6b 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.tree.stderr
@@ -22,13 +22,13 @@
 help: the protected tag <TAG> was created here, in the initial state Reserved
   --> tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs:LL:CC
    |
-LL |     unsafe { ptr.write(0) };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn myfun2(ptr: *mut i32) -> i32 {
+   |                             ^^^
 help: the protected tag <TAG> later transitioned to Unique due to a child write access at offsets [0x0..0x4]
   --> tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs:LL:CC
    |
-LL |     unsafe { ptr.write(0) };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn myfun2(ptr: *mut i32) -> i32 {
+   |                             ^^^
    = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference
    = note: stack backtrace:
            0: myfun2
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs
index 26f2e73..beb0f72 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs
@@ -12,10 +12,10 @@ struct S(
 type A = [i32; 4];
 
 fn main() {
-    fn f(_: S) {}
+    fn f(_: S) {} //~ ERROR: type S passing argument of type [i32; 4]
 
     // These two types have the same size but are still not compatible.
     let g = unsafe { std::mem::transmute::<fn(S), fn(A)>(f) };
 
-    g(Default::default()) //~ ERROR: type S passing argument of type [i32; 4]
+    g(Default::default())
 }
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr
index 56e69e8..62ba807 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr
@@ -1,13 +1,18 @@
 error: Undefined Behavior: calling a function whose parameter #1 has type S passing argument of type [i32; 4]
   --> tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs:LL:CC
    |
-LL |     g(Default::default())
-   |     ^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
+LL |     fn f(_: S) {}
+   |          ^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
    = help: if you think this code should be accepted anyway, please report an issue with Miri
+   = note: stack backtrace:
+           0: main::f
+               at tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs:LL:CC
+           1: main
+               at tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.rs
index 0cca4a1..a40e5b4 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.rs
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.rs
@@ -1,7 +1,7 @@
 fn main() {
-    fn f(_: f32) {}
+    fn f(_: f32) {} //~ ERROR: type f32 passing argument of type i32
 
     let g = unsafe { std::mem::transmute::<fn(f32), fn(i32)>(f) };
 
-    g(42) //~ ERROR: type f32 passing argument of type i32
+    g(42)
 }
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr
index cbef9d2..8147d00 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr
@@ -1,13 +1,18 @@
 error: Undefined Behavior: calling a function whose parameter #1 has type f32 passing argument of type i32
   --> tests/fail/function_pointers/abi_mismatch_int_vs_float.rs:LL:CC
    |
-LL |     g(42)
-   |     ^^^^^ Undefined Behavior occurred here
+LL |     fn f(_: f32) {}
+   |          ^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
    = help: if you think this code should be accepted anyway, please report an issue with Miri
+   = note: stack backtrace:
+           0: main::f
+               at tests/fail/function_pointers/abi_mismatch_int_vs_float.rs:LL:CC
+           1: main
+               at tests/fail/function_pointers/abi_mismatch_int_vs_float.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.rs
index 053a4a5..8c2d064 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.rs
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.rs
@@ -1,7 +1,7 @@
 fn main() {
-    fn f(_: *const [i32]) {}
+    fn f(_: *const [i32]) {} //~ ERROR: type *const [i32] passing argument of type *const i32
 
     let g = unsafe { std::mem::transmute::<fn(*const [i32]), fn(*const i32)>(f) };
 
-    g(&42 as *const i32) //~ ERROR: type *const [i32] passing argument of type *const i32
+    g(&42 as *const i32)
 }
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr
index cd14ea1..f9195a8 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr
@@ -1,13 +1,18 @@
 error: Undefined Behavior: calling a function whose parameter #1 has type *const [i32] passing argument of type *const i32
   --> tests/fail/function_pointers/abi_mismatch_raw_pointer.rs:LL:CC
    |
-LL |     g(&42 as *const i32)
-   |     ^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
+LL |     fn f(_: *const [i32]) {}
+   |          ^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
    = help: if you think this code should be accepted anyway, please report an issue with Miri
+   = note: stack backtrace:
+           0: main::f
+               at tests/fail/function_pointers/abi_mismatch_raw_pointer.rs:LL:CC
+           1: main
+               at tests/fail/function_pointers/abi_mismatch_raw_pointer.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.rs
index f3dffcc..79485a2 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.rs
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.rs
@@ -7,10 +7,10 @@
 struct S2(i32);
 
 fn callee(_s: S2) {}
+//~^ ERROR: type S2 passing argument of type S1
 
 fn main() {
     let fnptr: fn(S2) = callee;
     let fnptr: fn(S1) = unsafe { std::mem::transmute(fnptr) };
     fnptr(S1(NonZero::new(1).unwrap()));
-    //~^ ERROR: type S2 passing argument of type S1
 }
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.stderr
index 0e52dc0..3e4be1e 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_repr_C.stderr
@@ -1,13 +1,18 @@
 error: Undefined Behavior: calling a function whose parameter #1 has type S2 passing argument of type S1
   --> tests/fail/function_pointers/abi_mismatch_repr_C.rs:LL:CC
    |
-LL |     fnptr(S1(NonZero::new(1).unwrap()));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
+LL | fn callee(_s: S2) {}
+   |           ^^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
    = help: if you think this code should be accepted anyway, please report an issue with Miri
+   = note: stack backtrace:
+           0: callee
+               at tests/fail/function_pointers/abi_mismatch_repr_C.rs:LL:CC
+           1: main
+               at tests/fail/function_pointers/abi_mismatch_repr_C.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.rs
index 05b645c..8bf46af 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.rs
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.rs
@@ -1,9 +1,9 @@
 fn main() {
-    fn f() -> u32 {
+    fn f() -> u32 { //~ ERROR: type u32 passing return place of type ()
         42
     }
 
     let g = unsafe { std::mem::transmute::<fn() -> u32, fn()>(f) };
 
-    g() //~ ERROR: type u32 passing return place of type ()
+    g()
 }
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.stderr
index ba94090..9f20618 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_return_type.stderr
@@ -1,13 +1,18 @@
 error: Undefined Behavior: calling a function with return type u32 passing return place of type ()
   --> tests/fail/function_pointers/abi_mismatch_return_type.rs:LL:CC
    |
-LL |     g()
-   |     ^^^ Undefined Behavior occurred here
+LL |     fn f() -> u32 {
+   |               ^^^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
    = help: if you think this code should be accepted anyway, please report an issue with Miri
+   = note: stack backtrace:
+           0: main::f
+               at tests/fail/function_pointers/abi_mismatch_return_type.rs:LL:CC
+           1: main
+               at tests/fail/function_pointers/abi_mismatch_return_type.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.rs
index ca43c06..0b06496 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.rs
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.rs
@@ -1,7 +1,7 @@
 fn main() {
-    fn f(_: (i32, i32)) {}
+    fn f(_: (i32, i32)) {} //~ ERROR: type (i32, i32) passing argument of type i32
 
     let g = unsafe { std::mem::transmute::<fn((i32, i32)), fn(i32)>(f) };
 
-    g(42) //~ ERROR: type (i32, i32) passing argument of type i32
+    g(42)
 }
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.stderr
index ab9c0e7..b85ac39 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_simple.stderr
@@ -1,13 +1,18 @@
 error: Undefined Behavior: calling a function whose parameter #1 has type (i32, i32) passing argument of type i32
   --> tests/fail/function_pointers/abi_mismatch_simple.rs:LL:CC
    |
-LL |     g(42)
-   |     ^^^^^ Undefined Behavior occurred here
+LL |     fn f(_: (i32, i32)) {}
+   |          ^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
    = help: if you think this code should be accepted anyway, please report an issue with Miri
+   = note: stack backtrace:
+           0: main::f
+               at tests/fail/function_pointers/abi_mismatch_simple.rs:LL:CC
+           1: main
+               at tests/fail/function_pointers/abi_mismatch_simple.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.rs
index 920fb51..fc9a107 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.rs
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.rs
@@ -1,7 +1,7 @@
 fn main() {
-    fn f(_: (i32, i32)) {}
+    fn f(_: (i32, i32)) {} //~ ERROR: calling a function with fewer arguments than it requires
 
     let g = unsafe { std::mem::transmute::<fn((i32, i32)), fn()>(f) };
 
-    g() //~ ERROR: calling a function with fewer arguments than it requires
+    g()
 }
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.stderr
index 06e6ccb..271ec64 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_few_args.stderr
@@ -1,11 +1,16 @@
 error: Undefined Behavior: calling a function with fewer arguments than it requires
   --> tests/fail/function_pointers/abi_mismatch_too_few_args.rs:LL:CC
    |
-LL |     g()
-   |     ^^^ Undefined Behavior occurred here
+LL |     fn f(_: (i32, i32)) {}
+   |          ^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: stack backtrace:
+           0: main::f
+               at tests/fail/function_pointers/abi_mismatch_too_few_args.rs:LL:CC
+           1: main
+               at tests/fail/function_pointers/abi_mismatch_too_few_args.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.rs
index c0e96a4..744c528 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.rs
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.rs
@@ -1,7 +1,7 @@
 fn main() {
-    fn f() {}
+    fn f() {} //~ ERROR: calling a function with more arguments than it expected
 
     let g = unsafe { std::mem::transmute::<fn(), fn(i32)>(f) };
 
-    g(42) //~ ERROR: calling a function with more arguments than it expected
+    g(42)
 }
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.stderr
index d343eb8..1721f0f 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_too_many_args.stderr
@@ -1,11 +1,16 @@
 error: Undefined Behavior: calling a function with more arguments than it expected
   --> tests/fail/function_pointers/abi_mismatch_too_many_args.rs:LL:CC
    |
-LL |     g(42)
-   |     ^^^^^ Undefined Behavior occurred here
+LL |     fn f() {}
+   |     ^^^^^^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: stack backtrace:
+           0: main::f
+               at tests/fail/function_pointers/abi_mismatch_too_many_args.rs:LL:CC
+           1: main
+               at tests/fail/function_pointers/abi_mismatch_too_many_args.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.rs b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.rs
index dedcaac..ed5b469 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.rs
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.rs
@@ -2,10 +2,10 @@
 use std::simd;
 
 fn main() {
-    fn f(_: simd::u32x8) {}
+    fn f(_: simd::u32x8) {} //~ ERROR: type std::simd::Simd<u32, 8> passing argument of type std::simd::Simd<u64, 4>
 
     // These two vector types have the same size but are still not compatible.
     let g = unsafe { std::mem::transmute::<fn(simd::u32x8), fn(simd::u64x4)>(f) };
 
-    g(Default::default()) //~ ERROR: type std::simd::Simd<u32, 8> passing argument of type std::simd::Simd<u64, 4>
+    g(Default::default())
 }
diff --git a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.stderr b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.stderr
index 1176589..59823fa 100644
--- a/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/abi_mismatch_vector.stderr
@@ -1,13 +1,18 @@
 error: Undefined Behavior: calling a function whose parameter #1 has type std::simd::Simd<u32, 8> passing argument of type std::simd::Simd<u64, 4>
   --> tests/fail/function_pointers/abi_mismatch_vector.rs:LL:CC
    |
-LL |     g(Default::default())
-   |     ^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
+LL |     fn f(_: simd::u32x8) {}
+   |          ^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
    = help: if you think this code should be accepted anyway, please report an issue with Miri
+   = note: stack backtrace:
+           0: main::f
+               at tests/fail/function_pointers/abi_mismatch_vector.rs:LL:CC
+           1: main
+               at tests/fail/function_pointers/abi_mismatch_vector.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/intrinsics/typed-swap-invalid-array.stderr b/src/tools/miri/tests/fail/intrinsics/typed-swap-invalid-array.stderr
index 6cdcd11..e366aa9 100644
--- a/src/tools/miri/tests/fail/intrinsics/typed-swap-invalid-array.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/typed-swap-invalid-array.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at [0]: encountered 0x02, but expected a boolean
+error: Undefined Behavior: constructing invalid value of type [bool; 100]: at [0], encountered 0x02, but expected a boolean
   --> tests/fail/intrinsics/typed-swap-invalid-array.rs:LL:CC
    |
 LL |         typed_swap_nonoverlapping(a, b);
diff --git a/src/tools/miri/tests/fail/intrinsics/typed-swap-invalid-scalar.left.stderr b/src/tools/miri/tests/fail/intrinsics/typed-swap-invalid-scalar.left.stderr
index 223f743..58e2030 100644
--- a/src/tools/miri/tests/fail/intrinsics/typed-swap-invalid-scalar.left.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/typed-swap-invalid-scalar.left.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered 0x02, but expected a boolean
+error: Undefined Behavior: constructing invalid value of type bool: encountered 0x02, but expected a boolean
   --> tests/fail/intrinsics/typed-swap-invalid-scalar.rs:LL:CC
    |
 LL |         typed_swap_nonoverlapping(a, b);
diff --git a/src/tools/miri/tests/fail/intrinsics/typed-swap-invalid-scalar.right.stderr b/src/tools/miri/tests/fail/intrinsics/typed-swap-invalid-scalar.right.stderr
index 59e3920..b5bf8d7 100644
--- a/src/tools/miri/tests/fail/intrinsics/typed-swap-invalid-scalar.right.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/typed-swap-invalid-scalar.right.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered 0x03, but expected a boolean
+error: Undefined Behavior: constructing invalid value of type bool: encountered 0x03, but expected a boolean
   --> tests/fail/intrinsics/typed-swap-invalid-scalar.rs:LL:CC
    |
 LL |         typed_swap_nonoverlapping(a, b);
diff --git a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr
index d0f7cc1..47acb43 100644
--- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a value of the never type `!`
+error: Undefined Behavior: constructing invalid value of type !: encountered a value of the never type `!`
   --> tests/fail/intrinsics/uninit_uninhabited_type.rs:LL:CC
    |
 LL |     let _ = unsafe { std::mem::uninitialized::<!>() };
diff --git a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr
index 1646721..ab6f913 100644
--- a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a null function pointer
+error: Undefined Behavior: constructing invalid value of type fn(): encountered a null function pointer
   --> tests/fail/intrinsics/zero_fn_ptr.rs:LL:CC
    |
 LL |     let _ = unsafe { std::mem::zeroed::<fn()>() };
diff --git a/src/tools/miri/tests/fail/issue-miri-1112.stderr b/src/tools/miri/tests/fail/issue-miri-1112.stderr
index 0c5c6a9..9873591 100644
--- a/src/tools/miri/tests/fail/issue-miri-1112.stderr
+++ b/src/tools/miri/tests/fail/issue-miri-1112.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered $HEX[ALLOC]<TAG>, but expected a vtable pointer
+error: Undefined Behavior: constructing invalid value of type *mut FunnyPointer: encountered $HEX[ALLOC]<TAG>, but expected a vtable pointer
   --> tests/fail/issue-miri-1112.rs:LL:CC
    |
 LL |         let obj = std::mem::transmute::<FatPointer, *mut FunnyPointer>(obj);
diff --git a/src/tools/miri/tests/fail/match/closures/deref-in-pattern.stderr b/src/tools/miri/tests/fail/match/closures/deref-in-pattern.stderr
index cbb74df..9bbbc1b 100644
--- a/src/tools/miri/tests/fail/match/closures/deref-in-pattern.stderr
+++ b/src/tools/miri/tests/fail/match/closures/deref-in-pattern.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a dangling reference (use-after-free)
+error: Undefined Behavior: constructing invalid value of type &u32: encountered a dangling reference (use-after-free)
   --> tests/fail/match/closures/deref-in-pattern.rs:LL:CC
    |
 LL |       let _ = || {
diff --git a/src/tools/miri/tests/fail/match/closures/partial-pattern.stderr b/src/tools/miri/tests/fail/match/closures/partial-pattern.stderr
index b8ca045..ab50f9b 100644
--- a/src/tools/miri/tests/fail/match/closures/partial-pattern.stderr
+++ b/src/tools/miri/tests/fail/match/closures/partial-pattern.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a dangling reference (use-after-free)
+error: Undefined Behavior: constructing invalid value of type &u32: encountered a dangling reference (use-after-free)
   --> tests/fail/match/closures/partial-pattern.rs:LL:CC
    |
 LL |       let _ = || {
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr
index 6f097c3..8a3448f 100644
--- a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
+error: Undefined Behavior: constructing invalid value of type &i32: encountered a dangling reference ($HEX[noalloc] has no provenance)
   --> tests/fail/provenance/int_copy_looses_provenance0.rs:LL:CC
    |
 LL |     let _val = unsafe { *ptr.read() };
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr
index f3d1d8c..d4fb5b5 100644
--- a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
+error: Undefined Behavior: constructing invalid value of type &i32: encountered a dangling reference ($HEX[noalloc] has no provenance)
   --> tests/fail/provenance/int_copy_looses_provenance1.rs:LL:CC
    |
 LL |     let _val = unsafe { *ptr.read() };
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr
index 8374232..bdeb8a4 100644
--- a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
+error: Undefined Behavior: constructing invalid value of type &i32: encountered a dangling reference ($HEX[noalloc] has no provenance)
   --> tests/fail/provenance/int_copy_looses_provenance2.rs:LL:CC
    |
 LL |     let _val = unsafe { *ptr.read() };
diff --git a/src/tools/miri/tests/fail/shims/ctor_wrong_ret_type.rs b/src/tools/miri/tests/fail/shims/ctor_wrong_ret_type.rs
index 3629e43..1e10f68 100644
--- a/src/tools/miri/tests/fail/shims/ctor_wrong_ret_type.rs
+++ b/src/tools/miri/tests/fail/shims/ctor_wrong_ret_type.rs
@@ -1,4 +1,5 @@
 unsafe extern "C" fn ctor() -> i32 {
+    //~^ERROR: calling a function with return type i32 passing return place of type ()
     0
 }
 
@@ -30,7 +31,6 @@ macro_rules! ctor {
         )]
         #[used]
         static $ident: unsafe extern "C" fn() -> i32 = $ctor;
-        //~^ERROR: calling a function with return type i32 passing return place of type ()
     };
 }
 
diff --git a/src/tools/miri/tests/fail/shims/ctor_wrong_ret_type.stderr b/src/tools/miri/tests/fail/shims/ctor_wrong_ret_type.stderr
index 1b4cd23..4e474db 100644
--- a/src/tools/miri/tests/fail/shims/ctor_wrong_ret_type.stderr
+++ b/src/tools/miri/tests/fail/shims/ctor_wrong_ret_type.stderr
@@ -1,18 +1,21 @@
 error: Undefined Behavior: calling a function with return type i32 passing return place of type ()
   --> tests/fail/shims/ctor_wrong_ret_type.rs:LL:CC
    |
-LL |         static $ident: unsafe extern "C" fn() -> i32 = $ctor;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred due to this code
-...
-LL | ctor! { CTOR = ctor }
-   | --------------------- in this macro invocation
+LL | unsafe extern "C" fn ctor() -> i32 {
+   |                                ^^^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
    = help: if you think this code should be accepted anyway, please report an issue with Miri
-   = note: this error occurred while pushing a call frame onto an empty stack
-   = note: the span indicates which code caused the function to be called, but may not be the literal call site
+note: the current function got called indirectly due to this code
+  --> tests/fail/shims/ctor_wrong_ret_type.rs:LL:CC
+   |
+LL |         static $ident: unsafe extern "C" fn() -> i32 = $ctor;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | ctor! { CTOR = ctor }
+   | --------------------- in this macro invocation
    = note: this error originates in the macro `ctor` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.rs b/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.rs
index 233b927..03b716c 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.rs
@@ -2,7 +2,7 @@
 // (i.e, no EscapeToRaw happened).
 // We could, in principle, do EscapeToRaw lazily to allow this code, but that
 // would no alleviate the need for EscapeToRaw (see `ref_raw_int_raw` in
-// `run-pass/stacked-borrows.rs`), and thus increase overall complexity.
+// `pass/both_borrows/int-to-ptr.rs`), and thus increase overall complexity.
 use std::mem;
 
 fn main() {
diff --git a/src/tools/miri/tests/fail/storage-live-resets-var.stderr b/src/tools/miri/tests/fail/storage-live-resets-var.stderr
index b3dd4ea..418e5f5 100644
--- a/src/tools/miri/tests/fail/storage-live-resets-var.stderr
+++ b/src/tools/miri/tests/fail/storage-live-resets-var.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered uninitialized memory, but expected an integer
+error: Undefined Behavior: constructing invalid value of type i32: encountered uninitialized memory, but expected an integer
   --> tests/fail/storage-live-resets-var.rs:LL:CC
    |
 LL |             _val2 = val;
diff --git a/src/tools/miri/tests/fail/tail_calls/signature-mismatch-arg.rs b/src/tools/miri/tests/fail/tail_calls/signature-mismatch-arg.rs
index 36bd1e9..e747bfd 100644
--- a/src/tools/miri/tests/fail/tail_calls/signature-mismatch-arg.rs
+++ b/src/tools/miri/tests/fail/tail_calls/signature-mismatch-arg.rs
@@ -2,16 +2,14 @@
 #![allow(incomplete_features)]
 
 fn main() {
-    // FIXME(explicit_tail_calls):
-    //   the error should point to `become g(x)`,
-    //   but tail calls mess up the backtrace it seems like...
     f(0);
-    //~^ error: type i32 passing argument of type u32
 }
 
 fn f(x: u32) {
     let g = unsafe { std::mem::transmute::<fn(i32), fn(u32)>(g) };
-    become g(x);
+    become g(x); // FIXME ideally this should also be involved in the error somehow,
+    // but by the time we pass the argument, `f`'s stackframe has already been popped.
 }
 
 fn g(_: i32) {}
+//~^ error: type i32 passing argument of type u32
diff --git a/src/tools/miri/tests/fail/tail_calls/signature-mismatch-arg.stderr b/src/tools/miri/tests/fail/tail_calls/signature-mismatch-arg.stderr
index f5eccae..9c10db8 100644
--- a/src/tools/miri/tests/fail/tail_calls/signature-mismatch-arg.stderr
+++ b/src/tools/miri/tests/fail/tail_calls/signature-mismatch-arg.stderr
@@ -1,13 +1,18 @@
 error: Undefined Behavior: calling a function whose parameter #1 has type i32 passing argument of type u32
   --> tests/fail/tail_calls/signature-mismatch-arg.rs:LL:CC
    |
-LL |     f(0);
-   |     ^^^^ Undefined Behavior occurred here
+LL | fn g(_: i32) {}
+   |      ^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
    = help: if you think this code should be accepted anyway, please report an issue with Miri
+   = note: stack backtrace:
+           0: g
+               at tests/fail/tail_calls/signature-mismatch-arg.rs:LL:CC
+           1: main
+               at tests/fail/tail_calls/signature-mismatch-arg.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.stderr b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.stderr
index 2b98a2f..ea4b495 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.stderr
+++ b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN)
+error: Undefined Behavior: constructing invalid value of type &mut PartialDrop: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN)
   --> RUSTLIB/core/src/ptr/mod.rs:LL:CC
    |
 LL | / pub const unsafe fn drop_in_place<T: PointeeSized>(to_drop: *mut T)
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr
index 0be5ef9..7c85a3b 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr
+++ b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN)
+error: Undefined Behavior: constructing invalid value of type &dyn std::fmt::Debug: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN)
   --> tests/fail/unaligned_pointers/dyn_alignment.rs:LL:CC
    |
 LL |         let _ptr = &*ptr;
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.rs b/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.rs
index 92917c8..38ec7a7 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.rs
@@ -10,6 +10,6 @@ fn main() {
     unsafe {
         let unaligned = MaybeDangling::new(a.as_ptr().byte_add(1));
         transmute::<MaybeDangling<*const u16>, MaybeDangling<&u16>>(unaligned)
-        //~^ ERROR: Undefined Behavior: constructing invalid value: encountered an unaligned reference
+        //~^ ERROR: encountered an unaligned reference
     };
 }
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.stderr b/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.stderr
index 9a50a03..190976c 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.stderr
+++ b/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN)
+error: Undefined Behavior: constructing invalid value of type std::mem::MaybeDangling<&u16>: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN)
   --> tests/fail/unaligned_pointers/maybe_dangling_unalighed.rs:LL:CC
    |
 LL |         transmute::<MaybeDangling<*const u16>, MaybeDangling<&u16>>(unaligned)
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/reference_to_packed.stderr b/src/tools/miri/tests/fail/unaligned_pointers/reference_to_packed.stderr
index 2f30793..d8252e5 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/reference_to_packed.stderr
+++ b/src/tools/miri/tests/fail/unaligned_pointers/reference_to_packed.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN)
+error: Undefined Behavior: constructing invalid value of type &i32: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN)
   --> tests/fail/unaligned_pointers/reference_to_packed.rs:LL:CC
    |
 LL |     mem::transmute(x)
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ref_addr_of.stderr b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ref_addr_of.stderr
index dfd6c14..8527317 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ref_addr_of.stderr
+++ b/src/tools/miri/tests/fail/unaligned_pointers/unaligned_ref_addr_of.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN)
+error: Undefined Behavior: constructing invalid value of type &u32: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN)
   --> tests/fail/unaligned_pointers/unaligned_ref_addr_of.rs:LL:CC
    |
 LL |         let _x = unsafe { &*x };
diff --git a/src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr
index 2b0dbd3..cf22b56 100644
--- a/src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr
+++ b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at .bytes[2]: encountered uninitialized memory, but expected an integer
+error: Undefined Behavior: constructing invalid value of type Bar: at .bytes[2], encountered uninitialized memory, but expected an integer
   --> tests/fail/uninit/padding-struct-in-union.rs:LL:CC
    |
 LL |     let _val = unsafe { (foobar.foo, foobar.bar) };
diff --git a/src/tools/miri/tests/fail/uninit/padding-union.stderr b/src/tools/miri/tests/fail/uninit/padding-union.stderr
index 30d0862..7851bb6 100644
--- a/src/tools/miri/tests/fail/uninit/padding-union.stderr
+++ b/src/tools/miri/tests/fail/uninit/padding-union.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at [1]: encountered uninitialized memory, but expected an integer
+error: Undefined Behavior: constructing invalid value of type [u8; 4]: at [1], encountered uninitialized memory, but expected an integer
   --> tests/fail/uninit/padding-union.rs:LL:CC
    |
 LL |         let _val = *c;
diff --git a/src/tools/miri/tests/fail/uninit/uninit-after-aggregate-assign.stderr b/src/tools/miri/tests/fail/uninit/uninit-after-aggregate-assign.stderr
index e8deb57..d4048bb 100644
--- a/src/tools/miri/tests/fail/uninit/uninit-after-aggregate-assign.stderr
+++ b/src/tools/miri/tests/fail/uninit/uninit-after-aggregate-assign.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at [1]: encountered uninitialized memory, but expected an integer
+error: Undefined Behavior: constructing invalid value of type [u8; 4]: at [1], encountered uninitialized memory, but expected an integer
   --> tests/fail/uninit/uninit-after-aggregate-assign.rs:LL:CC
    |
 LL |             _val = *sptr2; // should hence be UB
diff --git a/src/tools/miri/tests/fail/validity/box-custom-alloc-dangling-ptr.stderr b/src/tools/miri/tests/fail/validity/box-custom-alloc-dangling-ptr.stderr
index b470e79..3de7f6c 100644
--- a/src/tools/miri/tests/fail/validity/box-custom-alloc-dangling-ptr.stderr
+++ b/src/tools/miri/tests/fail/validity/box-custom-alloc-dangling-ptr.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a dangling box (0x4[noalloc] has no provenance)
+error: Undefined Behavior: constructing invalid value of type std::boxed::Box<i32, MyAlloc>: encountered a dangling box (0x4[noalloc] has no provenance)
   --> tests/fail/validity/box-custom-alloc-dangling-ptr.rs:LL:CC
    |
 LL |         std::mem::transmute(b)
diff --git a/src/tools/miri/tests/fail/validity/box-custom-alloc-invalid-alloc.stderr b/src/tools/miri/tests/fail/validity/box-custom-alloc-invalid-alloc.stderr
index d7594ab..f2fa738 100644
--- a/src/tools/miri/tests/fail/validity/box-custom-alloc-invalid-alloc.stderr
+++ b/src/tools/miri/tests/fail/validity/box-custom-alloc-invalid-alloc.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at .1.my_alloc_field1: encountered uninitialized memory, but expected an integer
+error: Undefined Behavior: constructing invalid value of type std::boxed::Box<i32, MyAlloc>: at .1.my_alloc_field1, encountered uninitialized memory, but expected an integer
   --> tests/fail/validity/box-custom-alloc-invalid-alloc.rs:LL:CC
    |
 LL |         std::mem::transmute(b)
diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_arg.rs b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_arg.rs
index 6ab7356..8657e3a 100644
--- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_arg.rs
+++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_arg.rs
@@ -5,9 +5,9 @@ fn main() {
     // from raw ptr to reference. This is ABI-compatible, so it's not the call that
     // should fail, but validation should.
     fn f(_x: &i32) {}
+    //~^ ERROR: encountered a null reference
 
     let g: fn(*const i32) = unsafe { std::mem::transmute(f as fn(&i32)) };
 
     g(0usize as *const i32)
-    //~^ ERROR: encountered a null reference
 }
diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_arg.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_arg.stderr
index 02e0ebe..1859ec5 100644
--- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_arg.stderr
+++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_arg.stderr
@@ -1,11 +1,16 @@
-error: Undefined Behavior: constructing invalid value: encountered a null reference
+error: Undefined Behavior: constructing invalid value of type &i32: encountered a null reference
   --> tests/fail/validity/cast_fn_ptr_invalid_callee_arg.rs:LL:CC
    |
-LL |     g(0usize as *const i32)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
+LL |     fn f(_x: &i32) {}
+   |          ^^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: stack backtrace:
+           0: main::f
+               at tests/fail/validity/cast_fn_ptr_invalid_callee_arg.rs:LL:CC
+           1: main
+               at tests/fail/validity/cast_fn_ptr_invalid_callee_arg.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr
index 6fc1bc0..26db49e 100644
--- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr
+++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
+error: Undefined Behavior: constructing invalid value of type std::num::NonZero<u32>: at .0.0, encountered 0, but expected something greater or equal to 1
   --> tests/fail/validity/cast_fn_ptr_invalid_callee_ret.rs:LL:CC
    |
 LL |     f();
diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs
index 7ca26bf..7bc2623 100644
--- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs
+++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs
@@ -5,7 +5,7 @@
 use std::num::NonZero;
 use std::ptr;
 
-fn f(c: u32) {
+fn f(c: u32) { //~ERROR: expected something greater or equal to 1
     println!("{c}");
 }
 
@@ -20,7 +20,7 @@ fn call(f: fn(NonZero<u32>)) {
             let tmp = ptr::addr_of!(c);
             let ptr = tmp as *const NonZero<u32>;
             // The call site now is a `NonZero<u32>` to `u32` transmute.
-            Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue()) //~ERROR: expected something greater or equal to 1
+            Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue())
         }
         retblock = {
             Return()
diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr
index 3b23a6c..fa67150 100644
--- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr
+++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr
@@ -1,15 +1,17 @@
-error: Undefined Behavior: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
+error: Undefined Behavior: constructing invalid value of type std::num::NonZero<u32>: at .0.0, encountered 0, but expected something greater or equal to 1
   --> tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs:LL:CC
    |
-LL |             Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
+LL | fn f(c: u32) {
+   |      ^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: stack backtrace:
-           0: call
+           0: f
                at tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs:LL:CC
-           1: main
+           1: call
+               at tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs:LL:CC
+           2: main
                at tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_ret.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_ret.stderr
index 03d6637..d922532 100644
--- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_ret.stderr
+++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_ret.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a null reference
+error: Undefined Behavior: constructing invalid value of type &i32: encountered a null reference
   --> tests/fail/validity/cast_fn_ptr_invalid_caller_ret.rs:LL:CC
    |
 LL |     let _x = g();
diff --git a/src/tools/miri/tests/fail/validity/dangling_ref1.stderr b/src/tools/miri/tests/fail/validity/dangling_ref1.stderr
index 05467c4..0020c64 100644
--- a/src/tools/miri/tests/fail/validity/dangling_ref1.stderr
+++ b/src/tools/miri/tests/fail/validity/dangling_ref1.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a dangling reference (0x10[noalloc] has no provenance)
+error: Undefined Behavior: constructing invalid value of type &i32: encountered a dangling reference (0x10[noalloc] has no provenance)
   --> tests/fail/validity/dangling_ref1.rs:LL:CC
    |
 LL |     let _x: &i32 = unsafe { mem::transmute(16usize) };
diff --git a/src/tools/miri/tests/fail/validity/dangling_ref2.stderr b/src/tools/miri/tests/fail/validity/dangling_ref2.stderr
index eb1b6e2..a1c8de2 100644
--- a/src/tools/miri/tests/fail/validity/dangling_ref2.stderr
+++ b/src/tools/miri/tests/fail/validity/dangling_ref2.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
+error: Undefined Behavior: constructing invalid value of type &i32: encountered a dangling reference (going beyond the bounds of its allocation)
   --> tests/fail/validity/dangling_ref2.rs:LL:CC
    |
 LL |     let _x: &i32 = unsafe { mem::transmute(ptr) };
diff --git a/src/tools/miri/tests/fail/validity/dangling_ref3.stderr b/src/tools/miri/tests/fail/validity/dangling_ref3.stderr
index ec2238c..0bf2598 100644
--- a/src/tools/miri/tests/fail/validity/dangling_ref3.stderr
+++ b/src/tools/miri/tests/fail/validity/dangling_ref3.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a dangling reference (use-after-free)
+error: Undefined Behavior: constructing invalid value of type &i32: encountered a dangling reference (use-after-free)
   --> tests/fail/validity/dangling_ref3.rs:LL:CC
    |
 LL |     let _x: &i32 = unsafe { mem::transmute(dangling()) };
diff --git a/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.stderr b/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.stderr
index 383c13cc..9df01f0 100644
--- a/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.stderr
+++ b/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: wrong trait in wide pointer vtable: expected `Trait<for<'a> fn(&'a ())>`, but encountered `Trait<fn(&())>`
+error: Undefined Behavior: constructing invalid value of type &dyn Trait<for<'a> fn(&'a ())>: wrong trait in wide pointer vtable: expected `Trait<for<'a> fn(&'a ())>`, but encountered `Trait<fn(&())>`
   --> tests/fail/validity/dyn-transmute-inner-binder.rs:LL:CC
    |
 LL |     let y: &dyn Trait<for<'a> fn(&'a ())> = unsafe { std::mem::transmute(x) };
diff --git a/src/tools/miri/tests/fail/validity/invalid_bool.stderr b/src/tools/miri/tests/fail/validity/invalid_bool.stderr
index b667449..a403c8d 100644
--- a/src/tools/miri/tests/fail/validity/invalid_bool.stderr
+++ b/src/tools/miri/tests/fail/validity/invalid_bool.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered 0x02, but expected a boolean
+error: Undefined Behavior: constructing invalid value of type bool: encountered 0x02, but expected a boolean
   --> tests/fail/validity/invalid_bool.rs:LL:CC
    |
 LL |     let _b = unsafe { std::mem::transmute::<u8, bool>(2) };
diff --git a/src/tools/miri/tests/fail/validity/invalid_bool_uninit.stderr b/src/tools/miri/tests/fail/validity/invalid_bool_uninit.stderr
index 800bc4f..86767c6 100644
--- a/src/tools/miri/tests/fail/validity/invalid_bool_uninit.stderr
+++ b/src/tools/miri/tests/fail/validity/invalid_bool_uninit.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at [0]: encountered uninitialized memory, but expected a boolean
+error: Undefined Behavior: constructing invalid value of type [bool; 1]: at [0], encountered uninitialized memory, but expected a boolean
   --> tests/fail/validity/invalid_bool_uninit.rs:LL:CC
    |
 LL |     let _b = unsafe { MyUninit { init: () }.uninit };
diff --git a/src/tools/miri/tests/fail/validity/invalid_char.stderr b/src/tools/miri/tests/fail/validity/invalid_char.stderr
index 7f57988..cb81038 100644
--- a/src/tools/miri/tests/fail/validity/invalid_char.stderr
+++ b/src/tools/miri/tests/fail/validity/invalid_char.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered $HEX, but expected a valid unicode scalar value (in `0..=$HEX` but not in `$HEX..=$HEX`)
+error: Undefined Behavior: constructing invalid value of type char: encountered $HEX, but expected a valid unicode scalar value (in `0..=$HEX` but not in `$HEX..=$HEX`)
   --> tests/fail/validity/invalid_char.rs:LL:CC
    |
 LL |     let _val = match unsafe { std::mem::transmute::<i32, char>(-1) } {
diff --git a/src/tools/miri/tests/fail/validity/invalid_char_uninit.stderr b/src/tools/miri/tests/fail/validity/invalid_char_uninit.stderr
index de8c1f3..78acda6 100644
--- a/src/tools/miri/tests/fail/validity/invalid_char_uninit.stderr
+++ b/src/tools/miri/tests/fail/validity/invalid_char_uninit.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at [0]: encountered uninitialized memory, but expected a unicode scalar value
+error: Undefined Behavior: constructing invalid value of type [char; 1]: at [0], encountered uninitialized memory, but expected a unicode scalar value
   --> tests/fail/validity/invalid_char_uninit.rs:LL:CC
    |
 LL |     let _b = unsafe { MyUninit { init: () }.uninit };
diff --git a/src/tools/miri/tests/fail/validity/invalid_enum_tag.rs b/src/tools/miri/tests/fail/validity/invalid_enum_tag.rs
index fa115e1..9ef4a30 100644
--- a/src/tools/miri/tests/fail/validity/invalid_enum_tag.rs
+++ b/src/tools/miri/tests/fail/validity/invalid_enum_tag.rs
@@ -7,5 +7,5 @@ pub enum Foo {
 }
 
 fn main() {
-    let _f = unsafe { std::mem::transmute::<i32, Foo>(42) }; //~ ERROR: constructing invalid value at .<enum-tag>: encountered 0x0000002a, but expected a valid enum tag
+    let _f = unsafe { std::mem::transmute::<i32, Foo>(42) }; //~ ERROR: constructing invalid value of type Foo: at .<enum-tag>, encountered 0x0000002a, but expected a valid enum tag
 }
diff --git a/src/tools/miri/tests/fail/validity/invalid_enum_tag.stderr b/src/tools/miri/tests/fail/validity/invalid_enum_tag.stderr
index d7f2991..bd182df 100644
--- a/src/tools/miri/tests/fail/validity/invalid_enum_tag.stderr
+++ b/src/tools/miri/tests/fail/validity/invalid_enum_tag.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at .<enum-tag>: encountered $HEX, but expected a valid enum tag
+error: Undefined Behavior: constructing invalid value of type Foo: at .<enum-tag>, encountered $HEX, but expected a valid enum tag
   --> tests/fail/validity/invalid_enum_tag.rs:LL:CC
    |
 LL |     let _f = unsafe { std::mem::transmute::<i32, Foo>(42) };
diff --git a/src/tools/miri/tests/fail/validity/invalid_fnptr_null.stderr b/src/tools/miri/tests/fail/validity/invalid_fnptr_null.stderr
index 20b2234..6750dcb 100644
--- a/src/tools/miri/tests/fail/validity/invalid_fnptr_null.stderr
+++ b/src/tools/miri/tests/fail/validity/invalid_fnptr_null.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a null function pointer
+error: Undefined Behavior: constructing invalid value of type fn(): encountered a null function pointer
   --> tests/fail/validity/invalid_fnptr_null.rs:LL:CC
    |
 LL |     let _b: fn() = unsafe { std::mem::transmute(0usize) };
diff --git a/src/tools/miri/tests/fail/validity/invalid_fnptr_uninit.stderr b/src/tools/miri/tests/fail/validity/invalid_fnptr_uninit.stderr
index 513b90b..60994e2 100644
--- a/src/tools/miri/tests/fail/validity/invalid_fnptr_uninit.stderr
+++ b/src/tools/miri/tests/fail/validity/invalid_fnptr_uninit.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at [0]: encountered uninitialized memory, but expected a function pointer
+error: Undefined Behavior: constructing invalid value of type [fn(); 1]: at [0], encountered uninitialized memory, but expected a function pointer
   --> tests/fail/validity/invalid_fnptr_uninit.rs:LL:CC
    |
 LL |     let _b = unsafe { MyUninit { init: () }.uninit };
diff --git a/src/tools/miri/tests/fail/validity/invalid_wide_raw.stderr b/src/tools/miri/tests/fail/validity/invalid_wide_raw.stderr
index a3c7815..cb3c098 100644
--- a/src/tools/miri/tests/fail/validity/invalid_wide_raw.stderr
+++ b/src/tools/miri/tests/fail/validity/invalid_wide_raw.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered null pointer, but expected a vtable pointer
+error: Undefined Behavior: constructing invalid value of type *mut dyn main::T: encountered null pointer, but expected a vtable pointer
   --> tests/fail/validity/invalid_wide_raw.rs:LL:CC
    |
 LL |     dbg!(S { x: unsafe { std::mem::transmute((0usize, 0usize)) } });
diff --git a/src/tools/miri/tests/fail/validity/match_binder_checks_validity1.stderr b/src/tools/miri/tests/fail/validity/match_binder_checks_validity1.stderr
index 0ca8bc9..c905f3a 100644
--- a/src/tools/miri/tests/fail/validity/match_binder_checks_validity1.stderr
+++ b/src/tools/miri/tests/fail/validity/match_binder_checks_validity1.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a value of uninhabited type `main::Void`
+error: Undefined Behavior: constructing invalid value of type main::Void: encountered a value of uninhabited type `main::Void`
   --> tests/fail/validity/match_binder_checks_validity1.rs:LL:CC
    |
 LL |             _x => println!("hi from the void!"),
diff --git a/src/tools/miri/tests/fail/validity/match_binder_checks_validity2.stderr b/src/tools/miri/tests/fail/validity/match_binder_checks_validity2.stderr
index 281314e..02caf64 100644
--- a/src/tools/miri/tests/fail/validity/match_binder_checks_validity2.stderr
+++ b/src/tools/miri/tests/fail/validity/match_binder_checks_validity2.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered 0x03, but expected a boolean
+error: Undefined Behavior: constructing invalid value of type bool: encountered 0x03, but expected a boolean
   --> tests/fail/validity/match_binder_checks_validity2.rs:LL:CC
    |
 LL |             _x => println!("hi from the void!"),
diff --git a/src/tools/miri/tests/fail/validity/maybe_dangling_null.rs b/src/tools/miri/tests/fail/validity/maybe_dangling_null.rs
index 21dba86..9b3c80b 100644
--- a/src/tools/miri/tests/fail/validity/maybe_dangling_null.rs
+++ b/src/tools/miri/tests/fail/validity/maybe_dangling_null.rs
@@ -9,5 +9,5 @@
 fn main() {
     let null = MaybeDangling::new(null());
     unsafe { transmute::<MaybeDangling<*const u8>, MaybeDangling<&u8>>(null) };
-    //~^ ERROR: Undefined Behavior: constructing invalid value: encountered a null reference
+    //~^ ERROR: encountered a null reference
 }
diff --git a/src/tools/miri/tests/fail/validity/maybe_dangling_null.stderr b/src/tools/miri/tests/fail/validity/maybe_dangling_null.stderr
index 6502347..041a6b1 100644
--- a/src/tools/miri/tests/fail/validity/maybe_dangling_null.stderr
+++ b/src/tools/miri/tests/fail/validity/maybe_dangling_null.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a null reference
+error: Undefined Behavior: constructing invalid value of type std::mem::MaybeDangling<&u8>: encountered a null reference
   --> tests/fail/validity/maybe_dangling_null.rs:LL:CC
    |
 LL |     unsafe { transmute::<MaybeDangling<*const u8>, MaybeDangling<&u8>>(null) };
diff --git a/src/tools/miri/tests/fail/validity/nonzero.stderr b/src/tools/miri/tests/fail/validity/nonzero.stderr
index e5fcdad..2b35240 100644
--- a/src/tools/miri/tests/fail/validity/nonzero.stderr
+++ b/src/tools/miri/tests/fail/validity/nonzero.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered 0, but expected something greater or equal to 1
+error: Undefined Behavior: constructing invalid value of type NonZero<i32>: encountered 0, but expected something greater or equal to 1
   --> tests/fail/validity/nonzero.rs:LL:CC
    |
 LL |     let _x = Some(unsafe { NonZero(0) });
diff --git a/src/tools/miri/tests/fail/validity/recursive-validity-box-bool.stderr b/src/tools/miri/tests/fail/validity/recursive-validity-box-bool.stderr
index d658909..9cb6430 100644
--- a/src/tools/miri/tests/fail/validity/recursive-validity-box-bool.stderr
+++ b/src/tools/miri/tests/fail/validity/recursive-validity-box-bool.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at .<deref>: encountered 0x03, but expected a boolean
+error: Undefined Behavior: constructing invalid value of type std::boxed::Box<bool>: at .<deref>, encountered 0x03, but expected a boolean
   --> tests/fail/validity/recursive-validity-box-bool.rs:LL:CC
    |
 LL |     let xref_wrong_type: Box<bool> = unsafe { std::mem::transmute(xref) };
diff --git a/src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.stderr b/src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.stderr
index 1120726..933e48a 100644
--- a/src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.stderr
+++ b/src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at .<deref>: encountered 0x03, but expected a boolean
+error: Undefined Behavior: constructing invalid value of type &bool: at .<deref>, encountered 0x03, but expected a boolean
   --> tests/fail/validity/recursive-validity-ref-bool.rs:LL:CC
    |
 LL |     let xref_wrong_type: &bool = unsafe { std::mem::transmute(xref) };
diff --git a/src/tools/miri/tests/fail/validity/ref_to_uninhabited1.stderr b/src/tools/miri/tests/fail/validity/ref_to_uninhabited1.stderr
index f1a0591..645a978 100644
--- a/src/tools/miri/tests/fail/validity/ref_to_uninhabited1.stderr
+++ b/src/tools/miri/tests/fail/validity/ref_to_uninhabited1.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a box pointing to uninhabited type !
+error: Undefined Behavior: constructing invalid value of type std::boxed::Box<!>: encountered a box pointing to uninhabited type !
   --> tests/fail/validity/ref_to_uninhabited1.rs:LL:CC
    |
 LL |         let x: Box<!> = transmute(&mut 42);
diff --git a/src/tools/miri/tests/fail/validity/ref_to_uninhabited2.stderr b/src/tools/miri/tests/fail/validity/ref_to_uninhabited2.stderr
index 4d25de4..37b265a 100644
--- a/src/tools/miri/tests/fail/validity/ref_to_uninhabited2.stderr
+++ b/src/tools/miri/tests/fail/validity/ref_to_uninhabited2.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered a reference pointing to uninhabited type (i32, Void)
+error: Undefined Behavior: constructing invalid value of type &(i32, Void): encountered a reference pointing to uninhabited type (i32, Void)
   --> tests/fail/validity/ref_to_uninhabited2.rs:LL:CC
    |
 LL |         let _x: &(i32, Void) = transmute(&42);
diff --git a/src/tools/miri/tests/fail/validity/too-big-slice.stderr b/src/tools/miri/tests/fail/validity/too-big-slice.stderr
index 9d4c347..7377d20 100644
--- a/src/tools/miri/tests/fail/validity/too-big-slice.stderr
+++ b/src/tools/miri/tests/fail/validity/too-big-slice.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
+error: Undefined Behavior: constructing invalid value of type &[u8]: encountered invalid reference metadata: slice is bigger than largest supported object
   --> tests/fail/validity/too-big-slice.rs:LL:CC
    |
 LL | ...   let _x: &[u8] = mem::transmute((ptr, usize::MAX));
diff --git a/src/tools/miri/tests/fail/validity/too-big-unsized.stderr b/src/tools/miri/tests/fail/validity/too-big-unsized.stderr
index 6c07308..0fc6339 100644
--- a/src/tools/miri/tests/fail/validity/too-big-unsized.stderr
+++ b/src/tools/miri/tests/fail/validity/too-big-unsized.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered invalid reference metadata: total size is bigger than largest supported object
+error: Undefined Behavior: constructing invalid value of type &MySlice: encountered invalid reference metadata: total size is bigger than largest supported object
   --> tests/fail/validity/too-big-unsized.rs:LL:CC
    |
 LL | ...   let _x: &MySlice = mem::transmute((ptr, isize::MAX as usize));
diff --git a/src/tools/miri/tests/fail/validity/transmute_through_ptr.rs b/src/tools/miri/tests/fail/validity/transmute_through_ptr.rs
index 60b3bdd..b49c774 100644
--- a/src/tools/miri/tests/fail/validity/transmute_through_ptr.rs
+++ b/src/tools/miri/tests/fail/validity/transmute_through_ptr.rs
@@ -14,6 +14,6 @@ fn main() {
     let mut x = Bool::True;
     evil(&mut x);
     let y = x; // reading this ought to be enough to trigger validation
-    //~^ ERROR: constructing invalid value at .<enum-tag>: encountered 0x0000002c, but expected a valid enum tag
+    //~^ ERROR: constructing invalid value of type Bool: at .<enum-tag>, encountered 0x0000002c, but expected a valid enum tag
     println!("{:?}", y); // make sure it is used (and not optimized away)
 }
diff --git a/src/tools/miri/tests/fail/validity/transmute_through_ptr.stderr b/src/tools/miri/tests/fail/validity/transmute_through_ptr.stderr
index 998ff79..d531df6 100644
--- a/src/tools/miri/tests/fail/validity/transmute_through_ptr.stderr
+++ b/src/tools/miri/tests/fail/validity/transmute_through_ptr.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at .<enum-tag>: encountered $HEX, but expected a valid enum tag
+error: Undefined Behavior: constructing invalid value of type Bool: at .<enum-tag>, encountered $HEX, but expected a valid enum tag
   --> tests/fail/validity/transmute_through_ptr.rs:LL:CC
    |
 LL |     let y = x; // reading this ought to be enough to trigger validation
diff --git a/src/tools/miri/tests/fail/validity/uninhabited_variant.stderr b/src/tools/miri/tests/fail/validity/uninhabited_variant.stderr
index 76ee250..8f120cb 100644
--- a/src/tools/miri/tests/fail/validity/uninhabited_variant.stderr
+++ b/src/tools/miri/tests/fail/validity/uninhabited_variant.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
+error: Undefined Behavior: constructing invalid value of type E: at .<enum-tag>, encountered an uninhabited enum variant
   --> tests/fail/validity/uninhabited_variant.rs:LL:CC
    |
 LL |         std::mem::transmute::<u32, E>(1);
diff --git a/src/tools/miri/tests/fail/validity/uninit_float.stderr b/src/tools/miri/tests/fail/validity/uninit_float.stderr
index 7f3c94a..82e0b20 100644
--- a/src/tools/miri/tests/fail/validity/uninit_float.stderr
+++ b/src/tools/miri/tests/fail/validity/uninit_float.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at [0]: encountered uninitialized memory, but expected a floating point number
+error: Undefined Behavior: constructing invalid value of type [f32; 1]: at [0], encountered uninitialized memory, but expected a floating point number
   --> tests/fail/validity/uninit_float.rs:LL:CC
    |
 LL |     let _val: [f32; 1] = unsafe { std::mem::uninitialized() };
diff --git a/src/tools/miri/tests/fail/validity/uninit_integer.stderr b/src/tools/miri/tests/fail/validity/uninit_integer.stderr
index a80396f..038ffde 100644
--- a/src/tools/miri/tests/fail/validity/uninit_integer.stderr
+++ b/src/tools/miri/tests/fail/validity/uninit_integer.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at [0]: encountered uninitialized memory, but expected an integer
+error: Undefined Behavior: constructing invalid value of type [usize; 1]: at [0], encountered uninitialized memory, but expected an integer
   --> tests/fail/validity/uninit_integer.rs:LL:CC
    |
 LL |     let _val = unsafe { std::mem::MaybeUninit::<[usize; 1]>::uninit().assume_init() };
diff --git a/src/tools/miri/tests/fail/validity/uninit_raw_ptr.stderr b/src/tools/miri/tests/fail/validity/uninit_raw_ptr.stderr
index 946d74d..ecfca66 100644
--- a/src/tools/miri/tests/fail/validity/uninit_raw_ptr.stderr
+++ b/src/tools/miri/tests/fail/validity/uninit_raw_ptr.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at [0]: encountered uninitialized memory, but expected a raw pointer
+error: Undefined Behavior: constructing invalid value of type [*const u8; 1]: at [0], encountered uninitialized memory, but expected a raw pointer
   --> tests/fail/validity/uninit_raw_ptr.rs:LL:CC
    |
 LL |     let _val = unsafe { std::mem::MaybeUninit::<[*const u8; 1]>::uninit().assume_init() };
diff --git a/src/tools/miri/tests/fail/validity/wrong-dyn-trait-assoc-type.stderr b/src/tools/miri/tests/fail/validity/wrong-dyn-trait-assoc-type.stderr
index ea77d11..74d8a46 100644
--- a/src/tools/miri/tests/fail/validity/wrong-dyn-trait-assoc-type.stderr
+++ b/src/tools/miri/tests/fail/validity/wrong-dyn-trait-assoc-type.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: wrong trait in wide pointer vtable: expected `Trait<Assoc = bool>`, but encountered `Trait<Assoc = u8>`
+error: Undefined Behavior: constructing invalid value of type std::boxed::Box<dyn Trait<Assoc = bool>>: wrong trait in wide pointer vtable: expected `Trait<Assoc = bool>`, but encountered `Trait<Assoc = u8>`
   --> tests/fail/validity/wrong-dyn-trait-assoc-type.rs:LL:CC
    |
 LL |     let v: Box<dyn Trait<Assoc = bool>> = unsafe { std::mem::transmute(v) };
diff --git a/src/tools/miri/tests/fail/validity/wrong-dyn-trait-generic.stderr b/src/tools/miri/tests/fail/validity/wrong-dyn-trait-generic.stderr
index f9e2f15..9273e39 100644
--- a/src/tools/miri/tests/fail/validity/wrong-dyn-trait-generic.stderr
+++ b/src/tools/miri/tests/fail/validity/wrong-dyn-trait-generic.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: wrong trait in wide pointer vtable: expected `Trait<u32>`, but encountered `Trait<i32>`
+error: Undefined Behavior: constructing invalid value of type *const dyn Trait<u32>: wrong trait in wide pointer vtable: expected `Trait<u32>`, but encountered `Trait<i32>`
   --> tests/fail/validity/wrong-dyn-trait-generic.rs:LL:CC
    |
 LL |     let _y: *const dyn Trait<u32> = unsafe { mem::transmute(x) };
diff --git a/src/tools/miri/tests/fail/validity/wrong-dyn-trait.stderr b/src/tools/miri/tests/fail/validity/wrong-dyn-trait.stderr
index 47efd0b..6ca55c2 100644
--- a/src/tools/miri/tests/fail/validity/wrong-dyn-trait.stderr
+++ b/src/tools/miri/tests/fail/validity/wrong-dyn-trait.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: wrong trait in wide pointer vtable: expected `std::fmt::Debug`, but encountered `std::marker::Send`
+error: Undefined Behavior: constructing invalid value of type *const dyn std::fmt::Debug: wrong trait in wide pointer vtable: expected `std::fmt::Debug`, but encountered `std::marker::Send`
   --> tests/fail/validity/wrong-dyn-trait.rs:LL:CC
    |
 LL |     let _y: *const dyn fmt::Debug = unsafe { mem::transmute(x) };
diff --git a/src/tools/miri/tests/native-lib/fail/invalid_retval.rs b/src/tools/miri/tests/native-lib/fail/invalid_retval.rs
index 4967866..e4bcbeb 100644
--- a/src/tools/miri/tests/native-lib/fail/invalid_retval.rs
+++ b/src/tools/miri/tests/native-lib/fail/invalid_retval.rs
@@ -9,6 +9,6 @@
 
 fn main() {
     unsafe {
-        u8_id(2); //~ ERROR: invalid value: encountered 0x02, but expected a boolean
+        u8_id(2); //~ ERROR: encountered 0x02, but expected a boolean
     }
 }
diff --git a/src/tools/miri/tests/native-lib/fail/invalid_retval.stderr b/src/tools/miri/tests/native-lib/fail/invalid_retval.stderr
index 9db2982..b3b99cc 100644
--- a/src/tools/miri/tests/native-lib/fail/invalid_retval.stderr
+++ b/src/tools/miri/tests/native-lib/fail/invalid_retval.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value: encountered 0x02, but expected a boolean
+error: Undefined Behavior: constructing invalid value of type bool: encountered 0x02, but expected a boolean
   --> tests/native-lib/fail/invalid_retval.rs:LL:CC
    |
 LL |         u8_id(2);
diff --git a/src/tools/miri/tests/native-lib/fail/uninit_struct.stderr b/src/tools/miri/tests/native-lib/fail/uninit_struct.stderr
index 9833b65..83e8170 100644
--- a/src/tools/miri/tests/native-lib/fail/uninit_struct.stderr
+++ b/src/tools/miri/tests/native-lib/fail/uninit_struct.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: constructing invalid value at .part_1.high: encountered uninitialized memory, but expected an integer
+error: Undefined Behavior: constructing invalid value of type ComplexStruct: at .part_1.high, encountered uninitialized memory, but expected an integer
   --> tests/native-lib/fail/uninit_struct.rs:LL:CC
    |
 LL |     unsafe { pass_struct_complex(*arg.as_ptr(), 0, 0, 0) };
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket.rs b/src/tools/miri/tests/pass-dep/libc/libc-socket.rs
index 0a5f8c2..e3c14e6 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-socket.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-socket.rs
@@ -1,10 +1,14 @@
 //@ignore-target: windows # No libc socket on Windows
 //@compile-flags: -Zmiri-disable-isolation
 
+#![feature(io_error_inprogress)]
+
 #[path = "../../utils/libc.rs"]
 mod libc_utils;
 use std::io::{self, ErrorKind};
-use std::mem::MaybeUninit;
+use std::time::Duration;
+#[allow(unused)]
+use std::{mem::MaybeUninit, thread};
 
 use libc_utils::*;
 
@@ -28,6 +32,8 @@ fn main() {
 
     test_listen();
 
+    test_accept_connect();
+
     test_getsockname_ipv4();
     test_getsockname_ipv4_random_port();
     test_getsockname_ipv4_unbound();
@@ -117,7 +123,7 @@ fn test_set_nosigpipe_invalid_len() {
     // By providing a u64 of size 8 bytes we trigger an invalid length error.
     let err = setsockopt(sockfd, libc::SOL_SOCKET, libc::SO_NOSIGPIPE, 1u64).unwrap_err();
     assert_eq!(err.kind(), ErrorKind::InvalidInput);
-    // check that it is the right kind of `InvalidInput`
+    // Check that it is the right kind of `InvalidInput`.
     assert_eq!(err.raw_os_error(), Some(libc::EINVAL));
 }
 
@@ -137,7 +143,7 @@ fn test_bind_ipv4_invalid_addr_len() {
         .unwrap_err()
     };
     assert_eq!(err.kind(), ErrorKind::InvalidInput);
-    // check that it is the right kind of `InvalidInput`
+    // Check that it is the right kind of `InvalidInput`.
     assert_eq!(err.raw_os_error(), Some(libc::EINVAL));
 }
 
@@ -166,12 +172,86 @@ fn test_listen() {
         ));
     }
 
-    // Use the supported backlog value to avoid the warning.
-    let backlog = 128;
+    unsafe {
+        errno_check(libc::listen(sockfd, 16));
+    }
+}
+
+/// Test accepting connections by running a server in a separate thread and connecting clients
+/// from the main thread.
+/// This function tests both
+/// - Connecting when the server is already accepting
+/// - Accepting when there is already an incoming connection
+fn test_accept_connect() {
+    // Create a new non-blocking server socket.
+    let server_sockfd =
+        unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() };
+    let client_sockfd =
+        unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() };
+    let addr = net::ipv4_sock_addr(net::IPV4_LOCALHOST, 0);
+    unsafe {
+        errno_check(libc::bind(
+            server_sockfd,
+            (&addr as *const libc::sockaddr_in).cast::<libc::sockaddr>(),
+            size_of::<libc::sockaddr_in>() as libc::socklen_t,
+        ));
+    }
 
     unsafe {
-        errno_check(libc::listen(sockfd, backlog));
+        errno_check(libc::listen(server_sockfd, 16));
     }
+
+    // Retrieve actual listener address because we used a randomized port.
+    let (_, server_addr) =
+        sockname(|storage, len| unsafe { libc::getsockname(server_sockfd, storage, len) }).unwrap();
+
+    let LibcSocketAddr::V4(addr) = server_addr else {
+        // We bound an IPv4 address so we also expect
+        // an IPv4 address to be returned.
+        panic!()
+    };
+
+    // Spawn the server thread.
+    let server_thread = thread::spawn(move || {
+        let (_peerfd, _peer_addr) =
+            sockname(|storage, len| unsafe { libc::accept(server_sockfd, storage, len) }).unwrap();
+
+        // Yield back to the client thread to test whether calling `connect` first also
+        // works.
+        thread::sleep(Duration::from_millis(10));
+
+        let (_peerfd, _peer_addr) =
+            sockname(|storage, len| unsafe { libc::accept(server_sockfd, storage, len) }).unwrap();
+    });
+
+    // Yield to server thread to ensure `accept` is called before we try
+    // to connect.
+    thread::sleep(Duration::from_millis(10));
+
+    // Test connecting to an already accepting server.
+    unsafe {
+        errno_check(libc::connect(
+            client_sockfd,
+            (&addr as *const libc::sockaddr_in).cast::<libc::sockaddr>(),
+            size_of::<libc::sockaddr_in>() as libc::socklen_t,
+        ));
+    }
+
+    // Server thread should now be in its `sleep`.
+    // Test connecting when there is no actively ongoing `accept`.
+    // We need a new client socket since we cannot connect a socket multiple times.
+    let client_sockfd =
+        unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() };
+
+    unsafe {
+        errno_check(libc::connect(
+            client_sockfd,
+            (&addr as *const libc::sockaddr_in).cast::<libc::sockaddr>(),
+            size_of::<libc::sockaddr_in>() as libc::socklen_t,
+        ));
+    }
+
+    server_thread.join().unwrap();
 }
 
 /// Test the `getsockname` syscall on an IPv4 socket which is bound.
@@ -188,17 +268,15 @@ fn test_getsockname_ipv4() {
             size_of::<libc::sockaddr_in>() as libc::socklen_t,
         ));
     }
-    // Use the supported backlog value to avoid the warning.
-    let backlog = 128;
 
     unsafe {
-        errno_check(libc::listen(sockfd, backlog));
+        errno_check(libc::listen(sockfd, 16));
     }
 
-    let sockname =
+    let (_, sock_addr) =
         sockname(|storage, len| unsafe { libc::getsockname(sockfd, storage, len) }).unwrap();
 
-    let LibcSocketAddr::V4(sock_addr) = sockname else {
+    let LibcSocketAddr::V4(sock_addr) = sock_addr else {
         // We bound an IPv4 address so we also expect
         // an IPv4 address to be returned.
         panic!()
@@ -225,17 +303,15 @@ fn test_getsockname_ipv4_random_port() {
             size_of::<libc::sockaddr_in>() as libc::socklen_t,
         ));
     }
-    // Use the supported backlog value to avoid the warning.
-    let backlog = 128;
 
     unsafe {
-        errno_check(libc::listen(sockfd, backlog));
+        errno_check(libc::listen(sockfd, 16));
     }
 
-    let sockname =
+    let (_, sock_addr) =
         sockname(|storage, len| unsafe { libc::getsockname(sockfd, storage, len) }).unwrap();
 
-    let LibcSocketAddr::V4(sock_addr) = sockname else {
+    let LibcSocketAddr::V4(sock_addr) = sock_addr else {
         // We bound an IPv4 address so we also expect
         // an IPv4 address to be returned.
         panic!()
@@ -252,12 +328,12 @@ fn test_getsockname_ipv4_unbound() {
     let sockfd =
         unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() };
 
-    let sockname =
+    let (_, sock_addr) =
         sockname(|storage, len| unsafe { libc::getsockname(sockfd, storage, len) }).unwrap();
 
     // Libc representation of an unspecified IPv4 address with zero port.
     let addr = net::ipv4_sock_addr([0, 0, 0, 0], 0);
-    let LibcSocketAddr::V4(sock_addr) = sockname else {
+    let LibcSocketAddr::V4(sock_addr) = sock_addr else {
         // We bound an IPv4 address so we also expect
         // an IPv4 address to be returned.
         panic!()
@@ -282,17 +358,15 @@ fn test_getsockname_ipv6() {
             size_of::<libc::sockaddr_in6>() as libc::socklen_t,
         ));
     }
-    // Use the supported backlog value to avoid the warning.
-    let backlog = 128;
 
     unsafe {
-        errno_check(libc::listen(sockfd, backlog));
+        errno_check(libc::listen(sockfd, 16));
     }
 
-    let sockname =
+    let (_, sock_addr) =
         sockname(|storage, len| unsafe { libc::getsockname(sockfd, storage, len) }).unwrap();
 
-    let LibcSocketAddr::V6(sock_addr) = sockname else {
+    let LibcSocketAddr::V6(sock_addr) = sock_addr else {
         // We bound an IPv6 address so we also expect
         // an IPv6 address to be returned.
         panic!()
@@ -338,27 +412,31 @@ enum LibcSocketAddr {
 /// Wraps a call to a platform function that returns a socket address.
 /// This is very much the same as the function with the same name in the
 /// standard library implementation.
-fn sockname<F>(f: F) -> io::Result<LibcSocketAddr>
+/// Returns a tuple containing the actual return value of the performed
+/// syscall and the written address of it.
+fn sockname<F>(f: F) -> io::Result<(libc::c_int, LibcSocketAddr)>
 where
     F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int,
 {
     let mut storage = MaybeUninit::<libc::sockaddr_storage>::zeroed();
     let mut len = size_of::<libc::sockaddr_storage>() as libc::socklen_t;
-    errno_result(f(storage.as_mut_ptr().cast(), &mut len))?;
+    let value = errno_result(f(storage.as_mut_ptr().cast(), &mut len))?;
     // SAFETY:
     // The caller guarantees that the storage has been successfully initialized
     // and its size written to `len` if `f` returns a success.
-    unsafe {
+    let address = unsafe {
         match (*storage.as_ptr()).ss_family as libc::c_int {
             libc::AF_INET => {
                 assert!(len as usize >= size_of::<libc::sockaddr_in>());
-                Ok(LibcSocketAddr::V4(*(storage.as_ptr() as *const _ as *const libc::sockaddr_in)))
+                LibcSocketAddr::V4(*(storage.as_ptr() as *const _ as *const libc::sockaddr_in))
             }
             libc::AF_INET6 => {
                 assert!(len as usize >= size_of::<libc::sockaddr_in6>());
-                Ok(LibcSocketAddr::V6(*(storage.as_ptr() as *const _ as *const libc::sockaddr_in6)))
+                LibcSocketAddr::V6(*(storage.as_ptr() as *const _ as *const libc::sockaddr_in6))
             }
-            _ => Err(io::Error::new(ErrorKind::InvalidInput, "invalid argument")),
+            _ => return Err(io::Error::new(ErrorKind::InvalidInput, "invalid argument")),
         }
-    }
+    };
+
+    Ok((value, address))
 }
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-time.rs b/src/tools/miri/tests/pass-dep/libc/libc-time.rs
index b80fb00..141e000 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-time.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-time.rs
@@ -3,6 +3,7 @@
 
 #[path = "../../utils/libc.rs"]
 mod libc_utils;
+
 use std::time::{Duration, Instant};
 use std::{env, mem, ptr};
 
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-uname.rs b/src/tools/miri/tests/pass-dep/libc/libc-uname.rs
new file mode 100644
index 0000000..b071e05
--- /dev/null
+++ b/src/tools/miri/tests/pass-dep/libc/libc-uname.rs
@@ -0,0 +1,40 @@
+//@ignore-target: windows # No libc
+
+#[path = "../../utils/libc.rs"]
+mod libc_utils;
+
+use std::ffi::CStr;
+use std::{io, ptr};
+
+use libc_utils::*;
+
+fn main() {
+    test_ok();
+    test_null_ptr();
+}
+
+fn test_ok() {
+    // SAFETY: all zeros for `utsname` is valid.
+    let mut uname: libc::utsname = unsafe { std::mem::zeroed() };
+    errno_check(unsafe { libc::uname(&mut uname) });
+
+    assert_eq!(unsafe { CStr::from_ptr(&uname.sysname as *const _) }, c"Miri");
+    assert_eq!(unsafe { CStr::from_ptr(&uname.nodename as *const _) }, c"Miri");
+    assert_eq!(
+        unsafe { CStr::from_ptr(&uname.release as *const _) }.to_str().unwrap(),
+        env!("CARGO_PKG_VERSION")
+    );
+    assert_eq!(unsafe { CStr::from_ptr(&uname.version as *const _) }, c"Miri 0.1.0");
+    assert_eq!(
+        unsafe { CStr::from_ptr(&uname.machine as *const _) }.to_str().unwrap(),
+        std::env::consts::ARCH
+    );
+    #[cfg(any(target_os = "linux", target_os = "android"))]
+    assert_eq!(unsafe { CStr::from_ptr(&uname.domainname as *const _) }, c"(none)");
+}
+
+fn test_null_ptr() {
+    let err = errno_result(unsafe { libc::uname(ptr::null_mut()) }).unwrap_err();
+    assert_eq!(err.raw_os_error(), Some(libc::EFAULT));
+    assert_eq!(io::Error::last_os_error().raw_os_error(), Some(libc::EFAULT));
+}
diff --git a/src/tools/miri/tests/pass-dep/libc/socket-unsupported-listen-backlog.rs b/src/tools/miri/tests/pass-dep/libc/socket-unsupported-listen-backlog.rs
deleted file mode 100644
index 193a6c6..0000000
--- a/src/tools/miri/tests/pass-dep/libc/socket-unsupported-listen-backlog.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-//@ignore-target: windows # No libc socket on Windows
-//@compile-flags: -Zmiri-disable-isolation
-
-#[path = "../../utils/libc.rs"]
-mod libc_utils;
-use libc_utils::*;
-
-fn main() {
-    let sockfd =
-        unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() };
-    let addr = net::ipv4_sock_addr(net::IPV4_LOCALHOST, 2345);
-    unsafe {
-        errno_check(libc::bind(
-            sockfd,
-            (&addr as *const libc::sockaddr_in).cast::<libc::sockaddr>(),
-            size_of::<libc::sockaddr_in>() as libc::socklen_t,
-        ));
-    }
-
-    // Only supported value is 128, thus we use 127 to trigger the warning.
-    let backlog = 127;
-
-    unsafe {
-        let errno = libc::listen(sockfd, backlog);
-        errno_check(errno);
-    }
-}
diff --git a/src/tools/miri/tests/pass-dep/libc/socket-unsupported-listen-backlog.stderr b/src/tools/miri/tests/pass-dep/libc/socket-unsupported-listen-backlog.stderr
deleted file mode 100644
index 94582af..0000000
--- a/src/tools/miri/tests/pass-dep/libc/socket-unsupported-listen-backlog.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-warning: called `listen` on socket with backlog value of 127 but only 128 is supported
-  --> tests/pass-dep/libc/socket-unsupported-listen-backlog.rs:LL:CC
-   |
-LL |         let errno = libc::listen(sockfd, backlog);
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to `listen` with unsupported backlog value
-   |
-   = note: the given value will be ignored and a backlog of 128 will be used instead
-
diff --git a/src/tools/miri/tests/pass-dep/shims/socket.rs b/src/tools/miri/tests/pass-dep/shims/socket.rs
deleted file mode 100644
index 787dd5e..0000000
--- a/src/tools/miri/tests/pass-dep/shims/socket.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-//@ignore-target: windows # No libc socket on Windows
-//@compile-flags: -Zmiri-disable-isolation
-
-use std::net::TcpListener;
-
-fn main() {
-    create_ipv4_listener();
-    create_ipv6_listener();
-}
-
-fn create_ipv4_listener() {
-    let _listener_ipv4 = TcpListener::bind("127.0.0.1:0").unwrap();
-}
-
-fn create_ipv6_listener() {
-    let _listener_ipv6 = TcpListener::bind("[::1]:0").unwrap();
-}
diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs
index 0b5a71a..e545490 100644
--- a/src/tools/miri/tests/pass/float.rs
+++ b/src/tools/miri/tests/pass/float.rs
@@ -7,12 +7,16 @@
 #![allow(arithmetic_overflow)]
 #![allow(internal_features)]
 #![allow(unnecessary_transmutes)]
+#![deny(deprecated_in_future)]
 
 use std::any::type_name;
 use std::cmp::min;
+use std::f16::consts as f16_consts;
+use std::f32::consts as f32_consts;
+use std::f64::consts as f64_consts;
+use std::f128::consts as f128_consts;
 use std::fmt::{Debug, Display, LowerHex};
 use std::hint::black_box;
-use std::{f16, f32, f64, f128};
 
 #[path = "../utils/mod.rs"]
 mod utils;
@@ -21,7 +25,7 @@
 /// Compare the two floats, allowing for $ulp many ULPs of error.
 ///
 /// ULP means "Units in the Last Place" or "Units of Least Precision".
-/// The ULP of a float `a`` is the smallest possible change at `a`, so the ULP difference represents how
+/// The ULP of a float `a` is the smallest possible change at `a`, so the ULP difference represents how
 /// many discrete floating-point steps are needed to reach the actual value from the expected value.
 ///
 /// Essentially ULP can be seen as a distance metric of floating-point numbers, but with
@@ -1018,10 +1022,10 @@ fn mul_add() {
     assert_eq!(3.0f64.mul_add(2.0f64, 5.0f64), 11.0);
     assert_eq!(3.0f128.mul_add(2.0f128, 5.0f128), 11.0);
 
-    assert_eq!(0.0f16.mul_add(-2.0f16, f16::consts::E), f16::consts::E);
-    assert_eq!(0.0f32.mul_add(-2.0f32, f32::consts::E), f32::consts::E);
-    assert_eq!(0.0f64.mul_add(-2.0f64, f64::consts::E), f64::consts::E);
-    assert_eq!(0.0f128.mul_add(-2.0f128, f128::consts::E), f128::consts::E);
+    assert_eq!(0.0f16.mul_add(-2.0f16, f16_consts::E), f16_consts::E);
+    assert_eq!(0.0f32.mul_add(-2.0f32, f32_consts::E), f32_consts::E);
+    assert_eq!(0.0f64.mul_add(-2.0f64, f64_consts::E), f64_consts::E);
+    assert_eq!(0.0f128.mul_add(-2.0f128, f128_consts::E), f128_consts::E);
 
     assert_eq!((-3.2f16).mul_add(2.4, f16::NEG_INFINITY), f16::NEG_INFINITY);
     assert_eq!((-3.2f32).mul_add(2.4, f32::NEG_INFINITY), f32::NEG_INFINITY);
@@ -1124,16 +1128,16 @@ fn ldexp(a: f64, b: i32) -> f64 {
     assert_biteq((-0f32).powi(9), -0.0, "-0^x = -0 where x is negative");
     assert_biteq((-0f64).powi(99), -0.0, "-0^x = -0 where x is negative");
 
-    assert_approx_eq!(1f16.exp(), f16::consts::E);
-    assert_approx_eq!(1f32.exp(), f32::consts::E);
-    assert_approx_eq!(1f64.exp(), f64::consts::E);
+    assert_approx_eq!(1f16.exp(), f16_consts::E);
+    assert_approx_eq!(1f32.exp(), f32_consts::E);
+    assert_approx_eq!(1f64.exp(), f64_consts::E);
     assert_eq!(0f16.exp(), 1.0);
     assert_eq!(0f32.exp(), 1.0);
     assert_eq!(0f64.exp(), 1.0);
 
-    assert_approx_eq!(1f16.exp_m1(), f16::consts::E - 1.0);
-    assert_approx_eq!(1f32.exp_m1(), f32::consts::E - 1.0);
-    assert_approx_eq!(1f64.exp_m1(), f64::consts::E - 1.0);
+    assert_approx_eq!(1f16.exp_m1(), f16_consts::E - 1.0);
+    assert_approx_eq!(1f32.exp_m1(), f32_consts::E - 1.0);
+    assert_approx_eq!(1f64.exp_m1(), f64_consts::E - 1.0);
     assert_approx_eq!(f16::NEG_INFINITY.exp_m1(), -1.0);
     assert_approx_eq!(f32::NEG_INFINITY.exp_m1(), -1.0);
     assert_approx_eq!(f64::NEG_INFINITY.exp_m1(), -1.0);
@@ -1145,9 +1149,9 @@ fn ldexp(a: f64, b: i32) -> f64 {
     assert_eq!(0f32.exp2(), 1.0);
     assert_eq!(0f64.exp2(), 1.0);
 
-    assert_approx_eq!(f16::consts::E.ln(), 1f16);
-    assert_approx_eq!(f32::consts::E.ln(), 1f32);
-    assert_approx_eq!(f64::consts::E.ln(), 1f64);
+    assert_approx_eq!(f16_consts::E.ln(), 1f16);
+    assert_approx_eq!(f32_consts::E.ln(), 1f32);
+    assert_approx_eq!(f64_consts::E.ln(), 1f64);
     assert_eq!(1f16.ln(), 0.0);
     assert_eq!(1f32.ln(), 0.0);
     assert_eq!(1f64.ln(), 0.0);
@@ -1158,11 +1162,11 @@ fn ldexp(a: f64, b: i32) -> f64 {
 
     assert_approx_eq!(10f16.log10(), 1f16);
     assert_approx_eq!(10f32.log10(), 1f32);
-    assert_approx_eq!(f64::consts::E.log10(), f64::consts::LOG10_E);
+    assert_approx_eq!(f64_consts::E.log10(), f64_consts::LOG10_E);
 
     assert_approx_eq!(8f16.log2(), 3f16);
     assert_approx_eq!(8f32.log2(), 3f32);
-    assert_approx_eq!(f64::consts::E.log2(), f64::consts::LOG2_E);
+    assert_approx_eq!(f64_consts::E.log2(), f64_consts::LOG2_E);
 
     #[allow(deprecated)]
     {
@@ -1188,13 +1192,13 @@ fn ldexp(a: f64, b: i32) -> f64 {
     assert_eq!(0f16.sin(), 0f16);
     assert_eq!(0f32.sin(), 0f32);
     assert_eq!(0f64.sin(), 0f64);
-    assert_approx_eq!(f16::consts::FRAC_PI_6.sin(), 0.5);
-    assert_approx_eq!(f32::consts::FRAC_PI_6.sin(), 0.5);
-    assert_approx_eq!(f64::consts::FRAC_PI_6.sin(), 0.5);
+    assert_approx_eq!(f16_consts::FRAC_PI_6.sin(), 0.5);
+    assert_approx_eq!(f32_consts::FRAC_PI_6.sin(), 0.5);
+    assert_approx_eq!(f64_consts::FRAC_PI_6.sin(), 0.5);
     // Increase error tolerance to 16ULP because of the extra operation.
-    assert_approx_eq!(f16::consts::FRAC_PI_4.sin().asin(), f16::consts::FRAC_PI_4, 16);
-    assert_approx_eq!(f32::consts::FRAC_PI_4.sin().asin(), f32::consts::FRAC_PI_4, 16);
-    assert_approx_eq!(f64::consts::FRAC_PI_4.sin().asin(), f64::consts::FRAC_PI_4, 16);
+    assert_approx_eq!(f16_consts::FRAC_PI_4.sin().asin(), f16_consts::FRAC_PI_4, 16);
+    assert_approx_eq!(f32_consts::FRAC_PI_4.sin().asin(), f32_consts::FRAC_PI_4, 16);
+    assert_approx_eq!(f64_consts::FRAC_PI_4.sin().asin(), f64_consts::FRAC_PI_4, 16);
     assert_biteq(0.0f16.asin(), 0.0f16, "asin(+0) = +0");
     assert_biteq((-0.0f16).asin(), -0.0, "asin(-0) = -0");
     assert_biteq(0.0f32.asin(), 0.0f32, "asin(+0) = +0");
@@ -1211,12 +1215,12 @@ fn ldexp(a: f64, b: i32) -> f64 {
 
     // Ensure `sin` always returns something that is a valid input for `asin`, and same for
     // `cos` and `acos`.
-    let halve_pi_f16 = std::f16::consts::FRAC_PI_2;
-    let halve_pi_f32 = std::f32::consts::FRAC_PI_2;
-    let halve_pi_f64 = std::f64::consts::FRAC_PI_2;
-    let pi_f16 = std::f16::consts::PI;
-    let pi_f32 = std::f32::consts::PI;
-    let pi_f64 = std::f64::consts::PI;
+    let halve_pi_f16 = f16_consts::FRAC_PI_2;
+    let halve_pi_f32 = f32_consts::FRAC_PI_2;
+    let halve_pi_f64 = f64_consts::FRAC_PI_2;
+    let pi_f16 = f16_consts::PI;
+    let pi_f32 = f32_consts::PI;
+    let pi_f64 = f64_consts::PI;
     for _ in 0..64 {
         // sin() should be clamped to [-1, 1] so asin() can never return NaN
         assert!(!halve_pi_f16.sin().asin().is_nan());
@@ -1231,13 +1235,13 @@ fn ldexp(a: f64, b: i32) -> f64 {
     assert_eq!(0f16.cos(), 1f16);
     assert_eq!(0f32.cos(), 1f32);
     assert_eq!(0f64.cos(), 1f64);
-    assert_approx_eq!(f16::consts::FRAC_PI_3.cos(), 0.5);
-    assert_approx_eq!(f32::consts::FRAC_PI_3.cos(), 0.5);
-    assert_approx_eq!(f64::consts::FRAC_PI_3.cos(), 0.5);
+    assert_approx_eq!(f16_consts::FRAC_PI_3.cos(), 0.5);
+    assert_approx_eq!(f32_consts::FRAC_PI_3.cos(), 0.5);
+    assert_approx_eq!(f64_consts::FRAC_PI_3.cos(), 0.5);
     // Increase error tolerance to 16ULP because of the extra operation.
-    assert_approx_eq!(f16::consts::FRAC_PI_4.cos().acos(), f16::consts::FRAC_PI_4, 16);
-    assert_approx_eq!(f32::consts::FRAC_PI_4.cos().acos(), f32::consts::FRAC_PI_4, 16);
-    assert_approx_eq!(f64::consts::FRAC_PI_4.cos().acos(), f64::consts::FRAC_PI_4, 16);
+    assert_approx_eq!(f16_consts::FRAC_PI_4.cos().acos(), f16_consts::FRAC_PI_4, 16);
+    assert_approx_eq!(f32_consts::FRAC_PI_4.cos().acos(), f32_consts::FRAC_PI_4, 16);
+    assert_approx_eq!(f64_consts::FRAC_PI_4.cos().acos(), f64_consts::FRAC_PI_4, 16);
     assert_biteq(1.0f16.acos(), 0.0, "acos(1) = 0");
     assert_biteq(1.0f32.acos(), 0.0, "acos(1) = 0");
     assert_biteq(1.0f64.acos(), 0.0, "acos(1) = 0");
@@ -1313,15 +1317,15 @@ macro_rules! fixed_atan2_cases{
 
     assert_approx_eq!(
         1.0f16.tanh(),
-        (1.0 - f16::consts::E.powi(-2)) / (1.0 + f16::consts::E.powi(-2))
+        (1.0 - f16_consts::E.powi(-2)) / (1.0 + f16_consts::E.powi(-2))
     );
     assert_approx_eq!(
         1.0f32.tanh(),
-        (1.0 - f32::consts::E.powi(-2)) / (1.0 + f32::consts::E.powi(-2))
+        (1.0 - f32_consts::E.powi(-2)) / (1.0 + f32_consts::E.powi(-2))
     );
     assert_approx_eq!(
         1.0f64.tanh(),
-        (1.0 - f64::consts::E.powi(-2)) / (1.0 + f64::consts::E.powi(-2))
+        (1.0 - f64_consts::E.powi(-2)) / (1.0 + f64_consts::E.powi(-2))
     );
     assert_eq!(f16::INFINITY.tanh(), 1.0);
     assert_eq!(f16::NEG_INFINITY.tanh(), -1.0);
@@ -1337,22 +1341,22 @@ macro_rules! fixed_atan2_cases{
     assert_approx_eq!(5.0f16.gamma(), 24.0);
     assert_approx_eq!(5.0f32.gamma(), 24.0);
     assert_approx_eq!(5.0f64.gamma(), 24.0);
-    assert_approx_eq!((-0.5f16).gamma(), (-2.0) * f16::consts::PI.sqrt());
-    assert_approx_eq!((-0.5f32).gamma(), (-2.0) * f32::consts::PI.sqrt());
-    assert_approx_eq!((-0.5f64).gamma(), (-2.0) * f64::consts::PI.sqrt());
+    assert_approx_eq!((-0.5f16).gamma(), (-2.0) * f16_consts::PI.sqrt());
+    assert_approx_eq!((-0.5f32).gamma(), (-2.0) * f32_consts::PI.sqrt());
+    assert_approx_eq!((-0.5f64).gamma(), (-2.0) * f64_consts::PI.sqrt());
 
     assert_eq!(2.0f16.ln_gamma(), (0.0, 1));
     assert_eq!(2.0f32.ln_gamma(), (0.0, 1));
     assert_eq!(2.0f64.ln_gamma(), (0.0, 1));
     // Gamma(-0.5) = -2*sqrt(π)
     let (val, sign) = (-0.5f16).ln_gamma();
-    assert_approx_eq!(val, (2.0 * f16::consts::PI.sqrt()).ln());
+    assert_approx_eq!(val, (2.0 * f16_consts::PI.sqrt()).ln());
     assert_eq!(sign, -1);
     let (val, sign) = (-0.5f32).ln_gamma();
-    assert_approx_eq!(val, (2.0 * f32::consts::PI.sqrt()).ln());
+    assert_approx_eq!(val, (2.0 * f32_consts::PI.sqrt()).ln());
     assert_eq!(sign, -1);
     let (val, sign) = (-0.5f64).ln_gamma();
-    assert_approx_eq!(val, (2.0 * f64::consts::PI.sqrt()).ln());
+    assert_approx_eq!(val, (2.0 * f64_consts::PI.sqrt()).ln());
     assert_eq!(sign, -1);
 
     assert_approx_eq!(1.0f16.erf(), 0.84270079294971486934122063508260926f16);
@@ -1551,7 +1555,7 @@ fn test_operations_f16(a: f16, b: f16) {
         check_nondet(|| a.log(b));
         check_nondet(|| a.exp());
         check_nondet(|| 10f16.exp2());
-        check_nondet(|| f16::consts::E.ln());
+        check_nondet(|| f16_consts::E.ln());
         check_nondet(|| 10f16.log10());
         check_nondet(|| 8f16.log2());
         check_nondet(|| 1f16.sin());
@@ -1587,7 +1591,7 @@ fn test_operations_f32(a: f32, b: f32) {
         check_nondet(|| a.log(b));
         check_nondet(|| a.exp());
         check_nondet(|| 10f32.exp2());
-        check_nondet(|| f32::consts::E.ln());
+        check_nondet(|| f32_consts::E.ln());
         check_nondet(|| 10f32.log10());
         check_nondet(|| 8f32.log2());
         check_nondet(|| 1f32.ln_1p());
@@ -1624,8 +1628,8 @@ fn test_operations_f64(a: f64, b: f64) {
         check_nondet(|| a.exp());
         check_nondet(|| 50f64.exp2());
         check_nondet(|| 3f64.ln());
-        check_nondet(|| f64::consts::E.log10());
-        check_nondet(|| f64::consts::E.log2());
+        check_nondet(|| f64_consts::E.log10());
+        check_nondet(|| f64_consts::E.log2());
         check_nondet(|| 1f64.ln_1p());
         check_nondet(|| 27.0f64.cbrt());
         check_nondet(|| 3.0f64.hypot(4.0f64));
diff --git a/src/tools/miri/tests/pass/packed-struct-dyn-trait.rs b/src/tools/miri/tests/pass/packed-struct-dyn-trait.rs
index bb73c26..2e61e77 100644
--- a/src/tools/miri/tests/pass/packed-struct-dyn-trait.rs
+++ b/src/tools/miri/tests/pass/packed-struct-dyn-trait.rs
@@ -1,4 +1,3 @@
-// run-pass
 use std::ptr::addr_of;
 
 // When the unsized tail is a `dyn Trait`, its alignments is only dynamically known. This means the
diff --git a/src/tools/miri/tests/pass/shims/socket.rs b/src/tools/miri/tests/pass/shims/socket.rs
new file mode 100644
index 0000000..2e63e00
--- /dev/null
+++ b/src/tools/miri/tests/pass/shims/socket.rs
@@ -0,0 +1,36 @@
+//@ignore-target: windows # No libc socket on Windows
+//@compile-flags: -Zmiri-disable-isolation
+
+use std::net::{TcpListener, TcpStream};
+use std::thread;
+
+fn main() {
+    test_create_ipv4_listener();
+    test_create_ipv6_listener();
+    test_accept_and_connect();
+}
+
+fn test_create_ipv4_listener() {
+    let _listener_ipv4 = TcpListener::bind("127.0.0.1:0").unwrap();
+}
+
+fn test_create_ipv6_listener() {
+    let _listener_ipv6 = TcpListener::bind("[::1]:0").unwrap();
+}
+
+/// Try to connect to a TCP listener running in a separate thread and
+/// accepting connections.
+fn test_accept_and_connect() {
+    let listener = TcpListener::bind("127.0.0.1:0").unwrap();
+    // Get local address with randomized port to know where
+    // we need to connect to.
+    let address = listener.local_addr().unwrap();
+
+    let handle = thread::spawn(move || {
+        let (_stream, _addr) = listener.accept().unwrap();
+    });
+
+    let _stream = TcpStream::connect(address).unwrap();
+
+    handle.join().unwrap();
+}
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs
index be3f961..9136b5e 100644
--- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse.rs
@@ -6,9 +6,10 @@
 use std::arch::x86::*;
 #[cfg(target_arch = "x86_64")]
 use std::arch::x86_64::*;
-use std::f32::NAN;
 use std::mem::transmute;
 
+const NAN: f32 = f32::NAN;
+
 fn main() {
     assert!(is_x86_feature_detected!("sse"));
 
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs
index 242aa0e..570da30 100644
--- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-sse2.rs
@@ -6,9 +6,10 @@
 use std::arch::x86::*;
 #[cfg(target_arch = "x86_64")]
 use std::arch::x86_64::*;
-use std::f64::NAN;
 use std::mem::transmute;
 
+const NAN: f64 = f64::NAN;
+
 fn main() {
     assert!(is_x86_feature_detected!("sse2"));
 
diff --git a/src/tools/rust-analyzer/README.md b/src/tools/rust-analyzer/README.md
index 6d2a673..06d63a2 100644
--- a/src/tools/rust-analyzer/README.md
+++ b/src/tools/rust-analyzer/README.md
@@ -20,6 +20,8 @@
 [Architecture](https://rust-analyzer.github.io/book/contributing/architecture.html)
 in the manual.
 
+[![codecov](https://codecov.io/github/rust-lang/rust-analyzer/graph/badge.svg)](https://app.codecov.io/github/rust-lang/rust-analyzer/tree/master)
+
 ## Quick Start
 
 https://rust-analyzer.github.io/book/installation.html
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ir_print.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ir_print.rs
index 998aab5..6593154 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ir_print.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ir_print.rs
@@ -1,7 +1,5 @@
 //! Things related to IR printing in the next-trait-solver.
 
-use std::any::type_name_of_val;
-
 use rustc_type_ir::{self as ty, ir_print::IrPrint};
 
 use super::SolverDefId;
@@ -82,7 +80,10 @@ fn print_debug(
         t: &ty::TraitPredicate<Self>,
         fmt: &mut std::fmt::Formatter<'_>,
     ) -> std::fmt::Result {
-        fmt.write_str(&format!("TODO: {:?}", type_name_of_val(t)))
+        match t.polarity {
+            ty::PredicatePolarity::Positive => write!(fmt, "{:?}", t.trait_ref),
+            ty::PredicatePolarity::Negative => write!(fmt, "!{:?}", t.trait_ref),
+        }
     }
 }
 impl<'db> IrPrint<rustc_type_ir::HostEffectPredicate<Self>> for DbInterner<'db> {
@@ -97,7 +98,11 @@ fn print_debug(
         t: &rustc_type_ir::HostEffectPredicate<Self>,
         fmt: &mut std::fmt::Formatter<'_>,
     ) -> std::fmt::Result {
-        fmt.write_str(&format!("TODO: {:?}", type_name_of_val(t)))
+        let prefix = match t.constness {
+            ty::BoundConstness::Const => "const",
+            ty::BoundConstness::Maybe => "[const]",
+        };
+        write!(fmt, "{prefix} {:?}", t.trait_ref)
     }
 }
 impl<'db> IrPrint<ty::ExistentialTraitRef<Self>> for DbInterner<'db> {
@@ -183,7 +188,7 @@ fn print_debug(
         t: &ty::NormalizesTo<Self>,
         fmt: &mut std::fmt::Formatter<'_>,
     ) -> std::fmt::Result {
-        fmt.write_str(&format!("TODO: {:?}", type_name_of_val(t)))
+        write!(fmt, "NormalizesTo({} -> {:?})", t.alias, t.term)
     }
 }
 impl<'db> IrPrint<ty::SubtypePredicate<Self>> for DbInterner<'db> {
@@ -198,7 +203,7 @@ fn print_debug(
         t: &ty::SubtypePredicate<Self>,
         fmt: &mut std::fmt::Formatter<'_>,
     ) -> std::fmt::Result {
-        fmt.write_str(&format!("TODO: {:?}", type_name_of_val(t)))
+        write!(fmt, "{:?} <: {:?}", t.a, t.b)
     }
 }
 impl<'db> IrPrint<ty::CoercePredicate<Self>> for DbInterner<'db> {
@@ -210,7 +215,7 @@ fn print_debug(
         t: &ty::CoercePredicate<Self>,
         fmt: &mut std::fmt::Formatter<'_>,
     ) -> std::fmt::Result {
-        fmt.write_str(&format!("TODO: {:?}", type_name_of_val(t)))
+        write!(fmt, "CoercePredicate({:?} -> {:?})", t.a, t.b)
     }
 }
 impl<'db> IrPrint<ty::FnSig<Self>> for DbInterner<'db> {
@@ -219,7 +224,9 @@ fn print(t: &ty::FnSig<Self>, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Re
     }
 
     fn print_debug(t: &ty::FnSig<Self>, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        fmt.write_str(&format!("TODO: {:?}", type_name_of_val(t)))
+        let tys = t.inputs_and_output.as_slice();
+        let (output, inputs) = tys.split_last().unwrap();
+        write!(fmt, "fn({:?}) -> {:?}", inputs, output)
     }
 }
 
@@ -235,6 +242,10 @@ fn print_debug(
         t: &rustc_type_ir::PatternKind<DbInterner<'db>>,
         fmt: &mut std::fmt::Formatter<'_>,
     ) -> std::fmt::Result {
-        fmt.write_str(&format!("TODO: {:?}", type_name_of_val(t)))
+        match t {
+            ty::PatternKind::Range { start, end } => write!(fmt, "{:?}..={:?}", start, end),
+            ty::PatternKind::Or(list) => write!(fmt, "or({:?})", list),
+            ty::PatternKind::NotNull => fmt.write_str("!null"),
+        }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs b/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs
index 2bd675b..29a933f 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs
@@ -217,6 +217,7 @@ pub(crate) fn from_fn_no_implications(db: &'db dyn HirDatabase, owner: FunctionI
     ("relaxed-simd", &["simd128"]),
     // BPF
     ("alu32", &[]),
+    ("allows-misaligned-mem-access", &[]),
     // CSKY
     ("10e60", &["7e10"]),
     ("2e3", &["e2"]),
diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
index 050777a..7f672a6 100644
--- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
@@ -51,20 +51,6 @@ fn from(d: $diag $(<$lt>)?) -> $AnyDiagnostic<$db> {
         )*
     };
 }
-// FIXME Accept something like the following in the macro call instead
-// diagnostics![
-// pub struct BreakOutsideOfLoop {
-//     pub expr: InFile<AstPtr<ast::Expr>>,
-//     pub is_break: bool,
-//     pub bad_value_break: bool,
-// }, ...
-// or more concisely
-// BreakOutsideOfLoop {
-//     expr: InFile<AstPtr<ast::Expr>>,
-//     is_break: bool,
-//     bad_value_break: bool,
-// }, ...
-// ]
 
 diagnostics![AnyDiagnostic<'db> ->
     AwaitOutsideOfAsync,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs
index 99ee50f..da1322d 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs
@@ -84,6 +84,7 @@ fn get_replacement_node(ctx: &AssistContext<'_>) -> Option<(ParentType, ast::Exp
             match parent {
                 ast::LetStmt(it) => it.initializer()?,
                 ast::LetExpr(it) => it.expr()?,
+                ast::BinExpr(it) => it.rhs()?,
                 ast::Static(it) => it.body()?,
                 ast::Const(it) => it.body()?,
                 _ => return None,
@@ -176,6 +177,70 @@ fn foo() {
 }
 "#,
         );
+
+        check_assist(
+            add_braces,
+            r#"
+fn foo() {
+    let x;
+    x =$0 n + 100;
+}
+"#,
+            r#"
+fn foo() {
+    let x;
+    x = {
+        n + 100
+    };
+}
+"#,
+        );
+
+        check_assist(
+            add_braces,
+            r#"
+fn foo() {
+    if let x =$0 n + 100 {}
+}
+"#,
+            r#"
+fn foo() {
+    if let x = {
+        n + 100
+    } {}
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn suggest_add_braces_for_const_initializer() {
+        check_assist(
+            add_braces,
+            r#"
+const X: i32 =$0 1 + 2;
+"#,
+            r#"
+const X: i32 = {
+    1 + 2
+};
+"#,
+        );
+    }
+
+    #[test]
+    fn suggest_add_braces_for_static_initializer() {
+        check_assist(
+            add_braces,
+            r#"
+static X: i32 $0= 1 + 2;
+"#,
+            r#"
+static X: i32 = {
+    1 + 2
+};
+"#,
+        );
     }
 
     #[test]
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_label_to_loop.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_label_to_loop.rs
index b84ad24..6a408e5 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_label_to_loop.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_label_to_loop.rs
@@ -3,11 +3,7 @@
 };
 use syntax::{
     SyntaxToken, T,
-    ast::{
-        self, AstNode, HasLoopBody,
-        make::{self, tokens},
-        syntax_factory::SyntaxFactory,
-    },
+    ast::{self, AstNode, HasLoopBody, syntax_factory::SyntaxFactory},
     syntax_editor::{Position, SyntaxEditor},
 };
 
@@ -35,9 +31,9 @@
 // }
 // ```
 pub(crate) fn add_label_to_loop(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
-    let loop_kw = ctx.find_token_syntax_at_offset(T![loop])?;
-    let loop_expr = loop_kw.parent().and_then(ast::LoopExpr::cast)?;
-    if loop_expr.label().is_some() {
+    let loop_expr = ctx.find_node_at_offset::<ast::AnyHasLoopBody>()?;
+    let loop_kw = loop_token(&loop_expr)?;
+    if loop_expr.label().is_some() || !loop_kw.text_range().contains_inclusive(ctx.offset()) {
         return None;
     }
 
@@ -52,8 +48,8 @@ pub(crate) fn add_label_to_loop(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
             let label = make.lifetime("'l");
             let elements = vec![
                 label.syntax().clone().into(),
-                make::token(T![:]).into(),
-                tokens::single_space().into(),
+                make.token(T![:]).into(),
+                make.whitespace(" ").into(),
             ];
             editor.insert_all(Position::before(&loop_kw), elements);
 
@@ -80,6 +76,14 @@ pub(crate) fn add_label_to_loop(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
     )
 }
 
+fn loop_token(loop_expr: &ast::AnyHasLoopBody) -> Option<syntax::SyntaxToken> {
+    loop_expr
+        .syntax()
+        .children_with_tokens()
+        .filter_map(|it| it.into_token())
+        .find(|it| matches!(it.kind(), T![for] | T![loop] | T![while]))
+}
+
 fn insert_label_after_token(
     editor: &mut SyntaxEditor,
     make: &SyntaxFactory,
@@ -88,7 +92,7 @@ fn insert_label_after_token(
     builder: &mut SourceChangeBuilder,
 ) {
     let label = make.lifetime("'l");
-    let elements = vec![tokens::single_space().into(), label.syntax().clone().into()];
+    let elements = vec![make.whitespace(" ").into(), label.syntax().clone().into()];
     editor.insert_all(Position::after(token), elements);
 
     if let Some(cap) = ctx.config.snippet_cap {
@@ -124,6 +128,48 @@ fn main() {
     }
 
     #[test]
+    fn add_label_to_while_expr() {
+        check_assist(
+            add_label_to_loop,
+            r#"
+fn main() {
+    while$0 true {
+        break;
+        continue;
+    }
+}"#,
+            r#"
+fn main() {
+    ${1:'l}: while true {
+        break ${2:'l};
+        continue ${0:'l};
+    }
+}"#,
+        );
+    }
+
+    #[test]
+    fn add_label_to_for_expr() {
+        check_assist(
+            add_label_to_loop,
+            r#"
+fn main() {
+    for$0 _ in 0..5 {
+        break;
+        continue;
+    }
+}"#,
+            r#"
+fn main() {
+    ${1:'l}: for _ in 0..5 {
+        break ${2:'l};
+        continue ${0:'l};
+    }
+}"#,
+        );
+    }
+
+    #[test]
     fn add_label_to_outer_loop() {
         check_assist(
             add_label_to_loop,
@@ -194,4 +240,29 @@ fn main() {
 }"#,
         );
     }
+
+    #[test]
+    fn do_not_add_label_if_outside_keyword() {
+        check_assist_not_applicable(
+            add_label_to_loop,
+            r#"
+fn main() {
+    'l: loop {$0
+        break 'l;
+        continue 'l;
+    }
+}"#,
+        );
+
+        check_assist_not_applicable(
+            add_label_to_loop,
+            r#"
+fn main() {
+    'l: while true {$0
+        break 'l;
+        continue 'l;
+    }
+}"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_lifetime_to_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_lifetime_to_type.rs
index 27dbdcf..265ee3d 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_lifetime_to_type.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_lifetime_to_type.rs
@@ -1,4 +1,7 @@
-use syntax::ast::{self, AstNode, HasGenericParams, HasName};
+use syntax::{
+    SyntaxKind, SyntaxNode, SyntaxToken,
+    ast::{self, AstNode, HasGenericParams, HasName},
+};
 
 use crate::{AssistContext, AssistId, Assists};
 
@@ -21,7 +24,7 @@
 // ```
 pub(crate) fn add_lifetime_to_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
     let ref_type_focused = ctx.find_node_at_offset::<ast::RefType>()?;
-    if ref_type_focused.lifetime().is_some() {
+    if ref_type_focused.lifetime().is_some_and(|lifetime| lifetime.text() != "'_") {
         return None;
     }
 
@@ -34,10 +37,10 @@ pub(crate) fn add_lifetime_to_type(acc: &mut Assists, ctx: &AssistContext<'_>) -
         return None;
     }
 
-    let ref_types = fetch_borrowed_types(&node)?;
+    let changes = fetch_borrowed_types(&node)?;
     let target = node.syntax().text_range();
 
-    acc.add(AssistId::generate("add_lifetime_to_type"), "Add lifetime", target, |builder| {
+    acc.add(AssistId::quick_fix("add_lifetime_to_type"), "Add lifetime", target, |builder| {
         match node.generic_param_list() {
             Some(gen_param) => {
                 if let Some(left_angle) = gen_param.l_angle_token() {
@@ -51,16 +54,21 @@ pub(crate) fn add_lifetime_to_type(acc: &mut Assists, ctx: &AssistContext<'_>) -
             }
         }
 
-        for ref_type in ref_types {
-            if let Some(amp_token) = ref_type.amp_token() {
-                builder.insert(amp_token.text_range().end(), "'a ");
+        for change in changes {
+            match change {
+                Change::Replace(it) => {
+                    builder.replace(it.text_range(), "'a");
+                }
+                Change::Insert(it) => {
+                    builder.insert(it.text_range().end(), "'a ");
+                }
             }
         }
     })
 }
 
-fn fetch_borrowed_types(node: &ast::Adt) -> Option<Vec<ast::RefType>> {
-    let ref_types: Vec<ast::RefType> = match node {
+fn fetch_borrowed_types(node: &ast::Adt) -> Option<Vec<Change>> {
+    let ref_types: Vec<_> = match node {
         ast::Adt::Enum(enum_) => {
             let variant_list = enum_.variant_list()?;
             variant_list
@@ -79,55 +87,50 @@ fn fetch_borrowed_types(node: &ast::Adt) -> Option<Vec<ast::RefType>> {
         }
         ast::Adt::Union(un) => {
             let record_field_list = un.record_field_list()?;
-            record_field_list
-                .fields()
-                .filter_map(|r_field| {
-                    if let ast::Type::RefType(ref_type) = r_field.ty()?
-                        && ref_type.lifetime().is_none()
-                    {
-                        return Some(ref_type);
-                    }
-
-                    None
-                })
-                .collect()
+            find_ref_types_from_field_list(&record_field_list.into())?
         }
     };
 
     if ref_types.is_empty() { None } else { Some(ref_types) }
 }
 
-fn find_ref_types_from_field_list(field_list: &ast::FieldList) -> Option<Vec<ast::RefType>> {
-    let ref_types: Vec<ast::RefType> = match field_list {
-        ast::FieldList::RecordFieldList(record_list) => record_list
-            .fields()
-            .filter_map(|f| {
-                if let ast::Type::RefType(ref_type) = f.ty()?
-                    && ref_type.lifetime().is_none()
-                {
-                    return Some(ref_type);
-                }
-
-                None
-            })
-            .collect(),
-        ast::FieldList::TupleFieldList(tuple_field_list) => tuple_field_list
-            .fields()
-            .filter_map(|f| {
-                if let ast::Type::RefType(ref_type) = f.ty()?
-                    && ref_type.lifetime().is_none()
-                {
-                    return Some(ref_type);
-                }
-
-                None
-            })
-            .collect(),
+fn find_ref_types_from_field_list(field_list: &ast::FieldList) -> Option<Vec<Change>> {
+    let ref_types: Vec<_> = match field_list {
+        ast::FieldList::RecordFieldList(record_list) => {
+            record_list.fields().flat_map(|f| infer_lifetimes(f.syntax())).collect()
+        }
+        ast::FieldList::TupleFieldList(tuple_field_list) => {
+            tuple_field_list.fields().flat_map(|f| infer_lifetimes(f.syntax())).collect()
+        }
     };
 
     if ref_types.is_empty() { None } else { Some(ref_types) }
 }
 
+enum Change {
+    Replace(SyntaxToken),
+    Insert(SyntaxToken),
+}
+
+fn infer_lifetimes(node: &SyntaxNode) -> Vec<Change> {
+    node.children()
+        .filter(|it| !matches!(it.kind(), SyntaxKind::FN_PTR_TYPE | SyntaxKind::TYPE_BOUND_LIST))
+        .flat_map(|it| {
+            infer_lifetimes(&it)
+                .into_iter()
+                .chain(ast::Lifetime::cast(it.clone()).and_then(|lt| {
+                    lt.lifetime_ident_token().filter(|lt| lt.text() == "'_").map(Change::Replace)
+                }))
+                .chain(
+                    ast::RefType::cast(it)
+                        .filter(|ty| ty.lifetime().is_none())
+                        .and_then(|ty| ty.amp_token())
+                        .map(Change::Insert),
+                )
+        })
+        .collect()
+}
+
 #[cfg(test)]
 mod tests {
     use crate::tests::{check_assist, check_assist_not_applicable};
@@ -165,6 +168,24 @@ fn add_lifetime_to_struct() {
     }
 
     #[test]
+    fn add_lifetime_to_nested_types() {
+        check_assist(
+            add_lifetime_to_type,
+            r#"struct Foo { a: &$0i32, b: &(&i32, fn(&str) -> &str) }"#,
+            r#"struct Foo<'a> { a: &'a i32, b: &'a (&'a i32, fn(&str) -> &str) }"#,
+        );
+    }
+
+    #[test]
+    fn add_lifetime_to_explicit_infer_lifetime() {
+        check_assist(
+            add_lifetime_to_type,
+            r#"struct Foo { a: &'_ $0i32, b: &'_ (&'_ i32, fn(&str) -> &str) }"#,
+            r#"struct Foo<'a> { a: &'a i32, b: &'a (&'a i32, fn(&str) -> &str) }"#,
+        );
+    }
+
+    #[test]
     fn add_lifetime_to_enum() {
         check_assist(
             add_lifetime_to_type,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs
index c0ce057..8124fec 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs
@@ -245,14 +245,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
                 .arms()
                 .filter(|arm| {
                     if matches!(arm.pat(), Some(ast::Pat::WildcardPat(_))) {
-                        let is_empty_expr = arm.expr().is_none_or(|e| match e {
-                            ast::Expr::BlockExpr(b) => {
-                                b.statements().next().is_none() && b.tail_expr().is_none()
-                            }
-                            ast::Expr::TupleExpr(t) => t.fields().next().is_none(),
-                            _ => false,
-                        });
-                        if is_empty_expr {
+                        if arm.expr().is_none_or(is_empty_expr) {
                             false
                         } else {
                             cov_mark::hit!(add_missing_match_arms_empty_expr);
@@ -347,12 +340,24 @@ fn cursor_at_trivial_match_arm_list(
     //     $0
     // }
     if let Some(last_arm) = match_arm_list.arms().last() {
-        let last_arm_range = ctx.sema.original_range_opt(last_arm.syntax())?.range;
+        let last_node = match last_arm.expr() {
+            Some(expr) => expr.syntax().clone(),
+            None => last_arm.syntax().clone(),
+        };
+        let last_node_range = ctx.sema.original_range_opt(&last_node)?.range;
         let match_expr_range = ctx.sema.original_range_opt(match_expr.syntax())?.range;
-        if last_arm_range.end() <= ctx.offset() && ctx.offset() < match_expr_range.end() {
+        if last_node_range.end() <= ctx.offset() && ctx.offset() < match_expr_range.end() {
             cov_mark::hit!(add_missing_match_arms_end_of_last_arm);
             return Some(());
         }
+
+        if ast::Expr::cast(last_node.clone()).is_some_and(is_empty_expr)
+            && last_node_range.contains(ctx.offset())
+            && !last_node.text().contains_char('\n')
+        {
+            cov_mark::hit!(add_missing_match_arms_end_of_last_empty_arm);
+            return Some(());
+        }
     }
 
     // match { _$0 => {...} }
@@ -371,6 +376,14 @@ fn is_variant_missing(existing_pats: &[Pat], var: &Pat) -> bool {
     !existing_pats.iter().any(|pat| does_pat_match_variant(pat, var))
 }
 
+fn is_empty_expr(e: ast::Expr) -> bool {
+    match e {
+        ast::Expr::BlockExpr(b) => b.statements().next().is_none() && b.tail_expr().is_none(),
+        ast::Expr::TupleExpr(t) => t.fields().next().is_none(),
+        _ => false,
+    }
+}
+
 // Fixme: this is still somewhat limited, use hir_ty::diagnostics::match_check?
 fn does_pat_match_variant(pat: &Pat, var: &Pat) -> bool {
     match (pat, var) {
@@ -1066,7 +1079,7 @@ fn main() {
 
     #[test]
     fn add_missing_match_arms_end_of_last_arm() {
-        cov_mark::check!(add_missing_match_arms_end_of_last_arm);
+        cov_mark::check_count!(add_missing_match_arms_end_of_last_arm, 2);
         check_assist(
             add_missing_match_arms,
             r#"
@@ -1097,6 +1110,103 @@ fn main() {
 }
 "#,
         );
+
+        check_assist(
+            add_missing_match_arms,
+            r#"
+enum A { One, Two }
+enum B { One, Two }
+
+fn main() {
+    let a = A::One;
+    let b = B::One;
+    match (a, b) {
+        (A::Two, B::One) => 2$0,
+    }
+}
+"#,
+            r#"
+enum A { One, Two }
+enum B { One, Two }
+
+fn main() {
+    let a = A::One;
+    let b = B::One;
+    match (a, b) {
+        (A::Two, B::One) => 2,
+        (A::One, B::One) => ${1:todo!()},
+        (A::One, B::Two) => ${2:todo!()},
+        (A::Two, B::Two) => ${3:todo!()},$0
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn add_missing_match_arms_end_of_last_empty_arm() {
+        cov_mark::check_count!(add_missing_match_arms_end_of_last_empty_arm, 2);
+        check_assist(
+            add_missing_match_arms,
+            r#"
+enum A { One, Two }
+enum B { One, Two }
+
+fn main() {
+    let a = A::One;
+    let b = B::One;
+    match (a, b) {
+        (A::Two, B::One) => {$0}
+    }
+}
+"#,
+            r#"
+enum A { One, Two }
+enum B { One, Two }
+
+fn main() {
+    let a = A::One;
+    let b = B::One;
+    match (a, b) {
+        (A::Two, B::One) => {}
+        (A::One, B::One) => ${1:todo!()},
+        (A::One, B::Two) => ${2:todo!()},
+        (A::Two, B::Two) => ${3:todo!()},$0
+    }
+}
+"#,
+        );
+
+        check_assist(
+            add_missing_match_arms,
+            r#"
+enum A { One, Two }
+enum B { One, Two }
+
+fn main() {
+    let a = A::One;
+    let b = B::One;
+    match (a, b) {
+        (A::Two, B::One) => ($0)
+    }
+}
+"#,
+            r#"
+enum A { One, Two }
+enum B { One, Two }
+
+fn main() {
+    let a = A::One;
+    let b = B::One;
+    match (a, b) {
+        (A::Two, B::One) => (),
+        (A::One, B::One) => ${1:todo!()},
+        (A::One, B::Two) => ${2:todo!()},
+        (A::Two, B::Two) => ${3:todo!()},$0
+    }
+}
+"#,
+        );
     }
 
     #[test]
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs
index 80d0a6d..4ee4970 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs
@@ -197,7 +197,7 @@ pub(crate) fn apply_demorgan_iterator(acc: &mut Assists, ctx: &AssistContext<'_>
     let (name, arg_expr) = validate_method_call_expr(ctx, &method_call)?;
 
     let ast::Expr::ClosureExpr(closure_expr) = arg_expr else { return None };
-    let closure_body = closure_expr.body()?.clone_for_update();
+    let closure_body = closure_expr.body()?;
 
     let op_range = method_call.syntax().text_range();
     let label = format!("Apply De Morgan's law to `Iterator::{}`", name.text().as_str());
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs
index 9347798..e88778a 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_to_enum.rs
@@ -533,7 +533,7 @@ fn make_bool_enum(make_pub: bool, make: &SyntaxFactory) -> ast::Enum {
             ],
         ),
     ));
-    make.enum_(
+    make.item_enum(
         [derive_eq],
         if make_pub { Some(make.visibility_pub()) } else { None },
         make.name("Bool"),
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs
index 5a223e1..9f9ced9 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs
@@ -220,7 +220,7 @@ pub(crate) fn convert_closure_to_fn(acc: &mut Assists, ctx: &AssistContext<'_>)
             }
 
             let body = if wrap_body_in_block {
-                make::block_expr([], Some(body))
+                make::block_expr([], Some(body.reset_indent().indent(1.into())))
             } else {
                 ast::BlockExpr::cast(body.syntax().clone()).unwrap()
             };
@@ -971,6 +971,32 @@ fn closure() {
 }
 "#,
         );
+        check_assist(
+            convert_closure_to_fn,
+            r#"
+//- minicore: copy
+fn foo() {
+    {
+        let closure = |$0| match () {
+            () => {},
+        };
+        closure();
+    }
+}
+"#,
+            r#"
+fn foo() {
+    {
+        fn closure() {
+            match () {
+                () => {},
+            }
+        }
+        closure();
+    }
+}
+"#,
+        );
     }
 
     #[test]
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_for_to_while_let.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_for_to_while_let.rs
index d64e9ce..d409374 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_for_to_while_let.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_for_to_while_let.rs
@@ -2,7 +2,7 @@
 use ide_db::{famous_defs::FamousDefs, syntax_helpers::suggest_name};
 use syntax::{
     AstNode,
-    ast::{self, HasAttrs, HasLoopBody, edit::IndentLevel, make, syntax_factory::SyntaxFactory},
+    ast::{self, HasAttrs, HasLoopBody, edit::IndentLevel, syntax_factory::SyntaxFactory},
     syntax_editor::Position,
 };
 
@@ -57,13 +57,13 @@ pub(crate) fn convert_for_loop_to_while_let(
             {
                 (expr, Some(make.name_ref(method.as_str())))
             } else if let ast::Expr::RefExpr(_) = iterable {
-                (make::expr_paren(iterable).into(), Some(make.name_ref("into_iter")))
+                (make.expr_paren(iterable).into(), Some(make.name_ref("into_iter")))
             } else {
                 (iterable, Some(make.name_ref("into_iter")))
             };
 
             let iterable = if let Some(method) = method {
-                make::expr_method_call(iterable, method, make::arg_list([])).into()
+                make.expr_method_call(iterable, method, make.arg_list([])).into()
             } else {
                 iterable
             };
@@ -89,17 +89,18 @@ pub(crate) fn convert_for_loop_to_while_let(
                 for_loop.syntax(),
                 &mut editor,
                 for_loop.attrs().map(|it| it.clone_for_update()),
+                &make,
             );
 
             editor.insert(
                 Position::before(for_loop.syntax()),
-                make::tokens::whitespace(format!("\n{indent}").as_str()),
+                make.whitespace(format!("\n{indent}").as_str()),
             );
             editor.insert(Position::before(for_loop.syntax()), mut_expr.syntax());
 
-            let opt_pat = make.tuple_struct_pat(make::ext::ident_path("Some"), [pat]);
+            let opt_pat = make.tuple_struct_pat(make.ident_path("Some"), [pat]);
             let iter_next_expr = make.expr_method_call(
-                make.expr_path(make::ext::ident_path(&tmp_var)),
+                make.expr_path(make.ident_path(&tmp_var)),
                 make.name_ref("next"),
                 make.arg_list([]),
             );
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs
index 6a74d21..66ccd2a 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs
@@ -1,6 +1,6 @@
 use ide_db::{famous_defs::FamousDefs, traits::resolve_target_trait};
 use syntax::ast::edit::IndentLevel;
-use syntax::ast::{self, AstNode, HasGenericArgs, HasName, make};
+use syntax::ast::{self, AstNode, HasGenericArgs, HasName, syntax_factory::SyntaxFactory};
 use syntax::syntax_editor::{Element, Position};
 
 use crate::{AssistContext, AssistId, Assists};
@@ -74,36 +74,25 @@ pub(crate) fn convert_from_to_tryfrom(acc: &mut Assists, ctx: &AssistContext<'_>
         "Convert From to TryFrom",
         impl_.syntax().text_range(),
         |builder| {
+            let make = SyntaxFactory::with_mappings();
             let mut editor = builder.make_editor(impl_.syntax());
-            editor.replace(
-                trait_ty.syntax(),
-                make::ty(&format!("TryFrom<{from_type}>")).syntax().clone_for_update(),
-            );
+
+            editor.replace(trait_ty.syntax(), make.ty(&format!("TryFrom<{from_type}>")).syntax());
             editor.replace(
                 from_fn_return_type.syntax(),
-                make::ty("Result<Self, Self::Error>").syntax().clone_for_update(),
+                make.ty("Result<Self, Self::Error>").syntax(),
             );
-            editor
-                .replace(from_fn_name.syntax(), make::name("try_from").syntax().clone_for_update());
-            editor.replace(
-                tail_expr.syntax(),
-                wrap_ok(tail_expr.clone()).syntax().clone_for_update(),
-            );
+            editor.replace(from_fn_name.syntax(), make.name("try_from").syntax());
+            editor.replace(tail_expr.syntax(), wrap_ok(&make, tail_expr.clone()).syntax());
 
             for r in return_exprs {
-                let t = r.expr().unwrap_or_else(make::ext::expr_unit);
-                editor.replace(t.syntax(), wrap_ok(t.clone()).syntax().clone_for_update());
+                let t = r.expr().unwrap_or_else(|| make.expr_unit());
+                editor.replace(t.syntax(), wrap_ok(&make, t.clone()).syntax());
             }
 
-            let error_type = ast::AssocItem::TypeAlias(make::ty_alias(
-                None,
-                "Error",
-                None,
-                None,
-                None,
-                Some((make::ty_unit(), None)),
-            ))
-            .clone_for_update();
+            let error_type_alias =
+                make.ty_alias(None, "Error", None, None, None, Some((make.ty("()"), None)));
+            let error_type = ast::AssocItem::TypeAlias(error_type_alias);
 
             if let Some(cap) = ctx.config.snippet_cap
                 && let ast::AssocItem::TypeAlias(type_alias) = &error_type
@@ -117,22 +106,19 @@ pub(crate) fn convert_from_to_tryfrom(acc: &mut Assists, ctx: &AssistContext<'_>
             editor.insert_all(
                 Position::after(associated_l_curly),
                 vec![
-                    make::tokens::whitespace(&format!("\n{indent}")).syntax_element(),
+                    make.whitespace(&format!("\n{indent}")).syntax_element(),
                     error_type.syntax().syntax_element(),
-                    make::tokens::whitespace("\n").syntax_element(),
+                    make.whitespace("\n").syntax_element(),
                 ],
             );
+            editor.add_mappings(make.finish_with_mappings());
             builder.add_file_edits(ctx.vfs_file_id(), editor);
         },
     )
 }
 
-fn wrap_ok(expr: ast::Expr) -> ast::Expr {
-    make::expr_call(
-        make::expr_path(make::ext::ident_path("Ok")),
-        make::arg_list(std::iter::once(expr)),
-    )
-    .into()
+fn wrap_ok(make: &SyntaxFactory, expr: ast::Expr) -> ast::Expr {
+    make.expr_call(make.expr_path(make.path_from_text("Ok")), make.arg_list([expr])).into()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
index e518c39..42fceb8 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
@@ -1,14 +1,18 @@
 use either::Either;
 use ide_db::{defs::Definition, search::FileReference};
-use itertools::Itertools;
 use syntax::{
-    SyntaxKind,
-    ast::{self, AstNode, HasAttrs, HasGenericParams, HasVisibility},
+    NodeOrToken, SyntaxKind, SyntaxNode, T,
+    algo::next_non_trivia_token,
+    ast::{
+        self, AstNode, HasAttrs, HasGenericParams, HasVisibility, syntax_factory::SyntaxFactory,
+    },
     match_ast,
-    syntax_editor::{Position, SyntaxEditor},
+    syntax_editor::{Element, Position, SyntaxEditor},
 };
 
-use crate::{AssistContext, AssistId, Assists, assist_context::SourceChangeBuilder};
+use crate::{
+    AssistContext, AssistId, Assists, assist_context::SourceChangeBuilder, utils::cover_edit_range,
+};
 
 // Assist: convert_named_struct_to_tuple_struct
 //
@@ -81,17 +85,17 @@ pub(crate) fn convert_named_struct_to_tuple_struct(
         AssistId::refactor_rewrite("convert_named_struct_to_tuple_struct"),
         "Convert to tuple struct",
         strukt_or_variant.syntax().text_range(),
-        |edit| {
-            edit_field_references(ctx, edit, record_fields.fields());
-            edit_struct_references(ctx, edit, strukt_def);
-            edit_struct_def(ctx, edit, &strukt_or_variant, record_fields);
+        |builder| {
+            edit_field_references(ctx, builder, record_fields.fields());
+            edit_struct_references(ctx, builder, strukt_def);
+            edit_struct_def(ctx, builder, &strukt_or_variant, record_fields);
         },
     )
 }
 
 fn edit_struct_def(
     ctx: &AssistContext<'_>,
-    edit: &mut SourceChangeBuilder,
+    builder: &mut SourceChangeBuilder,
     strukt: &Either<ast::Struct, ast::Variant>,
     record_fields: ast::RecordFieldList,
 ) {
@@ -108,24 +112,23 @@ fn edit_struct_def(
         let field = ast::TupleField::cast(field_syntax)?;
         Some(field)
     });
-    let tuple_fields = ast::make::tuple_field_list(tuple_fields);
-    let record_fields_text_range = record_fields.syntax().text_range();
 
-    edit.edit_file(ctx.vfs_file_id());
-    edit.replace(record_fields_text_range, tuple_fields.syntax().text());
+    let make = SyntaxFactory::without_mappings();
+    let mut edit = builder.make_editor(strukt.syntax());
 
+    let tuple_fields = make.tuple_field_list(tuple_fields);
+
+    let mut elements = vec![tuple_fields.syntax().clone().into()];
     if let Either::Left(strukt) = strukt {
         if let Some(w) = strukt.where_clause() {
-            let mut where_clause = w.to_string();
-            if where_clause.ends_with(',') {
-                where_clause.pop();
-            }
-            where_clause.push(';');
+            edit.delete(w.syntax());
 
-            edit.delete(w.syntax().text_range());
-            edit.insert(record_fields_text_range.end(), ast::make::tokens::single_newline().text());
-            edit.insert(record_fields_text_range.end(), where_clause);
-            edit.insert(record_fields_text_range.end(), ast::make::tokens::single_newline().text());
+            elements.extend([
+                make.whitespace("\n").into(),
+                remove_trailing_comma(w).into(),
+                make.token(T![;]).into(),
+                make.whitespace("\n").into(),
+            ]);
 
             if let Some(tok) = strukt
                 .generic_param_list()
@@ -133,25 +136,28 @@ fn edit_struct_def(
                 .and_then(|tok| tok.next_token())
                 .filter(|tok| tok.kind() == SyntaxKind::WHITESPACE)
             {
-                edit.delete(tok.text_range());
+                edit.delete(tok);
             }
         } else {
-            edit.insert(record_fields_text_range.end(), ";");
+            elements.push(make.token(T![;]).into());
         }
     }
+    edit.replace_with_many(record_fields.syntax(), elements);
 
     if let Some(tok) = record_fields
         .l_curly_token()
         .and_then(|tok| tok.prev_token())
         .filter(|tok| tok.kind() == SyntaxKind::WHITESPACE)
     {
-        edit.delete(tok.text_range())
+        edit.delete(tok)
     }
+
+    builder.add_file_edits(ctx.vfs_file_id(), edit);
 }
 
 fn edit_struct_references(
     ctx: &AssistContext<'_>,
-    edit: &mut SourceChangeBuilder,
+    builder: &mut SourceChangeBuilder,
     strukt: Either<hir::Struct, hir::Variant>,
 ) {
     let strukt_def = match strukt {
@@ -161,17 +167,20 @@ fn edit_struct_references(
     let usages = strukt_def.usages(&ctx.sema).include_self_refs().all();
 
     for (file_id, refs) in usages {
-        edit.edit_file(file_id.file_id(ctx.db()));
+        let source = ctx.sema.parse(file_id);
+        let mut edit = builder.make_editor(source.syntax());
         for r in refs {
-            process_struct_name_reference(ctx, r, edit);
+            process_struct_name_reference(ctx, r, &mut edit, &source);
         }
+        builder.add_file_edits(file_id.file_id(ctx.db()), edit);
     }
 }
 
 fn process_struct_name_reference(
     ctx: &AssistContext<'_>,
     r: FileReference,
-    edit: &mut SourceChangeBuilder,
+    edit: &mut SyntaxEditor,
+    source: &ast::SourceFile,
 ) -> Option<()> {
     // First check if it's the last semgnet of a path that directly belongs to a record
     // expression/pattern.
@@ -192,36 +201,26 @@ fn process_struct_name_reference(
     match_ast! {
         match parent {
             ast::RecordPat(record_struct_pat) => {
-                // When we failed to get the original range for the whole struct expression node,
+                // When we failed to get the original range for the whole struct pattern node,
                 // we can't provide any reasonable edit. Leave it untouched.
-                let file_range = ctx.sema.original_range_opt(record_struct_pat.syntax())?;
-                edit.replace(
-                    file_range.range,
-                    ast::make::tuple_struct_pat(
-                        record_struct_pat.path()?,
-                        record_struct_pat
-                            .record_pat_field_list()?
-                            .fields()
-                            .filter_map(|pat| pat.pat())
-                            .chain(record_struct_pat.record_pat_field_list()?
-                                .rest_pat()
-                                .map(Into::into))
-                    )
-                    .to_string()
+                record_to_tuple_struct_like(
+                    ctx,
+                    source,
+                    edit,
+                    record_struct_pat.record_pat_field_list()?,
+                    |it| it.fields().filter_map(|it| it.name_ref()),
                 );
             },
             ast::RecordExpr(record_expr) => {
-                // When we failed to get the original range for the whole struct pattern node,
+                // When we failed to get the original range for the whole struct expression node,
                 // we can't provide any reasonable edit. Leave it untouched.
-                let file_range = ctx.sema.original_range_opt(record_expr.syntax())?;
-                let path = record_expr.path()?;
-                let args = record_expr
-                    .record_expr_field_list()?
-                    .fields()
-                    .filter_map(|f| f.expr())
-                    .join(", ");
-
-                edit.replace(file_range.range, format!("{path}({args})"));
+                record_to_tuple_struct_like(
+                    ctx,
+                    source,
+                    edit,
+                    record_expr.record_expr_field_list()?,
+                    |it| it.fields().filter_map(|it| it.name_ref()),
+                );
             },
             _ => {}
         }
@@ -230,11 +229,67 @@ fn process_struct_name_reference(
     Some(())
 }
 
+fn record_to_tuple_struct_like<T, I>(
+    ctx: &AssistContext<'_>,
+    source: &ast::SourceFile,
+    edit: &mut SyntaxEditor,
+    field_list: T,
+    fields: impl FnOnce(&T) -> I,
+) -> Option<()>
+where
+    T: AstNode,
+    I: IntoIterator<Item = ast::NameRef>,
+{
+    let make = SyntaxFactory::without_mappings();
+    let orig = ctx.sema.original_range_opt(field_list.syntax())?;
+    let list_range = cover_edit_range(source, orig.range);
+
+    let l_curly = match list_range.start() {
+        NodeOrToken::Node(node) => node.first_token()?,
+        NodeOrToken::Token(t) => t.clone(),
+    };
+    let r_curly = match list_range.end() {
+        NodeOrToken::Node(node) => node.last_token()?,
+        NodeOrToken::Token(t) => t.clone(),
+    };
+
+    if l_curly.kind() == T!['{'] {
+        delete_whitespace(edit, l_curly.prev_token());
+        delete_whitespace(edit, l_curly.next_token());
+        edit.replace(l_curly, make.token(T!['(']));
+    }
+    if r_curly.kind() == T!['}'] {
+        delete_whitespace(edit, r_curly.prev_token());
+        edit.replace(r_curly, make.token(T![')']));
+    }
+
+    for name_ref in fields(&field_list) {
+        let Some(orig) = ctx.sema.original_range_opt(name_ref.syntax()) else { continue };
+        let name_range = cover_edit_range(source, orig.range);
+
+        if let Some(colon) = next_non_trivia_token(name_range.end().clone())
+            && colon.kind() == T![:]
+        {
+            edit.delete(&colon);
+            edit.delete_all(name_range);
+
+            if let Some(next) = next_non_trivia_token(colon.clone())
+                && next.kind() != T!['}']
+            {
+                // Avoid overlapping delete whitespace on `{ field: }`
+                delete_whitespace(edit, colon.next_token());
+            }
+        }
+    }
+    Some(())
+}
+
 fn edit_field_references(
     ctx: &AssistContext<'_>,
-    edit: &mut SourceChangeBuilder,
+    builder: &mut SourceChangeBuilder,
     fields: impl Iterator<Item = ast::RecordField>,
 ) {
+    let make = SyntaxFactory::without_mappings();
     for (index, field) in fields.enumerate() {
         let field = match ctx.sema.to_def(&field) {
             Some(it) => it,
@@ -243,19 +298,46 @@ fn edit_field_references(
         let def = Definition::Field(field);
         let usages = def.usages(&ctx.sema).all();
         for (file_id, refs) in usages {
-            edit.edit_file(file_id.file_id(ctx.db()));
+            let source = ctx.sema.parse(file_id);
+            let mut edit = builder.make_editor(source.syntax());
+
             for r in refs {
                 if let Some(name_ref) = r.name.as_name_ref() {
                     // Only edit the field reference if it's part of a `.field` access
                     if name_ref.syntax().parent().and_then(ast::FieldExpr::cast).is_some() {
-                        edit.replace(r.range, index.to_string());
+                        edit.replace_all(
+                            cover_edit_range(&source, r.range),
+                            vec![make.name_ref(&index.to_string()).syntax().clone().into()],
+                        );
                     }
                 }
             }
+
+            builder.add_file_edits(file_id.file_id(ctx.db()), edit);
         }
     }
 }
 
+fn delete_whitespace(edit: &mut SyntaxEditor, whitespace: Option<impl Element>) {
+    let Some(whitespace) = whitespace else { return };
+    let NodeOrToken::Token(token) = whitespace.syntax_element() else { return };
+
+    if token.kind() == SyntaxKind::WHITESPACE && !token.text().contains('\n') {
+        edit.delete(token);
+    }
+}
+
+fn remove_trailing_comma(w: ast::WhereClause) -> SyntaxNode {
+    let w = w.syntax().clone_subtree();
+    let mut editor = SyntaxEditor::new(w.clone());
+    if let Some(last) = w.last_child_or_token()
+        && last.kind() == T![,]
+    {
+        editor.delete(last);
+    }
+    editor.finish().new_root().clone()
+}
+
 #[cfg(test)]
 mod tests {
     use crate::tests::{check_assist, check_assist_not_applicable};
@@ -678,6 +760,102 @@ struct Wrap<T>(T)
     }
 
     #[test]
+    fn convert_constructor_expr_uses_self() {
+        // regression test for #21595
+        check_assist(
+            convert_named_struct_to_tuple_struct,
+            r#"
+struct $0Foo { field1: u32 }
+impl Foo {
+    fn clone(&self) -> Self {
+        Self { field1: self.field1 }
+    }
+}"#,
+            r#"
+struct Foo(u32);
+impl Foo {
+    fn clone(&self) -> Self {
+        Self(self.0)
+    }
+}"#,
+        );
+
+        check_assist(
+            convert_named_struct_to_tuple_struct,
+            r#"
+macro_rules! id {
+    ($($t:tt)*) => { $($t)* }
+}
+struct $0Foo { field1: u32 }
+impl Foo {
+    fn clone(&self) -> Self {
+        id!(Self { field1: self.field1 })
+    }
+}"#,
+            r#"
+macro_rules! id {
+    ($($t:tt)*) => { $($t)* }
+}
+struct Foo(u32);
+impl Foo {
+    fn clone(&self) -> Self {
+        id!(Self(self.0))
+    }
+}"#,
+        );
+    }
+
+    #[test]
+    fn convert_pat_uses_self() {
+        // regression test for #21595
+        check_assist(
+            convert_named_struct_to_tuple_struct,
+            r#"
+enum Foo {
+    $0Value { field: &'static Foo },
+    Nil,
+}
+fn foo(foo: &Foo) {
+    if let Foo::Value { field: Foo::Value { field } } = foo {}
+}"#,
+            r#"
+enum Foo {
+    Value(&'static Foo),
+    Nil,
+}
+fn foo(foo: &Foo) {
+    if let Foo::Value(Foo::Value(field)) = foo {}
+}"#,
+        );
+
+        check_assist(
+            convert_named_struct_to_tuple_struct,
+            r#"
+macro_rules! id {
+    ($($t:tt)*) => { $($t)* }
+}
+enum Foo {
+    $0Value { field: &'static Foo },
+    Nil,
+}
+fn foo(foo: &Foo) {
+    if let id!(Foo::Value { field: Foo::Value { field } }) = foo {}
+}"#,
+            r#"
+macro_rules! id {
+    ($($t:tt)*) => { $($t)* }
+}
+enum Foo {
+    Value(&'static Foo),
+    Nil,
+}
+fn foo(foo: &Foo) {
+    if let id!(Foo::Value(Foo::Value(field))) = foo {}
+}"#,
+        );
+    }
+
+    #[test]
     fn not_applicable_other_than_record_variant() {
         check_assist_not_applicable(
             convert_named_struct_to_tuple_struct,
@@ -1042,7 +1220,9 @@ macro_rules! id {
 
 fn test() {
     id! {
-        let s = Struct(42);
+        let s = Struct(
+            42,
+        );
         let Struct(value) = s;
         let Struct(inner) = s;
     }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs
index dc51bf4..db45916 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs
@@ -10,14 +10,14 @@
     ast::{
         self,
         edit::{AstNodeEdit, IndentLevel},
-        make,
+        syntax_factory::SyntaxFactory,
     },
 };
 
 use crate::{
     AssistId,
     assist_context::{AssistContext, Assists},
-    utils::{invert_boolean_expression_legacy, is_never_block},
+    utils::{invert_boolean_expression, is_never_block},
 };
 
 // Assist: convert_to_guarded_return
@@ -69,6 +69,7 @@ fn if_expr_to_guarded_return(
     acc: &mut Assists,
     ctx: &AssistContext<'_>,
 ) -> Option<()> {
+    let make = SyntaxFactory::without_mappings();
     let else_block = match if_expr.else_branch() {
         Some(ast::ElseBranch::Block(block_expr)) if is_never_block(&ctx.sema, &block_expr) => {
             Some(block_expr)
@@ -88,7 +89,7 @@ fn if_expr_to_guarded_return(
         return None;
     }
 
-    let let_chains = flat_let_chain(cond);
+    let let_chains = flat_let_chain(cond, &make);
 
     let then_branch = if_expr.then_branch()?;
     let then_block = then_branch.stmt_list()?;
@@ -110,7 +111,8 @@ fn if_expr_to_guarded_return(
 
     let early_expression = else_block
         .or_else(|| {
-            early_expression(parent_container, &ctx.sema).map(ast::make::tail_only_block_expr)
+            early_expression(parent_container, &ctx.sema, &make)
+                .map(ast::make::tail_only_block_expr)
         })?
         .reset_indent();
 
@@ -133,6 +135,7 @@ fn if_expr_to_guarded_return(
         "Convert to guarded return",
         target,
         |edit| {
+            let make = SyntaxFactory::without_mappings();
             let if_indent_level = IndentLevel::from_node(if_expr.syntax());
             let replacement = let_chains.into_iter().map(|expr| {
                 if let ast::Expr::LetExpr(let_expr) = &expr
@@ -140,15 +143,15 @@ fn if_expr_to_guarded_return(
                 {
                     // If-let.
                     let let_else_stmt =
-                        make::let_else_stmt(pat, None, expr, early_expression.clone());
+                        make.let_else_stmt(pat, None, expr, early_expression.clone());
                     let let_else_stmt = let_else_stmt.indent(if_indent_level);
                     let_else_stmt.syntax().clone()
                 } else {
                     // If.
                     let new_expr = {
-                        let then_branch = clean_stmt_block(&early_expression);
-                        let cond = invert_boolean_expression_legacy(expr);
-                        make::expr_if(cond, then_branch, None).indent(if_indent_level)
+                        let then_branch = clean_stmt_block(&early_expression, &make);
+                        let cond = invert_boolean_expression(&make, expr);
+                        make.expr_if(cond, then_branch, None).indent(if_indent_level)
                     };
                     new_expr.syntax().clone()
                 }
@@ -159,7 +162,7 @@ fn if_expr_to_guarded_return(
                 .enumerate()
                 .flat_map(|(i, node)| {
                     (i != 0)
-                        .then(|| make::tokens::whitespace(newline).into())
+                        .then(|| make.whitespace(newline).into())
                         .into_iter()
                         .chain(node.children_with_tokens())
                 })
@@ -201,12 +204,13 @@ fn let_stmt_to_guarded_return(
     let happy_pattern = try_enum.happy_pattern(pat);
     let target = let_stmt.syntax().text_range();
 
+    let make = SyntaxFactory::without_mappings();
     let early_expression: ast::Expr = {
         let parent_block =
             let_stmt.syntax().parent()?.ancestors().find_map(ast::BlockExpr::cast)?;
         let parent_container = parent_block.syntax().parent()?;
 
-        early_expression(parent_container, &ctx.sema)?
+        early_expression(parent_container, &ctx.sema, &make)?
     };
 
     acc.add(
@@ -215,9 +219,10 @@ fn let_stmt_to_guarded_return(
         target,
         |edit| {
             let let_indent_level = IndentLevel::from_node(let_stmt.syntax());
+            let make = SyntaxFactory::without_mappings();
 
             let replacement = {
-                let let_else_stmt = make::let_else_stmt(
+                let let_else_stmt = make.let_else_stmt(
                     happy_pattern,
                     let_stmt.ty(),
                     expr.reset_indent(),
@@ -228,6 +233,7 @@ fn let_stmt_to_guarded_return(
             };
             let mut editor = edit.make_editor(let_stmt.syntax());
             editor.replace(let_stmt.syntax(), replacement);
+            editor.add_mappings(make.finish_with_mappings());
             edit.add_file_edits(ctx.vfs_file_id(), editor);
         },
     )
@@ -236,38 +242,39 @@ fn let_stmt_to_guarded_return(
 fn early_expression(
     parent_container: SyntaxNode,
     sema: &Semantics<'_, RootDatabase>,
+    make: &SyntaxFactory,
 ) -> Option<ast::Expr> {
     let return_none_expr = || {
-        let none_expr = make::expr_path(make::ext::ident_path("None"));
-        make::expr_return(Some(none_expr))
+        let none_expr = make.expr_path(make.ident_path("None"));
+        make.expr_return(Some(none_expr))
     };
     if let Some(fn_) = ast::Fn::cast(parent_container.clone())
         && let Some(fn_def) = sema.to_def(&fn_)
         && let Some(TryEnum::Option) = TryEnum::from_ty(sema, &fn_def.ret_type(sema.db))
     {
-        return Some(return_none_expr());
+        return Some(return_none_expr().into());
     }
     if let Some(body) = ast::ClosureExpr::cast(parent_container.clone()).and_then(|it| it.body())
         && let Some(ret_ty) = sema.type_of_expr(&body).map(TypeInfo::original)
         && let Some(TryEnum::Option) = TryEnum::from_ty(sema, &ret_ty)
     {
-        return Some(return_none_expr());
+        return Some(return_none_expr().into());
     }
 
     Some(match parent_container.kind() {
-        WHILE_EXPR | LOOP_EXPR | FOR_EXPR => make::expr_continue(None),
-        FN | CLOSURE_EXPR => make::expr_return(None),
+        WHILE_EXPR | LOOP_EXPR | FOR_EXPR => make.expr_continue(None).into(),
+        FN | CLOSURE_EXPR => make.expr_return(None).into(),
         _ => return None,
     })
 }
 
-fn flat_let_chain(mut expr: ast::Expr) -> Vec<ast::Expr> {
+fn flat_let_chain(mut expr: ast::Expr, make: &SyntaxFactory) -> Vec<ast::Expr> {
     let mut chains = vec![];
     let mut reduce_cond = |rhs| {
         if !matches!(rhs, ast::Expr::LetExpr(_))
             && let Some(last) = chains.pop_if(|last| !matches!(last, ast::Expr::LetExpr(_)))
         {
-            chains.push(make::expr_bin_op(rhs, ast::BinaryOp::LogicOp(ast::LogicOp::And), last));
+            chains.push(make.expr_bin_op(rhs, ast::BinaryOp::LogicOp(ast::LogicOp::And), last));
         } else {
             chains.push(rhs);
         }
@@ -286,12 +293,12 @@ fn flat_let_chain(mut expr: ast::Expr) -> Vec<ast::Expr> {
     chains
 }
 
-fn clean_stmt_block(block: &ast::BlockExpr) -> ast::BlockExpr {
+fn clean_stmt_block(block: &ast::BlockExpr, make: &SyntaxFactory) -> ast::BlockExpr {
     if block.statements().next().is_none()
         && let Some(tail_expr) = block.tail_expr()
         && block.modifier().is_none()
     {
-        make::block_expr(once(make::expr_stmt(tail_expr).into()), None)
+        make.block_expr(once(make.expr_stmt(tail_expr).into()), None)
     } else {
         block.clone()
     }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
index f8b9bb6..f1eae83 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
@@ -1,17 +1,21 @@
 use either::Either;
-use hir::FileRangeWrapper;
-use ide_db::defs::{Definition, NameRefClass};
-use std::ops::RangeInclusive;
+use ide_db::{
+    defs::{Definition, NameRefClass},
+    search::FileReference,
+};
 use syntax::{
-    SyntaxElement, SyntaxKind, SyntaxNode, T, TextSize,
+    SyntaxKind, T,
     ast::{
-        self, AstNode, HasAttrs, HasGenericParams, HasVisibility, syntax_factory::SyntaxFactory,
+        self, AstNode, HasArgList, HasAttrs, HasGenericParams, HasVisibility,
+        syntax_factory::SyntaxFactory,
     },
     match_ast,
     syntax_editor::{Element, Position, SyntaxEditor},
 };
 
-use crate::{AssistContext, AssistId, Assists, assist_context::SourceChangeBuilder};
+use crate::{
+    AssistContext, AssistId, Assists, assist_context::SourceChangeBuilder, utils::cover_edit_range,
+};
 
 // Assist: convert_tuple_struct_to_named_struct
 //
@@ -147,93 +151,121 @@ fn edit_struct_references(
     };
     let usages = strukt_def.usages(&ctx.sema).include_self_refs().all();
 
-    let edit_node = |node: SyntaxNode| -> Option<SyntaxNode> {
-        let make = SyntaxFactory::without_mappings();
-        match_ast! {
-            match node {
-                ast::TupleStructPat(tuple_struct_pat) => {
-                    Some(make.record_pat_with_fields(
-                        tuple_struct_pat.path()?,
-                        generate_record_pat_list(&tuple_struct_pat, names),
-                    ).syntax().clone())
-                },
-                // for tuple struct creations like Foo(42)
-                ast::CallExpr(call_expr) => {
-                    let path = call_expr.syntax().descendants().find_map(ast::PathExpr::cast).and_then(|expr| expr.path())?;
-
-                    // this also includes method calls like Foo::new(42), we should skip them
-                    if let Some(name_ref) = path.segment().and_then(|s| s.name_ref()) {
-                        match NameRefClass::classify(&ctx.sema, &name_ref) {
-                            Some(NameRefClass::Definition(Definition::SelfType(_), _)) => {},
-                            Some(NameRefClass::Definition(def, _)) if def == strukt_def => {},
-                            _ => return None,
-                        };
-                    }
-
-                    let arg_list = call_expr.syntax().descendants().find_map(ast::ArgList::cast)?;
-                    Some(
-                        make.record_expr(
-                            path,
-                            ast::make::record_expr_field_list(arg_list.args().zip(names).map(
-                                |(expr, name)| {
-                                    ast::make::record_expr_field(
-                                        ast::make::name_ref(&name.to_string()),
-                                        Some(expr),
-                                    )
-                                },
-                            )),
-                        ).syntax().clone()
-                    )
-                },
-                _ => None,
-            }
-        }
-    };
-
     for (file_id, refs) in usages {
         let source = ctx.sema.parse(file_id);
-        let source = source.syntax();
+        let mut editor = edit.make_editor(source.syntax());
 
-        let mut editor = edit.make_editor(source);
-        for r in refs.iter().rev() {
-            if let Some((old_node, new_node)) = r
-                .name
-                .syntax()
-                .ancestors()
-                .find_map(|node| Some((node.clone(), edit_node(node.clone())?)))
-            {
-                if let Some(old_node) = ctx.sema.original_syntax_node_rooted(&old_node) {
-                    editor.replace(old_node, new_node);
-                } else {
-                    let FileRangeWrapper { file_id: _, range } = ctx.sema.original_range(&old_node);
-                    let parent = source.covering_element(range);
-                    match parent {
-                        SyntaxElement::Token(token) => {
-                            editor.replace(token, new_node.syntax_element());
-                        }
-                        SyntaxElement::Node(parent_node) => {
-                            // replace the part of macro
-                            // ```
-                            // foo!(a, Test::A(0));
-                            //     ^^^^^^^^^^^^^^^ // parent_node
-                            //         ^^^^^^^^^^  // replace_range
-                            // ```
-                            let start = parent_node
-                                .children_with_tokens()
-                                .find(|t| t.text_range().contains(range.start()));
-                            let end = parent_node
-                                .children_with_tokens()
-                                .find(|t| t.text_range().contains(range.end() - TextSize::new(1)));
-                            if let (Some(start), Some(end)) = (start, end) {
-                                let replace_range = RangeInclusive::new(start, end);
-                                editor.replace_all(replace_range, vec![new_node.into()]);
-                            }
-                        }
+        for r in refs {
+            process_struct_name_reference(ctx, r, &mut editor, &source, &strukt_def, names);
+        }
+
+        edit.add_file_edits(file_id.file_id(ctx.db()), editor);
+    }
+}
+
+fn process_struct_name_reference(
+    ctx: &AssistContext<'_>,
+    r: FileReference,
+    editor: &mut SyntaxEditor,
+    source: &ast::SourceFile,
+    strukt_def: &Definition,
+    names: &[ast::Name],
+) -> Option<()> {
+    let make = SyntaxFactory::without_mappings();
+    let name_ref = r.name.as_name_ref()?;
+    let path_segment = name_ref.syntax().parent().and_then(ast::PathSegment::cast)?;
+    let full_path = path_segment.syntax().parent().and_then(ast::Path::cast)?.top_path();
+
+    if full_path.segment()?.name_ref()? != *name_ref {
+        // `name_ref` isn't the last segment of the path, so `full_path` doesn't point to the
+        // struct we want to edit.
+        return None;
+    }
+
+    let parent = full_path.syntax().parent()?;
+    match_ast! {
+        match parent {
+            ast::TupleStructPat(tuple_struct_pat) => {
+                let range = ctx.sema.original_range_opt(tuple_struct_pat.syntax())?.range;
+                let new = make.record_pat_with_fields(
+                    full_path,
+                    generate_record_pat_list(&tuple_struct_pat, names),
+                );
+                editor.replace_all(cover_edit_range(source, range), vec![new.syntax().clone().into()]);
+            },
+            ast::PathExpr(path_expr) => {
+                let call_expr = path_expr.syntax().parent().and_then(ast::CallExpr::cast)?;
+
+                // this also includes method calls like Foo::new(42), we should skip them
+                match NameRefClass::classify(&ctx.sema, name_ref) {
+                    Some(NameRefClass::Definition(Definition::SelfType(_), _)) => {},
+                    Some(NameRefClass::Definition(def, _)) if def == *strukt_def => {},
+                    _ => return None,
+                }
+
+                let arg_list = call_expr.arg_list()?;
+                let mut first_insert = vec![];
+                for (expr, name) in arg_list.args().zip(names) {
+                    let range = ctx.sema.original_range_opt(expr.syntax())?.range;
+                    let place = cover_edit_range(source, range);
+                    let elements = vec![
+                        make.name_ref(&name.text()).syntax().clone().into(),
+                        make.token(T![:]).into(),
+                        make.whitespace(" ").into(),
+                    ];
+                    if first_insert.is_empty() {
+                        // XXX: SyntaxEditor cannot insert after deleted element
+                        first_insert = elements;
+                    } else {
+                        editor.insert_all(Position::before(place.start()), elements);
                     }
                 }
-            }
+                process_delimiter(ctx, source, editor, &arg_list, first_insert);
+            },
+            _ => {}
         }
-        edit.add_file_edits(file_id.file_id(ctx.db()), editor);
+    }
+    Some(())
+}
+
+fn process_delimiter(
+    ctx: &AssistContext<'_>,
+    source: &ast::SourceFile,
+    editor: &mut SyntaxEditor,
+    list: &impl AstNode,
+    first_insert: Vec<syntax::SyntaxElement>,
+) {
+    let Some(range) = ctx.sema.original_range_opt(list.syntax()) else { return };
+    let place = cover_edit_range(source, range.range);
+
+    let l_paren = match place.start() {
+        syntax::NodeOrToken::Node(node) => node.first_token(),
+        syntax::NodeOrToken::Token(t) => Some(t.clone()),
+    };
+    let r_paren = match place.end() {
+        syntax::NodeOrToken::Node(node) => node.last_token(),
+        syntax::NodeOrToken::Token(t) => Some(t.clone()),
+    };
+
+    let make = SyntaxFactory::without_mappings();
+    if let Some(l_paren) = l_paren
+        && l_paren.kind() == T!['(']
+    {
+        let mut open_delim = vec![
+            make.whitespace(" ").into(),
+            make.token(T!['{']).into(),
+            make.whitespace(" ").into(),
+        ];
+        open_delim.extend(first_insert);
+        editor.replace_with_many(l_paren, open_delim);
+    }
+    if let Some(r_paren) = r_paren
+        && r_paren.kind() == T![')']
+    {
+        editor.replace_with_many(
+            r_paren,
+            vec![make.whitespace(" ").into(), make.token(T!['}']).into()],
+        );
     }
 }
 
@@ -252,13 +284,15 @@ fn edit_field_references(
         let usages = def.usages(&ctx.sema).all();
         for (file_id, refs) in usages {
             let source = ctx.sema.parse(file_id);
-            let source = source.syntax();
-            let mut editor = edit.make_editor(source);
+            let mut editor = edit.make_editor(source.syntax());
             for r in refs {
                 if let Some(name_ref) = r.name.as_name_ref()
-                    && let Some(original) = ctx.sema.original_ast_node(name_ref.clone())
+                    && let Some(original) = ctx.sema.original_range_opt(name_ref.syntax())
                 {
-                    editor.replace(original.syntax(), name.syntax());
+                    editor.replace_all(
+                        cover_edit_range(&source, original.range),
+                        vec![name.syntax().clone().into()],
+                    );
                 }
             }
             edit.add_file_edits(file_id.file_id(ctx.db()), editor);
@@ -739,6 +773,64 @@ struct Wrap<T>
 "#,
         );
     }
+
+    #[test]
+    fn convert_expr_uses_self() {
+        check_assist(
+            convert_tuple_struct_to_named_struct,
+            r#"
+macro_rules! id {
+    ($($t:tt)*) => { $($t)* }
+}
+struct T$0(u8);
+fn test(t: T) {
+    T(t.0);
+    id!(T(t.0));
+}"#,
+            r#"
+macro_rules! id {
+    ($($t:tt)*) => { $($t)* }
+}
+struct T { field1: u8 }
+fn test(t: T) {
+    T { field1: t.field1 };
+    id!(T { field1: t.field1 });
+}"#,
+        );
+    }
+
+    #[test]
+    #[ignore = "FIXME overlap edits in nested uses self"]
+    fn convert_pat_uses_self() {
+        check_assist(
+            convert_tuple_struct_to_named_struct,
+            r#"
+macro_rules! id {
+    ($($t:tt)*) => { $($t)* }
+}
+enum T {
+    $0Value(&'static T),
+    Nil,
+}
+fn test(t: T) {
+    if let T::Value(T::Value(t)) = t {}
+    if let id!(T::Value(T::Value(t))) = t {}
+}"#,
+            r#"
+macro_rules! id {
+    ($($t:tt)*) => { $($t)* }
+}
+enum T {
+    Value { field1: &'static T },
+    Nil,
+}
+fn test(t: T) {
+    if let T::Value { field1: T::Value { field1: t } } = t {}
+    if let id!(T::Value { field1: T::Value { field1: t } }) = t {}
+}"#,
+        );
+    }
+
     #[test]
     fn not_applicable_other_than_tuple_variant() {
         check_assist_not_applicable(
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs
index 9fd8b4b..f8215d6 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs
@@ -6,7 +6,7 @@
     ast::{
         self, HasLoopBody,
         edit::{AstNodeEdit, IndentLevel},
-        make,
+        syntax_factory::SyntaxFactory,
     },
     syntax_editor::{Element, Position},
 };
@@ -14,7 +14,7 @@
 use crate::{
     AssistId,
     assist_context::{AssistContext, Assists},
-    utils::invert_boolean_expression_legacy,
+    utils::invert_boolean_expression,
 };
 
 // Assist: convert_while_to_loop
@@ -52,44 +52,47 @@ pub(crate) fn convert_while_to_loop(acc: &mut Assists, ctx: &AssistContext<'_>)
         "Convert while to loop",
         target,
         |builder| {
+            let make = SyntaxFactory::without_mappings();
             let mut edit = builder.make_editor(while_expr.syntax());
             let while_indent_level = IndentLevel::from_node(while_expr.syntax());
 
-            let break_block = make::block_expr(
-                iter::once(make::expr_stmt(make::expr_break(None, None)).into()),
-                None,
-            )
-            .indent(IndentLevel(1));
+            let break_block = make
+                .block_expr(
+                    iter::once(make.expr_stmt(make.expr_break(None, None).into()).into()),
+                    None,
+                )
+                .indent(IndentLevel(1));
 
             edit.replace_all(
                 while_kw.syntax_element()..=while_cond.syntax().syntax_element(),
-                vec![make::token(T![loop]).syntax_element()],
+                vec![make.token(T![loop]).syntax_element()],
             );
 
             if is_pattern_cond(while_cond.clone()) {
                 let then_branch = while_body.reset_indent().indent(IndentLevel(1));
-                let if_expr = make::expr_if(while_cond, then_branch, Some(break_block.into()));
-                let stmts = iter::once(make::expr_stmt(if_expr.into()).into());
-                let block_expr = make::block_expr(stmts, None);
+                let if_expr = make.expr_if(while_cond, then_branch, Some(break_block.into()));
+                let stmts = iter::once(make.expr_stmt(if_expr.into()).into());
+                let block_expr = make.block_expr(stmts, None);
                 edit.replace(while_body.syntax(), block_expr.indent(while_indent_level).syntax());
             } else {
-                let if_cond = invert_boolean_expression_legacy(while_cond);
-                let if_expr = make::expr_if(if_cond, break_block, None).indent(while_indent_level);
+                let if_cond = invert_boolean_expression(&make, while_cond);
+                let if_expr = make.expr_if(if_cond, break_block, None).indent(while_indent_level);
                 if !while_body.syntax().text().contains_char('\n') {
                     edit.insert(
                         Position::after(&l_curly),
-                        make::tokens::whitespace(&format!("\n{while_indent_level}")),
+                        make.whitespace(&format!("\n{while_indent_level}")),
                     );
                 }
                 edit.insert_all(
                     Position::after(&l_curly),
                     vec![
-                        make::tokens::whitespace(&format!("\n{}", while_indent_level + 1)).into(),
+                        make.whitespace(&format!("\n{}", while_indent_level + 1)).into(),
                         if_expr.syntax().syntax_element(),
                     ],
                 );
             };
 
+            edit.add_mappings(make.finish_with_mappings());
             builder.add_file_edits(ctx.vfs_file_id(), edit);
         },
     )
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs
index 4c4cee1..0f5ef05 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs
@@ -381,23 +381,20 @@ fn build_usage_edit(
         Some(field_expr) => Some({
             let field_name: SmolStr = field_expr.name_ref()?.to_string().into();
             let new_field_name = field_names.get(&field_name)?;
-            let new_expr = ast::make::expr_path(ast::make::ext::ident_path(new_field_name));
+            let new_expr = make.expr_path(make.ident_path(new_field_name));
 
             // If struct binding is a reference, we might need to deref field usages
             if data.is_ref {
                 let (replace_expr, ref_data) = determine_ref_and_parens(ctx, &field_expr);
-                (
-                    replace_expr.syntax().clone_for_update(),
-                    ref_data.wrap_expr(new_expr).syntax().clone_for_update(),
-                )
+                (replace_expr.syntax().clone(), ref_data.wrap_expr(new_expr, make).syntax().clone())
             } else {
-                (field_expr.syntax().clone(), new_expr.syntax().clone_for_update())
+                (field_expr.syntax().clone(), new_expr.syntax().clone())
             }
         }),
         None => Some((
             usage.name.syntax().as_node().unwrap().clone(),
             make.expr_macro(
-                ast::make::ext::ident_path("todo"),
+                make.ident_path("todo"),
                 make.token_tree(syntax::SyntaxKind::L_PAREN, []),
             )
             .syntax()
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_try_expr.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_try_expr.rs
index 9976e34..4022030 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_try_expr.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_try_expr.rs
@@ -9,7 +9,6 @@
     ast::{
         self,
         edit::{AstNodeEdit, IndentLevel},
-        make,
         syntax_factory::SyntaxFactory,
     },
 };
@@ -68,41 +67,46 @@ pub(crate) fn desugar_try_expr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
         AssistId::refactor_rewrite("desugar_try_expr_match"),
         "Replace try expression with match",
         target,
-        |edit| {
+        |builder| {
+            let make = SyntaxFactory::with_mappings();
+            let mut editor = builder.make_editor(try_expr.syntax());
+
             let sad_pat = match try_enum {
-                TryEnum::Option => make::path_pat(make::ext::ident_path("None")),
-                TryEnum::Result => make::tuple_struct_pat(
-                    make::ext::ident_path("Err"),
-                    iter::once(make::path_pat(make::ext::ident_path("err"))),
-                )
-                .into(),
+                TryEnum::Option => make.path_pat(make.ident_path("None")),
+                TryEnum::Result => make
+                    .tuple_struct_pat(
+                        make.ident_path("Err"),
+                        iter::once(make.path_pat(make.ident_path("err"))),
+                    )
+                    .into(),
             };
             let sad_expr = match try_enum {
-                TryEnum::Option => {
-                    make::expr_return(Some(make::expr_path(make::ext::ident_path("None"))))
-                }
-                TryEnum::Result => make::expr_return(Some(
-                    make::expr_call(
-                        make::expr_path(make::ext::ident_path("Err")),
-                        make::arg_list(iter::once(make::expr_path(make::ext::ident_path("err")))),
+                TryEnum::Option => make.expr_return(Some(make.expr_path(make.ident_path("None")))),
+                TryEnum::Result => make.expr_return(Some(
+                    make.expr_call(
+                        make.expr_path(make.ident_path("Err")),
+                        make.arg_list(iter::once(make.expr_path(make.ident_path("err")))),
                     )
                     .into(),
                 )),
             };
 
-            let happy_arm = make::match_arm(
-                try_enum.happy_pattern(make::ident_pat(false, false, make::name("it")).into()),
+            let happy_arm = make.match_arm(
+                try_enum.happy_pattern(make.ident_pat(false, false, make.name("it")).into()),
                 None,
-                make::expr_path(make::ext::ident_path("it")),
+                make.expr_path(make.ident_path("it")),
             );
-            let sad_arm = make::match_arm(sad_pat, None, sad_expr);
+            let sad_arm = make.match_arm(sad_pat, None, sad_expr.into());
 
-            let match_arm_list = make::match_arm_list([happy_arm, sad_arm]);
+            let match_arm_list = make.match_arm_list([happy_arm, sad_arm]);
 
-            let expr_match = make::expr_match(expr.clone(), match_arm_list)
+            let expr_match = make
+                .expr_match(expr.clone(), match_arm_list)
                 .indent(IndentLevel::from_node(try_expr.syntax()));
 
-            edit.replace_ast::<ast::Expr>(try_expr.clone().into(), expr_match.into());
+            editor.replace(try_expr.syntax(), expr_match.syntax());
+            editor.add_mappings(make.finish_with_mappings());
+            builder.add_file_edits(ctx.vfs_file_id(), editor);
         },
     );
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs
index 61af2de..35e8baa 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs
@@ -8,7 +8,7 @@
     AstNode, AstToken, NodeOrToken,
     SyntaxKind::WHITESPACE,
     SyntaxToken, T,
-    ast::{self, TokenTree, make, syntax_factory::SyntaxFactory},
+    ast::{self, TokenTree, syntax_factory::SyntaxFactory},
 };
 
 // Assist: extract_expressions_from_format_string
@@ -57,6 +57,7 @@ pub(crate) fn extract_expressions_from_format_string(
         "Extract format expressions",
         tt.syntax().text_range(),
         |edit| {
+            let make = SyntaxFactory::without_mappings();
             // Extract existing arguments in macro
             let mut raw_tokens = tt.token_trees_and_tokens().skip(1).collect_vec();
             let format_string_index = format_str_index(&raw_tokens, &fmt_string);
@@ -94,14 +95,14 @@ pub(crate) fn extract_expressions_from_format_string(
             let mut new_tt_bits = raw_tokens;
             let mut placeholder_indexes = vec![];
 
-            new_tt_bits.push(NodeOrToken::Token(make::tokens::literal(&new_fmt)));
+            new_tt_bits.push(NodeOrToken::Token(make.expr_literal(&new_fmt).token().clone()));
 
             for arg in extracted_args {
                 if matches!(arg, Arg::Expr(_) | Arg::Placeholder) {
                     // insert ", " before each arg
                     new_tt_bits.extend_from_slice(&[
-                        NodeOrToken::Token(make::token(T![,])),
-                        NodeOrToken::Token(make::tokens::single_space()),
+                        NodeOrToken::Token(make.token(T![,])),
+                        NodeOrToken::Token(make.whitespace(" ")),
                     ]);
                 }
 
@@ -109,7 +110,7 @@ pub(crate) fn extract_expressions_from_format_string(
                     Arg::Expr(s) => {
                         // insert arg
                         let expr = ast::Expr::parse(&s, ctx.edition()).syntax_node();
-                        let mut expr_tt = utils::tt_from_syntax(expr);
+                        let mut expr_tt = utils::tt_from_syntax(expr, &make);
                         new_tt_bits.append(&mut expr_tt);
                     }
                     Arg::Placeholder => {
@@ -120,7 +121,7 @@ pub(crate) fn extract_expressions_from_format_string(
                             }
                             None => {
                                 placeholder_indexes.push(new_tt_bits.len());
-                                new_tt_bits.push(NodeOrToken::Token(make::token(T![_])));
+                                new_tt_bits.push(NodeOrToken::Token(make.token(T![_])));
                             }
                         }
                     }
@@ -129,7 +130,6 @@ pub(crate) fn extract_expressions_from_format_string(
             }
 
             // Insert new args
-            let make = SyntaxFactory::with_mappings();
             let new_tt = make.token_tree(tt_delimiter, new_tt_bits);
             let mut editor = edit.make_editor(tt.syntax());
             editor.replace(tt.syntax(), new_tt.syntax());
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs
index 7c60184..7071106 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs
@@ -9,7 +9,6 @@
     ast::{
         self, AstNode,
         edit::{AstNodeEdit, IndentLevel},
-        make,
         syntax_factory::SyntaxFactory,
     },
     syntax_editor::Position,
@@ -75,7 +74,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
             .next()
             .and_then(ast::Expr::cast)
         {
-            expr.syntax().ancestors().find_map(valid_target_expr)?.syntax().clone()
+            expr.syntax().ancestors().find_map(valid_target_expr(ctx))?.syntax().clone()
         } else {
             return None;
         }
@@ -96,7 +95,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
     let to_extract = node
         .descendants()
         .take_while(|it| range.contains_range(it.text_range()))
-        .find_map(valid_target_expr)?;
+        .find_map(valid_target_expr(ctx))?;
 
     let ty = ctx.sema.type_of_expr(&to_extract).map(TypeInfo::adjusted);
     if matches!(&ty, Some(ty_info) if ty_info.is_unit()) {
@@ -176,7 +175,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
                 let mut editor = edit.make_editor(&expr_replace);
 
                 let pat_name = make.name(&var_name);
-                let name_expr = make.expr_path(make::ext::ident_path(&var_name));
+                let name_expr = make.expr_path(make.ident_path(&var_name));
 
                 if let Some(cap) = ctx.config.snippet_cap {
                     let tabstop = edit.make_tabstop_before(cap);
@@ -233,7 +232,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
                             Position::before(place),
                             vec![
                                 new_stmt.syntax().clone().into(),
-                                make::tokens::whitespace(&trailing_ws).into(),
+                                make.whitespace(&trailing_ws).into(),
                             ],
                         );
 
@@ -283,14 +282,19 @@ fn peel_parens(mut expr: ast::Expr) -> ast::Expr {
 
 /// Check whether the node is a valid expression which can be extracted to a variable.
 /// In general that's true for any expression, but in some cases that would produce invalid code.
-fn valid_target_expr(node: SyntaxNode) -> Option<ast::Expr> {
-    match node.kind() {
-        SyntaxKind::PATH_EXPR | SyntaxKind::LOOP_EXPR | SyntaxKind::LET_EXPR => None,
+fn valid_target_expr(ctx: &AssistContext<'_>) -> impl Fn(SyntaxNode) -> Option<ast::Expr> {
+    |node| match node.kind() {
+        SyntaxKind::LOOP_EXPR | SyntaxKind::LET_EXPR => None,
         SyntaxKind::BREAK_EXPR => ast::BreakExpr::cast(node).and_then(|e| e.expr()),
         SyntaxKind::RETURN_EXPR => ast::ReturnExpr::cast(node).and_then(|e| e.expr()),
         SyntaxKind::BLOCK_EXPR => {
             ast::BlockExpr::cast(node).filter(|it| it.is_standalone()).map(ast::Expr::from)
         }
+        SyntaxKind::PATH_EXPR => {
+            let path_expr = ast::PathExpr::cast(node)?;
+            let path_resolution = ctx.sema.resolve_path(&path_expr.path()?)?;
+            like_const_value(ctx, path_resolution).then_some(path_expr.into())
+        }
         _ => ast::Expr::cast(node),
     }
 }
@@ -455,6 +459,31 @@ fn from(to_extract: &ast::Expr, kind: &ExtractionKind) -> Option<Anchor> {
     }
 }
 
+fn like_const_value(ctx: &AssistContext<'_>, path_resolution: hir::PathResolution) -> bool {
+    let db = ctx.db();
+    let adt_like_const_value = |adt: Option<hir::Adt>| matches!(adt, Some(hir::Adt::Struct(s)) if s.kind(db) == hir::StructKind::Unit);
+    match path_resolution {
+        hir::PathResolution::Def(def) => match def {
+            hir::ModuleDef::Adt(adt) => adt_like_const_value(Some(adt)),
+            hir::ModuleDef::Variant(variant) => variant.kind(db) == hir::StructKind::Unit,
+            hir::ModuleDef::TypeAlias(ty) => adt_like_const_value(ty.ty(db).as_adt()),
+            hir::ModuleDef::Const(_) | hir::ModuleDef::Static(_) => true,
+            hir::ModuleDef::Trait(_)
+            | hir::ModuleDef::BuiltinType(_)
+            | hir::ModuleDef::Macro(_)
+            | hir::ModuleDef::Module(_) => false,
+            hir::ModuleDef::Function(_) => false, // no extract named function
+        },
+        hir::PathResolution::SelfType(ty) => adt_like_const_value(ty.self_ty(db).as_adt()),
+        hir::PathResolution::ConstParam(_) => true,
+        hir::PathResolution::Local(_)
+        | hir::PathResolution::TypeParam(_)
+        | hir::PathResolution::BuiltinAttr(_)
+        | hir::PathResolution::ToolModule(_)
+        | hir::PathResolution::DeriveHelper(_) => false,
+    }
+}
+
 #[cfg(test)]
 mod tests {
     // NOTE: We use check_assist_by_label, but not check_assist_not_applicable_by_label
@@ -1748,6 +1777,27 @@ fn main() {
     }
 
     #[test]
+    fn extract_non_local_path_expr() {
+        check_assist_by_label(
+            extract_variable,
+            r#"
+struct Foo;
+fn foo() -> Foo {
+    $0Foo$0
+}
+"#,
+            r#"
+struct Foo;
+fn foo() -> Foo {
+    let $0foo = Foo;
+    foo
+}
+"#,
+            "Extract into variable",
+        );
+    }
+
+    #[test]
     fn extract_var_for_return_not_applicable() {
         check_assist_not_applicable(extract_variable, "fn foo() { $0return$0; } ");
     }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs
index c1eb1a7..63033c7 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs
@@ -4,7 +4,7 @@
     ast::{
         self, AstNode, HasGenericParams, HasName, HasVisibility as _,
         edit::{AstNodeEdit, IndentLevel},
-        make,
+        syntax_factory::SyntaxFactory,
     },
     syntax_editor::Position,
 };
@@ -100,7 +100,6 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
         let Some(impl_def) = find_struct_impl(ctx, &adt, std::slice::from_ref(&name)) else {
             continue;
         };
-        let field = make::ext::field_from_idents(["self", &field_name])?;
 
         acc.add_group(
             &GroupLabel("Generate delegate methods…".to_owned()),
@@ -108,10 +107,14 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
             format!("Generate delegate for `{field_name}.{name}()`",),
             target,
             |edit| {
+                let make = SyntaxFactory::without_mappings();
+                let field = make
+                    .field_from_idents(["self", &field_name])
+                    .expect("always be a valid expression");
                 // Create the function
                 let method_source = match ctx.sema.source(method) {
                     Some(source) => {
-                        let v = source.value.clone_for_update();
+                        let v = source.value;
                         let source_scope = ctx.sema.scope(v.syntax());
                         let target_scope = ctx.sema.scope(strukt.syntax());
                         if let (Some(s), Some(t)) = (source_scope, target_scope) {
@@ -132,42 +135,42 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
                 let is_unsafe = method_source.unsafe_token().is_some();
                 let is_gen = method_source.gen_token().is_some();
 
-                let fn_name = make::name(&name);
+                let fn_name = make.name(&name);
 
                 let type_params = method_source.generic_param_list();
                 let where_clause = method_source.where_clause();
                 let params =
-                    method_source.param_list().unwrap_or_else(|| make::param_list(None, []));
+                    method_source.param_list().unwrap_or_else(|| make.param_list(None, []));
 
                 // compute the `body`
                 let arg_list = method_source
                     .param_list()
-                    .map(convert_param_list_to_arg_list)
-                    .unwrap_or_else(|| make::arg_list([]));
+                    .map(|v| convert_param_list_to_arg_list(v, &make))
+                    .unwrap_or_else(|| make.arg_list([]));
 
-                let tail_expr =
-                    make::expr_method_call(field, make::name_ref(&name), arg_list).into();
+                let tail_expr = make.expr_method_call(field, make.name_ref(&name), arg_list).into();
                 let tail_expr_finished =
-                    if is_async { make::expr_await(tail_expr) } else { tail_expr };
-                let body = make::block_expr([], Some(tail_expr_finished));
+                    if is_async { make.expr_await(tail_expr).into() } else { tail_expr };
+                let body = make.block_expr([], Some(tail_expr_finished));
 
                 let ret_type = method_source.ret_type();
 
-                let f = make::fn_(
-                    None,
-                    vis,
-                    fn_name,
-                    type_params,
-                    where_clause,
-                    params,
-                    body,
-                    ret_type,
-                    is_async,
-                    is_const,
-                    is_unsafe,
-                    is_gen,
-                )
-                .indent(IndentLevel(1));
+                let f = make
+                    .fn_(
+                        None,
+                        vis,
+                        fn_name,
+                        type_params,
+                        where_clause,
+                        params,
+                        body,
+                        ret_type,
+                        is_async,
+                        is_const,
+                        is_unsafe,
+                        is_gen,
+                    )
+                    .indent(IndentLevel(1));
                 let item = ast::AssocItem::Fn(f.clone());
 
                 let mut editor = edit.make_editor(strukt.syntax());
@@ -179,7 +182,7 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
                             Some(item)
                         }
                         None => {
-                            let assoc_item_list = make::assoc_item_list(Some(vec![item]));
+                            let assoc_item_list = make.assoc_item_list(vec![item]);
                             editor.insert(
                                 Position::last_child_of(impl_def.syntax()),
                                 assoc_item_list.syntax(),
@@ -192,17 +195,16 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
                         let ty_params = strukt.generic_param_list();
                         let ty_args = ty_params.as_ref().map(|it| it.to_generic_args());
                         let where_clause = strukt.where_clause();
-                        let assoc_item_list = make::assoc_item_list(Some(vec![item]));
+                        let assoc_item_list = make.assoc_item_list(vec![item]);
 
-                        let impl_def = make::impl_(
+                        let impl_def = make.impl_(
                             None,
                             ty_params,
                             ty_args,
-                            make::ty_path(make::ext::ident_path(name)),
+                            syntax::ast::Type::PathType(make.ty_path(make.ident_path(name))),
                             where_clause,
                             Some(assoc_item_list),
-                        )
-                        .clone_for_update();
+                        );
 
                         // Fixup impl_def indentation
                         let indent = strukt.indent_level();
@@ -213,7 +215,7 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
                         editor.insert_all(
                             Position::after(strukt.syntax()),
                             vec![
-                                make::tokens::whitespace(&format!("\n\n{indent}")).into(),
+                                make.whitespace(&format!("\n\n{indent}")).into(),
                                 impl_def.syntax().clone().into(),
                             ],
                         );
@@ -227,6 +229,7 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
                     let tabstop = edit.make_tabstop_before(cap);
                     editor.add_annotation(fn_.syntax(), tabstop);
                 }
+                editor.add_mappings(make.finish_with_mappings());
                 edit.add_file_edits(ctx.vfs_file_id(), editor);
             },
         )?;
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs
index 921f04f..f703e4d 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs
@@ -782,7 +782,7 @@ fn func_assoc_item(
                 };
 
                 // Build argument list with self expression prepended
-                let other_args = convert_param_list_to_arg_list(l);
+                let other_args = convert_param_list_to_arg_list(l, &make);
                 let all_args: Vec<ast::Expr> =
                     std::iter::once(tail_expr_self).chain(other_args.args()).collect();
                 let args = make.arg_list(all_args);
@@ -790,13 +790,13 @@ fn func_assoc_item(
                 make.expr_call(make.expr_path(qualified_path), args).into()
             }
             None => make
-                .expr_call(make.expr_path(qualified_path), convert_param_list_to_arg_list(l))
+                .expr_call(make.expr_path(qualified_path), convert_param_list_to_arg_list(l, &make))
                 .into(),
         },
         None => make
             .expr_call(
                 make.expr_path(qualified_path),
-                convert_param_list_to_arg_list(make.param_list(None, Vec::new())),
+                convert_param_list_to_arg_list(make.param_list(None, Vec::new()), &make),
             )
             .into(),
     };
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_trait_from_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_trait_from_impl.rs
index 8bc4d50..1286abe 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_trait_from_impl.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_trait_from_impl.rs
@@ -1,8 +1,10 @@
 use crate::assist_context::{AssistContext, Assists};
 use ide_db::assists::AssistId;
 use syntax::{
-    AstNode, SyntaxKind, T,
-    ast::{self, HasGenericParams, HasName, HasVisibility, edit::AstNodeEdit, make},
+    AstNode, AstToken, SyntaxKind, T,
+    ast::{
+        self, HasDocComments, HasGenericParams, HasName, HasVisibility, edit::AstNodeEdit, make,
+    },
     syntax_editor::{Position, SyntaxEditor},
 };
 
@@ -45,7 +47,7 @@
 //     };
 // }
 //
-// trait ${0:NewTrait}<const N: usize> {
+// trait ${0:Create}<const N: usize> {
 //     // Used as an associated constant.
 //     const CONST_ASSOC: usize = N * 4;
 //
@@ -54,7 +56,7 @@
 //     const_maker! {i32, 7}
 // }
 //
-// impl<const N: usize> ${0:NewTrait}<N> for Foo<N> {
+// impl<const N: usize> ${0:Create}<N> for Foo<N> {
 //     // Used as an associated constant.
 //     const CONST_ASSOC: usize = N * 4;
 //
@@ -107,7 +109,7 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
             };
             let trait_ast = make::trait_(
                 false,
-                "NewTrait",
+                &trait_name(&impl_assoc_items).text(),
                 impl_ast.generic_param_list(),
                 impl_ast.where_clause(),
                 trait_items,
@@ -133,6 +135,7 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
             let mut editor = builder.make_editor(impl_ast.syntax());
             impl_assoc_items.assoc_items().for_each(|item| {
                 remove_items_visibility(&mut editor, &item);
+                remove_doc_comments(&mut editor, &item);
             });
 
             editor.insert_all(Position::before(impl_name.syntax()), elements);
@@ -160,6 +163,18 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_
     Some(())
 }
 
+fn trait_name(items: &ast::AssocItemList) -> ast::Name {
+    let mut fn_names = items
+        .assoc_items()
+        .filter_map(|x| if let ast::AssocItem::Fn(f) = x { f.name() } else { None });
+    fn_names
+        .next()
+        .and_then(|name| {
+            fn_names.next().is_none().then(|| make::name(&stdx::to_camel_case(&name.text())))
+        })
+        .unwrap_or_else(|| make::name("NewTrait"))
+}
+
 /// `E0449` Trait items always share the visibility of their trait
 fn remove_items_visibility(editor: &mut SyntaxEditor, item: &ast::AssocItem) {
     if let Some(has_vis) = ast::AnyHasVisibility::cast(item.syntax().clone()) {
@@ -175,6 +190,17 @@ fn remove_items_visibility(editor: &mut SyntaxEditor, item: &ast::AssocItem) {
     }
 }
 
+fn remove_doc_comments(editor: &mut SyntaxEditor, item: &ast::AssocItem) {
+    for doc in item.doc_comments() {
+        if let Some(next) = doc.syntax().next_token()
+            && next.kind() == SyntaxKind::WHITESPACE
+        {
+            editor.delete(next);
+        }
+        editor.delete(doc.syntax());
+    }
+}
+
 fn strip_body(editor: &mut SyntaxEditor, item: &ast::AssocItem) {
     if let ast::AssocItem::Fn(f) = item
         && let Some(body) = f.body()
@@ -226,11 +252,47 @@ fn add(&mut self, x: f64) {
             r#"
 struct Foo(f64);
 
-trait NewTrait {
+trait Add {
     fn add(&mut self, x: f64);
 }
 
-impl NewTrait for Foo {
+impl Add for Foo {
+    fn add(&mut self, x: f64) {
+        self.0 += x;
+    }
+}"#,
+        )
+    }
+
+    #[test]
+    fn test_remove_doc_comments() {
+        check_assist_no_snippet_cap(
+            generate_trait_from_impl,
+            r#"
+struct Foo(f64);
+
+impl F$0oo {
+    /// Add `x`
+    ///
+    /// # Examples
+    #[cfg(true)]
+    fn add(&mut self, x: f64) {
+        self.0 += x;
+    }
+}"#,
+            r#"
+struct Foo(f64);
+
+trait Add {
+    /// Add `x`
+    ///
+    /// # Examples
+    #[cfg(true)]
+    fn add(&mut self, x: f64);
+}
+
+impl Add for Foo {
+    #[cfg(true)]
     fn add(&mut self, x: f64) {
         self.0 += x;
     }
@@ -339,11 +401,11 @@ pub fn a_func() -> Option<()> {
             r#"
 struct Foo;
 
-trait NewTrait {
+trait AFunc {
     fn a_func() -> Option<()>;
 }
 
-impl NewTrait for Foo {
+impl AFunc for Foo {
     fn a_func() -> Option<()> {
         Some(())
     }
@@ -373,11 +435,11 @@ fn foo() {}
 }"#,
             r#"
 mod a {
-    trait NewTrait {
+    trait Foo {
         fn foo();
     }
 
-    impl NewTrait for S {
+    impl Foo for S {
         fn foo() {}
     }
 }"#,
@@ -385,6 +447,28 @@ fn foo() {}
     }
 
     #[test]
+    fn test_multi_fn_impl_not_suggest_trait_name() {
+        check_assist_no_snippet_cap(
+            generate_trait_from_impl,
+            r#"
+impl S$0 {
+    fn foo() {}
+    fn bar() {}
+}"#,
+            r#"
+trait NewTrait {
+    fn foo();
+    fn bar();
+}
+
+impl NewTrait for S {
+    fn foo() {}
+    fn bar() {}
+}"#,
+        )
+    }
+
+    #[test]
     fn test_snippet_cap_is_some() {
         check_assist(
             generate_trait_from_impl,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs
index 5d4bdc6..f55ef42 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs
@@ -1,3 +1,4 @@
+use either::{Either, for_both};
 use hir::{PathResolution, Semantics};
 use ide_db::{
     EditionedFileId, RootDatabase,
@@ -5,8 +6,9 @@
     search::{FileReference, FileReferenceNode, UsageSearchResult},
 };
 use syntax::{
-    SyntaxElement, TextRange,
+    Direction, TextRange,
     ast::{self, AstNode, AstToken, HasName, syntax_factory::SyntaxFactory},
+    syntax_editor::{Element, SyntaxEditor},
 };
 
 use crate::{
@@ -36,12 +38,15 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>)
     let InlineData { let_stmt, delete_let, references, target } =
         if let Some(path_expr) = ctx.find_node_at_offset::<ast::PathExpr>() {
             inline_usage(&ctx.sema, path_expr, range, file_id)
-        } else if let Some(let_stmt) = ctx.find_node_at_offset::<ast::LetStmt>() {
+        } else if let Some(let_stmt) = ctx.find_node_at_offset() {
             inline_let(&ctx.sema, let_stmt, range, file_id)
         } else {
             None
         }?;
-    let initializer_expr = let_stmt.initializer()?;
+    let initializer_expr = match &let_stmt {
+        either::Either::Left(it) => it.initializer()?,
+        either::Either::Right(it) => it.expr()?,
+    };
 
     let wrap_in_parens = references
         .into_iter()
@@ -81,13 +86,15 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>)
             let mut editor = builder.make_editor(&target);
             if delete_let {
                 editor.delete(let_stmt.syntax());
-                if let Some(whitespace) = let_stmt
-                    .syntax()
-                    .next_sibling_or_token()
-                    .and_then(SyntaxElement::into_token)
-                    .and_then(ast::Whitespace::cast)
+
+                if let Some(bin_expr) = let_stmt.syntax().parent().and_then(ast::BinExpr::cast)
+                    && let Some(op_token) = bin_expr.op_token()
                 {
-                    editor.delete(whitespace.syntax());
+                    editor.delete(&op_token);
+                    remove_whitespace(op_token, Direction::Prev, &mut editor);
+                    remove_whitespace(let_stmt.syntax(), Direction::Prev, &mut editor);
+                } else {
+                    remove_whitespace(let_stmt.syntax(), Direction::Next, &mut editor);
                 }
             }
 
@@ -116,7 +123,7 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>)
 }
 
 struct InlineData {
-    let_stmt: ast::LetStmt,
+    let_stmt: Either<ast::LetStmt, ast::LetExpr>,
     delete_let: bool,
     target: ast::NameOrNameRef,
     references: Vec<FileReference>,
@@ -124,11 +131,11 @@ struct InlineData {
 
 fn inline_let(
     sema: &Semantics<'_, RootDatabase>,
-    let_stmt: ast::LetStmt,
+    let_stmt: Either<ast::LetStmt, ast::LetExpr>,
     range: TextRange,
     file_id: EditionedFileId,
 ) -> Option<InlineData> {
-    let bind_pat = match let_stmt.pat()? {
+    let bind_pat = match for_both!(&let_stmt, it => it.pat())? {
         ast::Pat::IdentPat(pat) => pat,
         _ => return None,
     };
@@ -187,7 +194,7 @@ fn inline_usage(
 
     let bind_pat = source.as_ident_pat()?;
 
-    let let_stmt = ast::LetStmt::cast(bind_pat.syntax().parent()?)?;
+    let let_stmt = AstNode::cast(bind_pat.syntax().parent()?)?;
 
     let UsageSearchResult { mut references } = Definition::Local(local).usages(sema).all();
     let mut references = references.remove(&file_id)?;
@@ -197,6 +204,23 @@ fn inline_usage(
     Some(InlineData { let_stmt, delete_let, target: ast::NameOrNameRef::NameRef(name), references })
 }
 
+fn remove_whitespace(elem: impl Element, dir: Direction, editor: &mut SyntaxEditor) {
+    let token = match elem.syntax_element() {
+        syntax::NodeOrToken::Node(node) => match dir {
+            Direction::Next => node.last_token(),
+            Direction::Prev => node.first_token(),
+        },
+        syntax::NodeOrToken::Token(t) => Some(t),
+    };
+    let next_token = match dir {
+        Direction::Next => token.and_then(|it| it.next_token()),
+        Direction::Prev => token.and_then(|it| it.prev_token()),
+    };
+    if let Some(whitespace) = next_token.and_then(ast::Whitespace::cast) {
+        editor.delete(whitespace.syntax());
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use crate::tests::{check_assist, check_assist_not_applicable};
@@ -405,6 +429,38 @@ fn foo() {
     }
 
     #[test]
+    fn test_inline_let_expr() {
+        check_assist(
+            inline_local_variable,
+            r"
+fn bar(a: usize) {}
+fn foo() {
+    if let a$0 = 1
+        && true
+    {
+        a + 1;
+        if a > 10 {}
+        while a > 10 {}
+        let b = a * 10;
+        bar(a);
+    }
+}",
+            r"
+fn bar(a: usize) {}
+fn foo() {
+    if true
+    {
+        1 + 1;
+        if 1 > 10 {}
+        while 1 > 10 {}
+        let b = 1 * 10;
+        bar(1);
+    }
+}",
+        );
+    }
+
+    #[test]
     fn test_not_inline_mut_variable() {
         cov_mark::check!(test_not_inline_mut_variable);
         check_assist_not_applicable(
@@ -817,6 +873,70 @@ fn f() {
     }
 
     #[test]
+    fn let_expr_works_on_local_usage() {
+        check_assist(
+            inline_local_variable,
+            r#"
+fn f() {
+    if let xyz = 0
+        && true
+    {
+        xyz$0;
+    }
+}
+"#,
+            r#"
+fn f() {
+    if true
+    {
+        0;
+    }
+}
+"#,
+        );
+
+        check_assist(
+            inline_local_variable,
+            r#"
+fn f() {
+    if let xyz = true
+        && xyz$0
+    {
+    }
+}
+"#,
+            r#"
+fn f() {
+    if true
+    {
+    }
+}
+"#,
+        );
+
+        check_assist(
+            inline_local_variable,
+            r#"
+fn f() {
+    if true
+        && let xyz = 0
+    {
+        xyz$0;
+    }
+}
+"#,
+            r#"
+fn f() {
+    if true
+    {
+        0;
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
     fn does_not_remove_let_when_multiple_usages() {
         check_assist(
             inline_local_variable,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs
index c7a48f3..f3ebe61 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs
@@ -12,7 +12,7 @@
 use syntax::ast::syntax_factory::SyntaxFactory;
 use syntax::syntax_editor::SyntaxEditor;
 use syntax::{
-    AstNode, NodeOrToken, SyntaxNode,
+    AstNode, NodeOrToken, SyntaxKind, SyntaxNode, T,
     ast::{self, HasGenericParams, HasName},
 };
 
@@ -322,12 +322,42 @@ fn create_replacement(
         if let Some(old_lifetime) = ast::Lifetime::cast(syntax.clone()) {
             if let Some(new_lifetime) = lifetime_map.0.get(&old_lifetime.to_string()) {
                 if new_lifetime.text() == "'_" {
-                    removals.push(NodeOrToken::Node(syntax.clone()));
+                    // Check if this lifetime is inside a LifetimeArg (in angle brackets)
+                    if let Some(lifetime_arg) =
+                        old_lifetime.syntax().parent().and_then(ast::LifetimeArg::cast)
+                    {
+                        // Remove LifetimeArg and associated comma/whitespace
+                        let lifetime_arg_syntax = lifetime_arg.syntax();
+                        removals.push(NodeOrToken::Node(lifetime_arg_syntax.clone()));
 
-                    if let Some(ws) = syntax.next_sibling_or_token() {
-                        removals.push(ws.clone());
+                        // Remove comma and whitespace (look forward then backward)
+                        let comma_and_ws: Vec<_> = lifetime_arg_syntax
+                            .siblings_with_tokens(syntax::Direction::Next)
+                            .skip(1)
+                            .take_while(|it| it.as_token().is_some())
+                            .take_while_inclusive(|it| it.kind() == T![,])
+                            .collect();
+
+                        if comma_and_ws.iter().any(|it| it.kind() == T![,]) {
+                            removals.extend(comma_and_ws);
+                        } else {
+                            // No comma after, try before
+                            let comma_and_ws: Vec<_> = lifetime_arg_syntax
+                                .siblings_with_tokens(syntax::Direction::Prev)
+                                .skip(1)
+                                .take_while(|it| it.as_token().is_some())
+                                .take_while_inclusive(|it| it.kind() == T![,])
+                                .collect();
+                            removals.extend(comma_and_ws);
+                        }
+                        continue;
                     }
-
+                    removals.push(NodeOrToken::Node(syntax.clone()));
+                    if let Some(ws) = syntax.next_sibling_or_token()
+                        && ws.kind() == SyntaxKind::WHITESPACE
+                    {
+                        removals.push(ws);
+                    }
                     continue;
                 }
 
@@ -349,6 +379,34 @@ fn create_replacement(
         }
     }
 
+    // Deduplicate removals to avoid intersecting changes
+    removals.sort_by_key(|n| n.text_range().start());
+    removals.dedup();
+
+    // Remove GenericArgList entirely if all its args are being removed (avoids empty angle brackets)
+    let generic_arg_lists_to_check: Vec<_> =
+        updated_concrete_type.descendants().filter_map(ast::GenericArgList::cast).collect();
+
+    for generic_arg_list in generic_arg_lists_to_check {
+        let will_be_empty = generic_arg_list.generic_args().all(|arg| match arg {
+            ast::GenericArg::LifetimeArg(lt_arg) => removals.iter().any(|removal| {
+                if let NodeOrToken::Node(node) = removal { node == lt_arg.syntax() } else { false }
+            }),
+            _ => false,
+        });
+
+        if will_be_empty && generic_arg_list.generic_args().next().is_some() {
+            removals.retain(|removal| {
+                if let NodeOrToken::Node(node) = removal {
+                    !node.ancestors().any(|anc| anc == *generic_arg_list.syntax())
+                } else {
+                    true
+                }
+            });
+            removals.push(NodeOrToken::Node(generic_arg_list.syntax().clone()));
+        }
+    }
+
     for (old, new) in replacements {
         editor.replace(old, new);
     }
@@ -946,6 +1004,48 @@ trait Tr {
         );
     }
 
+    #[test]
+    fn inline_types_with_lifetime() {
+        check_assist(
+            inline_type_alias_uses,
+            r#"
+struct A<'a, 'b>(pub &'a mut &'b mut ());
+
+type $0T<'a, 'b> = A<'a, 'b>;
+
+fn foo(_: T) {}
+"#,
+            r#"
+struct A<'a, 'b>(pub &'a mut &'b mut ());
+
+
+
+fn foo(_: A) {}
+"#,
+        );
+    }
+
+    #[test]
+    fn mixed_lifetime_and_type_args() {
+        check_assist(
+            inline_type_alias,
+            r#"
+type Foo<'a, T> = Bar<'a, T>;
+struct Bar<'a, T>(&'a T);
+fn main() {
+    let a: $0Foo<u32>;
+}
+"#,
+            r#"
+type Foo<'a, T> = Bar<'a, T>;
+struct Bar<'a, T>(&'a T);
+fn main() {
+    let a: Bar<u32>;
+}
+"#,
+        );
+    }
+
     mod inline_type_alias_uses {
         use crate::{handlers::inline_type_alias::inline_type_alias_uses, tests::check_assist};
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/invert_if.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/invert_if.rs
index bf82d8d..c8cb7bb 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/invert_if.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/invert_if.rs
@@ -1,13 +1,13 @@
 use ide_db::syntax_helpers::node_ext::is_pattern_cond;
 use syntax::{
     T,
-    ast::{self, AstNode},
+    ast::{self, AstNode, syntax_factory::SyntaxFactory},
 };
 
 use crate::{
     AssistId,
     assist_context::{AssistContext, Assists},
-    utils::invert_boolean_expression_legacy,
+    utils::invert_boolean_expression,
 };
 
 // Assist: invert_if
@@ -50,7 +50,8 @@ pub(crate) fn invert_if(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()
     };
 
     acc.add(AssistId::refactor_rewrite("invert_if"), "Invert if", if_range, |edit| {
-        let flip_cond = invert_boolean_expression_legacy(cond.clone());
+        let make = SyntaxFactory::without_mappings();
+        let flip_cond = invert_boolean_expression(&make, cond.clone());
         edit.replace_ast(cond, flip_cond);
 
         let else_node = else_block.syntax();
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs
index 9ba73d2..42bc058 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs
@@ -49,8 +49,9 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
             SyntaxElement::Node(n) => n,
             SyntaxElement::Token(t) => t.parent()?,
         };
-        let mut selected_nodes =
-            parent_node.children().filter(|it| selection_range.contains_range(it.text_range()));
+        let mut selected_nodes = parent_node.children().filter(|it| {
+            selection_range.intersect(it.text_range()).is_some_and(|it| !it.is_empty())
+        });
 
         let first_selected = selected_nodes.next()?;
         let edits = match_ast! {
@@ -678,6 +679,25 @@ fn merge_selection_uses() {
     }
 
     #[test]
+    fn merge_partial_selection_uses() {
+        cov_mark::check!(merge_with_selected_use_item_neighbors);
+        check_assist(
+            merge_imports,
+            r"
+use std::fmt::Error;
+$0use std::fmt::Display;
+use std::fmt::Debug;
+use std::fmt::Write;
+use$0 std::fmt::Result;
+",
+            r"
+use std::fmt::Error;
+use std::fmt::{Debug, Display, Result, Write};
+",
+        );
+    }
+
+    #[test]
     fn merge_selection_use_trees() {
         cov_mark::check!(merge_with_selected_use_tree_neighbors);
         check_assist(
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs
index b4c347f..8058737 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs
@@ -3,7 +3,7 @@
     SyntaxKind::WHITESPACE,
     TextRange,
     ast::{
-        AstNode, BlockExpr, ElseBranch, Expr, IfExpr, MatchArm, Pat, edit::AstNodeEdit, make,
+        AstNode, BlockExpr, ElseBranch, Expr, IfExpr, MatchArm, Pat, edit::AstNodeEdit,
         prec::ExprPrecedence, syntax_factory::SyntaxFactory,
     },
     syntax_editor::Element,
@@ -53,14 +53,15 @@ pub(crate) fn move_guard_to_arm_body(acc: &mut Assists, ctx: &AssistContext<'_>)
     let space_after_arrow = match_arm.fat_arrow_token()?.next_sibling_or_token();
 
     let arm_expr = match_arm.expr()?;
+    let make = SyntaxFactory::without_mappings();
     let if_branch = chain([&match_arm], &rest_arms)
         .rfold(None, |else_branch, arm| {
             if let Some(guard) = arm.guard() {
-                let then_branch = crate::utils::wrap_block(&arm.expr()?);
+                let then_branch = crate::utils::wrap_block(&arm.expr()?, &make);
                 let guard_condition = guard.condition()?.reset_indent();
-                Some(make::expr_if(guard_condition, then_branch, else_branch).into())
+                Some(make.expr_if(guard_condition, then_branch, else_branch).into())
             } else {
-                arm.expr().map(|it| crate::utils::wrap_block(&it).into())
+                arm.expr().map(|it| crate::utils::wrap_block(&it, &make).into())
             }
         })?
         .indent(arm_expr.indent_level());
@@ -84,7 +85,7 @@ pub(crate) fn move_guard_to_arm_body(acc: &mut Assists, ctx: &AssistContext<'_>)
             if let Some(element) = space_after_arrow
                 && element.kind() == WHITESPACE
             {
-                edit.replace(element, make::tokens::single_space());
+                edit.replace(element, make.whitespace(" "));
             }
 
             edit.delete(guard.syntax());
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs
index 495a84d6..8b9e657 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs
@@ -1,6 +1,6 @@
 use hir::{AsAssocItem, AssocItem, AssocItemContainer, ItemInNs, ModuleDef, db::HirDatabase};
 use ide_db::assists::AssistId;
-use syntax::{AstNode, ast};
+use syntax::{AstNode, ast, ast::syntax_factory::SyntaxFactory};
 
 use crate::{
     assist_context::{AssistContext, Assists},
@@ -52,19 +52,25 @@ pub(crate) fn qualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) ->
         cfg,
     )?;
 
-    let qualify_candidate = QualifyCandidate::ImplMethod(ctx.sema.db, call, resolved_call);
+    let qualify_candidate = QualifyCandidate::ImplMethod(ctx.sema.db, call.clone(), resolved_call);
 
     acc.add(
         AssistId::refactor_rewrite("qualify_method_call"),
         format!("Qualify `{ident}` method call"),
         range,
         |builder| {
+            let make = SyntaxFactory::with_mappings();
+            let mut editor = builder.make_editor(call.syntax());
             qualify_candidate.qualify(
-                |replace_with: String| builder.replace(range, replace_with),
+                |_| {},
+                &mut editor,
+                &make,
                 &receiver_path,
                 item_in_ns,
                 current_edition,
-            )
+            );
+            editor.add_mappings(make.finish_with_mappings());
+            builder.add_file_edits(ctx.vfs_file_id(), editor);
         },
     );
     Some(())
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs
index b3cf296..c059f75 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs
@@ -11,7 +11,8 @@
 use syntax::ast::HasGenericArgs;
 use syntax::{
     AstNode, ast,
-    ast::{HasArgList, make},
+    ast::{HasArgList, syntax_factory::SyntaxFactory},
+    syntax_editor::SyntaxEditor,
 };
 
 use crate::{
@@ -54,25 +55,25 @@ pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
     let qualify_candidate = match candidate {
         ImportCandidate::Path(candidate) if !candidate.qualifier.is_empty() => {
             cov_mark::hit!(qualify_path_qualifier_start);
-            let path = ast::Path::cast(syntax_under_caret)?;
+            let path = ast::Path::cast(syntax_under_caret.clone())?;
             let (prev_segment, segment) = (path.qualifier()?.segment()?, path.segment()?);
             QualifyCandidate::QualifierStart(segment, prev_segment.generic_arg_list())
         }
         ImportCandidate::Path(_) => {
             cov_mark::hit!(qualify_path_unqualified_name);
-            let path = ast::Path::cast(syntax_under_caret)?;
+            let path = ast::Path::cast(syntax_under_caret.clone())?;
             let generics = path.segment()?.generic_arg_list();
             QualifyCandidate::UnqualifiedName(generics)
         }
         ImportCandidate::TraitAssocItem(_) => {
             cov_mark::hit!(qualify_path_trait_assoc_item);
-            let path = ast::Path::cast(syntax_under_caret)?;
+            let path = ast::Path::cast(syntax_under_caret.clone())?;
             let (qualifier, segment) = (path.qualifier()?, path.segment()?);
             QualifyCandidate::TraitAssocItem(qualifier, segment)
         }
         ImportCandidate::TraitMethod(_) => {
             cov_mark::hit!(qualify_path_trait_method);
-            let mcall_expr = ast::MethodCallExpr::cast(syntax_under_caret)?;
+            let mcall_expr = ast::MethodCallExpr::cast(syntax_under_caret.clone())?;
             QualifyCandidate::TraitMethod(ctx.sema.db, mcall_expr)
         }
     };
@@ -101,12 +102,18 @@ pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
             label(ctx.db(), candidate, &import, current_edition),
             range,
             |builder| {
+                let make = SyntaxFactory::with_mappings();
+                let mut editor = builder.make_editor(&syntax_under_caret);
                 qualify_candidate.qualify(
                     |replace_with: String| builder.replace(range, replace_with),
+                    &mut editor,
+                    &make,
                     &import.import_path,
                     import.item_to_import,
                     current_edition,
-                )
+                );
+                editor.add_mappings(make.finish_with_mappings());
+                builder.add_file_edits(ctx.vfs_file_id(), editor);
             },
         );
     }
@@ -124,6 +131,8 @@ impl QualifyCandidate<'_> {
     pub(crate) fn qualify(
         &self,
         mut replacer: impl FnMut(String),
+        editor: &mut SyntaxEditor,
+        make: &SyntaxFactory,
         import: &hir::ModPath,
         item: hir::ItemInNs,
         edition: Edition,
@@ -142,10 +151,10 @@ pub(crate) fn qualify(
                 replacer(format!("<{qualifier} as {import}>::{segment}"));
             }
             QualifyCandidate::TraitMethod(db, mcall_expr) => {
-                Self::qualify_trait_method(db, mcall_expr, replacer, import, item);
+                Self::qualify_trait_method(db, mcall_expr, editor, make, import, item);
             }
             QualifyCandidate::ImplMethod(db, mcall_expr, hir_fn) => {
-                Self::qualify_fn_call(db, mcall_expr, replacer, import, hir_fn);
+                Self::qualify_fn_call(db, mcall_expr, editor, make, import, hir_fn);
             }
         }
     }
@@ -153,7 +162,8 @@ pub(crate) fn qualify(
     fn qualify_fn_call(
         db: &RootDatabase,
         mcall_expr: &ast::MethodCallExpr,
-        mut replacer: impl FnMut(String),
+        editor: &mut SyntaxEditor,
+        make: &SyntaxFactory,
         import: ast::Path,
         hir_fn: &hir::Function,
     ) -> Option<()> {
@@ -165,15 +175,17 @@ fn qualify_fn_call(
 
         if let Some(self_access) = hir_fn.self_param(db).map(|sp| sp.access(db)) {
             let receiver = match self_access {
-                hir::Access::Shared => make::expr_ref(receiver, false),
-                hir::Access::Exclusive => make::expr_ref(receiver, true),
+                hir::Access::Shared => make.expr_ref(receiver, false),
+                hir::Access::Exclusive => make.expr_ref(receiver, true),
                 hir::Access::Owned => receiver,
             };
             let arg_list = match arg_list {
-                Some(args) => make::arg_list(iter::once(receiver).chain(args)),
-                None => make::arg_list(iter::once(receiver)),
+                Some(args) => make.arg_list(iter::once(receiver).chain(args)),
+                None => make.arg_list(iter::once(receiver)),
             };
-            replacer(format!("{import}::{method_name}{generics}{arg_list}"));
+            let call_path = make.path_from_text(&format!("{import}::{method_name}{generics}"));
+            let call_expr = make.expr_call(make.expr_path(call_path), arg_list);
+            editor.replace(mcall_expr.syntax(), call_expr.syntax());
         }
         Some(())
     }
@@ -181,14 +193,15 @@ fn qualify_fn_call(
     fn qualify_trait_method(
         db: &RootDatabase,
         mcall_expr: &ast::MethodCallExpr,
-        replacer: impl FnMut(String),
+        editor: &mut SyntaxEditor,
+        make: &SyntaxFactory,
         import: ast::Path,
         item: hir::ItemInNs,
     ) -> Option<()> {
         let trait_method_name = mcall_expr.name_ref()?;
         let trait_ = item_as_trait(db, item)?;
         let method = find_trait_method(db, trait_, &trait_method_name)?;
-        Self::qualify_fn_call(db, mcall_expr, replacer, import, &method)
+        Self::qualify_fn_call(db, mcall_expr, editor, make, import, &method)
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs
index d22e951..38d8c38 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs
@@ -1,8 +1,11 @@
 use either::Either;
 use ide_db::syntax_helpers::suggest_name;
-use syntax::ast::{self, AstNode, HasArgList, syntax_factory::SyntaxFactory};
+use syntax::ast::{self, AstNode, HasArgList, prec::ExprPrecedence, syntax_factory::SyntaxFactory};
 
-use crate::{AssistContext, AssistId, Assists, utils::cover_let_chain};
+use crate::{
+    AssistContext, AssistId, Assists,
+    utils::{cover_let_chain, wrap_paren, wrap_paren_in_call},
+};
 
 // Assist: replace_is_some_with_if_let_some
 //
@@ -39,6 +42,7 @@ pub(crate) fn replace_is_method_with_if_let_method(
     match method_kind {
         "is_some" | "is_ok" => {
             let receiver = call_expr.receiver()?;
+            let make = SyntaxFactory::with_mappings();
 
             let mut name_generator = suggest_name::NameGenerator::new_from_scope_locals(
                 ctx.sema.scope(has_cond.syntax()),
@@ -48,7 +52,7 @@ pub(crate) fn replace_is_method_with_if_let_method(
             } else {
                 name_generator.for_variable(&receiver, &ctx.sema)
             };
-            let (pat, predicate) = method_predicate(&call_expr).unzip();
+            let (pat, predicate) = method_predicate(&call_expr, &var_name, &make);
 
             let (assist_id, message, text) = if method_kind == "is_some" {
                 ("replace_is_some_with_if_let_some", "Replace `is_some` with `let Some`", "Some")
@@ -61,13 +65,9 @@ pub(crate) fn replace_is_method_with_if_let_method(
                 message,
                 call_expr.syntax().text_range(),
                 |edit| {
-                    let make = SyntaxFactory::with_mappings();
                     let mut editor = edit.make_editor(call_expr.syntax());
 
-                    let var_pat = pat.unwrap_or_else(|| {
-                        make.ident_pat(false, false, make.name(&var_name)).into()
-                    });
-                    let pat = make.tuple_struct_pat(make.ident_path(text), [var_pat]).into();
+                    let pat = make.tuple_struct_pat(make.ident_path(text), [pat]).into();
                     let let_expr = make.expr_let(pat, receiver);
 
                     if let Some(cap) = ctx.config.snippet_cap
@@ -81,6 +81,7 @@ pub(crate) fn replace_is_method_with_if_let_method(
 
                     let new_expr = if let Some(predicate) = predicate {
                         let op = ast::BinaryOp::LogicOp(ast::LogicOp::And);
+                        let predicate = wrap_paren(predicate, &make, ExprPrecedence::LAnd);
                         make.expr_bin(let_expr.into(), op, predicate).into()
                     } else {
                         ast::Expr::from(let_expr)
@@ -96,14 +97,23 @@ pub(crate) fn replace_is_method_with_if_let_method(
     }
 }
 
-fn method_predicate(call_expr: &ast::MethodCallExpr) -> Option<(ast::Pat, ast::Expr)> {
-    let argument = call_expr.arg_list()?.args().next()?;
-    match argument {
-        ast::Expr::ClosureExpr(it) => {
-            let pat = it.param_list()?.params().next()?.pat()?;
-            Some((pat, it.body()?))
-        }
-        _ => None,
+fn method_predicate(
+    call_expr: &ast::MethodCallExpr,
+    name: &str,
+    make: &SyntaxFactory,
+) -> (ast::Pat, Option<ast::Expr>) {
+    let argument = call_expr.arg_list().and_then(|it| it.args().next());
+    if let Some(ast::Expr::ClosureExpr(it)) = argument.clone()
+        && let Some(pat) = it.param_list().and_then(|it| it.params().next()?.pat())
+    {
+        (pat, it.body())
+    } else {
+        let pat = make.ident_pat(false, false, make.name(name));
+        let expr = argument.map(|expr| {
+            let arg_list = make.arg_list([make.expr_path(make.ident_path(name))]);
+            make.expr_call(wrap_paren_in_call(expr, make), arg_list).into()
+        });
+        (pat.into(), expr)
     }
 }
 
@@ -234,6 +244,54 @@ fn main() {
 }
 "#,
         );
+
+        check_assist(
+            replace_is_method_with_if_let_method,
+            r#"
+fn main() {
+    let x = Some(1);
+    if x.is_som$0e_and(|it| it != 3 || it > 10) {}
+}
+"#,
+            r#"
+fn main() {
+    let x = Some(1);
+    if let Some(it) = x && (it != 3 || it > 10) {}
+}
+"#,
+        );
+
+        check_assist(
+            replace_is_method_with_if_let_method,
+            r#"
+fn main() {
+    let x = Some(1);
+    if x.is_som$0e_and(predicate) {}
+}
+"#,
+            r#"
+fn main() {
+    let x = Some(1);
+    if let Some(x1) = x && predicate(x1) {}
+}
+"#,
+        );
+
+        check_assist(
+            replace_is_method_with_if_let_method,
+            r#"
+fn main() {
+    let x = Some(1);
+    if x.is_som$0e_and(func.f) {}
+}
+"#,
+            r#"
+fn main() {
+    let x = Some(1);
+    if let Some(x1) = x && (func.f)(x1) {}
+}
+"#,
+        );
     }
 
     #[test]
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs
index 5587f1b..6ff5f0b 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs
@@ -86,8 +86,8 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext<'_>
 }
 
 fn let_expr_needs_paren(expr: &ast::Expr) -> bool {
-    let fake_expr_let =
-        ast::make::expr_let(ast::make::tuple_pat(None).into(), ast::make::ext::expr_unit());
+    let make = SyntaxFactory::without_mappings();
+    let fake_expr_let = make.expr_let(make.tuple_pat(None).into(), make.expr_unit());
     let Some(fake_expr) = fake_expr_let.expr() else {
         stdx::never!();
         return false;
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs
index 6ca3e26..6e4dd8c 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs
@@ -2,10 +2,10 @@
 use ide_db::{RootDatabase, assists::AssistId, defs::Definition};
 use syntax::{
     AstNode,
-    ast::{self, Expr, HasArgList, make},
+    ast::{self, Expr, HasArgList, make, syntax_factory::SyntaxFactory},
 };
 
-use crate::{AssistContext, Assists};
+use crate::{AssistContext, Assists, utils::wrap_paren_in_call};
 
 // Assist: replace_with_lazy_method
 //
@@ -177,11 +177,7 @@ fn into_call(param: &Expr, sema: &Semantics<'_, RootDatabase>) -> Expr {
         }
     })()
     .unwrap_or_else(|| {
-        let callable = if needs_parens_in_call(param) {
-            make::expr_paren(param.clone()).into()
-        } else {
-            param.clone()
-        };
+        let callable = wrap_paren_in_call(param.clone(), &SyntaxFactory::without_mappings());
         make::expr_call(callable, make::arg_list(Vec::new())).into()
     })
 }
@@ -200,12 +196,6 @@ fn ends_is(name: &str, end: &str) -> bool {
     name.strip_suffix(end).is_some_and(|s| s.is_empty() || s.ends_with('_'))
 }
 
-fn needs_parens_in_call(param: &Expr) -> bool {
-    let call = make::expr_call(make::ext::expr_unit(), make::arg_list(Vec::new()));
-    let callable = call.expr().expect("invalid make call");
-    param.needs_parens_in_place_of(call.syntax(), callable.syntax())
-}
-
 #[cfg(test)]
 mod tests {
     use crate::tests::check_assist;
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs
index e4f5e35..e029d78 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs
@@ -45,6 +45,7 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
                 ast::LoopExpr(it) => it.syntax().clone(),
                 ast::WhileExpr(it) => it.syntax().clone(),
                 ast::MatchArm(it) => it.parent_match().syntax().clone(),
+                ast::LetElse(it) => it.syntax().parent()?,
                 ast::LetStmt(it) => {
                     replacement = wrap_let(&it, replacement);
                     prefer_container = Some(it.syntax().clone());
@@ -557,6 +558,40 @@ fn main() {
     }
 
     #[test]
+    fn simple_let_else() {
+        check_assist(
+            unwrap_block,
+            r#"
+fn main() {
+    let Some(2) = None else {$0
+        return;
+    };
+}
+"#,
+            r#"
+fn main() {
+    return;
+}
+"#,
+        );
+        check_assist(
+            unwrap_block,
+            r#"
+fn main() {
+    let Some(2) = None else {$0
+        return
+    };
+}
+"#,
+            r#"
+fn main() {
+    return
+}
+"#,
+        );
+    }
+
+    #[test]
     fn unwrap_match_arm() {
         check_assist(
             unwrap_block,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs
index 46f3e85..e03274b 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs
@@ -1,3 +1,6 @@
+use std::iter;
+
+use either::Either;
 use syntax::{
     AstNode, T,
     ast::{self, edit::AstNodeEdit},
@@ -24,11 +27,16 @@
 // ```
 pub(crate) fn unwrap_tuple(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
     let let_kw = ctx.find_token_syntax_at_offset(T![let])?;
-    let let_stmt = let_kw.parent().and_then(ast::LetStmt::cast)?;
-    let indent_level = let_stmt.indent_level().0 as usize;
-    let pat = let_stmt.pat()?;
-    let ty = let_stmt.ty();
-    let init = let_stmt.initializer()?;
+    let let_stmt = let_kw.parent().and_then(Either::<ast::LetStmt, ast::LetExpr>::cast)?;
+    let mut indent_level = let_stmt.indent_level();
+    let pat = either::for_both!(&let_stmt, it => it.pat())?;
+    let (ty, init, prefix, suffix) = match &let_stmt {
+        Either::Left(let_stmt) => (let_stmt.ty(), let_stmt.initializer()?, "", ";"),
+        Either::Right(let_expr) => {
+            indent_level += 1;
+            (None, let_expr.expr()?, "&& ", "")
+        }
+    };
 
     // This only applies for tuple patterns, types, and initializers.
     let tuple_pat = match pat {
@@ -60,25 +68,19 @@ pub(crate) fn unwrap_tuple(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
         "Unwrap tuple",
         let_kw.text_range(),
         |edit| {
-            let indents = "    ".repeat(indent_level);
+            let mut decls = String::new();
 
             // If there is an ascribed type, insert that type for each declaration,
             // otherwise, omit that type.
-            if let Some(tys) = tuple_ty {
-                let mut zipped_decls = String::new();
-                for (pat, ty, expr) in
-                    itertools::izip!(tuple_pat.fields(), tys.fields(), tuple_init.fields())
-                {
-                    zipped_decls.push_str(&format!("{indents}let {pat}: {ty} = {expr};\n"))
-                }
-                edit.replace(parent.text_range(), zipped_decls.trim());
-            } else {
-                let mut zipped_decls = String::new();
-                for (pat, expr) in itertools::izip!(tuple_pat.fields(), tuple_init.fields()) {
-                    zipped_decls.push_str(&format!("{indents}let {pat} = {expr};\n"));
-                }
-                edit.replace(parent.text_range(), zipped_decls.trim());
+            let tys =
+                tuple_ty.into_iter().flat_map(|it| it.fields().map(Some)).chain(iter::repeat(None));
+            for (pat, ty, expr) in itertools::izip!(tuple_pat.fields(), tys, tuple_init.fields()) {
+                let ty = ty.map_or_else(String::new, |ty| format!(": {ty}"));
+                decls.push_str(&format!("{prefix}let {pat}{ty} = {expr}{suffix}\n{indent_level}"))
             }
+
+            let s = decls.trim();
+            edit.replace(parent.text_range(), s.strip_prefix(prefix).unwrap_or(s));
         },
     )
 }
@@ -124,6 +126,28 @@ fn main() {
     }
 
     #[test]
+    fn unwrap_tuples_in_let_expr() {
+        check_assist(
+            unwrap_tuple,
+            r#"
+fn main() {
+    if $0let (foo, bar) = ("Foo", "Bar") {
+        code();
+    }
+}
+"#,
+            r#"
+fn main() {
+    if let foo = "Foo"
+        && let bar = "Bar" {
+        code();
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
     fn unwrap_tuple_with_types() {
         check_assist(
             unwrap_tuple,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs
index 7d5740b..36df4af 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs
@@ -2,7 +2,7 @@
 use itertools::Itertools;
 use syntax::{
     NodeOrToken, SyntaxToken, T, TextRange, algo,
-    ast::{self, AstNode, make, syntax_factory::SyntaxFactory},
+    ast::{self, AstNode, edit::AstNodeEdit, make, syntax_factory::SyntaxFactory},
 };
 
 use crate::{AssistContext, AssistId, Assists};
@@ -27,7 +27,7 @@
 
 enum WrapUnwrapOption {
     WrapDerive { derive: TextRange, attr: ast::Attr },
-    WrapAttr(ast::Attr),
+    WrapAttr(Vec<ast::Attr>),
 }
 
 /// Attempts to get the derive attribute from a derive attribute list
@@ -102,9 +102,9 @@ fn attempt_get_derive(attr: ast::Attr, ident: SyntaxToken) -> WrapUnwrapOption {
     if ident.parent().and_then(ast::TokenTree::cast).is_none()
         || !attr.simple_name().map(|v| v.eq("derive")).unwrap_or_default()
     {
-        WrapUnwrapOption::WrapAttr(attr)
+        WrapUnwrapOption::WrapAttr(vec![attr])
     } else {
-        attempt_attr().unwrap_or(WrapUnwrapOption::WrapAttr(attr))
+        attempt_attr().unwrap_or_else(|| WrapUnwrapOption::WrapAttr(vec![attr]))
     }
 }
 pub(crate) fn wrap_unwrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
@@ -118,13 +118,27 @@ pub(crate) fn wrap_unwrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>) -
                 Some(attempt_get_derive(attr, ident))
             }
 
-            (Some(attr), _) => Some(WrapUnwrapOption::WrapAttr(attr)),
+            (Some(attr), _) => Some(WrapUnwrapOption::WrapAttr(vec![attr])),
             _ => None,
         }
     } else {
         let covering_element = ctx.covering_element();
         match covering_element {
-            NodeOrToken::Node(node) => ast::Attr::cast(node).map(WrapUnwrapOption::WrapAttr),
+            NodeOrToken::Node(node) => {
+                if let Some(attr) = ast::Attr::cast(node.clone()) {
+                    Some(WrapUnwrapOption::WrapAttr(vec![attr]))
+                } else {
+                    let attrs = node
+                        .children()
+                        .filter(|it| it.text_range().intersect(ctx.selection_trimmed()).is_some())
+                        .map(ast::Attr::cast)
+                        .collect::<Option<Vec<_>>>()?;
+                    if attrs.is_empty() {
+                        return None;
+                    }
+                    Some(WrapUnwrapOption::WrapAttr(attrs))
+                }
+            }
             NodeOrToken::Token(ident) if ident.kind() == syntax::T![ident] => {
                 let attr = ident.parent_ancestors().find_map(ast::Attr::cast)?;
                 Some(attempt_get_derive(attr, ident))
@@ -133,10 +147,12 @@ pub(crate) fn wrap_unwrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>) -
         }
     }?;
     match option {
-        WrapUnwrapOption::WrapAttr(attr) if attr.simple_name().as_deref() == Some("cfg_attr") => {
-            unwrap_cfg_attr(acc, attr)
-        }
-        WrapUnwrapOption::WrapAttr(attr) => wrap_cfg_attr(acc, ctx, attr),
+        WrapUnwrapOption::WrapAttr(attrs) => match &attrs[..] {
+            [attr] if attr.simple_name().as_deref() == Some("cfg_attr") => {
+                unwrap_cfg_attr(acc, attrs.into_iter().next().unwrap())
+            }
+            _ => wrap_cfg_attrs(acc, ctx, attrs),
+        },
         WrapUnwrapOption::WrapDerive { derive, attr } => wrap_derive(acc, ctx, attr, derive),
     }
 }
@@ -220,40 +236,51 @@ fn wrap_derive(
     );
     Some(())
 }
-fn wrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>, attr: ast::Attr) -> Option<()> {
-    let range = attr.syntax().text_range();
-    let path = attr.path()?;
+fn wrap_cfg_attrs(acc: &mut Assists, ctx: &AssistContext<'_>, attrs: Vec<ast::Attr>) -> Option<()> {
+    let (first_attr, last_attr) = (attrs.first()?, attrs.last()?);
+    let range = first_attr.syntax().text_range().cover(last_attr.syntax().text_range());
+    let path_attrs =
+        attrs.iter().map(|attr| Some((attr.path()?, attr.clone()))).collect::<Option<Vec<_>>>()?;
     let handle_source_change = |edit: &mut SourceChangeBuilder| {
         let make = SyntaxFactory::with_mappings();
-        let mut editor = edit.make_editor(attr.syntax());
-        let mut raw_tokens =
-            vec![NodeOrToken::Token(make.token(T![,])), NodeOrToken::Token(make.whitespace(" "))];
-        path.syntax().descendants_with_tokens().for_each(|it| {
-            if let NodeOrToken::Token(token) = it {
-                raw_tokens.push(NodeOrToken::Token(token));
-            }
-        });
-        if let Some(meta) = attr.meta() {
-            if let (Some(eq), Some(expr)) = (meta.eq_token(), meta.expr()) {
-                raw_tokens.push(NodeOrToken::Token(make.whitespace(" ")));
-                raw_tokens.push(NodeOrToken::Token(eq));
-                raw_tokens.push(NodeOrToken::Token(make.whitespace(" ")));
+        let mut editor = edit.make_editor(first_attr.syntax());
+        let mut raw_tokens = vec![];
+        for (path, attr) in path_attrs {
+            raw_tokens.extend([
+                NodeOrToken::Token(make.token(T![,])),
+                NodeOrToken::Token(make.whitespace(" ")),
+            ]);
+            path.syntax().descendants_with_tokens().for_each(|it| {
+                if let NodeOrToken::Token(token) = it {
+                    raw_tokens.push(NodeOrToken::Token(token));
+                }
+            });
+            if let Some(meta) = attr.meta() {
+                if let (Some(eq), Some(expr)) = (meta.eq_token(), meta.expr()) {
+                    raw_tokens.push(NodeOrToken::Token(make.whitespace(" ")));
+                    raw_tokens.push(NodeOrToken::Token(eq));
+                    raw_tokens.push(NodeOrToken::Token(make.whitespace(" ")));
 
-                expr.syntax().descendants_with_tokens().for_each(|it| {
-                    if let NodeOrToken::Token(token) = it {
-                        raw_tokens.push(NodeOrToken::Token(token));
-                    }
-                });
-            } else if let Some(tt) = meta.token_tree() {
-                raw_tokens.extend(tt.token_trees_and_tokens());
+                    expr.syntax().descendants_with_tokens().for_each(|it| {
+                        if let NodeOrToken::Token(token) = it {
+                            raw_tokens.push(NodeOrToken::Token(token));
+                        }
+                    });
+                } else if let Some(tt) = meta.token_tree() {
+                    raw_tokens.extend(tt.token_trees_and_tokens());
+                }
             }
         }
         let meta =
             make.meta_token_tree(make.ident_path("cfg_attr"), make.token_tree(T!['('], raw_tokens));
-        let cfg_attr =
-            if attr.excl_token().is_some() { make.attr_inner(meta) } else { make.attr_outer(meta) };
+        let cfg_attr = if first_attr.excl_token().is_some() {
+            make.attr_inner(meta)
+        } else {
+            make.attr_outer(meta)
+        };
 
-        editor.replace(attr.syntax(), cfg_attr.syntax());
+        let syntax_range = first_attr.syntax().clone().into()..=last_attr.syntax().clone().into();
+        editor.replace_all(syntax_range, vec![cfg_attr.syntax().clone().into()]);
 
         if let Some(snippet_cap) = ctx.config.snippet_cap
             && let Some(first_meta) =
@@ -332,7 +359,8 @@ fn unwrap_cfg_attr(acc: &mut Assists, attr: ast::Attr) -> Option<()> {
         return None;
     }
     let handle_source_change = |f: &mut SourceChangeBuilder| {
-        let inner_attrs = inner_attrs.iter().map(|it| it.to_string()).join("\n");
+        let inner_attrs =
+            inner_attrs.iter().map(|it| it.to_string()).join(&format!("\n{}", attr.indent_level()));
         f.replace(range, inner_attrs);
     };
     acc.add(
@@ -414,6 +442,42 @@ pub struct Test {
             }
             "#,
         );
+        check_assist(
+            wrap_unwrap_cfg_attr,
+            r#"
+            pub struct Test {
+                #[other_attr]
+                $0#[foo]
+                #[bar]$0
+                #[other_attr]
+                test: u32,
+            }
+            "#,
+            r#"
+            pub struct Test {
+                #[other_attr]
+                #[cfg_attr($0, foo, bar)]
+                #[other_attr]
+                test: u32,
+            }
+            "#,
+        );
+        check_assist(
+            wrap_unwrap_cfg_attr,
+            r#"
+            pub struct Test {
+                #[cfg_attr(debug_assertions$0, foo, bar)]
+                test: u32,
+            }
+            "#,
+            r#"
+            pub struct Test {
+                #[foo]
+                #[bar]
+                test: u32,
+            }
+            "#,
+        );
     }
     #[test]
     fn to_from_eq_attr() {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
index 3040509..8ba4679 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
@@ -2282,7 +2282,7 @@ macro_rules! const_maker {
     };
 }
 
-trait ${0:NewTrait}<const N: usize> {
+trait ${0:Create}<const N: usize> {
     // Used as an associated constant.
     const CONST_ASSOC: usize = N * 4;
 
@@ -2291,7 +2291,7 @@ trait ${0:NewTrait}<const N: usize> {
     const_maker! {i32, 7}
 }
 
-impl<const N: usize> ${0:NewTrait}<N> for Foo<N> {
+impl<const N: usize> ${0:Create}<N> for Foo<N> {
     // Used as an associated constant.
     const CONST_ASSOC: usize = N * 4;
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
index b4055e7..0657e72 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
@@ -25,6 +25,7 @@
         edit::{AstNodeEdit, IndentLevel},
         edit_in_place::AttrsOwnerEdit,
         make,
+        prec::ExprPrecedence,
         syntax_factory::SyntaxFactory,
     },
     syntax_editor::{Element, Removable, SyntaxEditor},
@@ -86,17 +87,31 @@ pub fn extract_trivial_expression(block_expr: &ast::BlockExpr) -> Option<ast::Ex
     None
 }
 
-pub(crate) fn wrap_block(expr: &ast::Expr) -> ast::BlockExpr {
+pub(crate) fn wrap_block(expr: &ast::Expr, make: &SyntaxFactory) -> ast::BlockExpr {
     if let ast::Expr::BlockExpr(block) = expr
         && let Some(first) = block.syntax().first_token()
         && first.kind() == T!['{']
     {
         block.reset_indent()
     } else {
-        make::block_expr(None, Some(expr.reset_indent().indent(1.into())))
+        make.block_expr(None, Some(expr.reset_indent().indent(1.into())))
     }
 }
 
+pub(crate) fn wrap_paren(expr: ast::Expr, make: &SyntaxFactory, prec: ExprPrecedence) -> ast::Expr {
+    if expr.precedence().needs_parentheses_in(prec) { make.expr_paren(expr).into() } else { expr }
+}
+
+pub(crate) fn wrap_paren_in_call(expr: ast::Expr, make: &SyntaxFactory) -> ast::Expr {
+    if needs_parens_in_call(&expr) { make.expr_paren(expr).into() } else { expr }
+}
+
+fn needs_parens_in_call(param: &ast::Expr) -> bool {
+    let call = make::expr_call(make::ext::expr_unit(), make::arg_list(Vec::new()));
+    let callable = call.expr().expect("invalid make call");
+    param.needs_parens_in_place_of(call.syntax(), callable.syntax())
+}
+
 /// This is a method with a heuristics to support test methods annotated with custom test annotations, such as
 /// `#[test_case(...)]`, `#[tokio::test]` and similar.
 /// Also a regular `#[test]` annotation is supported.
@@ -275,11 +290,6 @@ pub(crate) fn invert_boolean_expression(make: &SyntaxFactory, expr: ast::Expr) -
     invert_special_case(make, &expr).unwrap_or_else(|| make.expr_prefix(T![!], expr).into())
 }
 
-// FIXME: Migrate usages of this function to the above function and remove this.
-pub(crate) fn invert_boolean_expression_legacy(expr: ast::Expr) -> ast::Expr {
-    invert_special_case_legacy(&expr).unwrap_or_else(|| make::expr_prefix(T![!], expr).into())
-}
-
 fn invert_special_case(make: &SyntaxFactory, expr: &ast::Expr) -> Option<ast::Expr> {
     match expr {
         ast::Expr::BinExpr(bin) => {
@@ -343,62 +353,11 @@ fn invert_special_case(make: &SyntaxFactory, expr: &ast::Expr) -> Option<ast::Ex
     }
 }
 
-fn invert_special_case_legacy(expr: &ast::Expr) -> Option<ast::Expr> {
-    match expr {
-        ast::Expr::BinExpr(bin) => {
-            let bin = bin.clone_subtree();
-            let op_token = bin.op_token()?;
-            let rev_token = match op_token.kind() {
-                T![==] => T![!=],
-                T![!=] => T![==],
-                T![<] => T![>=],
-                T![<=] => T![>],
-                T![>] => T![<=],
-                T![>=] => T![<],
-                // Parenthesize other expressions before prefixing `!`
-                _ => {
-                    return Some(
-                        make::expr_prefix(T![!], make::expr_paren(expr.clone()).into()).into(),
-                    );
-                }
-            };
-            let mut bin_editor = SyntaxEditor::new(bin.syntax().clone());
-            bin_editor.replace(op_token, make::token(rev_token));
-            ast::Expr::cast(bin_editor.finish().new_root().clone())
-        }
-        ast::Expr::MethodCallExpr(mce) => {
-            let receiver = mce.receiver()?;
-            let method = mce.name_ref()?;
-            let arg_list = mce.arg_list()?;
-
-            let method = match method.text().as_str() {
-                "is_some" => "is_none",
-                "is_none" => "is_some",
-                "is_ok" => "is_err",
-                "is_err" => "is_ok",
-                _ => return None,
-            };
-            Some(make::expr_method_call(receiver, make::name_ref(method), arg_list).into())
-        }
-        ast::Expr::PrefixExpr(pe) if pe.op_kind()? == ast::UnaryOp::Not => match pe.expr()? {
-            ast::Expr::ParenExpr(parexpr) => parexpr.expr(),
-            _ => pe.expr(),
-        },
-        ast::Expr::Literal(lit) => match lit.kind() {
-            ast::LiteralKind::Bool(b) => match b {
-                true => Some(ast::Expr::Literal(make::expr_literal("false"))),
-                false => Some(ast::Expr::Literal(make::expr_literal("true"))),
-            },
-            _ => None,
-        },
-        _ => None,
-    }
-}
-
 pub(crate) fn insert_attributes(
     before: impl Element,
     edit: &mut SyntaxEditor,
     attrs: impl IntoIterator<Item = ast::Attr>,
+    make: &SyntaxFactory,
 ) {
     let mut attrs = attrs.into_iter().peekable();
     if attrs.peek().is_none() {
@@ -410,9 +369,7 @@ pub(crate) fn insert_attributes(
     edit.insert_all(
         syntax::syntax_editor::Position::before(elem),
         attrs
-            .flat_map(|attr| {
-                [attr.syntax().clone().into(), make::tokens::whitespace(&whitespace).into()]
-            })
+            .flat_map(|attr| [attr.syntax().clone().into(), make.whitespace(&whitespace).into()])
             .collect(),
     );
 }
@@ -1095,18 +1052,21 @@ pub(crate) fn trimmed_text_range(source_file: &SourceFile, initial_range: TextRa
 
 /// Convert a list of function params to a list of arguments that can be passed
 /// into a function call.
-pub(crate) fn convert_param_list_to_arg_list(list: ast::ParamList) -> ast::ArgList {
+pub(crate) fn convert_param_list_to_arg_list(
+    list: ast::ParamList,
+    make: &SyntaxFactory,
+) -> ast::ArgList {
     let mut args = vec![];
     for param in list.params() {
         if let Some(ast::Pat::IdentPat(pat)) = param.pat()
             && let Some(name) = pat.name()
         {
             let name = name.to_string();
-            let expr = make::expr_path(make::ext::ident_path(&name));
+            let expr = make.expr_path(make.ident_path(&name));
             args.push(expr);
         }
     }
-    make::arg_list(args)
+    make.arg_list(args)
 }
 
 /// Calculate the number of hashes required for a raw string containing `s`
@@ -1191,7 +1151,10 @@ pub(crate) fn replace_record_field_expr(
 
 /// Creates a token tree list from a syntax node, creating the needed delimited sub token trees.
 /// Assumes that the input syntax node is a valid syntax tree.
-pub(crate) fn tt_from_syntax(node: SyntaxNode) -> Vec<NodeOrToken<ast::TokenTree, SyntaxToken>> {
+pub(crate) fn tt_from_syntax(
+    node: SyntaxNode,
+    make: &SyntaxFactory,
+) -> Vec<NodeOrToken<ast::TokenTree, SyntaxToken>> {
     let mut tt_stack = vec![(None, vec![])];
 
     for element in node.descendants_with_tokens() {
@@ -1219,7 +1182,7 @@ pub(crate) fn tt_from_syntax(node: SyntaxNode) -> Vec<NodeOrToken<ast::TokenTree
                     "mismatched opening and closing delimiters"
                 );
 
-                let sub_tt = make::token_tree(delimiter.expect("unbalanced delimiters"), tt);
+                let sub_tt = make.token_tree(delimiter.expect("unbalanced delimiters"), tt);
                 parent_tt.push(NodeOrToken::Node(sub_tt));
             }
             _ => {
@@ -1254,6 +1217,20 @@ pub(crate) fn cover_let_chain(mut expr: ast::Expr, range: TextRange) -> Option<a
     }
 }
 
+pub(crate) fn cover_edit_range(
+    source: &impl AstNode,
+    range: TextRange,
+) -> std::ops::RangeInclusive<syntax::SyntaxElement> {
+    let node = match source.syntax().covering_element(range) {
+        NodeOrToken::Node(node) => node,
+        NodeOrToken::Token(t) => t.parent().unwrap(),
+    };
+    let mut iter = node.children_with_tokens().filter(|it| range.contains_range(it.text_range()));
+    let first = iter.next().unwrap_or(node.into());
+    let last = iter.last().unwrap_or_else(|| first.clone());
+    first..=last
+}
+
 pub(crate) fn is_selected(
     it: &impl AstNode,
     selection: syntax::TextRange,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils/ref_field_expr.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils/ref_field_expr.rs
index df8ad41..fc9bf21 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/utils/ref_field_expr.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils/ref_field_expr.rs
@@ -5,7 +5,7 @@
 //! based on the parent of the existing expression.
 use syntax::{
     AstNode, T,
-    ast::{self, FieldExpr, MethodCallExpr, make, syntax_factory::SyntaxFactory},
+    ast::{self, FieldExpr, MethodCallExpr, syntax_factory::SyntaxFactory},
 };
 
 use crate::AssistContext;
@@ -119,13 +119,13 @@ pub(crate) struct RefData {
 
 impl RefData {
     /// Derefs `expr` and wraps it in parens if necessary
-    pub(crate) fn wrap_expr(&self, mut expr: ast::Expr) -> ast::Expr {
+    pub(crate) fn wrap_expr(&self, mut expr: ast::Expr, make: &SyntaxFactory) -> ast::Expr {
         if self.needs_deref {
-            expr = make::expr_prefix(T![*], expr).into();
+            expr = make.expr_prefix(T![*], expr).into();
         }
 
         if self.needs_parentheses {
-            expr = make::expr_paren(expr).into();
+            expr = make.expr_paren(expr).into();
         }
 
         expr
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs
index 96dac66..bd0b692 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs
@@ -30,14 +30,27 @@ pub(crate) fn complete_fn_param(
         _ => return None,
     };
 
+    let qualifier = param_qualifier(param);
     let comma_wrapper = comma_wrapper(ctx);
     let mut add_new_item_to_acc = |label: &str| {
-        let mk_item = |label: &str, range: TextRange| {
-            CompletionItem::new(CompletionItemKind::Binding, range, label, ctx.edition)
+        let label = label.strip_prefix(qualifier.as_str()).unwrap_or(label);
+        let insert = if label.starts_with('#') {
+            // FIXME: `#[attr] it: i32` -> `#[attr] mut it: i32`
+            label.to_smolstr()
+        } else {
+            format_smolstr!("{qualifier}{label}")
+        };
+        let mk_item = |insert_text: &str, range: TextRange| {
+            let mut item =
+                CompletionItem::new(CompletionItemKind::Binding, range, label, ctx.edition);
+            if insert_text != label {
+                item.insert_text(insert_text);
+            }
+            item
         };
         let item = match &comma_wrapper {
-            Some((fmt, range)) => mk_item(&fmt(label), *range),
-            None => mk_item(label, ctx.source_range()),
+            Some((fmt, range)) => mk_item(&fmt(&insert), *range),
+            None => mk_item(&insert, ctx.source_range()),
         };
         // Completion lookup is omitted intentionally here.
         // See the full discussion: https://github.com/rust-lang/rust-analyzer/issues/12073
@@ -75,9 +88,6 @@ fn fill_fn_params(
     let mut file_params = FxHashMap::default();
 
     let mut extract_params = |f: ast::Fn| {
-        if !is_simple_param(current_param) {
-            return;
-        }
         f.param_list().into_iter().flat_map(|it| it.params()).for_each(|param| {
             if let Some(pat) = param.pat() {
                 let whole_param = param.to_smolstr();
@@ -88,6 +98,9 @@ fn fill_fn_params(
     };
 
     for node in ctx.token.parent_ancestors() {
+        if !is_simple_param(current_param) {
+            break;
+        }
         match_ast! {
             match node {
                 ast::SourceFile(it) => it.items().filter_map(|item| match item {
@@ -214,3 +227,16 @@ fn is_simple_param(param: &ast::Param) -> bool {
         .pat()
         .is_none_or(|pat| matches!(pat, ast::Pat::IdentPat(ident_pat) if ident_pat.pat().is_none()))
 }
+
+fn param_qualifier(param: &ast::Param) -> SmolStr {
+    let mut b = syntax::SmolStrBuilder::new();
+    if let Some(ast::Pat::IdentPat(pat)) = param.pat() {
+        if pat.ref_token().is_some() {
+            b.push_str("ref ");
+        }
+        if pat.mut_token().is_some() {
+            b.push_str("mut ");
+        }
+    }
+    b.finish()
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
index ea53aef..5b91e7c 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
@@ -16,7 +16,7 @@
 use stdx::never;
 use syntax::{
     SmolStr,
-    SyntaxKind::{EXPR_STMT, STMT_LIST},
+    SyntaxKind::{CLOSURE_EXPR, EXPR_STMT, MATCH_ARM, STMT_LIST},
     T, TextRange, TextSize, ToSmolStr,
     ast::{self, AstNode, AstToken},
     format_smolstr, match_ast,
@@ -66,6 +66,12 @@ pub(crate) fn complete_postfix(
         Some(it) => it,
         None => return,
     };
+    let semi =
+        if expr_ctx.in_block_expr && ctx.token.next_token().is_none_or(|it| it.kind() != T![;]) {
+            ";"
+        } else {
+            ""
+        };
 
     let cfg = ctx.config.find_path_config(ctx.is_nightly);
 
@@ -151,12 +157,12 @@ pub(crate) fn complete_postfix(
                     .add_to(acc, ctx.db);
             }
             _ if matches!(parent.kind(), STMT_LIST | EXPR_STMT) => {
-                postfix_snippet("let", "let", &format!("let $0 = {receiver_text};"))
+                postfix_snippet("let", "let", &format!("let $0 = {receiver_text}{semi}"))
                     .add_to(acc, ctx.db);
-                postfix_snippet("letm", "let mut", &format!("let mut $0 = {receiver_text};"))
+                postfix_snippet("letm", "let mut", &format!("let mut $0 = {receiver_text}{semi}"))
                     .add_to(acc, ctx.db);
             }
-            _ if ast::MatchArm::can_cast(parent.kind()) => {
+            _ if matches!(parent.kind(), MATCH_ARM | CLOSURE_EXPR) => {
                 postfix_snippet(
                     "let",
                     "let",
@@ -307,26 +313,12 @@ pub(crate) fn complete_postfix(
         add_format_like_completions(acc, ctx, &dot_receiver_including_refs, cap, &literal_text);
     }
 
-    postfix_snippet(
-        "return",
-        "return expr",
-        &format!(
-            "return {receiver_text}{semi}",
-            semi = if expr_ctx.in_block_expr { ";" } else { "" }
-        ),
-    )
-    .add_to(acc, ctx.db);
+    postfix_snippet("return", "return expr", &format!("return {receiver_text}{semi}"))
+        .add_to(acc, ctx.db);
 
     if let Some(BreakableKind::Block | BreakableKind::Loop) = expr_ctx.in_breakable {
-        postfix_snippet(
-            "break",
-            "break expr",
-            &format!(
-                "break {receiver_text}{semi}",
-                semi = if expr_ctx.in_block_expr { ";" } else { "" }
-            ),
-        )
-        .add_to(acc, ctx.db);
+        postfix_snippet("break", "break expr", &format!("break {receiver_text}{semi}"))
+            .add_to(acc, ctx.db);
     }
 }
 
@@ -371,12 +363,20 @@ fn get_receiver_text(
         range.range = TextRange::at(range.range.start(), range.range.len() - TextSize::of('.'))
     }
     let file_text = sema.db.file_text(range.file_id.file_id(sema.db));
-    let mut text = file_text.text(sema.db)[range.range].to_owned();
+    let text = file_text.text(sema.db);
+    let indent_spaces = indent_of_tail_line(&text[TextRange::up_to(range.range.start())]);
+    let mut text = stdx::dedent_by(indent_spaces, &text[range.range]);
 
     // The receiver texts should be interpreted as-is, as they are expected to be
     // normal Rust expressions.
     escape_snippet_bits(&mut text);
-    text
+    return text;
+
+    fn indent_of_tail_line(text: &str) -> usize {
+        let tail_line = text.rsplit_once('\n').map_or(text, |(_, s)| s);
+        let trimmed = tail_line.trim_start_matches(' ');
+        tail_line.len() - trimmed.len()
+    }
 }
 
 /// Escapes `\` and `$` so that they don't get interpreted as snippet-specific constructs.
@@ -402,6 +402,10 @@ fn receiver_accessor(receiver: &ast::Expr) -> ast::Expr {
         .unwrap_or_else(|| receiver.clone())
 }
 
+/// Given an `initial_element`, tries to expand it to include deref(s), and then references.
+/// Returns the expanded expressions, and the added prefix as a string
+///
+/// For example, if called with the `42` in `&&mut *42`, would return `(&&mut *42, "&&mut *")`.
 fn include_references(initial_element: &ast::Expr) -> (ast::Expr, String) {
     let mut resulting_element = initial_element.clone();
     let mut prefix = String::new();
@@ -410,11 +414,8 @@ fn include_references(initial_element: &ast::Expr) -> (ast::Expr, String) {
 
     while let Some(parent_deref_element) =
         resulting_element.syntax().parent().and_then(ast::PrefixExpr::cast)
+        && parent_deref_element.op_kind() == Some(ast::UnaryOp::Deref)
     {
-        if parent_deref_element.op_kind() != Some(ast::UnaryOp::Deref) {
-            break;
-        }
-
         found_ref_or_deref = true;
         resulting_element = ast::Expr::from(parent_deref_element);
 
@@ -663,6 +664,22 @@ fn main() {
 
     #[test]
     fn let_middle_block() {
+        check_edit(
+            "let",
+            r#"
+fn main() {
+    baz.l$0
+    res
+}
+"#,
+            r#"
+fn main() {
+    let $0 = baz;
+    res
+}
+"#,
+        );
+
         check(
             r#"
 fn main() {
@@ -719,6 +736,20 @@ fn main() {
 
     #[test]
     fn let_tail_block() {
+        check_edit(
+            "let",
+            r#"
+fn main() {
+    baz.l$0
+}
+"#,
+            r#"
+fn main() {
+    let $0 = baz;
+}
+"#,
+        );
+
         check(
             r#"
 fn main() {
@@ -773,6 +804,23 @@ fn main() {
     }
 
     #[test]
+    fn let_before_semicolon() {
+        check_edit(
+            "let",
+            r#"
+fn main() {
+    baz.l$0;
+}
+"#,
+            r#"
+fn main() {
+    let $0 = baz;
+}
+"#,
+        );
+    }
+
+    #[test]
     fn option_iflet() {
         check_edit(
             "ifl",
@@ -966,6 +1014,28 @@ fn main() {
     }
 
     #[test]
+    fn closure_let_block() {
+        check_edit(
+            "let",
+            r#"
+fn main() {
+    let bar = 2;
+    let f = || bar.$0;
+}
+"#,
+            r#"
+fn main() {
+    let bar = 2;
+    let f = || {
+    let $1 = bar;
+    $0
+};
+}
+"#,
+        );
+    }
+
+    #[test]
     fn option_letelse() {
         check_edit(
             "lete",
@@ -1040,6 +1110,7 @@ fn main() {
     #[test]
     fn postfix_completion_for_references() {
         check_edit("dbg", r#"fn main() { &&42.$0 }"#, r#"fn main() { dbg!(&&42) }"#);
+        check_edit("dbg", r#"fn main() { &&*"hello".$0 }"#, r#"fn main() { dbg!(&&*"hello") }"#);
         check_edit("refm", r#"fn main() { &&42.$0 }"#, r#"fn main() { &&&mut 42 }"#);
         check_edit(
             "ifl",
@@ -1198,9 +1269,9 @@ fn main() {
 
 fn main() {
     ControlFlow::Break(match true {
-        true => "\${1:placeholder}",
-        false => "\\\$",
-    })
+    true => "\${1:placeholder}",
+    false => "\\\$",
+})
 }
 "#,
         );
@@ -1440,4 +1511,31 @@ fn foo() {
         "#,
         );
     }
+
+    #[test]
+    fn snippet_dedent() {
+        check_edit(
+            "let",
+            r#"
+//- minicore: option
+fn foo(x: Option<i32>, y: Option<i32>) {
+    let _f = || {
+        x
+            .and(y)
+            .map(|it| it+2)
+            .$0
+    };
+}
+"#,
+            r#"
+fn foo(x: Option<i32>, y: Option<i32>) {
+    let _f = || {
+        let $0 = x
+    .and(y)
+    .map(|it| it+2);
+    };
+}
+"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
index 4b0cc0c..bf89953 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
@@ -778,6 +778,16 @@ fn expected_type_and_name<'db>(
                     let ty = sema.type_of_pat(&ast::Pat::from(it)).map(TypeInfo::original);
                     (ty, None)
                 },
+                ast::TupleStructPat(it) => {
+                    let fields = it.path().and_then(|path| match sema.resolve_path(&path)? {
+                        hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) => Some(adt.as_struct()?.fields(sema.db)),
+                        hir::PathResolution::Def(hir::ModuleDef::Variant(variant)) => Some(variant.fields(sema.db)),
+                        _ => None,
+                    });
+                    let nr = it.fields().take_while(|it| it.syntax().text_range().end() <= token.text_range().start()).count();
+                    let ty = fields.and_then(|fields| Some(fields.get(nr)?.ty(sema.db).to_type(sema.db)));
+                    (ty, None)
+                },
                 ast::Fn(it) => {
                     cov_mark::hit!(expected_type_fn_ret_with_leading_char);
                     cov_mark::hit!(expected_type_fn_ret_without_leading_char);
@@ -944,10 +954,10 @@ fn classify_name_ref<'db>(
     let field_expr_handle = |receiver, node| {
         let receiver = find_opt_node_in_file(original_file, receiver);
         let receiver_is_ambiguous_float_literal = match &receiver {
-            Some(ast::Expr::Literal(l)) => matches! {
-                l.kind(),
-                ast::LiteralKind::FloatNumber { .. } if l.syntax().last_token().is_some_and(|it| it.text().ends_with('.'))
-            },
+            Some(ast::Expr::Literal(l)) => {
+                matches!(l.kind(), ast::LiteralKind::FloatNumber { .. })
+                    && l.syntax().last_token().is_some_and(|it| it.text().ends_with('.'))
+            }
             _ => false,
         };
 
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs
index e97d972..94d9049 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs
@@ -288,6 +288,50 @@ fn foo() -> Foo {
 }
 
 #[test]
+fn expected_type_tuple_struct_pat() {
+    check_expected_type_and_name(
+        r#"
+//- minicore: option
+struct Foo(Option<i32>);
+fn foo(x: Foo) -> Foo {
+   match x { Foo($0) => () }
+}
+"#,
+        expect![[r#"ty: Option<i32>, name: ?"#]],
+    );
+
+    check_expected_type_and_name(
+        r#"
+struct Foo(i32, u32, f32);
+fn foo(x: Foo) -> Foo {
+   match x { Foo($0) => () }
+}
+"#,
+        expect![[r#"ty: i32, name: ?"#]],
+    );
+
+    check_expected_type_and_name(
+        r#"
+struct Foo(i32, u32, f32);
+fn foo(x: Foo) -> Foo {
+   match x { Foo(num,$0) => () }
+}
+"#,
+        expect![[r#"ty: u32, name: ?"#]],
+    );
+
+    check_expected_type_and_name(
+        r#"
+struct Foo(i32, u32, f32);
+fn foo(x: Foo) -> Foo {
+   match x { Foo(num,$0,float) => () }
+}
+"#,
+        expect![[r#"ty: u32, name: ?"#]],
+    );
+}
+
+#[test]
 fn expected_type_if_let_without_leading_char() {
     cov_mark::check!(expected_type_if_let_without_leading_char);
     check_expected_type_and_name(
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs
index 475e00d..dfa3084 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs
@@ -678,7 +678,7 @@ fn main() {
     fn complete_fn_param() {
         // has mut kw
         check_edit(
-            "mut bar: u32",
+            "bar: u32",
             r#"
 fn f(foo: (), mut bar: u32) {}
 fn g(foo: (), mut ba$0)
@@ -689,10 +689,35 @@ fn g(foo: (), mut bar: u32)
 "#,
         );
 
-        // has type param
+        // has unmatched mut kw
+        check_edit(
+            "bar: u32",
+            r#"
+fn f(foo: (), bar: u32) {}
+fn g(foo: (), mut ba$0)
+"#,
+            r#"
+fn f(foo: (), bar: u32) {}
+fn g(foo: (), mut bar: u32)
+"#,
+        );
+
         check_edit(
             "mut bar: u32",
             r#"
+fn f(foo: (), mut bar: u32) {}
+fn g(foo: (), ba$0)
+"#,
+            r#"
+fn f(foo: (), mut bar: u32) {}
+fn g(foo: (), mut bar: u32)
+"#,
+        );
+
+        // has type param
+        check_edit(
+            "bar: u32",
+            r#"
 fn g(foo: (), mut ba$0: u32)
 fn f(foo: (), mut bar: u32) {}
 "#,
@@ -707,7 +732,7 @@ fn f(foo: (), mut bar: u32) {}
     fn complete_fn_mut_param_add_comma() {
         // add leading and trailing comma
         check_edit(
-            ", mut bar: u32,",
+            "bar: u32",
             r#"
 fn f(foo: (), mut bar: u32) {}
 fn g(foo: ()mut ba$0 baz: ())
@@ -746,7 +771,7 @@ fn g(foo: (), #[baz = "qux"] mut bar: u32)
         );
 
         check_edit(
-            r#", #[baz = "qux"] mut bar: u32"#,
+            r#"#[baz = "qux"] mut bar: u32"#,
             r#"
 fn f(foo: (), #[baz = "qux"] mut bar: u32) {}
 fn g(foo: ()#[baz = "qux"] mut ba$0)
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/fn_param.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/fn_param.rs
index d6d73da..aaa2256 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/fn_param.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/fn_param.rs
@@ -43,7 +43,7 @@ fn bar(file_id: usize) {}
 fn baz(file$0 id: u32) {}
 "#,
         expect![[r#"
-            bn file_id: usize,
+            bn file_id: usize
             kw mut
             kw ref
         "#]],
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs
index bcfe3a8..619bb23 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs
@@ -97,25 +97,37 @@ fn missing_record_expr_field_fixes(
         make::ty(&new_field_type.display_source_code(sema.db, module.into(), true).ok()?),
     );
 
-    let last_field = record_fields.fields().last()?;
-    let last_field_syntax = last_field.syntax();
-    let indent = IndentLevel::from_node(last_field_syntax);
+    let (indent, offset, postfix, needs_comma) =
+        if let Some(last_field) = record_fields.fields().last() {
+            let indent = IndentLevel::from_node(last_field.syntax());
+            let offset = last_field.syntax().text_range().end();
+            let needs_comma = !last_field.to_string().ends_with(',');
+            (indent, offset, String::new(), needs_comma)
+        } else {
+            let indent = IndentLevel::from_node(record_fields.syntax());
+            let offset = record_fields.l_curly_token()?.text_range().end();
+            let postfix = if record_fields.syntax().text().contains_char('\n') {
+                ",".into()
+            } else {
+                format!(",\n{indent}")
+            };
+            (indent + 1, offset, postfix, false)
+        };
 
     let mut new_field = new_field.to_string();
     // FIXME: check submodule instead of FileId
     if usage_file_id != def_file_id && !matches!(def_id, hir::VariantDef::Variant(_)) {
         new_field = format!("pub(crate) {new_field}");
     }
-    new_field = format!("\n{indent}{new_field}");
+    new_field = format!("\n{indent}{new_field}{postfix}");
 
-    let needs_comma = !last_field_syntax.to_string().ends_with(',');
     if needs_comma {
         new_field = format!(",{new_field}");
     }
 
     let source_change = SourceChange::from_text_edit(
         def_file_id.file_id(sema.db),
-        TextEdit::insert(last_field_syntax.text_range().end(), new_field),
+        TextEdit::insert(offset, new_field),
     );
 
     return Some(vec![fix(
@@ -335,6 +347,44 @@ struct Foo {
     }
 
     #[test]
+    fn test_add_field_from_usage_with_empty_struct() {
+        check_fix(
+            r"
+fn main() {
+    Foo { bar$0: false };
+}
+struct Foo {}
+",
+            r"
+fn main() {
+    Foo { bar: false };
+}
+struct Foo {
+    bar: bool,
+}
+",
+        );
+
+        check_fix(
+            r"
+fn main() {
+    Foo { bar$0: false };
+}
+struct Foo {
+}
+",
+            r"
+fn main() {
+    Foo { bar: false };
+}
+struct Foo {
+    bar: bool,
+}
+",
+        );
+    }
+
+    #[test]
     fn test_add_field_in_other_file_from_usage() {
         check_fix(
             r#"
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs
index c86ecd2..bc10e82 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs
@@ -1,4 +1,11 @@
-use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
+use either::Either;
+use hir::Semantics;
+use ide_db::text_edit::TextEdit;
+use ide_db::ty_filter::TryEnum;
+use ide_db::{RootDatabase, source_change::SourceChange};
+use syntax::{AstNode, ast};
+
+use crate::{Assist, Diagnostic, DiagnosticCode, DiagnosticsContext, fix};
 
 // Diagnostic: non-exhaustive-let
 //
@@ -15,11 +22,74 @@ pub(crate) fn non_exhaustive_let(
         d.pat.map(Into::into),
     )
     .stable()
+    .with_fixes(fixes(&ctx.sema, d))
+}
+
+fn fixes(sema: &Semantics<'_, RootDatabase>, d: &hir::NonExhaustiveLet) -> Option<Vec<Assist>> {
+    let root = sema.parse_or_expand(d.pat.file_id);
+    let pat = d.pat.value.to_node(&root);
+    let let_stmt = ast::LetStmt::cast(pat.syntax().parent()?)?;
+    let early_node =
+        sema.ancestors_with_macros(let_stmt.syntax().clone()).find_map(AstNode::cast)?;
+    let early_text = early_text(sema, &early_node);
+
+    if let_stmt.let_else().is_some() {
+        return None;
+    }
+    let hir::FileRangeWrapper { file_id, range } = sema.original_range_opt(let_stmt.syntax())?;
+    let insert_offset = if let Some(semicolon) = let_stmt.semicolon_token()
+        && let Some(token) = sema.parse(file_id).syntax().token_at_offset(range.end()).left_biased()
+        && token.kind() == semicolon.kind()
+    {
+        token.text_range().start()
+    } else {
+        range.end()
+    };
+    let semicolon = if let_stmt.semicolon_token().is_none() { ";" } else { "" };
+    let else_block = format!(" else {{ {early_text} }}{semicolon}");
+    let file_id = file_id.file_id(sema.db);
+
+    let source_change =
+        SourceChange::from_text_edit(file_id, TextEdit::insert(insert_offset, else_block));
+    let target = sema.original_range(let_stmt.syntax()).range;
+    Some(vec![fix("add_let_else_block", "Add let-else block", source_change, target)])
+}
+
+fn early_text(
+    sema: &Semantics<'_, RootDatabase>,
+    early_node: &Either<ast::AnyHasLoopBody, Either<ast::Fn, ast::ClosureExpr>>,
+) -> &'static str {
+    match early_node {
+        Either::Left(_any_loop) => "continue",
+        Either::Right(Either::Left(fn_)) => sema
+            .to_def(fn_)
+            .map(|fn_def| fn_def.ret_type(sema.db))
+            .map(|ty| return_text(&ty, sema))
+            .unwrap_or("return"),
+        Either::Right(Either::Right(closure)) => closure
+            .body()
+            .and_then(|expr| sema.type_of_expr(&expr))
+            .map(|ty| return_text(&ty.adjusted(), sema))
+            .unwrap_or("return"),
+    }
+}
+
+fn return_text(ty: &hir::Type<'_>, sema: &Semantics<'_, RootDatabase>) -> &'static str {
+    if ty.is_unit() {
+        "return"
+    } else if let Some(try_enum) = TryEnum::from_ty(sema, ty) {
+        match try_enum {
+            TryEnum::Option => "return None",
+            TryEnum::Result => "return Err($0)",
+        }
+    } else {
+        "return $0"
+    }
 }
 
 #[cfg(test)]
 mod tests {
-    use crate::tests::check_diagnostics;
+    use crate::tests::{check_diagnostics, check_fix};
 
     #[test]
     fn option_nonexhaustive() {
@@ -28,7 +98,7 @@ fn option_nonexhaustive() {
 //- minicore: option
 fn main() {
     let None = Some(5);
-      //^^^^ error: non-exhaustive pattern: `Some(_)` not covered
+      //^^^^ 💡 error: non-exhaustive pattern: `Some(_)` not covered
 }
 "#,
         );
@@ -54,7 +124,7 @@ fn option_nonexhaustive_inside_blocks() {
 fn main() {
     '_a: {
         let None = Some(5);
-          //^^^^ error: non-exhaustive pattern: `Some(_)` not covered
+          //^^^^ 💡 error: non-exhaustive pattern: `Some(_)` not covered
     }
 }
 "#,
@@ -66,7 +136,7 @@ fn main() {
 fn main() {
     let _ = async {
         let None = Some(5);
-          //^^^^ error: non-exhaustive pattern: `Some(_)` not covered
+          //^^^^ 💡 error: non-exhaustive pattern: `Some(_)` not covered
     };
 }
 "#,
@@ -78,7 +148,7 @@ fn main() {
 fn main() {
     unsafe {
         let None = Some(5);
-          //^^^^ error: non-exhaustive pattern: `Some(_)` not covered
+          //^^^^ 💡 error: non-exhaustive pattern: `Some(_)` not covered
     }
 }
 "#,
@@ -101,7 +171,7 @@ fn test(x: Result<i32, !>) {
 //- minicore: result
 fn test(x: Result<i32, &'static !>) {
     let Ok(_y) = x;
-      //^^^^^^ error: non-exhaustive pattern: `Err(_)` not covered
+      //^^^^^^ 💡 error: non-exhaustive pattern: `Err(_)` not covered
 }
 "#,
         );
@@ -133,6 +203,136 @@ fn foo(v: Enum<()>) {
     }
 
     #[test]
+    fn fix_return_in_loop() {
+        check_fix(
+            r#"
+//- minicore: option
+fn foo() {
+    while cond {
+        let None$0 = Some(5);
+    }
+}
+"#,
+            r#"
+fn foo() {
+    while cond {
+        let None = Some(5) else { continue };
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn fix_return_in_fn() {
+        check_fix(
+            r#"
+//- minicore: option
+fn foo() {
+    let None$0 = Some(5);
+}
+"#,
+            r#"
+fn foo() {
+    let None = Some(5) else { return };
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn fix_return_in_macro_expanded() {
+        check_fix(
+            r#"
+//- minicore: option
+macro_rules! identity { ($($t:tt)*) => { $($t)* }; }
+fn foo() {
+    identity! {
+        let None$0 = Some(5);
+    }
+}
+"#,
+            r#"
+macro_rules! identity { ($($t:tt)*) => { $($t)* }; }
+fn foo() {
+    identity! {
+        let None = Some(5) else { return };
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn fix_return_in_incomplete_let() {
+        check_fix(
+            r#"
+//- minicore: option
+fn foo() {
+    let None$0 = Some(5)
+}
+"#,
+            r#"
+fn foo() {
+    let None = Some(5) else { return };
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn fix_return_in_closure() {
+        check_fix(
+            r#"
+//- minicore: option
+fn foo() -> Option<()> {
+    let _f = || {
+        let None$0 = Some(5);
+    };
+}
+"#,
+            r#"
+fn foo() -> Option<()> {
+    let _f = || {
+        let None = Some(5) else { return };
+    };
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn fix_return_try_in_fn() {
+        check_fix(
+            r#"
+//- minicore: option
+fn foo() -> Option<()> {
+    let None$0 = Some(5);
+}
+"#,
+            r#"
+fn foo() -> Option<()> {
+    let None = Some(5) else { return None };
+}
+"#,
+        );
+
+        check_fix(
+            r#"
+//- minicore: option, result
+fn foo() -> Result<(), i32> {
+    let None$0 = Some(5);
+}
+"#,
+            r#"
+fn foo() -> Result<(), i32> {
+    let None = Some(5) else { return Err($0) };
+}
+"#,
+        );
+    }
+
+    #[test]
     fn regression_20259() {
         check_diagnostics(
             r#"
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs
index 7dc5b5b..04f48ae 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs
@@ -48,7 +48,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &RemoveUnnecessaryElse) -> Option<Vec<
     let mut indent = IndentLevel::from_node(if_expr.syntax());
     let has_parent_if_expr = if_expr.syntax().parent().and_then(ast::IfExpr::cast).is_some();
     if has_parent_if_expr {
-        indent = indent + 1;
+        indent += 1;
     }
     let else_replacement = match if_expr.else_branch()? {
         ast::ElseBranch::Block(block) => block
diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
index 95fcfce..8753eab 100644
--- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
@@ -42,6 +42,7 @@ pub struct LoadCargoConfig {
     pub load_out_dirs_from_check: bool,
     pub with_proc_macro_server: ProcMacroServerChoice,
     pub prefill_caches: bool,
+    pub num_worker_threads: usize,
     pub proc_macro_processes: usize,
 }
 
@@ -197,7 +198,7 @@ pub fn load_workspace_into_db(
     );
 
     if load_config.prefill_caches {
-        prime_caches::parallel_prime_caches(db, 1, &|_| ());
+        prime_caches::parallel_prime_caches(db, load_config.num_worker_threads, &|_| ());
     }
 
     Ok((vfs, proc_macro_server.and_then(Result::ok)))
@@ -744,16 +745,26 @@ mod tests {
 
     #[test]
     fn test_loading_rust_analyzer() {
-        let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap();
+        let cargo_toml_path = Path::new(env!("CARGO_MANIFEST_DIR"))
+            .parent()
+            .unwrap()
+            .parent()
+            .unwrap()
+            .join("Cargo.toml");
+        let cargo_toml_path = AbsPathBuf::assert_utf8(cargo_toml_path);
+        let manifest = ProjectManifest::from_manifest_file(cargo_toml_path).unwrap();
+
         let cargo_config = CargoConfig { set_test: true, ..CargoConfig::default() };
         let load_cargo_config = LoadCargoConfig {
             load_out_dirs_from_check: false,
             with_proc_macro_server: ProcMacroServerChoice::None,
             prefill_caches: false,
+            num_worker_threads: 1,
             proc_macro_processes: 1,
         };
+        let workspace = ProjectWorkspace::load(manifest, &cargo_config, &|_| {}).unwrap();
         let (db, _vfs, _proc_macro) =
-            load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {}).unwrap();
+            load_workspace(workspace, &cargo_config.extra_env, &load_cargo_config).unwrap();
 
         let n_crates = db.all_crates().len();
         // RA has quite a few crates, but the exact count doesn't matter
diff --git a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
index 9b91110..4ea136a 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
@@ -365,9 +365,27 @@ pub enum RunnableKind {
     /// May include {test_id} which will get the test clicked on by the user.
     TestOne,
 
+    /// Run tests matching a pattern (in RA, usually a path::to::module::of::tests)
+    /// May include {label} which will get the label from the `build` section of a crate.
+    /// May include {test_pattern} which will get the test module clicked on by the user.
+    TestMod,
+
+    /// Run a single doctest
+    /// May include {label} which will get the label from the `build` section of a crate.
+    /// May include {test_id} which will get the doctest clicked on by the user.
+    DocTestOne,
+
+    /// Run a single benchmark
+    /// May include {label} which will get the label from the `build` section of a crate.
+    /// May include {bench_id} which will get the benchmark clicked on by the user.
+    BenchOne,
+
     /// Template for checking a target, emitting rustc JSON diagnostics.
     /// May include {label} which will get the label from the `build` section of a crate.
     Flycheck,
+
+    /// For forwards-compatibility, i.e. old rust-analyzer binary with newer workspace discovery tools
+    Unknown,
 }
 
 #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
@@ -380,6 +398,8 @@ pub struct ProjectJsonData {
     crates: Vec<CrateData>,
     #[serde(default)]
     runnables: Vec<RunnableData>,
+    //
+    // New fields should be Option or #[serde(default)]. This applies to most of this datastructure.
 }
 
 #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Default)]
@@ -453,32 +473,40 @@ enum EditionData {
 }
 
 #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
-pub struct BuildData {
+struct BuildData {
     label: String,
     build_file: Utf8PathBuf,
     target_kind: TargetKindData,
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
-pub struct RunnableData {
-    pub program: String,
-    pub args: Vec<String>,
-    pub cwd: Utf8PathBuf,
-    pub kind: RunnableKindData,
+struct RunnableData {
+    program: String,
+    args: Vec<String>,
+    cwd: Utf8PathBuf,
+    kind: RunnableKindData,
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
 #[serde(rename_all = "camelCase")]
-pub enum RunnableKindData {
+enum RunnableKindData {
     Flycheck,
     Check,
     Run,
     TestOne,
+    TestMod,
+    DocTestOne,
+    BenchOne,
+
+    /// For forwards-compatibility, i.e. old rust-analyzer binary with newer workspace discovery tools
+    #[allow(unused)]
+    #[serde(other)]
+    Unknown,
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
 #[serde(rename_all = "camelCase")]
-pub enum TargetKindData {
+enum TargetKindData {
     Bin,
     /// Any kind of Cargo lib crate-type (dylib, rlib, proc-macro, ...).
     Lib,
@@ -541,7 +569,11 @@ fn from(data: RunnableKindData) -> Self {
             RunnableKindData::Check => RunnableKind::Check,
             RunnableKindData::Run => RunnableKind::Run,
             RunnableKindData::TestOne => RunnableKind::TestOne,
+            RunnableKindData::TestMod => RunnableKind::TestMod,
+            RunnableKindData::DocTestOne => RunnableKind::DocTestOne,
+            RunnableKindData::BenchOne => RunnableKind::BenchOne,
             RunnableKindData::Flycheck => RunnableKind::Flycheck,
+            RunnableKindData::Unknown => RunnableKind::Unknown,
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
index a03ed56..395cea6 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
@@ -193,6 +193,12 @@ fn rust_project_hello_world_project_model() {
 }
 
 #[test]
+fn rust_project_labeled_project_model() {
+    // This just needs to parse.
+    _ = load_rust_project("labeled-project.json");
+}
+
+#[test]
 fn rust_project_cfg_groups() {
     let (crate_graph, _proc_macros) = load_rust_project("cfg-groups.json");
     check_crate_graph(crate_graph, expect_file!["../test_data/output/rust_project_cfg_groups.txt"]);
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/labeled-project.json b/src/tools/rust-analyzer/crates/project-model/test_data/labeled-project.json
new file mode 100644
index 0000000..5c0e1f3
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/labeled-project.json
@@ -0,0 +1,37 @@
+{
+    "sysroot_src": null,
+    "crates": [
+        {
+            "display_name": "hello_world",
+            "root_module": "$ROOT$src/lib.rs",
+            "edition": "2018",
+            "deps": [],
+            "is_workspace_member": true,
+            "build": {
+                "label": "//:hello_world",
+                "build_file": "$ROOT$BUILD",
+                "target_kind": "bin"
+            }
+        }
+    ],
+    "runnables": [
+        {
+            "kind": "run",
+            "program": "bazel",
+            "args": ["run", "{label}"],
+            "cwd": "$ROOT$"
+        },
+        {
+            "kind": "flycheck",
+            "program": "$ROOT$custom-flychecker.sh",
+            "args": ["{label}"],
+            "cwd": "$ROOT$"
+        },
+        {
+            "kind": "we-ignore-unknown-runnable-kinds-for-forwards-compatibility",
+            "program": "abc",
+            "args": ["{label}"],
+            "cwd": "$ROOT$"
+        }
+    ]
+}
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
index 82f04aa..ad1cca0 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -91,6 +91,7 @@ pub fn run(self, verbosity: Verbosity) -> anyhow::Result<()> {
                 }
             },
             prefill_caches: false,
+            num_worker_threads: 1,
             proc_macro_processes: 1,
         };
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs
index 575c77f..efbaad3 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs
@@ -41,6 +41,7 @@ fn run_(self) -> anyhow::Result<()> {
             load_out_dirs_from_check: !self.disable_build_scripts,
             with_proc_macro_server,
             prefill_caches: false,
+            num_worker_threads: 1,
             proc_macro_processes: 1,
         };
         let (db, _vfs, _proc_macro) =
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
index d68f7ab..0384993 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
@@ -191,6 +191,9 @@
 
             /// Exclude code from vendored libraries from the resulting index.
             optional --exclude-vendored-libraries
+
+            /// The number of worker threads for cache priming. Defaults to the number of physical cores.
+            optional --num-threads num_threads: usize
         }
     }
 }
@@ -338,6 +341,7 @@ pub struct Scip {
     pub output: Option<PathBuf>,
     pub config_path: Option<PathBuf>,
     pub exclude_vendored_libraries: bool,
+    pub num_threads: Option<usize>,
 }
 
 impl RustAnalyzer {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs
index e5e238d..3950a58 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs
@@ -293,6 +293,7 @@ pub fn run(
             load_out_dirs_from_check: true,
             with_proc_macro_server: ProcMacroServerChoice::Sysroot,
             prefill_caches: false,
+            num_worker_threads: 1,
             proc_macro_processes: 1,
         };
         let path = AbsPathBuf::assert_utf8(env::current_dir()?.join(self.path));
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/prime_caches.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/prime_caches.rs
index d5da679..beedcfa 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/prime_caches.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/prime_caches.rs
@@ -38,6 +38,7 @@ pub fn run(self) -> anyhow::Result<()> {
             // we want to ensure that this command, not `load_workspace_at`,
             // is responsible for that work.
             prefill_caches: false,
+            num_worker_threads: 1,
             proc_macro_processes: config.proc_macro_num_processes(),
         };
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs
index d4a56d7..e8c88ca 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs
@@ -23,6 +23,7 @@ pub fn run(self) -> Result<()> {
             load_out_dirs_from_check: true,
             with_proc_macro_server: ProcMacroServerChoice::Sysroot,
             prefill_caches: false,
+            num_worker_threads: 1,
             proc_macro_processes: 1,
         };
         let (ref db, _vfs, _proc_macro) =
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
index e8c6c5f..49f2835 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
@@ -103,6 +103,7 @@ fn new() -> Result<Self> {
             load_out_dirs_from_check: false,
             with_proc_macro_server: ProcMacroServerChoice::Sysroot,
             prefill_caches: false,
+            num_worker_threads: 1,
             proc_macro_processes: 1,
         };
         let (db, _vfs, _proc_macro) =
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
index ed04766..ef6d439 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
@@ -52,6 +52,7 @@ pub fn run(self) -> anyhow::Result<()> {
             load_out_dirs_from_check: true,
             with_proc_macro_server: ProcMacroServerChoice::Sysroot,
             prefill_caches: true,
+            num_worker_threads: self.num_threads.unwrap_or_else(num_cpus::get_physical),
             proc_macro_processes: config.proc_macro_num_processes(),
         };
         let cargo_config = config.cargo(None);
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs
index 6bc0792..7b00aeb 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs
@@ -20,6 +20,7 @@ pub fn run(self) -> anyhow::Result<()> {
             load_out_dirs_from_check: true,
             with_proc_macro_server: ProcMacroServerChoice::Sysroot,
             prefill_caches: false,
+            num_worker_threads: 1,
             proc_macro_processes: 1,
         };
         let (ref db, vfs, _proc_macro) = load_workspace_at(
@@ -57,6 +58,7 @@ pub fn run(self) -> anyhow::Result<()> {
             load_out_dirs_from_check: true,
             with_proc_macro_server: ProcMacroServerChoice::Sysroot,
             prefill_caches: false,
+            num_worker_threads: 1,
             proc_macro_processes: 1,
         };
         let (ref db, _vfs, _proc_macro) = load_workspace_at(
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs
index 49c6fcb..2d9b870 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs
@@ -44,6 +44,7 @@ fn run_(self) -> anyhow::Result<()> {
             load_out_dirs_from_check: !self.disable_build_scripts,
             with_proc_macro_server,
             prefill_caches: false,
+            num_worker_threads: 1,
             proc_macro_processes: config.proc_macro_num_processes(),
         };
         let (db, vfs, _proc_macro) =
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index 0dda7f3..2ccd85f 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -948,18 +948,18 @@ pub enum MaxSubstitutionLength {
         /// Override the command used for bench runnables.
         /// The first element of the array should be the program to execute (for example, `cargo`).
         ///
-        /// Use the placeholders `${package}`, `${target_arg}`, `${target}`, `${test_name}` to dynamically
+        /// Use the placeholders `${package}`, `${target_arg}`, `${target}`, `${executable_args}` to dynamically
         /// replace the package name, target option (such as `--bin` or `--example`), the target name and
-        /// the test name (name of test function or test mod path).
+        /// the arguments passed to test binary args (includes `rust-analyzer.runnables.extraTestBinaryArgs`).
         runnables_bench_overrideCommand: Option<Vec<String>> = None,
         /// Command to be executed instead of 'cargo' for runnables.
         runnables_command: Option<String> = None,
         /// Override the command used for bench runnables.
         /// The first element of the array should be the program to execute (for example, `cargo`).
         ///
-        /// Use the placeholders `${package}`, `${target_arg}`, `${target}`, `${test_name}` to dynamically
+        /// Use the placeholders `${package}`, `${target_arg}`, `${target}`, `${executable_args}` to dynamically
         /// replace the package name, target option (such as `--bin` or `--example`), the target name and
-        /// the test name (name of test function or test mod path).
+        /// the arguments passed to test binary args (includes `rust-analyzer.runnables.extraTestBinaryArgs`).
         runnables_doctest_overrideCommand: Option<Vec<String>> = None,
         /// Additional arguments to be passed to cargo for runnables such as
         /// tests or binaries. For example, it may be `--release`.
@@ -977,9 +977,9 @@ pub enum MaxSubstitutionLength {
         /// Override the command used for test runnables.
         /// The first element of the array should be the program to execute (for example, `cargo`).
         ///
-        /// Use the placeholders `${package}`, `${target_arg}`, `${target}`, `${test_name}` to dynamically
+        /// Use the placeholders `${package}`, `${target_arg}`, `${target}`, `${executable_args}` to dynamically
         /// replace the package name, target option (such as `--bin` or `--example`), the target name and
-        /// the test name (name of test function or test mod path).
+        /// the arguments passed to test binary args (includes `rust-analyzer.runnables.extraTestBinaryArgs`).
         runnables_test_overrideCommand: Option<Vec<String>> = None,
 
         /// Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
index d16ca2f..6a74b8a 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
@@ -53,6 +53,7 @@ fn integrated_highlighting_benchmark() {
         load_out_dirs_from_check: true,
         with_proc_macro_server: ProcMacroServerChoice::Sysroot,
         prefill_caches: false,
+        num_worker_threads: 1,
         proc_macro_processes: 1,
     };
 
@@ -122,6 +123,7 @@ fn integrated_completion_benchmark() {
         load_out_dirs_from_check: true,
         with_proc_macro_server: ProcMacroServerChoice::Sysroot,
         prefill_caches: true,
+        num_worker_threads: 1,
         proc_macro_processes: 1,
     };
 
@@ -324,6 +326,7 @@ fn integrated_diagnostics_benchmark() {
         load_out_dirs_from_check: true,
         with_proc_macro_server: ProcMacroServerChoice::Sysroot,
         prefill_caches: true,
+        num_worker_threads: 1,
         proc_macro_processes: 1,
     };
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
index 64decc9..83edbc7 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
@@ -303,6 +303,15 @@ fn next_event(
         .map(Some)
     }
 
+    fn trigger_garbage_collection(&mut self) {
+        if cfg!(test) {
+            // Slow tests run the main loop in multiple threads, but GC isn't thread safe.
+            return;
+        }
+
+        self.analysis_host.trigger_garbage_collection();
+    }
+
     fn handle_event(&mut self, event: Event) {
         let loop_start = Instant::now();
         let _p = tracing::info_span!("GlobalState::handle_event", event = %event).entered();
@@ -383,7 +392,7 @@ fn handle_event(&mut self, event: Event) {
                             ));
                         }
                         PrimeCachesProgress::End { cancelled } => {
-                            self.analysis_host.trigger_garbage_collection();
+                            self.trigger_garbage_collection();
                             self.prime_caches_queue.op_completed(());
                             if cancelled {
                                 self.prime_caches_queue
@@ -542,7 +551,7 @@ fn handle_event(&mut self, event: Event) {
                 && self.fmt_pool.handle.is_empty()
                 && current_revision != self.last_gc_revision
             {
-                self.analysis_host.trigger_garbage_collection();
+                self.trigger_garbage_collection();
                 self.last_gc_revision = current_revision;
             }
         }
@@ -1178,6 +1187,8 @@ fn handle_flycheck_msg(&mut self, message: FlycheckMessage, cargo_finished: &mut
             } => self.diagnostics.clear_check_older_than_for_package(id, package_id, generation),
             FlycheckMessage::Progress { id, progress } => {
                 let format_with_id = |user_facing_command: String| {
+                    // When we're running multiple flychecks, we have to include a disambiguator in
+                    // the title, or the editor complains. Note that this is a user-facing string.
                     if self.flycheck.len() == 1 {
                         user_facing_command
                     } else {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs
index b8d9acc..8be061c 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs
@@ -6,7 +6,7 @@
 use cfg::{CfgAtom, CfgExpr};
 use hir::sym;
 use ide::{Cancellable, Crate, FileId, RunnableKind, TestId};
-use project_model::project_json::Runnable;
+use project_model::project_json::{self, Runnable};
 use project_model::{CargoFeatures, ManifestPath, TargetKind};
 use rustc_hash::FxHashSet;
 use triomphe::Arc;
@@ -72,48 +72,51 @@ pub(crate) struct ProjectJsonTargetSpec {
 }
 
 impl ProjectJsonTargetSpec {
+    fn find_replace_runnable(
+        &self,
+        kind: project_json::RunnableKind,
+        replacer: &dyn Fn(&Self, &str) -> String,
+    ) -> Option<Runnable> {
+        for runnable in &self.shell_runnables {
+            if runnable.kind == kind {
+                let mut runnable = runnable.clone();
+
+                let replaced_args: Vec<_> =
+                    runnable.args.iter().map(|arg| replacer(self, arg)).collect();
+                runnable.args = replaced_args;
+
+                return Some(runnable);
+            }
+        }
+
+        None
+    }
+
     pub(crate) fn runnable_args(&self, kind: &RunnableKind) -> Option<Runnable> {
         match kind {
-            RunnableKind::Bin => {
-                for runnable in &self.shell_runnables {
-                    if matches!(runnable.kind, project_model::project_json::RunnableKind::Run) {
-                        let mut runnable = runnable.clone();
-
-                        let replaced_args: Vec<_> = runnable
-                            .args
-                            .iter()
-                            .map(|arg| arg.replace("{label}", &self.label))
-                            .collect();
-                        runnable.args = replaced_args;
-
-                        return Some(runnable);
-                    }
-                }
-
-                None
-            }
+            RunnableKind::Bin => self
+                .find_replace_runnable(project_json::RunnableKind::Run, &|this, arg| {
+                    arg.replace("{label}", &this.label)
+                }),
             RunnableKind::Test { test_id, .. } => {
-                for runnable in &self.shell_runnables {
-                    if matches!(runnable.kind, project_model::project_json::RunnableKind::TestOne) {
-                        let mut runnable = runnable.clone();
-
-                        let replaced_args: Vec<_> = runnable
-                            .args
-                            .iter()
-                            .map(|arg| arg.replace("{test_id}", &test_id.to_string()))
-                            .map(|arg| arg.replace("{label}", &self.label))
-                            .collect();
-                        runnable.args = replaced_args;
-
-                        return Some(runnable);
-                    }
-                }
-
-                None
+                self.find_replace_runnable(project_json::RunnableKind::Run, &|this, arg| {
+                    arg.replace("{label}", &this.label).replace("{test_id}", &test_id.to_string())
+                })
             }
-            RunnableKind::TestMod { .. } => None,
-            RunnableKind::Bench { .. } => None,
-            RunnableKind::DocTest { .. } => None,
+            RunnableKind::TestMod { path } => self
+                .find_replace_runnable(project_json::RunnableKind::TestMod, &|this, arg| {
+                    arg.replace("{label}", &this.label).replace("{test_pattern}", path)
+                }),
+            RunnableKind::Bench { test_id } => {
+                self.find_replace_runnable(project_json::RunnableKind::BenchOne, &|this, arg| {
+                    arg.replace("{label}", &this.label).replace("{bench_id}", &test_id.to_string())
+                })
+            }
+            RunnableKind::DocTest { test_id } => {
+                self.find_replace_runnable(project_json::RunnableKind::DocTestOne, &|this, arg| {
+                    arg.replace("{label}", &this.label).replace("{test_id}", &test_id.to_string())
+                })
+            }
         }
     }
 }
@@ -129,38 +132,21 @@ pub(crate) fn runnable_args(
         let extra_test_binary_args = config.extra_test_binary_args;
 
         let mut cargo_args = Vec::new();
-        let mut executable_args = Vec::new();
+        let executable_args = Self::executable_args_for(kind, extra_test_binary_args);
 
         match kind {
-            RunnableKind::Test { test_id, attr } => {
+            RunnableKind::Test { .. } => {
                 cargo_args.push(config.test_command);
-                executable_args.push(test_id.to_string());
-                if let TestId::Path(_) = test_id {
-                    executable_args.push("--exact".to_owned());
-                }
-                executable_args.extend(extra_test_binary_args);
-                if attr.ignore {
-                    executable_args.push("--ignored".to_owned());
-                }
             }
-            RunnableKind::TestMod { path } => {
+            RunnableKind::TestMod { .. } => {
                 cargo_args.push(config.test_command);
-                executable_args.push(path.clone());
-                executable_args.extend(extra_test_binary_args);
             }
-            RunnableKind::Bench { test_id } => {
+            RunnableKind::Bench { .. } => {
                 cargo_args.push(config.bench_command);
-                executable_args.push(test_id.to_string());
-                if let TestId::Path(_) = test_id {
-                    executable_args.push("--exact".to_owned());
-                }
-                executable_args.extend(extra_test_binary_args);
             }
-            RunnableKind::DocTest { test_id } => {
+            RunnableKind::DocTest { .. } => {
                 cargo_args.push("test".to_owned());
                 cargo_args.push("--doc".to_owned());
-                executable_args.push(test_id.to_string());
-                executable_args.extend(extra_test_binary_args);
             }
             RunnableKind::Bin => {
                 let subcommand = match spec {
@@ -253,16 +239,70 @@ pub(crate) fn override_command(
             TargetKind::BuildScript | TargetKind::Other => "",
         };
 
+        let target = |kind, target| match kind {
+            TargetKind::Bin | TargetKind::Test | TargetKind::Bench | TargetKind::Example => target,
+            _ => "",
+        };
+
         let replace_placeholders = |arg: String| match &spec {
             Some(spec) => arg
                 .replace("${package}", &spec.package)
                 .replace("${target_arg}", target_arg(spec.target_kind))
-                .replace("${target}", &spec.target)
+                .replace("${target}", target(spec.target_kind, &spec.target))
                 .replace("${test_name}", &test_name),
             _ => arg,
         };
 
-        args.map(|args| args.into_iter().map(replace_placeholders).collect())
+        let extra_test_binary_args = config.extra_test_binary_args;
+        let executable_args = Self::executable_args_for(kind, extra_test_binary_args);
+
+        args.map(|mut args| {
+            let exec_args_idx = args.iter().position(|a| a == "${executable_args}");
+
+            if let Some(idx) = exec_args_idx {
+                args.splice(idx..idx + 1, executable_args);
+            }
+
+            args.into_iter().map(replace_placeholders).filter(|a| !a.trim().is_empty()).collect()
+        })
+    }
+
+    fn executable_args_for(
+        kind: &RunnableKind,
+        extra_test_binary_args: impl IntoIterator<Item = String>,
+    ) -> Vec<String> {
+        let mut executable_args = Vec::new();
+
+        match kind {
+            RunnableKind::Test { test_id, attr } => {
+                executable_args.push(test_id.to_string());
+                if let TestId::Path(_) = test_id {
+                    executable_args.push("--exact".to_owned());
+                }
+                executable_args.extend(extra_test_binary_args);
+                if attr.ignore {
+                    executable_args.push("--ignored".to_owned());
+                }
+            }
+            RunnableKind::TestMod { path } => {
+                executable_args.push(path.clone());
+                executable_args.extend(extra_test_binary_args);
+            }
+            RunnableKind::Bench { test_id } => {
+                executable_args.push(test_id.to_string());
+                if let TestId::Path(_) = test_id {
+                    executable_args.push("--exact".to_owned());
+                }
+                executable_args.extend(extra_test_binary_args);
+            }
+            RunnableKind::DocTest { test_id } => {
+                executable_args.push(test_id.to_string());
+                executable_args.extend(extra_test_binary_args);
+            }
+            RunnableKind::Bin => {}
+        }
+
+        executable_args
     }
 
     pub(crate) fn push_to(self, buf: &mut Vec<String>, kind: &RunnableKind) {
diff --git a/src/tools/rust-analyzer/crates/stdx/src/lib.rs b/src/tools/rust-analyzer/crates/stdx/src/lib.rs
index 7ab26b1..a1af4cc 100644
--- a/src/tools/rust-analyzer/crates/stdx/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/stdx/src/lib.rs
@@ -221,12 +221,7 @@ pub fn trim_indent(mut text: &str) -> String {
     if text.starts_with('\n') {
         text = &text[1..];
     }
-    let indent = text
-        .lines()
-        .filter(|it| !it.trim().is_empty())
-        .map(|it| it.len() - it.trim_start().len())
-        .min()
-        .unwrap_or(0);
+    let indent = indent_of(text);
     text.split_inclusive('\n')
         .map(
             |line| {
@@ -236,6 +231,25 @@ pub fn trim_indent(mut text: &str) -> String {
         .collect()
 }
 
+#[must_use]
+fn indent_of(text: &str) -> usize {
+    text.lines()
+        .filter(|it| !it.trim().is_empty())
+        .map(|it| it.len() - it.trim_start().len())
+        .min()
+        .unwrap_or(0)
+}
+
+#[must_use]
+pub fn dedent_by(spaces: usize, text: &str) -> String {
+    text.split_inclusive('\n')
+        .map(|line| {
+            let trimmed = line.trim_start_matches(' ');
+            if line.len() - trimmed.len() <= spaces { trimmed } else { &line[spaces..] }
+        })
+        .collect()
+}
+
 pub fn equal_range_by<T, F>(slice: &[T], mut key: F) -> ops::Range<usize>
 where
     F: FnMut(&T) -> Ordering,
@@ -367,6 +381,37 @@ fn main() {
     }
 
     #[test]
+    fn test_dedent() {
+        assert_eq!(dedent_by(0, ""), "");
+        assert_eq!(dedent_by(1, ""), "");
+        assert_eq!(dedent_by(2, ""), "");
+        assert_eq!(dedent_by(0, "foo"), "foo");
+        assert_eq!(dedent_by(2, "foo"), "foo");
+        assert_eq!(dedent_by(2, "  foo"), "foo");
+        assert_eq!(dedent_by(2, "    foo"), "  foo");
+        assert_eq!(dedent_by(2, "    foo\nbar"), "  foo\nbar");
+        assert_eq!(dedent_by(2, "foo\n    bar"), "foo\n  bar");
+        assert_eq!(dedent_by(2, "foo\n\n    bar"), "foo\n\n  bar");
+        assert_eq!(dedent_by(2, "foo\n.\n    bar"), "foo\n.\n  bar");
+        assert_eq!(dedent_by(2, "foo\n .\n    bar"), "foo\n.\n  bar");
+        assert_eq!(dedent_by(2, "foo\n   .\n    bar"), "foo\n .\n  bar");
+    }
+
+    #[test]
+    fn test_indent_of() {
+        assert_eq!(indent_of(""), 0);
+        assert_eq!(indent_of(" "), 0);
+        assert_eq!(indent_of(" x"), 1);
+        assert_eq!(indent_of(" x\n"), 1);
+        assert_eq!(indent_of(" x\ny"), 0);
+        assert_eq!(indent_of(" x\n y"), 1);
+        assert_eq!(indent_of(" x\n  y"), 1);
+        assert_eq!(indent_of("  x\n  y"), 2);
+        assert_eq!(indent_of("  x\n  y\n"), 2);
+        assert_eq!(indent_of("  x\n\n  y\n"), 2);
+    }
+
+    #[test]
     fn test_replace() {
         #[track_caller]
         fn test_replace(src: &str, from: char, to: &str, expected: &str) {
diff --git a/src/tools/rust-analyzer/crates/syntax/src/algo.rs b/src/tools/rust-analyzer/crates/syntax/src/algo.rs
index 3ab9c90..c679921 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/algo.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/algo.rs
@@ -132,3 +132,19 @@ pub fn previous_non_trivia_token(e: impl Into<SyntaxElement>) -> Option<SyntaxTo
     }
     None
 }
+
+pub fn next_non_trivia_token(e: impl Into<SyntaxElement>) -> Option<SyntaxToken> {
+    let mut token = match e.into() {
+        SyntaxElement::Node(n) => n.last_token()?,
+        SyntaxElement::Token(t) => t,
+    }
+    .next_token();
+    while let Some(inner) = token {
+        if !inner.kind().is_trivia() {
+            return Some(inner);
+        } else {
+            token = inner.next_token();
+        }
+    }
+    None
+}
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/edit.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/edit.rs
index 9b30642..194d069 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/edit.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/edit.rs
@@ -43,6 +43,12 @@ fn add(self, rhs: u8) -> IndentLevel {
     }
 }
 
+impl ops::AddAssign<u8> for IndentLevel {
+    fn add_assign(&mut self, rhs: u8) {
+        self.0 += rhs;
+    }
+}
+
 impl IndentLevel {
     pub fn single() -> IndentLevel {
         IndentLevel(0)
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs
index 50fe565..55c80ed 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs
@@ -5,7 +5,7 @@
     AstNode, NodeOrToken, SyntaxKind, SyntaxNode, SyntaxToken,
     ast::{
         self, HasArgList, HasAttrs, HasGenericArgs, HasGenericParams, HasLoopBody, HasName,
-        HasTypeBounds, HasVisibility, Param, RangeItem, make,
+        HasTypeBounds, HasVisibility, Lifetime, Param, RangeItem, make,
     },
     syntax_editor::SyntaxMappingBuilder,
 };
@@ -21,6 +21,14 @@ pub fn name_ref(&self, name: &str) -> ast::NameRef {
         make::name_ref(name).clone_for_update()
     }
 
+    pub fn name_ref_self_ty(&self) -> ast::NameRef {
+        make::name_ref_self_ty().clone_for_update()
+    }
+
+    pub fn expr_todo(&self) -> ast::Expr {
+        make::ext::expr_todo().clone_for_update()
+    }
+
     pub fn lifetime(&self, text: &str) -> ast::Lifetime {
         make::lifetime(text).clone_for_update()
     }
@@ -96,24 +104,47 @@ pub fn struct_(
         generic_param_list: Option<ast::GenericParamList>,
         field_list: ast::FieldList,
     ) -> ast::Struct {
-        make::struct_(visibility, strukt_name, generic_param_list, field_list).clone_for_update()
-    }
+        let ast = make::struct_(
+            visibility.clone(),
+            strukt_name.clone(),
+            generic_param_list.clone(),
+            field_list.clone(),
+        )
+        .clone_for_update();
 
-    pub fn enum_(
-        &self,
-        attrs: impl IntoIterator<Item = ast::Attr>,
-        visibility: Option<ast::Visibility>,
-        enum_name: ast::Name,
-        generic_param_list: Option<ast::GenericParamList>,
-        where_clause: Option<ast::WhereClause>,
-        variant_list: ast::VariantList,
-    ) -> ast::Enum {
-        make::enum_(attrs, visibility, enum_name, generic_param_list, where_clause, variant_list)
-            .clone_for_update()
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            if let Some(visibility) = visibility {
+                builder.map_node(
+                    visibility.syntax().clone(),
+                    ast.visibility().unwrap().syntax().clone(),
+                );
+            }
+            builder.map_node(strukt_name.syntax().clone(), ast.name().unwrap().syntax().clone());
+            if let Some(generic_param_list) = generic_param_list {
+                builder.map_node(
+                    generic_param_list.syntax().clone(),
+                    ast.generic_param_list().unwrap().syntax().clone(),
+                );
+            }
+            builder
+                .map_node(field_list.syntax().clone(), ast.field_list().unwrap().syntax().clone());
+            builder.finish(&mut mapping);
+        }
+
+        ast
     }
 
     pub fn unnamed_param(&self, ty: ast::Type) -> ast::Param {
-        make::unnamed_param(ty).clone_for_update()
+        let ast = make::unnamed_param(ty.clone()).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_node(ty.syntax().clone(), ast.ty().unwrap().syntax().clone());
+            builder.finish(&mut mapping);
+        }
+
+        ast
     }
 
     pub fn ty_fn_ptr<I: Iterator<Item = Param>>(
@@ -123,7 +154,27 @@ pub fn ty_fn_ptr<I: Iterator<Item = Param>>(
         params: I,
         ret_type: Option<ast::RetType>,
     ) -> ast::FnPtrType {
-        make::ty_fn_ptr(is_unsafe, abi, params, ret_type).clone_for_update()
+        let (params, params_input) = iterator_input(params);
+        let ast = make::ty_fn_ptr(is_unsafe, abi.clone(), params.into_iter(), ret_type.clone())
+            .clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            if let Some(abi) = abi {
+                builder.map_node(abi.syntax().clone(), ast.abi().unwrap().syntax().clone());
+            }
+            builder.map_children(
+                params_input,
+                ast.param_list().unwrap().params().map(|p| p.syntax().clone()),
+            );
+            if let Some(ret_type) = ret_type {
+                builder
+                    .map_node(ret_type.syntax().clone(), ast.ret_type().unwrap().syntax().clone());
+            }
+            builder.finish(&mut mapping);
+        }
+
+        ast
     }
 
     pub fn where_pred(
@@ -131,18 +182,61 @@ pub fn where_pred(
         path: Either<ast::Lifetime, ast::Type>,
         bounds: impl IntoIterator<Item = ast::TypeBound>,
     ) -> ast::WherePred {
-        make::where_pred(path, bounds).clone_for_update()
+        let (bounds, bounds_input) = iterator_input(bounds);
+        let ast = make::where_pred(path.clone(), bounds).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            match &path {
+                Either::Left(lifetime) => {
+                    builder.map_node(
+                        lifetime.syntax().clone(),
+                        ast.lifetime().unwrap().syntax().clone(),
+                    );
+                }
+                Either::Right(ty) => {
+                    builder.map_node(ty.syntax().clone(), ast.ty().unwrap().syntax().clone());
+                }
+            }
+            if let Some(type_bound_list) = ast.type_bound_list() {
+                builder.map_children(
+                    bounds_input,
+                    type_bound_list.bounds().map(|b| b.syntax().clone()),
+                );
+            }
+            builder.finish(&mut mapping);
+        }
+
+        ast
     }
 
     pub fn where_clause(
         &self,
         predicates: impl IntoIterator<Item = ast::WherePred>,
     ) -> ast::WhereClause {
-        make::where_clause(predicates).clone_for_update()
+        let (predicates, input) = iterator_input(predicates);
+        let ast = make::where_clause(predicates).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_children(input, ast.predicates().map(|p| p.syntax().clone()));
+            builder.finish(&mut mapping);
+        }
+
+        ast
     }
 
     pub fn impl_trait_type(&self, bounds: ast::TypeBoundList) -> ast::ImplTraitType {
-        make::impl_trait_type(bounds).clone_for_update()
+        let ast = make::impl_trait_type(bounds.clone()).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder
+                .map_node(bounds.syntax().clone(), ast.type_bound_list().unwrap().syntax().clone());
+            builder.finish(&mut mapping);
+        }
+
+        ast
     }
 
     pub fn expr_field(&self, receiver: ast::Expr, field: &str) -> ast::FieldExpr {
@@ -340,15 +434,53 @@ pub fn generic_ty_path_segment(
         name_ref: ast::NameRef,
         generic_args: impl IntoIterator<Item = ast::GenericArg>,
     ) -> ast::PathSegment {
-        make::generic_ty_path_segment(name_ref, generic_args).clone_for_update()
+        let (generic_args, input) = iterator_input(generic_args);
+        let ast = make::generic_ty_path_segment(name_ref.clone(), generic_args).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_node(name_ref.syntax().clone(), ast.name_ref().unwrap().syntax().clone());
+            builder.map_children(
+                input,
+                ast.generic_arg_list().unwrap().generic_args().map(|a| a.syntax().clone()),
+            );
+            builder.finish(&mut mapping);
+        }
+
+        ast
     }
 
     pub fn tail_only_block_expr(&self, tail_expr: ast::Expr) -> ast::BlockExpr {
-        make::tail_only_block_expr(tail_expr)
+        let ast = make::tail_only_block_expr(tail_expr.clone()).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let stmt_list = ast.stmt_list().unwrap();
+            let mut builder = SyntaxMappingBuilder::new(stmt_list.syntax().clone());
+            builder.map_node(
+                tail_expr.syntax().clone(),
+                stmt_list.tail_expr().unwrap().syntax().clone(),
+            );
+            builder.finish(&mut mapping);
+        }
+
+        ast
     }
 
     pub fn expr_bin_op(&self, lhs: ast::Expr, op: ast::BinaryOp, rhs: ast::Expr) -> ast::Expr {
-        make::expr_bin_op(lhs, op, rhs)
+        let ast::Expr::BinExpr(ast) =
+            make::expr_bin_op(lhs.clone(), op, rhs.clone()).clone_for_update()
+        else {
+            unreachable!()
+        };
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_node(lhs.syntax().clone(), ast.lhs().unwrap().syntax().clone());
+            builder.map_node(rhs.syntax().clone(), ast.rhs().unwrap().syntax().clone());
+            builder.finish(&mut mapping);
+        }
+
+        ast.into()
     }
 
     pub fn ty_placeholder(&self) -> ast::Type {
@@ -385,7 +517,23 @@ pub fn use_(
         visibility: Option<ast::Visibility>,
         use_tree: ast::UseTree,
     ) -> ast::Use {
-        make::use_(attrs, visibility, use_tree).clone_for_update()
+        let (attrs, attrs_input) = iterator_input(attrs);
+        let ast = make::use_(attrs, visibility.clone(), use_tree.clone()).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_children(attrs_input, ast.attrs().map(|attr| attr.syntax().clone()));
+            if let Some(visibility) = visibility {
+                builder.map_node(
+                    visibility.syntax().clone(),
+                    ast.visibility().unwrap().syntax().clone(),
+                );
+            }
+            builder.map_node(use_tree.syntax().clone(), ast.use_tree().unwrap().syntax().clone());
+            builder.finish(&mut mapping);
+        }
+
+        ast
     }
 
     pub fn use_tree(
@@ -395,7 +543,25 @@ pub fn use_tree(
         alias: Option<ast::Rename>,
         add_star: bool,
     ) -> ast::UseTree {
-        make::use_tree(path, use_tree_list, alias, add_star).clone_for_update()
+        let ast = make::use_tree(path.clone(), use_tree_list.clone(), alias.clone(), add_star)
+            .clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_node(path.syntax().clone(), ast.path().unwrap().syntax().clone());
+            if let Some(use_tree_list) = use_tree_list {
+                builder.map_node(
+                    use_tree_list.syntax().clone(),
+                    ast.use_tree_list().unwrap().syntax().clone(),
+                );
+            }
+            if let Some(alias) = alias {
+                builder.map_node(alias.syntax().clone(), ast.rename().unwrap().syntax().clone());
+            }
+            builder.finish(&mut mapping);
+        }
+
+        ast
     }
 
     pub fn path_unqualified(&self, segment: ast::PathSegment) -> ast::Path {
@@ -896,10 +1062,6 @@ pub fn expr_underscore(&self) -> ast::UnderscoreExpr {
             unreachable!()
         };
 
-        if let Some(mut mapping) = self.mappings() {
-            SyntaxMappingBuilder::new(ast.syntax().clone()).finish(&mut mapping);
-        }
-
         ast
     }
 
@@ -1765,6 +1927,65 @@ pub fn ty_ref(&self, ty: ast::Type, is_mut: bool) -> ast::Type {
         }
         ast
     }
+
+    pub fn field_from_idents<'a>(
+        &self,
+        parts: impl std::iter::IntoIterator<Item = &'a str>,
+    ) -> Option<ast::Expr> {
+        make::ext::field_from_idents(parts)
+    }
+
+    pub fn expr_await(&self, expr: ast::Expr) -> ast::AwaitExpr {
+        let ast::Expr::AwaitExpr(ast) = make::expr_await(expr.clone()).clone_for_update() else {
+            unreachable!()
+        };
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone());
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn expr_break(&self, label: Option<Lifetime>, expr: Option<ast::Expr>) -> ast::BreakExpr {
+        let ast::Expr::BreakExpr(ast) =
+            make::expr_break(label.clone(), expr.clone()).clone_for_update()
+        else {
+            unreachable!()
+        };
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            if let Some(label) = label {
+                builder.map_node(label.syntax().clone(), ast.lifetime().unwrap().syntax().clone());
+            }
+            if let Some(expr) = expr {
+                builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone());
+            }
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn expr_continue(&self, label: Option<Lifetime>) -> ast::ContinueExpr {
+        let ast::Expr::ContinueExpr(ast) = make::expr_continue(label.clone()).clone_for_update()
+        else {
+            unreachable!()
+        };
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            if let Some(label) = label {
+                builder.map_node(label.syntax().clone(), ast.lifetime().unwrap().syntax().clone());
+            }
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
 }
 
 // `ext` constructors
diff --git a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md
index 8460c2c..35fba5a 100644
--- a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md
+++ b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md
@@ -1380,9 +1380,9 @@
 Override the command used for bench runnables.
 The first element of the array should be the program to execute (for example, `cargo`).
 
-Use the placeholders `${package}`, `${target_arg}`, `${target}`, `${test_name}` to dynamically
+Use the placeholders `${package}`, `${target_arg}`, `${target}`, `${executable_args}` to dynamically
 replace the package name, target option (such as `--bin` or `--example`), the target name and
-the test name (name of test function or test mod path).
+the arguments passed to test binary args (includes `rust-analyzer.runnables.extraTestBinaryArgs`).
 
 
 ## rust-analyzer.runnables.command {#runnables.command}
@@ -1399,9 +1399,9 @@
 Override the command used for bench runnables.
 The first element of the array should be the program to execute (for example, `cargo`).
 
-Use the placeholders `${package}`, `${target_arg}`, `${target}`, `${test_name}` to dynamically
+Use the placeholders `${package}`, `${target_arg}`, `${target}`, `${executable_args}` to dynamically
 replace the package name, target option (such as `--bin` or `--example`), the target name and
-the test name (name of test function or test mod path).
+the arguments passed to test binary args (includes `rust-analyzer.runnables.extraTestBinaryArgs`).
 
 
 ## rust-analyzer.runnables.extraArgs {#runnables.extraArgs}
@@ -1444,9 +1444,9 @@
 Override the command used for test runnables.
 The first element of the array should be the program to execute (for example, `cargo`).
 
-Use the placeholders `${package}`, `${target_arg}`, `${target}`, `${test_name}` to dynamically
+Use the placeholders `${package}`, `${target_arg}`, `${target}`, `${executable_args}` to dynamically
 replace the package name, target option (such as `--bin` or `--example`), the target name and
-the test name (name of test function or test mod path).
+the arguments passed to test binary args (includes `rust-analyzer.runnables.extraTestBinaryArgs`).
 
 
 ## rust-analyzer.rustc.source {#rustc.source}
diff --git a/src/tools/rust-analyzer/editors/code/package-lock.json b/src/tools/rust-analyzer/editors/code/package-lock.json
index be0bdc8..047dbba 100644
--- a/src/tools/rust-analyzer/editors/code/package-lock.json
+++ b/src/tools/rust-analyzer/editors/code/package-lock.json
@@ -3697,9 +3697,9 @@
             }
         },
         "node_modules/flatted": {
-            "version": "3.3.3",
-            "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
-            "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+            "version": "3.4.2",
+            "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
+            "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
             "dev": true,
             "license": "ISC"
         },
@@ -6719,9 +6719,9 @@
             "license": "MIT"
         },
         "node_modules/undici": {
-            "version": "6.21.3",
-            "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz",
-            "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==",
+            "version": "6.24.1",
+            "resolved": "https://registry.npmjs.org/undici/-/undici-6.24.1.tgz",
+            "integrity": "sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==",
             "dev": true,
             "license": "MIT",
             "engines": {
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index fc20597..1dd513c 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -2865,7 +2865,7 @@
                 "title": "Runnables",
                 "properties": {
                     "rust-analyzer.runnables.bench.overrideCommand": {
-                        "markdownDescription": "Override the command used for bench runnables.\nThe first element of the array should be the program to execute (for example, `cargo`).\n\nUse the placeholders `${package}`, `${target_arg}`, `${target}`, `${test_name}` to dynamically\nreplace the package name, target option (such as `--bin` or `--example`), the target name and\nthe test name (name of test function or test mod path).",
+                        "markdownDescription": "Override the command used for bench runnables.\nThe first element of the array should be the program to execute (for example, `cargo`).\n\nUse the placeholders `${package}`, `${target_arg}`, `${target}`, `${executable_args}` to dynamically\nreplace the package name, target option (such as `--bin` or `--example`), the target name and\nthe arguments passed to test binary args (includes `rust-analyzer.runnables.extraTestBinaryArgs`).",
                         "default": null,
                         "type": [
                             "null",
@@ -2894,7 +2894,7 @@
                 "title": "Runnables",
                 "properties": {
                     "rust-analyzer.runnables.doctest.overrideCommand": {
-                        "markdownDescription": "Override the command used for bench runnables.\nThe first element of the array should be the program to execute (for example, `cargo`).\n\nUse the placeholders `${package}`, `${target_arg}`, `${target}`, `${test_name}` to dynamically\nreplace the package name, target option (such as `--bin` or `--example`), the target name and\nthe test name (name of test function or test mod path).",
+                        "markdownDescription": "Override the command used for bench runnables.\nThe first element of the array should be the program to execute (for example, `cargo`).\n\nUse the placeholders `${package}`, `${target_arg}`, `${target}`, `${executable_args}` to dynamically\nreplace the package name, target option (such as `--bin` or `--example`), the target name and\nthe arguments passed to test binary args (includes `rust-analyzer.runnables.extraTestBinaryArgs`).",
                         "default": null,
                         "type": [
                             "null",
@@ -2948,7 +2948,7 @@
                 "title": "Runnables",
                 "properties": {
                     "rust-analyzer.runnables.test.overrideCommand": {
-                        "markdownDescription": "Override the command used for test runnables.\nThe first element of the array should be the program to execute (for example, `cargo`).\n\nUse the placeholders `${package}`, `${target_arg}`, `${target}`, `${test_name}` to dynamically\nreplace the package name, target option (such as `--bin` or `--example`), the target name and\nthe test name (name of test function or test mod path).",
+                        "markdownDescription": "Override the command used for test runnables.\nThe first element of the array should be the program to execute (for example, `cargo`).\n\nUse the placeholders `${package}`, `${target_arg}`, `${target}`, `${executable_args}` to dynamically\nreplace the package name, target option (such as `--bin` or `--example`), the target name and\nthe arguments passed to test binary args (includes `rust-analyzer.runnables.extraTestBinaryArgs`).",
                         "default": null,
                         "type": [
                             "null",
diff --git a/src/tools/rustfmt/src/matches.rs b/src/tools/rustfmt/src/matches.rs
index 4741abb..50c0db8 100644
--- a/src/tools/rustfmt/src/matches.rs
+++ b/src/tools/rustfmt/src/matches.rs
@@ -571,7 +571,7 @@ fn rewrite_match_body(
 // The `if ...` guard on a match arm.
 fn rewrite_guard(
     context: &RewriteContext<'_>,
-    guard: &Option<Box<ast::Expr>>,
+    guard: &Option<Box<ast::Guard>>,
     shape: Shape,
     // The amount of space used up on this line for the pattern in
     // the arm (excludes offset).
@@ -586,7 +586,7 @@ fn rewrite_guard(
             .and_then(|s| s.sub_width_opt(5));
         if !multiline_pattern {
             if let Some(cond_shape) = cond_shape {
-                if let Ok(cond_str) = guard.rewrite_result(context, cond_shape) {
+                if let Ok(cond_str) = guard.cond.rewrite_result(context, cond_shape) {
                     if !cond_str.contains('\n') || pattern_width <= context.config.tab_spaces() {
                         return Ok(format!(" if {cond_str}"));
                     }
@@ -597,9 +597,9 @@ fn rewrite_guard(
         // Not enough space to put the guard after the pattern, try a newline.
         // 3 = `if `, 5 = ` => {`
         let cond_shape = Shape::indented(shape.indent.block_indent(context.config), context.config)
-            .offset_left(3, guard.span)?
-            .sub_width(5, guard.span)?;
-        let cond_str = guard.rewrite_result(context, cond_shape)?;
+            .offset_left(3, guard.span())?
+            .sub_width(5, guard.span())?;
+        let cond_str = guard.cond.rewrite_result(context, cond_shape)?;
         Ok(format!(
             "{}if {}",
             cond_shape.indent.to_string_with_newline(context.config),
diff --git a/src/tools/rustfmt/src/vertical.rs b/src/tools/rustfmt/src/vertical.rs
index 21e34d2..fd9a4a7 100644
--- a/src/tools/rustfmt/src/vertical.rs
+++ b/src/tools/rustfmt/src/vertical.rs
@@ -198,7 +198,7 @@ fn struct_field_prefix_max_min_width<T: AlignedItem>(
                 .rewrite_prefix(context, shape)
                 .map(|field_str| trimmed_last_line_width(&field_str))
         })
-        .fold_ok((0, ::std::usize::MAX), |(max_len, min_len), len| {
+        .fold_ok((0, usize::MAX), |(max_len, min_len), len| {
             (cmp::max(max_len, len), cmp::min(min_len, len))
         })
         .unwrap_or((0, 0))
diff --git a/src/tools/unicode-table-generator/src/case_mapping.rs b/src/tools/unicode-table-generator/src/case_mapping.rs
index 6345cb8..b7b3855 100644
--- a/src/tools/unicode-table-generator/src/case_mapping.rs
+++ b/src/tools/unicode-table-generator/src/case_mapping.rs
@@ -48,7 +48,7 @@
 use crate::fmt_helpers::Hex;
 use crate::{UnicodeData, fmt_list};
 
-pub(crate) fn generate_case_mapping(data: &UnicodeData) -> (String, [(String, usize); 2]) {
+pub(crate) fn generate_case_mapping(data: &UnicodeData) -> (String, [(String, usize); 3]) {
     let mut file = String::new();
 
     file.push_str("\n\n");
@@ -59,7 +59,10 @@
     file.push_str("\n\n");
     let (upper_tables, upper_desc, upper_size) = generate_tables("UPPER", &data.to_upper);
     file.push_str(&upper_tables);
-    (file, [(lower_desc, lower_size), (upper_desc, upper_size)])
+    file.push_str("\n\n");
+    let (title_tables, title_desc, title_size) = generate_tables("TITLE", &data.to_title);
+    file.push_str(&title_tables);
+    (file, [(lower_desc, lower_size), (upper_desc, upper_size), (title_desc, title_size)])
 }
 
 // So far, only planes 0 and 1 (Basic Multilingual Plane and Supplementary
@@ -336,14 +339,10 @@ unsafe fn reconstruct(plane: u16, low: u16) -> char {
     unsafe { char::from_u32_unchecked(((plane as u32) << 16) | (low as u32)) }
 }
 
-fn lookup(input: char, ascii: char, l1_lut: &L1Lut) -> [char; 3] {
-    if input.is_ascii() {
-        return [ascii, '\0', '\0'];
-    }
-
+fn lookup(input: char, l1_lut: &L1Lut) -> Option<[char; 3]> {
     let (input_high, input_low) = deconstruct(input);
     let Some(l2_lut) = l1_lut.l2_luts.get(input_high as usize) else {
-        return [input, '\0', '\0'];
+        return None;
     };
 
     let idx = l2_lut.singles.binary_search_by(|(range, _)| {
@@ -357,6 +356,7 @@ unsafe fn reconstruct(plane: u16, low: u16) -> char {
             Ordering::Equal
         }
     });
+
     if let Ok(idx) = idx {
         // SAFETY: binary search guarantees that the index is in bounds.
         let &(range, output_delta) = unsafe { l2_lut.singles.get_unchecked(idx) };
@@ -365,7 +365,7 @@ unsafe fn reconstruct(plane: u16, low: u16) -> char {
             let output_low = input_low.wrapping_add_signed(output_delta);
             // SAFETY: Table data are guaranteed to be valid Unicode.
             let output = unsafe { reconstruct(input_high, output_low) };
-            return [output, '\0', '\0'];
+            return Some([output, '\0', '\0']);
         }
     };
 
@@ -374,17 +374,36 @@ unsafe fn reconstruct(plane: u16, low: u16) -> char {
         let &(_, output_lows) = unsafe { l2_lut.multis.get_unchecked(idx) };
         // SAFETY: Table data are guaranteed to be valid Unicode.
         let output = output_lows.map(|output_low| unsafe { reconstruct(input_high, output_low) });
-        return output;
+        return Some(output);
     };
 
-    [input, '\0', '\0']
+    None
 }
 
 pub fn to_lower(c: char) -> [char; 3] {
-    lookup(c, c.to_ascii_lowercase(), &LOWERCASE_LUT)
+    // https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%253AChanges_When_Lowercased%253A%5D-%5B%253AASCII%253A%5D&abb=on
+    if c < '\u{C0}' {
+        return [c.to_ascii_lowercase(), '\0', '\0'];
+    }
+
+    lookup(c, &LOWERCASE_LUT).unwrap_or([c, '\0', '\0'])
 }
 
 pub fn to_upper(c: char) -> [char; 3] {
-    lookup(c, c.to_ascii_uppercase(), &UPPERCASE_LUT)
+    // https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%253AChanges_When_Uppercased%253A%5D-%5B%253AASCII%253A%5D&abb=on
+    if c < '\u{B5}' {
+        return [c.to_ascii_uppercase(), '\0', '\0'];
+    }
+
+    lookup(c, &UPPERCASE_LUT).unwrap_or([c, '\0', '\0'])
+}
+
+pub fn to_title(c: char) -> [char; 3] {
+    // https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%253AChanges_When_Titlecased%253A%5D-%5B%253AASCII%253A%5D&abb=on
+    if c < '\u{B5}' {
+        return [c.to_ascii_uppercase(), '\0', '\0'];
+    }
+
+    lookup(c, &TITLECASE_LUT).or_else(|| lookup(c, &UPPERCASE_LUT)).unwrap_or([c, '\0', '\0'])
 }
 ";
diff --git a/src/tools/unicode-table-generator/src/main.rs b/src/tools/unicode-table-generator/src/main.rs
index 4e7c40e..cdd137f 100644
--- a/src/tools/unicode-table-generator/src/main.rs
+++ b/src/tools/unicode-table-generator/src/main.rs
@@ -100,32 +100,25 @@
 
 struct UnicodeData {
     ranges: Vec<(&'static str, Vec<Range<u32>>)>,
+    /// Only stores mappings that are not to self
     to_upper: BTreeMap<u32, [u32; 3]>,
+    /// Only stores mappings that differ from `to_upper`
+    to_title: BTreeMap<u32, [u32; 3]>,
+    /// Only stores mappings that are not to self
     to_lower: BTreeMap<u32, [u32; 3]>,
 }
 
-fn to_mapping(origin: u32, codepoints: Vec<ucd_parse::Codepoint>) -> Option<[u32; 3]> {
-    let mut a = None;
-    let mut b = None;
-    let mut c = None;
-
-    for codepoint in codepoints {
-        if origin == codepoint.value() {
-            return None;
-        }
-
-        if a.is_none() {
-            a = Some(codepoint.value());
-        } else if b.is_none() {
-            b = Some(codepoint.value());
-        } else if c.is_none() {
-            c = Some(codepoint.value());
-        } else {
-            panic!("more than 3 mapped codepoints")
-        }
+fn to_mapping(
+    if_different_from: &[ucd_parse::Codepoint],
+    codepoints: &[ucd_parse::Codepoint],
+) -> Option<[u32; 3]> {
+    if codepoints == if_different_from {
+        return None;
     }
 
-    Some([a.unwrap(), b.unwrap_or(0), c.unwrap_or(0)])
+    let mut ret = [ucd_parse::Codepoint::default(); 3];
+    ret[0..codepoints.len()].copy_from_slice(codepoints);
+    Some(ret.map(ucd_parse::Codepoint::value))
 }
 
 static UNICODE_DIRECTORY: &str = "unicode-downloads";
@@ -145,8 +138,7 @@ fn load_data() -> UnicodeData {
         }
     }
 
-    let mut to_lower = BTreeMap::new();
-    let mut to_upper = BTreeMap::new();
+    let [mut to_lower, mut to_upper, mut to_title] = [const { BTreeMap::new() }; 3];
     for row in ucd_parse::UnicodeDataExpander::new(
         ucd_parse::parse::<_, ucd_parse::UnicodeData>(&UNICODE_DIRECTORY).unwrap(),
     ) {
@@ -172,6 +164,11 @@ fn load_data() -> UnicodeData {
         {
             to_upper.insert(row.codepoint.value(), [mapped.value(), 0, 0]);
         }
+        if let Some(mapped) = row.simple_titlecase_mapping
+            && Some(mapped) != row.simple_uppercase_mapping
+        {
+            to_title.insert(row.codepoint.value(), [mapped.value(), 0, 0]);
+        }
     }
 
     for row in ucd_parse::parse::<_, ucd_parse::SpecialCaseMapping>(&UNICODE_DIRECTORY).unwrap() {
@@ -181,12 +178,15 @@ fn load_data() -> UnicodeData {
         }
 
         let key = row.codepoint.value();
-        if let Some(lower) = to_mapping(key, row.lowercase) {
+        if let Some(lower) = to_mapping(&[row.codepoint], &row.lowercase) {
             to_lower.insert(key, lower);
         }
-        if let Some(upper) = to_mapping(key, row.uppercase) {
+        if let Some(upper) = to_mapping(&[row.codepoint], &row.uppercase) {
             to_upper.insert(key, upper);
         }
+        if let Some(title) = to_mapping(&row.uppercase, &row.titlecase) {
+            to_title.insert(key, title);
+        }
     }
 
     // Filter out ASCII codepoints.
@@ -207,7 +207,7 @@ fn load_data() -> UnicodeData {
         .collect();
 
     properties.sort_by_key(|p| p.0);
-    UnicodeData { ranges: properties, to_lower, to_upper }
+    UnicodeData { ranges: properties, to_lower, to_title, to_upper }
 }
 
 fn main() {
@@ -259,7 +259,7 @@ fn main() {
         total_bytes += emitter.bytes_used;
     }
     let (conversions, sizes) = case_mapping::generate_case_mapping(&unicode_data);
-    for (name, (desc, size)) in ["to_lower", "to_upper"].iter().zip(sizes) {
+    for (name, (desc, size)) in ["to_lower", "to_upper", "to_title"].iter().zip(sizes) {
         table_file.push_str(&format!("// {:16}: {:5} bytes, {desc}\n", name, size,));
         total_bytes += size;
     }
@@ -369,7 +369,11 @@ fn generate_tests(data: &UnicodeData) -> String {
         .unwrap();
     }
 
-    for (name, lut) in ["TO_LOWER", "TO_UPPER"].iter().zip([&data.to_lower, &data.to_upper]) {
+    for (name, lut) in ["TO_LOWER", "TO_UPPER", "TO_TITLE"].iter().zip([
+        &data.to_lower,
+        &data.to_upper,
+        &data.to_title,
+    ]) {
         let lut = lut
             .iter()
             .map(|(key, values)| {
diff --git a/tests/assembly-llvm/aarch64-arm-load-store.rs b/tests/assembly-llvm/aarch64-arm-load-store.rs
new file mode 100644
index 0000000..8296194
--- /dev/null
+++ b/tests/assembly-llvm/aarch64-arm-load-store.rs
@@ -0,0 +1,78 @@
+//@ assembly-output: emit-asm
+//
+//@ revisions: AARCH64
+//@[AARCH64] compile-flags: -Copt-level=3
+//@[AARCH64] only-aarch64-unknown-linux-gnu
+//
+//@ revisions: ARMV7
+//@[ARMV7] compile-flags: -Copt-level=3
+//@[ARMV7] only-armv7-unknown-linux-gnueabihf
+//@[ARMV7] ignore-thumb
+//@[ARMV7] ignore-android
+#![crate_type = "lib"]
+#![cfg_attr(target_arch = "arm", feature(arm_target_feature, stdarch_arm_neon_intrinsics))]
+
+#[cfg(target_arch = "aarch64")]
+use std::arch::aarch64::*;
+#[cfg(target_arch = "arm")]
+use std::arch::arm::*;
+
+// Loads of 3 are error-prone because a `repr(simd)` type's size is always rounded up to the next
+// power of 2. Hence, using `read_unaligned` and `write_unaligned` on such types is invalid, it
+// would go out of bounds.
+#[unsafe(no_mangle)]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "neon,v7"))]
+fn test_vld3q_f32(ptr: *const f32) -> float32x4x3_t {
+    // AARCH64-LABEL: test_vld3q_f32
+    // AARCH64: ld3 { v0.4s, v1.4s, v2.4s }, [x0]
+    // AARCH64: stp q0, q1, [x8]
+    // AARCH64: str q2, [x8, #32]
+    // AARCH64: ret
+    //
+    // ARMV7-LABEL: test_vld3q_f32
+    // ARMV7: vld3.32 {d16, d18, d20}, [r1]!
+    // ARMV7: vld3.32 {d17, d19, d21}, [r1]
+    // ARMV7: vst1.32 {d16, d17}, [r0]!
+    // ARMV7: vst1.32 {d18, d19}, [r0]!
+    // ARMV7: vst1.64 {d20, d21}, [r0]
+    // ARMV7: bx lr
+    unsafe { vld3q_f32(ptr) }
+}
+
+#[unsafe(no_mangle)]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "neon,v7"))]
+fn test_vld3q_s32(ptr: *const i32) -> int32x4x3_t {
+    // AARCH64-LABEL: test_vld3q_s32
+    // AARCH64: ld3 { v0.4s, v1.4s, v2.4s }, [x0]
+    // AARCH64: stp q0, q1, [x8]
+    // AARCH64: str q2, [x8, #32]
+    // AARCH64: ret
+    //
+    // ARMV7-LABEL: test_vld3q_s32
+    // ARMV7: vld3.32 {d16, d18, d20}, [r1]!
+    // ARMV7: vld3.32 {d17, d19, d21}, [r1]
+    // ARMV7: vst1.32 {d16, d17}, [r0]!
+    // ARMV7: vst1.32 {d18, d19}, [r0]!
+    // ARMV7: vst1.64 {d20, d21}, [r0]
+    // ARMV7: bx lr
+    unsafe { vld3q_s32(ptr) }
+}
+
+#[unsafe(no_mangle)]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "neon,v7"))]
+fn test_vld3q_u32(ptr: *const u32) -> uint32x4x3_t {
+    // AARCH64-LABEL: test_vld3q_u32
+    // AARCH64: ld3 { v0.4s, v1.4s, v2.4s }, [x0]
+    // AARCH64: stp q0, q1, [x8]
+    // AARCH64: str q2, [x8, #32]
+    // AARCH64: ret
+    //
+    // ARMV7-LABEL: test_vld3q_u32
+    // ARMV7: vld3.32 {d16, d18, d20}, [r1]!
+    // ARMV7: vld3.32 {d17, d19, d21}, [r1]
+    // ARMV7: vst1.32 {d16, d17}, [r0]!
+    // ARMV7: vst1.32 {d18, d19}, [r0]!
+    // ARMV7: vst1.64 {d20, d21}, [r0]
+    // ARMV7: bx lr
+    unsafe { vld3q_u32(ptr) }
+}
diff --git a/tests/assembly-llvm/bpf_unaligned.rs b/tests/assembly-llvm/bpf_unaligned.rs
new file mode 100644
index 0000000..466c3e4
--- /dev/null
+++ b/tests/assembly-llvm/bpf_unaligned.rs
@@ -0,0 +1,27 @@
+//@ add-minicore
+//@ assembly-output: emit-asm
+//@ compile-flags: --target bpfel-unknown-none -C target_feature=+allows-misaligned-mem-access
+//@ min-llvm-version: 22
+//@ needs-llvm-components: bpf
+#![feature(no_core)]
+#![crate_type = "rlib"]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+// CHECK-LABEL: test_load_i64:
+// CHECK:       r0 = *(u64 *)(r1 + 0)
+#[no_mangle]
+pub unsafe fn test_load_i64(p: *const u64) -> u64 {
+    let mut tmp: u64 = 0;
+    copy_nonoverlapping(p as *const u8, &mut tmp as *mut u64 as *mut u8, 8);
+    tmp
+}
+
+// CHECK-LABEL: test_store_i64:
+// CHECK:       *(u64 *)(r1 + 0) = r2
+#[no_mangle]
+pub unsafe fn test_store_i64(p: *mut u64, v: u64) {
+    copy_nonoverlapping(&v as *const u64 as *const u8, p as *mut u8, 8);
+}
diff --git a/tests/assembly-llvm/sanitizer/hwasan-vs-khwasan.rs b/tests/assembly-llvm/sanitizer/hwasan-vs-khwasan.rs
new file mode 100644
index 0000000..a4362b3
--- /dev/null
+++ b/tests/assembly-llvm/sanitizer/hwasan-vs-khwasan.rs
@@ -0,0 +1,31 @@
+// Verifies that HWASAN and KHWASAN emit different assembly instrumentation on AArch64.
+//
+//@ add-minicore
+//@ assembly-output: emit-asm
+//@ revisions: hwasan khwasan
+//@[hwasan] compile-flags: --target aarch64-unknown-linux-gnu -Zsanitizer=hwaddress
+//@[hwasan] needs-llvm-components: aarch64
+//@[khwasan] compile-flags: --target aarch64-unknown-none -Zsanitizer=kernel-hwaddress
+//@[khwasan] needs-llvm-components: aarch64
+//@ compile-flags: -Copt-level=1
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+extern crate minicore;
+
+// hwasan-LABEL: test:
+// hwasan:       adrp    x{{[0-9]+}}, :gottprel:__hwasan_tls
+// hwasan:       mrs     x{{[0-9]+}}, TPIDR_EL0
+// hwasan:       bl      __hwasan_check_x0_0_short_v2
+
+// khwasan-LABEL: test:
+// khwasan-NOT:   __hwasan_tls
+// khwasan:       orr     x{{[0-9]+}}, x0, #0xff00000000000000
+// khwasan:       bl      __hwasan_check_x0_67043328_fixed_0_short_v2
+
+#[no_mangle]
+pub fn test(b: &mut u8) -> u8 {
+    *b
+}
diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs
index c91c5df..d84357e 100644
--- a/tests/auxiliary/minicore.rs
+++ b/tests/auxiliary/minicore.rs
@@ -238,6 +238,8 @@ pub trait Sync {}
 
 impl Sync for () {}
 
+impl<T, const N: usize> Sync for [T; N] {}
+
 #[lang = "drop_in_place"]
 fn drop_in_place<T>(_: *mut T) {}
 
@@ -277,6 +279,10 @@ trait Drop {
     fn drop(&mut self);
 }
 
+#[rustc_nounwind]
+#[rustc_intrinsic]
+pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+
 pub mod mem {
     #[rustc_nounwind]
     #[rustc_intrinsic]
diff --git a/tests/codegen-llvm/bpf-allows-unaligned.rs b/tests/codegen-llvm/bpf-allows-unaligned.rs
new file mode 100644
index 0000000..c7a70d5
--- /dev/null
+++ b/tests/codegen-llvm/bpf-allows-unaligned.rs
@@ -0,0 +1,11 @@
+//@ only-bpf
+#![crate_type = "lib"]
+#![feature(bpf_target_feature)]
+#![no_std]
+
+#[no_mangle]
+#[target_feature(enable = "allows-misaligned-mem-access")]
+// CHECK: define noundef zeroext i8 @foo(i8 noundef returned %arg) unnamed_addr #0 {
+pub unsafe fn foo(arg: u8) -> u8 {
+    arg
+}
diff --git a/tests/codegen-llvm/debuginfo-callsite-flag.rs b/tests/codegen-llvm/debuginfo-callsite-flag.rs
new file mode 100644
index 0000000..f86adfc
--- /dev/null
+++ b/tests/codegen-llvm/debuginfo-callsite-flag.rs
@@ -0,0 +1,20 @@
+// Check that DIFlagAllCallsDescribed is set on subprogram definitions.
+
+//@ ignore-msvc (CodeView does not use DIFlagAllCallsDescribed)
+//@ compile-flags: -C debuginfo=2 -C opt-level=1 -C no-prepopulate-passes
+
+// CHECK: {{.*}}DISubprogram{{.*}}name: "foo"{{.*}}DIFlagAllCallsDescribed{{.*}}
+
+#[no_mangle]
+#[inline(never)]
+pub fn foo(x: i32) -> i32 {
+    bar(x + 1)
+}
+
+#[no_mangle]
+#[inline(never)]
+pub fn bar(x: i32) -> i32 {
+    x * 2
+}
+
+fn main() {}
diff --git a/tests/codegen-llvm/fromrangeiter-overflow-checks.rs b/tests/codegen-llvm/fromrangeiter-overflow-checks.rs
index 4d27f11..455c81c 100644
--- a/tests/codegen-llvm/fromrangeiter-overflow-checks.rs
+++ b/tests/codegen-llvm/fromrangeiter-overflow-checks.rs
@@ -2,7 +2,7 @@
 // runtime check that panics after yielding the maximum value of the range bound type. That is
 // tested for by tests/ui/iterators/rangefrom-overflow-overflow-checks.rs
 //
-// This test ensures that such a runtime check is *not* emitted when debug-assertions are
+// This test ensures such runtime checks are optimized out when debug-assertions are
 // enabled, but overflow-checks are explicitly disabled.
 
 //@ revisions: DEBUG NOCHECKS
@@ -11,17 +11,24 @@
 
 #![crate_type = "lib"]
 #![feature(new_range_api)]
-use std::range::{RangeFrom, RangeFromIter};
+use std::range::RangeFrom;
 
-// CHECK-LABEL: @iterrangefrom_remainder(
+// CHECK-LABEL: @rangefrom_increments(
 #[no_mangle]
-pub unsafe fn iterrangefrom_remainder(x: RangeFromIter<i32>) -> RangeFrom<i32> {
-    //        DEBUG: i32 noundef %x
-    //     NOCHECKS: i32 noundef returned %x
-    //        DEBUG: br i1
-    //        DEBUG: call core::panicking::panic_const::panic_const_add_overflow
-    //        DEBUG: unreachable
-    // NOCHECKS-NOT: unreachable
-    //     NOCHECKS: ret i32 %x
-    x.remainder()
+pub unsafe fn rangefrom_increments(range: RangeFrom<i32>) -> RangeFrom<i32> {
+    // Iterator is contained entirely within this function, so the optimizer should
+    // be able to see that `exhausted` is never set and optimize out any branches.
+
+    //         CHECK: i32 noundef %range
+    //         DEBUG: switch i32 %range
+    //         DEBUG: call core::panicking::panic_const::panic_const_add_overflow
+    //         DEBUG: unreachable
+    //  NOCHECKS-NOT: unreachable
+    //      NOCHECKS: [[REM:%[a-z_0-9.]+]] = add i32 %range, 2
+    // NOCHECKS-NEXT: ret i32 [[REM]]
+
+    let mut iter = range.into_iter();
+    let _ = iter.next();
+    let _ = iter.next();
+    iter.remainder()
 }
diff --git a/tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs b/tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs
new file mode 100644
index 0000000..93932d86
--- /dev/null
+++ b/tests/codegen-llvm/sanitizer/hwasan-vs-khwasan.rs
@@ -0,0 +1,39 @@
+// Verifies that HWASAN and KHWASAN emit different instrumentation.
+//
+//@ add-minicore
+//@ revisions: hwasan khwasan
+//@[hwasan] compile-flags: --target aarch64-unknown-linux-gnu -Zsanitizer=hwaddress
+//@[hwasan] needs-llvm-components: aarch64
+//@[khwasan] compile-flags: --target aarch64-unknown-none -Zsanitizer=kernel-hwaddress
+//@[khwasan] needs-llvm-components: aarch64
+//@ compile-flags: -Copt-level=0
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items, sanitize)]
+#![no_core]
+
+extern crate minicore;
+
+// hwasan-LABEL: define {{.*}} @test
+// hwasan:       @__hwasan_tls
+// hwasan:       call void @llvm.hwasan.check.memaccess.shortgranules
+// hwasan:       declare void @__hwasan_init()
+
+// The `__hwasan_tls` symbol is unconditionally declared by LLVM's `HWAddressSanitizer` pass.
+// However, in kernel mode KHWASAN does not actually use it (because shadow mapping is fixed
+// and the stack frame ring buffer is disabled). It remains an unused declaration in the LLVM IR
+// and is optimized out before the final assembly/object file is generated, so it does not end
+// up in the final binary. Thus, assert that it appears in the output, but not inside `test`.
+//
+// khwasan:       @__hwasan_tls
+// khwasan-LABEL: define {{.*}} @test
+// khwasan-NOT:   @__hwasan_tls
+//
+// Also test a few other things appear under the LABEL.
+//
+// khwasan-NOT:   @__hwasan_init
+// khwasan:       call void @llvm.hwasan.check.memaccess.shortgranules
+#[no_mangle]
+pub fn test(b: &mut u8) -> u8 {
+    *b
+}
diff --git a/tests/codegen-llvm/sanitizer/kasan-recover.rs b/tests/codegen-llvm/sanitizer/kasan-recover.rs
new file mode 100644
index 0000000..f0f9180
--- /dev/null
+++ b/tests/codegen-llvm/sanitizer/kasan-recover.rs
@@ -0,0 +1,31 @@
+// Verifies that KernelAddressSanitizer recovery mode can be enabled
+// with -Zsanitizer-recover=kernel-address.
+//
+//@ add-minicore
+//@ revisions: KASAN KASAN-RECOVER
+//@ compile-flags: -Copt-level=0
+//@ needs-llvm-components: x86
+//@ compile-flags: -Zsanitizer=kernel-address --target x86_64-unknown-none
+//@[KASAN-RECOVER] compile-flags: -Zsanitizer-recover=kernel-address
+
+#![feature(no_core, sanitize, lang_items)]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+// KASAN-LABEL: define{{.*}}@penguin(
+// KASAN:         call void @__asan_report_load4(
+// KASAN:         unreachable
+// KASAN:       }
+
+// KASAN-RECOVER-LABEL: define{{.*}}@penguin(
+// KASAN-RECOVER:         call void @__asan_report_load4_noabort(
+// KASAN-RECOVER-NOT:     unreachable
+// KASAN-RECOVER:       }
+
+#[no_mangle]
+pub unsafe fn penguin(p: *mut i32) -> i32 {
+    *p
+}
diff --git a/tests/codegen-llvm/sanitizer/khwasan-lifetime-markers.rs b/tests/codegen-llvm/sanitizer/khwasan-lifetime-markers.rs
new file mode 100644
index 0000000..26dc798
--- /dev/null
+++ b/tests/codegen-llvm/sanitizer/khwasan-lifetime-markers.rs
@@ -0,0 +1,20 @@
+// Verifies that `-Zsanitizer=kernel-hwaddress` enables lifetime markers.
+
+//@ add-minicore
+//@ compile-flags: -Zsanitizer=kernel-hwaddress -Copt-level=0
+//@ compile-flags: --target aarch64-unknown-none
+//@ needs-llvm-components: aarch64
+
+#![crate_type = "rlib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+// CHECK-LABEL: ; khwasan_lifetime_markers::test
+// CHECK:       call void @llvm.lifetime.start
+// CHECK:       call void @llvm.lifetime.end
+pub fn test() {
+    let _x = [0u8; 10];
+}
diff --git a/tests/codegen-llvm/sanitizer/khwasan-recover.rs b/tests/codegen-llvm/sanitizer/khwasan-recover.rs
new file mode 100644
index 0000000..452a0f5
--- /dev/null
+++ b/tests/codegen-llvm/sanitizer/khwasan-recover.rs
@@ -0,0 +1,34 @@
+// Verifies that KernelHWAddressSanitizer recovery mode can be enabled
+// with -Zsanitizer-recover=kernel-hwaddress.
+//
+//@ add-minicore
+//@ needs-llvm-components: aarch64
+//@ revisions: KHWASAN KHWASAN-RECOVER
+//@ no-prefer-dynamic
+//@ compile-flags: -Copt-level=0
+//@ compile-flags: -Zsanitizer=kernel-hwaddress --target aarch64-unknown-none
+//@[KHWASAN-RECOVER] compile-flags: -Zsanitizer-recover=kernel-hwaddress
+
+#![feature(no_core, sanitize, lang_items)]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+// KHWASAN-LABEL: define{{.*}}@penguin(
+// KHWASAN:         call void @llvm.hwasan.check.memaccess
+// KHWASAN:         ret i32
+// KHWASAN:       }
+// KHWASAN:       declare void @__hwasan_load4(i64)
+
+// KHWASAN-RECOVER-LABEL: define{{.*}}@penguin(
+// KHWASAN-RECOVER:         call void asm sideeffect "brk #2338", "{x0}"(i64 %{{[0-9]+}})
+// KHWASAN-RECOVER-NOT:     unreachable
+// KHWASAN-RECOVER:       }
+// KHWASAN-RECOVER:       declare void @__hwasan_load4_noabort(i64)
+
+#[no_mangle]
+pub unsafe fn penguin(p: *mut i32) -> i32 {
+    *p
+}
diff --git a/tests/codegen-llvm/sanitizer/sanitize-off-hwasan-khwasan.rs b/tests/codegen-llvm/sanitizer/sanitize-off-hwasan-khwasan.rs
new file mode 100644
index 0000000..313f480
--- /dev/null
+++ b/tests/codegen-llvm/sanitizer/sanitize-off-hwasan-khwasan.rs
@@ -0,0 +1,35 @@
+// Verifies that the `#[sanitize(hwaddress = "off")]` attribute also turns off
+// the kernel hardware-assisted address sanitizer.
+//
+//@ add-minicore
+//@ compile-flags: -Zsanitizer=kernel-hwaddress --target aarch64-unknown-none
+//@ compile-flags: -Ctarget-feature=-crt-static -Copt-level=0
+//@ needs-llvm-components: aarch64
+
+#![crate_type = "rlib"]
+#![feature(no_core, sanitize, lang_items)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+// CHECK-NOT:   sanitize_hwaddress
+// CHECK-LABEL: define {{.*}} @unsanitized
+// CHECK:       start:
+// CHECK-NOT:   call void @llvm.hwasan.check.memaccess
+// CHECK:       }
+#[sanitize(hwaddress = "off")]
+#[no_mangle]
+pub fn unsanitized(b: &mut u8) -> u8 {
+    *b
+}
+
+// CHECK:       sanitize_hwaddress
+// CHECK-LABEL: define {{.*}} @sanitized
+// CHECK:       start:
+// CHECK:       call void @llvm.hwasan.check.memaccess
+// CHECK:       }
+#[no_mangle]
+pub fn sanitized(b: &mut u8) -> u8 {
+    *b
+}
diff --git a/tests/codegen-llvm/sanitizer/sanitize-off-khwasan-hwasan.rs b/tests/codegen-llvm/sanitizer/sanitize-off-khwasan-hwasan.rs
new file mode 100644
index 0000000..a4491eb
--- /dev/null
+++ b/tests/codegen-llvm/sanitizer/sanitize-off-khwasan-hwasan.rs
@@ -0,0 +1,31 @@
+// Verifies that the `#[sanitize(kernel_hwaddress = "off")]` attribute also turns off
+// the hardware-assisted address sanitizer.
+//
+//@ needs-sanitizer-hwaddress
+//@ compile-flags: -Cunsafe-allow-abi-mismatch=sanitizer
+//@ compile-flags: -Ctarget-feature=-crt-static
+//@ compile-flags: -Zsanitizer=hwaddress -Copt-level=0
+
+#![crate_type = "lib"]
+#![feature(sanitize)]
+
+// CHECK-NOT:   sanitize_hwaddress
+// CHECK-LABEL: define {{.*}} @unsanitized
+// CHECK:       start:
+// CHECK-NOT:   call void @llvm.hwasan.check.memaccess
+// CHECK:       }
+#[sanitize(kernel_hwaddress = "off")]
+#[no_mangle]
+pub fn unsanitized(b: &mut u8) -> u8 {
+    *b
+}
+
+// CHECK:       sanitize_hwaddress
+// CHECK-LABEL: define {{.*}} @sanitized
+// CHECK:       start:
+// CHECK:       call void @llvm.hwasan.check.memaccess
+// CHECK:       }
+#[no_mangle]
+pub fn sanitized(b: &mut u8) -> u8 {
+    *b
+}
diff --git a/tests/codegen-llvm/sanitizer/sanitizer-recover.rs b/tests/codegen-llvm/sanitizer/sanitizer-recover.rs
index b8a24e3..5e05b92 100644
--- a/tests/codegen-llvm/sanitizer/sanitizer-recover.rs
+++ b/tests/codegen-llvm/sanitizer/sanitizer-recover.rs
@@ -5,7 +5,7 @@
 //@ needs-sanitizer-memory
 //@ revisions:ASAN ASAN-RECOVER MSAN MSAN-RECOVER MSAN-RECOVER-LTO
 //@ no-prefer-dynamic
-//@                   compile-flags: -C unsafe-allow-abi-mismatch=sanitizer
+//@                   compile-flags: -Cunsafe-allow-abi-mismatch=sanitizer
 //@                   compile-flags: -Ctarget-feature=-crt-static
 //@[ASAN]             compile-flags: -Zsanitizer=address -Copt-level=0
 //@[ASAN-RECOVER]     compile-flags: -Zsanitizer=address -Zsanitizer-recover=address -Copt-level=0
diff --git a/tests/pretty/autodiff/trait.pp b/tests/pretty/autodiff/trait.pp
new file mode 100644
index 0000000..cb2fe0c
--- /dev/null
+++ b/tests/pretty/autodiff/trait.pp
@@ -0,0 +1,43 @@
+//@ compile-flags: -Zautodiff=Enable -Zautodiff=NoPostopt -C opt-level=3 -Clto=fat
+//@ no-prefer-dynamic
+//@ needs-enzyme
+
+// Just check it does not crash for now
+// CHECK: ;
+#![feature(autodiff)]
+#![feature(core_intrinsics)]
+#![feature(rustc_attrs)]
+
+use std::autodiff::autodiff_reverse;
+
+struct Foo {
+    a: f64,
+}
+
+trait MyTrait {
+    #[rustc_autodiff]
+    fn f(&self, x: f64) -> f64;
+    #[rustc_autodiff(Reverse, 1, Const, Active, Active)]
+    fn df(&self, x: f64, seed: f64) -> (f64, f64) {
+        std::hint::black_box(seed);
+        std::hint::black_box(x);
+        ::std::intrinsics::autodiff(
+            Self::f as for<'a> fn(&'a Self, _: f64) -> f64,
+            Self::df,
+            (self, x, seed),
+        )
+
+    }
+}
+
+impl MyTrait for Foo {
+    fn f(&self, x: f64) -> f64 {
+        x.sin()
+    }
+}
+
+fn main() {
+    let foo = Foo { a: 3.0f64 };
+    dbg!(foo.df(2.0, 1.0));
+    dbg!(2.0_f64.cos());
+}
diff --git a/tests/pretty/autodiff/trait.rs b/tests/pretty/autodiff/trait.rs
new file mode 100644
index 0000000..a308cf3
--- /dev/null
+++ b/tests/pretty/autodiff/trait.rs
@@ -0,0 +1,32 @@
+//@ compile-flags: -Zautodiff=Enable -Zautodiff=NoPostopt -C opt-level=3 -Clto=fat
+//@ no-prefer-dynamic
+//@ needs-enzyme
+
+// Just check it does not crash for now
+// CHECK: ;
+#![feature(autodiff)]
+#![feature(core_intrinsics)]
+#![feature(rustc_attrs)]
+
+use std::autodiff::autodiff_reverse;
+
+struct Foo {
+    a: f64,
+}
+
+trait MyTrait {
+    #[autodiff_reverse(df, Const, Active, Active)]
+    fn f(&self, x: f64) -> f64;
+}
+
+impl MyTrait for Foo {
+    fn f(&self, x: f64) -> f64 {
+        x.sin()
+    }
+}
+
+fn main() {
+    let foo = Foo { a: 3.0f64 };
+    dbg!(foo.df(2.0, 1.0));
+    dbg!(2.0_f64.cos());
+}
diff --git a/tests/pretty/or-pattern-paren.pp b/tests/pretty/or-pattern-paren.pp
new file mode 100644
index 0000000..6ea94eb
--- /dev/null
+++ b/tests/pretty/or-pattern-paren.pp
@@ -0,0 +1,27 @@
+#![feature(prelude_import)]
+#![no_std]
+#![feature(box_patterns)]
+extern crate std;
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+
+//@ pretty-compare-only
+//@ pretty-mode:expanded
+//@ pp-exact:or-pattern-paren.pp
+
+macro_rules! or_pat { ($($name:pat),+) => { $($name)|+ } }
+
+fn check_at(x: Option<i32>) {
+    match x {
+        Some(v @ (1 | 2 | 3)) =>
+
+
+            {
+            ::std::io::_print(format_args!("{0}\n", v));
+        }
+        _ => {}
+    }
+}
+fn check_ref(x: &i32) { match x { &(1 | 2 | 3) => {} _ => {} } }
+fn check_box(x: Box<i32>) { match x { box (1 | 2 | 3) => {} _ => {} } }
+fn main() { check_at(Some(2)); check_ref(&1); check_box(Box::new(1)); }
diff --git a/tests/pretty/or-pattern-paren.rs b/tests/pretty/or-pattern-paren.rs
new file mode 100644
index 0000000..ea6a8f3
--- /dev/null
+++ b/tests/pretty/or-pattern-paren.rs
@@ -0,0 +1,36 @@
+#![feature(box_patterns)]
+
+//@ pretty-compare-only
+//@ pretty-mode:expanded
+//@ pp-exact:or-pattern-paren.pp
+
+macro_rules! or_pat {
+    ($($name:pat),+) => { $($name)|+ }
+}
+
+fn check_at(x: Option<i32>) {
+    match x {
+        Some(v @ or_pat!(1, 2, 3)) => println!("{v}"),
+        _ => {}
+    }
+}
+
+fn check_ref(x: &i32) {
+    match x {
+        &or_pat!(1, 2, 3) => {}
+        _ => {}
+    }
+}
+
+fn check_box(x: Box<i32>) {
+    match x {
+        box or_pat!(1, 2, 3) => {}
+        _ => {}
+    }
+}
+
+fn main() {
+    check_at(Some(2));
+    check_ref(&1);
+    check_box(Box::new(1));
+}
diff --git a/tests/run-make-cargo/rustdoc-scrape-examples-duplicated-calls/Cargo.toml b/tests/run-make-cargo/rustdoc-scrape-examples-duplicated-calls/Cargo.toml
new file mode 100644
index 0000000..4563b63
--- /dev/null
+++ b/tests/run-make-cargo/rustdoc-scrape-examples-duplicated-calls/Cargo.toml
@@ -0,0 +1,10 @@
+[workspace]
+
+[package]
+edition = "2024"
+name = "tester"
+version = "0.1.0"
+
+[[example]]
+doc-scrape-examples = true
+name = "window"
diff --git a/tests/run-make-cargo/rustdoc-scrape-examples-duplicated-calls/examples/window.rs b/tests/run-make-cargo/rustdoc-scrape-examples-duplicated-calls/examples/window.rs
new file mode 100644
index 0000000..19d9ad8
--- /dev/null
+++ b/tests/run-make-cargo/rustdoc-scrape-examples-duplicated-calls/examples/window.rs
@@ -0,0 +1,24 @@
+#![allow(dead_code)]
+use tester::Window;
+
+macro_rules! info {
+    ($s:literal, $x:expr) => {{
+        let _ = $x;
+    }};
+}
+
+struct WindowState {
+    window: Window,
+}
+
+impl WindowState {
+    fn takes_ref(&self) {
+        info!("{:?}", self.window.id());
+    }
+
+    fn takes_mut(&mut self) {
+        info!("{:?}", self.window.id());
+    }
+}
+
+fn main() {}
diff --git a/tests/run-make-cargo/rustdoc-scrape-examples-duplicated-calls/rmake.rs b/tests/run-make-cargo/rustdoc-scrape-examples-duplicated-calls/rmake.rs
new file mode 100644
index 0000000..67a328f
--- /dev/null
+++ b/tests/run-make-cargo/rustdoc-scrape-examples-duplicated-calls/rmake.rs
@@ -0,0 +1,11 @@
+//! This test ensures that the call locations are not duplicated when generating scraped examples.
+//! To ensure that, we check that this call doesn't fail.
+//! Regression test for <https://github.com/rust-lang/rust/issues/153837>.
+
+use run_make_support::{cargo, htmldocck};
+
+fn main() {
+    cargo().args(["rustdoc", "-Zunstable-options", "-Zrustdoc-scrape-examples"]).run();
+
+    htmldocck().arg("target/doc").arg("src/lib.rs").run();
+}
diff --git a/tests/run-make-cargo/rustdoc-scrape-examples-duplicated-calls/src/lib.rs b/tests/run-make-cargo/rustdoc-scrape-examples-duplicated-calls/src/lib.rs
new file mode 100644
index 0000000..8c86a37
--- /dev/null
+++ b/tests/run-make-cargo/rustdoc-scrape-examples-duplicated-calls/src/lib.rs
@@ -0,0 +1,13 @@
+//@has tester/struct.Window.html
+//@count - '//*[@class="docblock scraped-example-list"]//span[@class="highlight"]' 1
+//@has - '//*[@class="docblock scraped-example-list"]//span[@class="highlight"]' 'id'
+//@count - '//*[@class="docblock scraped-example-list"]//span[@class="highlight focus"]' 1
+//@has - '//*[@class="docblock scraped-example-list"]//span[@class="highlight focus"]' 'id'
+
+pub struct Window {}
+
+impl Window {
+    pub fn id(&self) -> u64 {
+        todo!()
+    }
+}
diff --git a/tests/run-make/compressed-debuginfo/rmake.rs b/tests/run-make/compressed-debuginfo/rmake.rs
index 5ba1a18..c8bde9c 100644
--- a/tests/run-make/compressed-debuginfo/rmake.rs
+++ b/tests/run-make/compressed-debuginfo/rmake.rs
@@ -23,7 +23,7 @@ fn check_compression(compression: &str, to_find: &str) {
         } else {
             assert_contains(
                 stderr,
-                format!("unknown debuginfo compression algorithm {compression}"),
+                format!("unsupported debuginfo compression algorithm {compression}"),
             );
         }
     });
diff --git a/tests/run-make/crate-loading/multiple-dep-versions.stderr b/tests/run-make/crate-loading/multiple-dep-versions.stderr
index ef7fb70..a683fdd 100644
--- a/tests/run-make/crate-loading/multiple-dep-versions.stderr
+++ b/tests/run-make/crate-loading/multiple-dep-versions.stderr
@@ -177,14 +177,14 @@
    |     this can't be annotated with `?` because it has type `Result<_, Error2>`
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
-help: the following other types implement trait `From<T>`
+help: `dependency::OtherError` implements trait `From<T>`
   --> replaced
    |
 LL | impl From<()> for OtherError {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dependency::OtherError` implements `From<()>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `From<()>`
 ...
 LL | impl From<i32> for OtherError {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dependency::OtherError` implements `From<i32>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `From<i32>`
    = note: there are multiple different versions of crate `dependency` in the dependency graph
    = help: you can use `cargo tree` to explore your dependency tree
 
diff --git a/tests/rustdoc-html/doc-cfg/trait-impls-manual.rs b/tests/rustdoc-html/doc-cfg/trait-impls-manual.rs
new file mode 100644
index 0000000..fbd96cc
--- /dev/null
+++ b/tests/rustdoc-html/doc-cfg/trait-impls-manual.rs
@@ -0,0 +1,92 @@
+// This test ensures that `doc_cfg` feature is working as expected on trait impls.
+// Regression test for <https://github.com/rust-lang/rust/issues/153655>.
+
+#![feature(doc_cfg)]
+#![doc(auto_cfg(hide(
+    target_pointer_width = "64",
+)))]
+
+#![crate_name = "foo"]
+
+pub trait Trait {
+    fn f(&self) {}
+}
+
+pub trait Bob {
+    fn bob(&self) {}
+}
+
+pub trait Foo {
+    fn foo(&self) {}
+}
+
+pub struct X;
+
+//@has 'foo/struct.X.html'
+//@count - '//*[@id="impl-Bob-for-X"]' 1
+//@count - '//*[@id="impl-Bob-for-X"]/*[@class="item-info"]' 0
+//@count - '//*[@id="impl-Trait-for-X"]' 1
+//@count - '//*[@id="impl-Trait-for-X"]/*[@class="item-info"]' 0
+
+// If you need to update this XPath, in particular `item-info`, update all
+// the others in this file.
+//@count - '//*[@id="impl-Foo-for-X"]/*[@class="item-info"]' 1
+
+//@has 'foo/trait.Trait.html'
+//@count - '//*[@id="impl-Trait-for-X"]' 1
+//@count - '//*[@id="impl-Trait-for-X"]/*[@class="item-info"]' 0
+#[doc(cfg(any(target_pointer_width = "64", target_arch = "wasm32")))]
+#[doc(auto_cfg(hide(target_arch = "wasm32")))]
+mod imp {
+    impl super::Trait for super::X { fn f(&self) {} }
+}
+
+//@has 'foo/trait.Bob.html'
+//@count - '//*[@id="impl-Bob-for-X"]' 1
+//@count - '//*[@id="impl-Bob-for-X"]/*[@class="item-info"]' 0
+#[doc(cfg(any(target_pointer_width = "64", target_arch = "wasm32")))]
+#[doc(auto_cfg = false)]
+mod imp2 {
+    impl super::Bob for super::X { fn bob(&self) {} }
+}
+
+//@has 'foo/trait.Foo.html'
+//@count - '//*[@id="impl-Foo-for-X"]/*[@class="item-info"]' 1
+// We use this to force xpath tests to be updated if `item-info` class is changed.
+#[doc(cfg(any(target_pointer_width = "64", target_arch = "wasm32")))]
+mod imp3 {
+    impl super::Foo for super::X { fn foo(&self) {} }
+}
+
+pub struct Y;
+
+//@has 'foo/struct.Y.html'
+//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]' 1
+//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]/*[@class="item-info"]' 0
+#[doc(cfg(any(target_pointer_width = "64", target_arch = "wasm32")))]
+#[doc(auto_cfg(hide(target_arch = "wasm32")))]
+mod imp4 {
+    impl super::Y { pub fn plain_auto() {} }
+}
+
+pub struct Z;
+
+//@has 'foo/struct.Z.html'
+//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]' 1
+//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]/*[@class="item-info"]' 0
+#[doc(cfg(any(target_pointer_width = "64", target_arch = "wasm32")))]
+#[doc(auto_cfg = false)]
+mod imp5 {
+    impl super::Z { pub fn plain_auto() {} }
+}
+
+// The "witness" which has the item info.
+pub struct W;
+
+//@has 'foo/struct.W.html'
+//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]' 1
+//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]/*[@class="item-info"]' 1
+#[doc(cfg(any(target_pointer_width = "64", target_arch = "wasm32")))]
+mod imp6 {
+    impl super::W { pub fn plain_auto() {} }
+}
diff --git a/tests/rustdoc-html/doc-cfg/trait-impls.rs b/tests/rustdoc-html/doc-cfg/trait-impls.rs
new file mode 100644
index 0000000..581d171
--- /dev/null
+++ b/tests/rustdoc-html/doc-cfg/trait-impls.rs
@@ -0,0 +1,92 @@
+// This test ensures that `doc_cfg` feature is working as expected on trait impls.
+// Regression test for <https://github.com/rust-lang/rust/issues/153655>.
+
+#![feature(doc_cfg)]
+#![doc(auto_cfg(hide(
+    target_pointer_width = "64",
+)))]
+
+#![crate_name = "foo"]
+
+pub trait Trait {
+    fn f(&self) {}
+}
+
+pub trait Bob {
+    fn bob(&self) {}
+}
+
+pub trait Foo {
+    fn foo(&self) {}
+}
+
+pub struct X;
+
+//@has 'foo/struct.X.html'
+//@count - '//*[@id="impl-Bob-for-X"]' 1
+//@count - '//*[@id="impl-Bob-for-X"]/*[@class="item-info"]' 0
+//@count - '//*[@id="impl-Trait-for-X"]' 1
+//@count - '//*[@id="impl-Trait-for-X"]/*[@class="item-info"]' 0
+
+// If you need to update this XPath, in particular `item-info`, update all
+// the others in this file.
+//@count - '//*[@id="impl-Foo-for-X"]/*[@class="item-info"]' 1
+
+//@has 'foo/trait.Trait.html'
+//@count - '//*[@id="impl-Trait-for-X"]' 1
+//@count - '//*[@id="impl-Trait-for-X"]/*[@class="item-info"]' 0
+#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
+#[doc(auto_cfg(hide(target_arch = "wasm32")))]
+mod imp {
+    impl super::Trait for super::X { fn f(&self) {} }
+}
+
+//@has 'foo/trait.Bob.html'
+//@count - '//*[@id="impl-Bob-for-X"]' 1
+//@count - '//*[@id="impl-Bob-for-X"]/*[@class="item-info"]' 0
+#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
+#[doc(auto_cfg = false)]
+mod imp2 {
+    impl super::Bob for super::X { fn bob(&self) {} }
+}
+
+//@has 'foo/trait.Foo.html'
+//@count - '//*[@id="impl-Foo-for-X"]/*[@class="item-info"]' 1
+// We use this to force xpath tests to be updated if `item-info` class is changed.
+#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
+mod imp3 {
+    impl super::Foo for super::X { fn foo(&self) {} }
+}
+
+pub struct Y;
+
+//@has 'foo/struct.Y.html'
+//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]' 1
+//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]/*[@class="item-info"]' 0
+#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
+#[doc(auto_cfg(hide(target_arch = "wasm32")))]
+mod imp4 {
+    impl super::Y { pub fn plain_auto() {} }
+}
+
+pub struct Z;
+
+//@has 'foo/struct.Z.html'
+//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]' 1
+//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]/*[@class="item-info"]' 0
+#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
+#[doc(auto_cfg = false)]
+mod imp5 {
+    impl super::Z { pub fn plain_auto() {} }
+}
+
+// The "witness" which has the item info.
+pub struct W;
+
+//@has 'foo/struct.W.html'
+//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]' 1
+//@count - '//*[@id="implementations-list"]/*[@class="impl-items"]/*[@class="item-info"]' 1
+#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
+mod imp6 {
+    impl super::W { pub fn plain_auto() {} }
+}
diff --git a/tests/ui/asm/aarch64/aarch64-sve.rs b/tests/ui/asm/aarch64/aarch64-sve.rs
index 81c82d5..a146d73 100644
--- a/tests/ui/asm/aarch64/aarch64-sve.rs
+++ b/tests/ui/asm/aarch64/aarch64-sve.rs
@@ -1,13 +1,17 @@
-//@ only-aarch64
 //@ build-pass
-//@ needs-asm-support
-
+//@ add-minicore
+//@ compile-flags: --target aarch64-unknown-linux-gnu
+//@ needs-llvm-components: aarch64
+//@ ignore-backends: gcc
 #![crate_type = "rlib"]
+#![feature(no_core)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
 
 // AArch64 test corresponding to arm64ec-sve.rs.
 
-use std::arch::asm;
-
 fn f(x: f64) {
     unsafe {
         asm!("", out("p0") _);
diff --git a/tests/ui/asm/aarch64/bad-options.rs b/tests/ui/asm/aarch64/bad-options.rs
index 9e721d5..ebba925 100644
--- a/tests/ui/asm/aarch64/bad-options.rs
+++ b/tests/ui/asm/aarch64/bad-options.rs
@@ -1,6 +1,13 @@
-//@ only-aarch64
+//@ add-minicore
+//@ compile-flags: --target aarch64-unknown-linux-gnu
+//@ needs-llvm-components: aarch64
+//@ ignore-backends: gcc
+#![crate_type = "lib"]
+#![feature(no_core)]
+#![no_core]
 
-use std::arch::{asm, global_asm};
+extern crate minicore;
+use minicore::*;
 
 fn main() {
     let mut foo = 0;
diff --git a/tests/ui/asm/aarch64/bad-options.stderr b/tests/ui/asm/aarch64/bad-options.stderr
index 54ab7ca..8f3e464 100644
--- a/tests/ui/asm/aarch64/bad-options.stderr
+++ b/tests/ui/asm/aarch64/bad-options.stderr
@@ -1,35 +1,35 @@
 error: the `nomem` and `readonly` options are mutually exclusive
-  --> $DIR/bad-options.rs:8:18
+  --> $DIR/bad-options.rs:15: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:17: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:17: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:20: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:22:20
    |
 LL |         asm!("{}", out(reg) foo, options(noreturn));
    |                    ^^^^^^^^^^^^
 
 error: asm with `clobber_abi` must specify explicit registers for outputs
-  --> $DIR/bad-options.rs:22:20
+  --> $DIR/bad-options.rs:29:20
    |
 LL |         asm!("{}", out(reg) foo, clobber_abi("C"));
    |                    ^^^^^^^^^^^^  ---------------- clobber_abi
@@ -37,48 +37,48 @@
    |                    generic outputs
 
 error: the `nomem` option cannot be used with `global_asm!`
-  --> $DIR/bad-options.rs:28:25
+  --> $DIR/bad-options.rs:35:25
    |
 LL | global_asm!("", options(nomem));
    |                         ^^^^^ the `nomem` option is not meaningful for global-scoped inline assembly
 
 error: the `readonly` option cannot be used with `global_asm!`
-  --> $DIR/bad-options.rs:30:25
+  --> $DIR/bad-options.rs:37:25
    |
 LL | global_asm!("", options(readonly));
    |                         ^^^^^^^^ the `readonly` option is not meaningful for global-scoped inline assembly
 
 error: the `noreturn` option cannot be used with `global_asm!`
-  --> $DIR/bad-options.rs:32:25
+  --> $DIR/bad-options.rs:39:25
    |
 LL | global_asm!("", options(noreturn));
    |                         ^^^^^^^^ the `noreturn` option is not meaningful for global-scoped inline assembly
 
 error: the `pure` option cannot be used with `global_asm!`
-  --> $DIR/bad-options.rs:34:25
+  --> $DIR/bad-options.rs:41:25
    |
 LL | global_asm!("", options(pure));
    |                         ^^^^ the `pure` option is not meaningful for global-scoped inline assembly
 
 error: the `nostack` option cannot be used with `global_asm!`
-  --> $DIR/bad-options.rs:36:25
+  --> $DIR/bad-options.rs:43:25
    |
 LL | global_asm!("", options(nostack));
    |                         ^^^^^^^ the `nostack` option is not meaningful for global-scoped inline assembly
 
 error: the `preserves_flags` option cannot be used with `global_asm!`
-  --> $DIR/bad-options.rs:38:25
+  --> $DIR/bad-options.rs:45:25
    |
 LL | global_asm!("", options(preserves_flags));
    |                         ^^^^^^^^^^^^^^^ the `preserves_flags` option is not meaningful for global-scoped inline assembly
 
 error: invalid ABI for `clobber_abi`
-  --> $DIR/bad-options.rs:20:18
+  --> $DIR/bad-options.rs:27:18
    |
 LL |         asm!("", clobber_abi("foo"));
    |                  ^^^^^^^^^^^^^^^^^^
    |
-   = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`
+   = note: the following ABIs are supported on this target: `C`, `system`, and `efiapi`
 
 error: aborting due to 13 previous errors
 
diff --git a/tests/ui/asm/aarch64/bad-reg.rs b/tests/ui/asm/aarch64/bad-reg.rs
index b99e5fe..39a3e38 100644
--- a/tests/ui/asm/aarch64/bad-reg.rs
+++ b/tests/ui/asm/aarch64/bad-reg.rs
@@ -1,7 +1,13 @@
-//@ only-aarch64
-//@ compile-flags: -C target-feature=+neon
+//@ add-minicore
+//@ compile-flags: --target aarch64-unknown-linux-gnu -C target-feature=+neon
+//@ needs-llvm-components: aarch64
+//@ ignore-backends: gcc
+#![crate_type = "lib"]
+#![feature(no_core)]
+#![no_core]
 
-use std::arch::asm;
+extern crate minicore;
+use minicore::*;
 
 fn main() {
     let mut foo = 0;
@@ -14,11 +20,11 @@ fn main() {
         asm!("", in("foo") foo);
         //~^ ERROR invalid register `foo`: unknown register
         asm!("{:z}", in(reg) foo);
-        //~^ ERROR invalid asm template modifier for this register class
+        //~^ ERROR invalid asm template modifier `z` for this register class
         asm!("{:r}", in(vreg) foo);
-        //~^ ERROR invalid asm template modifier for this register class
+        //~^ ERROR invalid asm template modifier `r` for this register class
         asm!("{:r}", in(vreg_low16) foo);
-        //~^ ERROR invalid asm template modifier for this register class
+        //~^ ERROR invalid asm template modifier `r` for this register class
         asm!("{:a}", const 0);
         //~^ ERROR asm template modifiers are not allowed for `const` arguments
         asm!("{:a}", sym main);
diff --git a/tests/ui/asm/aarch64/bad-reg.stderr b/tests/ui/asm/aarch64/bad-reg.stderr
index c76722f..9f3d54e 100644
--- a/tests/ui/asm/aarch64/bad-reg.stderr
+++ b/tests/ui/asm/aarch64/bad-reg.stderr
@@ -1,49 +1,49 @@
 error: invalid register class `foo`: unknown register class
-  --> $DIR/bad-reg.rs:12:20
+  --> $DIR/bad-reg.rs:18:20
    |
 LL |         asm!("{}", in(foo) foo);
    |                    ^^^^^^^^^^^
    |
-   = note: the following register classes are supported on this target: `reg`, `vreg`, `vreg_low16`, `preg`
+   = note: the following register classes are supported on this target: `reg`, `vreg`, `vreg_low16`, and `preg`
 
 error: invalid register `foo`: unknown register
-  --> $DIR/bad-reg.rs:14:18
+  --> $DIR/bad-reg.rs:20:18
    |
 LL |         asm!("", in("foo") foo);
    |                  ^^^^^^^^^^^^^
 
-error: invalid asm template modifier for this register class
-  --> $DIR/bad-reg.rs:16:15
+error: invalid asm template modifier `z` for this register class
+  --> $DIR/bad-reg.rs:22:15
    |
 LL |         asm!("{:z}", in(reg) foo);
    |               ^^^^   ----------- argument
    |               |
    |               template modifier
    |
-   = note: the `reg` register class supports the following template modifiers: `w`, `x`
+   = note: the `reg` register class supports the following template modifiers: `w` and `x`
 
-error: invalid asm template modifier for this register class
-  --> $DIR/bad-reg.rs:18:15
+error: invalid asm template modifier `r` for this register class
+  --> $DIR/bad-reg.rs:24:15
    |
 LL |         asm!("{:r}", in(vreg) foo);
    |               ^^^^   ------------ argument
    |               |
    |               template modifier
    |
-   = note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v`
+   = note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, and `v`
 
-error: invalid asm template modifier for this register class
-  --> $DIR/bad-reg.rs:20:15
+error: invalid asm template modifier `r` for this register class
+  --> $DIR/bad-reg.rs:26:15
    |
 LL |         asm!("{:r}", in(vreg_low16) foo);
    |               ^^^^   ------------------ argument
    |               |
    |               template modifier
    |
-   = note: the `vreg_low16` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v`
+   = note: the `vreg_low16` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, and `v`
 
 error: asm template modifiers are not allowed for `const` arguments
-  --> $DIR/bad-reg.rs:22:15
+  --> $DIR/bad-reg.rs:28:15
    |
 LL |         asm!("{:a}", const 0);
    |               ^^^^   ------- argument
@@ -51,7 +51,7 @@
    |               template modifier
 
 error: asm template modifiers are not allowed for `sym` arguments
-  --> $DIR/bad-reg.rs:24:15
+  --> $DIR/bad-reg.rs:30:15
    |
 LL |         asm!("{:a}", sym main);
    |               ^^^^   -------- argument
@@ -59,49 +59,49 @@
    |               template modifier
 
 error: invalid register `x29`: the frame pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:26:18
+  --> $DIR/bad-reg.rs:32:18
    |
 LL |         asm!("", in("x29") foo);
    |                  ^^^^^^^^^^^^^
 
 error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:28:18
+  --> $DIR/bad-reg.rs:34:18
    |
 LL |         asm!("", in("sp") foo);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `xzr`: the zero register cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:30:18
+  --> $DIR/bad-reg.rs:36:18
    |
 LL |         asm!("", in("xzr") foo);
    |                  ^^^^^^^^^^^^^
 
 error: invalid register `x19`: x19 is used internally by LLVM and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:32:18
+  --> $DIR/bad-reg.rs:38:18
    |
 LL |         asm!("", in("x19") foo);
    |                  ^^^^^^^^^^^^^
 
 error: register class `preg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:35:18
+  --> $DIR/bad-reg.rs:41:18
    |
 LL |         asm!("", in("p0") foo);
    |                  ^^^^^^^^^^^^
 
 error: register class `preg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:39:20
+  --> $DIR/bad-reg.rs:45:20
    |
 LL |         asm!("{}", in(preg) foo);
    |                    ^^^^^^^^^^^^
 
 error: register class `preg` can only be used as a clobber, not as an input or output
-  --> $DIR/bad-reg.rs:42:20
+  --> $DIR/bad-reg.rs:48:20
    |
 LL |         asm!("{}", out(preg) _);
    |                    ^^^^^^^^^^^
 
 error: register `w0` conflicts with register `x0`
-  --> $DIR/bad-reg.rs:48:32
+  --> $DIR/bad-reg.rs:54:32
    |
 LL |         asm!("", in("x0") foo, in("w0") bar);
    |                  ------------  ^^^^^^^^^^^^ register `w0`
@@ -109,7 +109,7 @@
    |                  register `x0`
 
 error: register `x0` conflicts with register `x0`
-  --> $DIR/bad-reg.rs:50:32
+  --> $DIR/bad-reg.rs:56:32
    |
 LL |         asm!("", in("x0") foo, out("x0") bar);
    |                  ------------  ^^^^^^^^^^^^^ register `x0`
@@ -117,13 +117,13 @@
    |                  register `x0`
    |
 help: use `lateout` instead of `out` to avoid conflict
-  --> $DIR/bad-reg.rs:50:18
+  --> $DIR/bad-reg.rs:56:18
    |
 LL |         asm!("", in("x0") foo, out("x0") bar);
    |                  ^^^^^^^^^^^^
 
 error: register `q0` conflicts with register `v0`
-  --> $DIR/bad-reg.rs:53:32
+  --> $DIR/bad-reg.rs:59:32
    |
 LL |         asm!("", in("v0") foo, in("q0") bar);
    |                  ------------  ^^^^^^^^^^^^ register `q0`
@@ -131,7 +131,7 @@
    |                  register `v0`
 
 error: register `q0` conflicts with register `v0`
-  --> $DIR/bad-reg.rs:55:32
+  --> $DIR/bad-reg.rs:61:32
    |
 LL |         asm!("", in("v0") foo, out("q0") bar);
    |                  ------------  ^^^^^^^^^^^^^ register `q0`
@@ -139,13 +139,13 @@
    |                  register `v0`
    |
 help: use `lateout` instead of `out` to avoid conflict
-  --> $DIR/bad-reg.rs:55:18
+  --> $DIR/bad-reg.rs:61:18
    |
 LL |         asm!("", in("v0") foo, out("q0") bar);
    |                  ^^^^^^^^^^^^
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:35:27
+  --> $DIR/bad-reg.rs:41:27
    |
 LL |         asm!("", in("p0") foo);
    |                           ^^^
@@ -153,7 +153,7 @@
    = note: register class `preg` supports these types: 
 
 error: type `i32` cannot be used with this register class
-  --> $DIR/bad-reg.rs:39:29
+  --> $DIR/bad-reg.rs:45:29
    |
 LL |         asm!("{}", in(preg) foo);
    |                             ^^^
diff --git a/tests/ui/asm/aarch64/duplicate-options.fixed b/tests/ui/asm/aarch64/duplicate-options.fixed
index b221c7c..efddf95 100644
--- a/tests/ui/asm/aarch64/duplicate-options.fixed
+++ b/tests/ui/asm/aarch64/duplicate-options.fixed
@@ -1,8 +1,14 @@
-//@ only-aarch64
-//@ needs-asm-support
 //@ run-rustfix
+//@ add-minicore
+//@ compile-flags: --target aarch64-unknown-linux-gnu
+//@ needs-llvm-components: aarch64
+//@ needs-asm-support
+//@ ignore-backends: gcc
+#![feature(no_core)]
+#![no_core]
 
-use std::arch::asm;
+extern crate minicore;
+use minicore::*;
 
 fn main() {
     unsafe {
diff --git a/tests/ui/asm/aarch64/duplicate-options.rs b/tests/ui/asm/aarch64/duplicate-options.rs
index 44a4518..ee45e7b 100644
--- a/tests/ui/asm/aarch64/duplicate-options.rs
+++ b/tests/ui/asm/aarch64/duplicate-options.rs
@@ -1,8 +1,14 @@
-//@ only-aarch64
-//@ needs-asm-support
 //@ run-rustfix
+//@ add-minicore
+//@ compile-flags: --target aarch64-unknown-linux-gnu
+//@ needs-llvm-components: aarch64
+//@ needs-asm-support
+//@ ignore-backends: gcc
+#![feature(no_core)]
+#![no_core]
 
-use std::arch::asm;
+extern crate minicore;
+use minicore::*;
 
 fn main() {
     unsafe {
diff --git a/tests/ui/asm/aarch64/duplicate-options.stderr b/tests/ui/asm/aarch64/duplicate-options.stderr
index feb3838..06bd9ea 100644
--- a/tests/ui/asm/aarch64/duplicate-options.stderr
+++ b/tests/ui/asm/aarch64/duplicate-options.stderr
@@ -1,53 +1,53 @@
 error: the `nomem` option was already provided
-  --> $DIR/duplicate-options.rs:9:33
+  --> $DIR/duplicate-options.rs:15:33
    |
 LL |         asm!("", options(nomem, nomem));
    |                                 ^^^^^ this option was already provided
 
 error: the `preserves_flags` option was already provided
-  --> $DIR/duplicate-options.rs:11:43
+  --> $DIR/duplicate-options.rs:17:43
    |
 LL |         asm!("", options(preserves_flags, preserves_flags));
    |                                           ^^^^^^^^^^^^^^^ this option was already provided
 
 error: the `nostack` option was already provided
-  --> $DIR/duplicate-options.rs:13:61
+  --> $DIR/duplicate-options.rs:19:61
    |
 LL |         asm!("", options(nostack, preserves_flags), options(nostack));
    |                                                             ^^^^^^^ this option was already provided
 
 error: the `nostack` option was already provided
-  --> $DIR/duplicate-options.rs:15:35
+  --> $DIR/duplicate-options.rs:21:35
    |
 LL |         asm!("", options(nostack, nostack), options(nostack), options(nostack));
    |                                   ^^^^^^^ this option was already provided
 
 error: the `nostack` option was already provided
-  --> $DIR/duplicate-options.rs:15:53
+  --> $DIR/duplicate-options.rs:21:53
    |
 LL |         asm!("", options(nostack, nostack), options(nostack), options(nostack));
    |                                                     ^^^^^^^ this option was already provided
 
 error: the `nostack` option was already provided
-  --> $DIR/duplicate-options.rs:15:71
+  --> $DIR/duplicate-options.rs:21:71
    |
 LL |         asm!("", options(nostack, nostack), options(nostack), options(nostack));
    |                                                                       ^^^^^^^ this option was already provided
 
 error: the `noreturn` option was already provided
-  --> $DIR/duplicate-options.rs:22:38
+  --> $DIR/duplicate-options.rs:28:38
    |
 LL |             options(preserves_flags, noreturn),
    |                                      ^^^^^^^^ this option was already provided
 
 error: the `nomem` option was already provided
-  --> $DIR/duplicate-options.rs:23:21
+  --> $DIR/duplicate-options.rs:29:21
    |
 LL |             options(nomem, nostack),
    |                     ^^^^^ this option was already provided
 
 error: the `noreturn` option was already provided
-  --> $DIR/duplicate-options.rs:24:21
+  --> $DIR/duplicate-options.rs:30:21
    |
 LL |             options(noreturn),
    |                     ^^^^^^^^ this option was already provided
diff --git a/tests/ui/asm/aarch64/interpolated-idents.rs b/tests/ui/asm/aarch64/interpolated-idents.rs
index 3d9cf76..d51fdbc 100644
--- a/tests/ui/asm/aarch64/interpolated-idents.rs
+++ b/tests/ui/asm/aarch64/interpolated-idents.rs
@@ -1,6 +1,13 @@
-//@ only-aarch64
-//@ needs-asm-support
-use std::arch::asm;
+//@ add-minicore
+//@ compile-flags: --target aarch64-unknown-linux-gnu
+//@ needs-llvm-components: aarch64
+//@ ignore-backends: gcc
+#![crate_type = "lib"]
+#![feature(no_core)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
 
 macro_rules! m {
     ($in:ident $out:ident $lateout:ident $inout:ident $inlateout:ident $const:ident $sym:ident
diff --git a/tests/ui/asm/aarch64/interpolated-idents.stderr b/tests/ui/asm/aarch64/interpolated-idents.stderr
index 74cb992..8537a5e 100644
--- a/tests/ui/asm/aarch64/interpolated-idents.stderr
+++ b/tests/ui/asm/aarch64/interpolated-idents.stderr
@@ -1,5 +1,5 @@
 error: the `nomem` and `readonly` options are mutually exclusive
-  --> $DIR/interpolated-idents.rs:13:13
+  --> $DIR/interpolated-idents.rs:20:13
    |
 LL |               $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack));
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -12,7 +12,7 @@
    = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: the `pure` and `noreturn` options are mutually exclusive
-  --> $DIR/interpolated-idents.rs:13:13
+  --> $DIR/interpolated-idents.rs:20:13
    |
 LL |               $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack));
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -25,7 +25,7 @@
    = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: asm outputs are not allowed with the `noreturn` option
-  --> $DIR/interpolated-idents.rs:10:32
+  --> $DIR/interpolated-idents.rs:17:32
    |
 LL |               asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x,
    |                                  ^^^^^^^^^  ^^^^^^^^^^^^^  ^^^^^^^^^^^  ^^^^^^^^^^^^^^^
diff --git a/tests/ui/asm/aarch64/parse-error.rs b/tests/ui/asm/aarch64/parse-error.rs
index 622f99a..f9ee9a1 100644
--- a/tests/ui/asm/aarch64/parse-error.rs
+++ b/tests/ui/asm/aarch64/parse-error.rs
@@ -1,6 +1,13 @@
-//@ only-aarch64
+//@ add-minicore
+//@ compile-flags: --target aarch64-unknown-linux-gnu
+//@ needs-llvm-components: aarch64
+//@ ignore-backends: gcc
+#![crate_type = "lib"]
+#![feature(no_core)]
+#![no_core]
 
-use std::arch::asm;
+extern crate minicore;
+use minicore::*;
 
 fn main() {
     let mut foo = 0;
diff --git a/tests/ui/asm/aarch64/parse-error.stderr b/tests/ui/asm/aarch64/parse-error.stderr
index ca21311..630f2a4 100644
--- a/tests/ui/asm/aarch64/parse-error.stderr
+++ b/tests/ui/asm/aarch64/parse-error.stderr
@@ -1,11 +1,11 @@
 error: explicit register arguments cannot have names
-  --> $DIR/parse-error.rs:9:18
+  --> $DIR/parse-error.rs:16:18
    |
 LL |         asm!("", a = in("x0") foo);
    |                  ^^^^^^^^^^^^^^^^
 
 error: positional arguments cannot follow named arguments or explicit register arguments
-  --> $DIR/parse-error.rs:15:35
+  --> $DIR/parse-error.rs:22:35
    |
 LL |         asm!("{1}", in("x0") foo, const bar);
    |                     ------------  ^^^^^^^^^ positional argument
@@ -13,7 +13,7 @@
    |                     explicit register argument
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/parse-error.rs:11:45
+  --> $DIR/parse-error.rs:18:45
    |
 LL |         asm!("{a}", in("x0") foo, a = const bar);
    |                                             ^^^ non-constant value
@@ -25,7 +25,7 @@
    |
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/parse-error.rs:13:45
+  --> $DIR/parse-error.rs:20:45
    |
 LL |         asm!("{a}", in("x0") foo, a = const bar);
    |                                             ^^^ non-constant value
@@ -37,7 +37,7 @@
    |
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/parse-error.rs:15:41
+  --> $DIR/parse-error.rs:22:41
    |
 LL |         asm!("{1}", in("x0") foo, const bar);
    |                                         ^^^ non-constant value
diff --git a/tests/ui/asm/aarch64/srcloc.rs b/tests/ui/asm/aarch64/srcloc.rs
index c635fa6..91a2ef3 100644
--- a/tests/ui/asm/aarch64/srcloc.rs
+++ b/tests/ui/asm/aarch64/srcloc.rs
@@ -1,12 +1,19 @@
-//@ only-aarch64
+//@ add-minicore
 //@ build-fail
 //@ needs-asm-support
-//@ compile-flags: -Ccodegen-units=1
+//@ compile-flags: --target aarch64-unknown-linux-gnu -Ccodegen-units=1
+//@ needs-llvm-components: aarch64
+//@ ignore-backends: gcc
+#![crate_type = "lib"]
+#![feature(no_core)]
+#![no_core]
 
-use std::arch::asm;
+extern crate minicore;
+use minicore::*;
 
 // Checks that inline asm errors are mapped to the correct line in the source code.
-
+#[unsafe(no_mangle)]
+#[rustfmt::skip]
 fn main() {
     unsafe {
         asm!("invalid_instruction");
diff --git a/tests/ui/asm/aarch64/srcloc.stderr b/tests/ui/asm/aarch64/srcloc.stderr
index b47f19b..44ee44f 100644
--- a/tests/ui/asm/aarch64/srcloc.stderr
+++ b/tests/ui/asm/aarch64/srcloc.stderr
@@ -1,5 +1,5 @@
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:12:15
+  --> $DIR/srcloc.rs:19:15
    |
 LL |         asm!("invalid_instruction");
    |               ^^^^^^^^^^^^^^^^^^^
@@ -11,7 +11,7 @@
    |     ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:16:13
+  --> $DIR/srcloc.rs:23:13
    |
 LL |             invalid_instruction
    |             ^^^^^^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@
    |             ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:21:13
+  --> $DIR/srcloc.rs:28:13
    |
 LL |             invalid_instruction
    |             ^^^^^^^^^^^^^^^^^^^
@@ -35,18 +35,6 @@
    |             ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:27:13
-   |
-LL |             invalid_instruction
-   |             ^^^^^^^^^^^^^^^^^^^
-   |
-note: instantiated into assembly here
-  --> <inline asm>:3:13
-   |
-LL |             invalid_instruction
-   |             ^
-
-error: unrecognized instruction mnemonic
   --> $DIR/srcloc.rs:34:13
    |
 LL |             invalid_instruction
@@ -59,7 +47,19 @@
    |             ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:39:14
+  --> $DIR/srcloc.rs:41:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:3:13
+   |
+LL |             invalid_instruction
+   |             ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:46:14
    |
 LL |         asm!(concat!("invalid", "_", "instruction"));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,7 +71,7 @@
    |     ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:43:14
+  --> $DIR/srcloc.rs:50:14
    |
 LL |             "invalid_instruction",
    |              ^^^^^^^^^^^^^^^^^^^
@@ -83,37 +83,25 @@
    |     ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:49:14
-   |
-LL |             "invalid_instruction",
-   |              ^^^^^^^^^^^^^^^^^^^
-   |
-note: instantiated into assembly here
-  --> <inline asm>:2:1
-   |
-LL | invalid_instruction
-   | ^
-
-error: unrecognized instruction mnemonic
   --> $DIR/srcloc.rs:56:14
    |
 LL |             "invalid_instruction",
    |              ^^^^^^^^^^^^^^^^^^^
    |
 note: instantiated into assembly here
-  --> <inline asm>:3:1
+  --> <inline asm>:2:1
    |
 LL | invalid_instruction
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:63:13
+  --> $DIR/srcloc.rs:63:14
    |
-LL |             concat!("invalid", "_", "instruction"),
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             "invalid_instruction",
+   |              ^^^^^^^^^^^^^^^^^^^
    |
 note: instantiated into assembly here
-  --> <inline asm>:2:1
+  --> <inline asm>:3:1
    |
 LL | invalid_instruction
    | ^
@@ -131,7 +119,19 @@
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:77:14
+  --> $DIR/srcloc.rs:77:13
+   |
+LL |             concat!("invalid", "_", "instruction"),
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:1
+   |
+LL | invalid_instruction
+   | ^
+
+error: unrecognized instruction mnemonic
+  --> $DIR/srcloc.rs:84:14
    |
 LL |             "invalid_instruction1",
    |              ^^^^^^^^^^^^^^^^^^^^
@@ -143,7 +143,7 @@
    |     ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:78:14
+  --> $DIR/srcloc.rs:85:14
    |
 LL |             "invalid_instruction2",
    |              ^^^^^^^^^^^^^^^^^^^^
@@ -155,7 +155,7 @@
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:84:13
+  --> $DIR/srcloc.rs:91:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction1", "\n",
@@ -170,7 +170,7 @@
    |     ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:84:13
+  --> $DIR/srcloc.rs:91:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction1", "\n",
@@ -185,7 +185,7 @@
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:93:13
+  --> $DIR/srcloc.rs:100:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction1", "\n",
@@ -200,7 +200,7 @@
    |     ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:93:13
+  --> $DIR/srcloc.rs:100:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction1", "\n",
@@ -215,7 +215,7 @@
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:97:13
+  --> $DIR/srcloc.rs:104:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction3", "\n",
@@ -230,7 +230,7 @@
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:97:13
+  --> $DIR/srcloc.rs:104:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction3", "\n",
@@ -245,7 +245,7 @@
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:108:13
+  --> $DIR/srcloc.rs:115:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction1", "\n",
@@ -260,7 +260,7 @@
    |     ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:108:13
+  --> $DIR/srcloc.rs:115:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction1", "\n",
@@ -275,7 +275,7 @@
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:112:13
+  --> $DIR/srcloc.rs:119:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction3", "\n",
@@ -290,7 +290,7 @@
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:112:13
+  --> $DIR/srcloc.rs:119:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction3", "\n",
@@ -305,7 +305,7 @@
    | ^
 
 error: unrecognized instruction mnemonic
-  --> $DIR/srcloc.rs:125:14
+  --> $DIR/srcloc.rs:132:14
    |
 LL |             "invalid_instruction"
    |              ^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/asm/aarch64/ttbr0_el2.rs b/tests/ui/asm/aarch64/ttbr0_el2.rs
index a283d75..4032c70 100644
--- a/tests/ui/asm/aarch64/ttbr0_el2.rs
+++ b/tests/ui/asm/aarch64/ttbr0_el2.rs
@@ -1,7 +1,15 @@
 //! Regression test for #97724, recognising ttbr0_el2 as a valid armv8 system register
-//@ only-aarch64
+//@ add-minicore
 //@ build-pass
-use std::arch::asm;
+//@ compile-flags: --target aarch64-unknown-linux-gnu
+//@ needs-llvm-components: aarch64
+//@ ignore-backends: gcc
+#![crate_type = "lib"]
+#![feature(no_core)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
 
 static PT: [u64; 512] = [0; 512];
 fn main() {
diff --git a/tests/ui/asm/x86_64/bad-clobber-abi.rs b/tests/ui/asm/x86_64/bad-clobber-abi.rs
index 5205a08..1b27c42 100644
--- a/tests/ui/asm/x86_64/bad-clobber-abi.rs
+++ b/tests/ui/asm/x86_64/bad-clobber-abi.rs
@@ -1,7 +1,12 @@
-//@ needs-asm-support
-//@ only-x86_64
+//@ add-minicore
+//@ compile-flags: --target x86_64-unknown-linux-gnu
+//@ needs-llvm-components: x86
+#![crate_type = "lib"]
+#![feature(no_core)]
+#![no_core]
 
-use std::arch::asm;
+extern crate minicore;
+use minicore::*;
 
 // checks various modes of failure for the `clobber_abi` argument (after parsing)
 
diff --git a/tests/ui/asm/x86_64/bad-clobber-abi.stderr b/tests/ui/asm/x86_64/bad-clobber-abi.stderr
index 46e91a3..a79506a 100644
--- a/tests/ui/asm/x86_64/bad-clobber-abi.stderr
+++ b/tests/ui/asm/x86_64/bad-clobber-abi.stderr
@@ -1,21 +1,21 @@
 error: invalid ABI for `clobber_abi`
-  --> $DIR/bad-clobber-abi.rs:11:18
+  --> $DIR/bad-clobber-abi.rs:16:18
    |
 LL |         asm!("", clobber_abi("foo"));
    |                  ^^^^^^^^^^^^^^^^^^
    |
-   = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
+   = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, and `sysv64`
 
 error: invalid ABI for `clobber_abi`
-  --> $DIR/bad-clobber-abi.rs:13:35
+  --> $DIR/bad-clobber-abi.rs:18:35
    |
 LL |         asm!("", clobber_abi("C", "foo"));
    |                                   ^^^^^
    |
-   = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
+   = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, and `sysv64`
 
 error: `C` ABI specified multiple times
-  --> $DIR/bad-clobber-abi.rs:15:35
+  --> $DIR/bad-clobber-abi.rs:20:35
    |
 LL |         asm!("", clobber_abi("C", "C"));
    |                              ---  ^^^
@@ -23,7 +23,7 @@
    |                              previously specified here
 
 error: `win64` ABI specified multiple times
-  --> $DIR/bad-clobber-abi.rs:18:39
+  --> $DIR/bad-clobber-abi.rs:23:39
    |
 LL |         asm!("", clobber_abi("win64", "efiapi"));
    |                              -------  ^^^^^^^^
@@ -33,15 +33,15 @@
    = note: these ABIs are equivalent on the current target
 
 error: invalid ABI for `clobber_abi`
-  --> $DIR/bad-clobber-abi.rs:20:35
+  --> $DIR/bad-clobber-abi.rs:25:35
    |
 LL |         asm!("", clobber_abi("C", "foo", "C"));
    |                                   ^^^^^
    |
-   = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
+   = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, and `sysv64`
 
 error: `C` ABI specified multiple times
-  --> $DIR/bad-clobber-abi.rs:20:42
+  --> $DIR/bad-clobber-abi.rs:25:42
    |
 LL |         asm!("", clobber_abi("C", "foo", "C"));
    |                              ---         ^^^
@@ -49,15 +49,15 @@
    |                              previously specified here
 
 error: invalid ABI for `clobber_abi`
-  --> $DIR/bad-clobber-abi.rs:23:39
+  --> $DIR/bad-clobber-abi.rs:28:39
    |
 LL |         asm!("", clobber_abi("win64", "foo", "efiapi"));
    |                                       ^^^^^
    |
-   = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
+   = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, and `sysv64`
 
 error: `win64` ABI specified multiple times
-  --> $DIR/bad-clobber-abi.rs:23:46
+  --> $DIR/bad-clobber-abi.rs:28:46
    |
 LL |         asm!("", clobber_abi("win64", "foo", "efiapi"));
    |                              -------         ^^^^^^^^
@@ -67,7 +67,7 @@
    = note: these ABIs are equivalent on the current target
 
 error: `C` ABI specified multiple times
-  --> $DIR/bad-clobber-abi.rs:26:36
+  --> $DIR/bad-clobber-abi.rs:31:36
    |
 LL |         asm!("", clobber_abi("C"), clobber_abi("C"));
    |                  ----------------  ^^^^^^^^^^^^^^^^
@@ -75,7 +75,7 @@
    |                  previously specified here
 
 error: `win64` ABI specified multiple times
-  --> $DIR/bad-clobber-abi.rs:29:40
+  --> $DIR/bad-clobber-abi.rs:34:40
    |
 LL |         asm!("", clobber_abi("win64"), clobber_abi("efiapi"));
    |                  --------------------  ^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/asm/x86_64/bad-options.rs b/tests/ui/asm/x86_64/bad-options.rs
index 123febc..594ee60 100644
--- a/tests/ui/asm/x86_64/bad-options.rs
+++ b/tests/ui/asm/x86_64/bad-options.rs
@@ -1,8 +1,13 @@
-//@ only-x86_64
-
+//@ add-minicore
+//@ compile-flags: --target x86_64-unknown-linux-gnu
+//@ needs-llvm-components: x86
+#![crate_type = "lib"]
+#![feature(no_core)]
+#![no_core]
 #![feature(asm_unwind)]
 
-use std::arch::{asm, global_asm};
+extern crate minicore;
+use minicore::*;
 
 fn main() {
     let mut foo = 0;
diff --git a/tests/ui/asm/x86_64/bad-options.stderr b/tests/ui/asm/x86_64/bad-options.stderr
index 366eb7c..576d5a1 100644
--- a/tests/ui/asm/x86_64/bad-options.stderr
+++ b/tests/ui/asm/x86_64/bad-options.stderr
@@ -1,41 +1,41 @@
 error: the `nomem` and `readonly` options are mutually exclusive
-  --> $DIR/bad-options.rs:10:18
+  --> $DIR/bad-options.rs:15:18
    |
 LL |         asm!("", options(nomem, readonly));
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `pure` and `noreturn` options are mutually exclusive
-  --> $DIR/bad-options.rs:12:18
+  --> $DIR/bad-options.rs:17:18
    |
 LL |         asm!("", options(pure, nomem, noreturn));
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: asm with the `pure` option must have at least one output
-  --> $DIR/bad-options.rs:12:18
+  --> $DIR/bad-options.rs:17:18
    |
 LL |         asm!("", options(pure, nomem, noreturn));
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: asm with the `pure` option must have at least one output
-  --> $DIR/bad-options.rs:15:33
+  --> $DIR/bad-options.rs:20:33
    |
 LL |         asm!("{}", in(reg) foo, options(pure, nomem));
    |                                 ^^^^^^^^^^^^^^^^^^^^
 
 error: asm outputs are not allowed with the `noreturn` option
-  --> $DIR/bad-options.rs:17:20
+  --> $DIR/bad-options.rs:22: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
+  --> $DIR/bad-options.rs:24:20
    |
 LL |         asm!("{}", label {}, options(may_unwind));
    |                    ^^^^^^^^
 
 error: asm with `clobber_abi` must specify explicit registers for outputs
-  --> $DIR/bad-options.rs:26:20
+  --> $DIR/bad-options.rs:31:20
    |
 LL |         asm!("{}", out(reg) foo, clobber_abi("C"));
    |                    ^^^^^^^^^^^^  ---------------- clobber_abi
@@ -43,7 +43,7 @@
    |                    generic outputs
 
 error: asm with `clobber_abi` must specify explicit registers for outputs
-  --> $DIR/bad-options.rs:28:20
+  --> $DIR/bad-options.rs:33:20
    |
 LL |         asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C"));
    |                    ^^^^^^^^^^^^  ----------------  ---------------- clobber_abi
@@ -52,51 +52,51 @@
    |                    generic outputs
 
 error: the `nomem` option cannot be used with `global_asm!`
-  --> $DIR/bad-options.rs:35:25
+  --> $DIR/bad-options.rs:40:25
    |
 LL | global_asm!("", options(nomem));
    |                         ^^^^^ the `nomem` option is not meaningful for global-scoped inline assembly
 
 error: the `readonly` option cannot be used with `global_asm!`
-  --> $DIR/bad-options.rs:37:25
+  --> $DIR/bad-options.rs:42:25
    |
 LL | global_asm!("", options(readonly));
    |                         ^^^^^^^^ the `readonly` option is not meaningful for global-scoped inline assembly
 
 error: the `noreturn` option cannot be used with `global_asm!`
-  --> $DIR/bad-options.rs:39:25
+  --> $DIR/bad-options.rs:44:25
    |
 LL | global_asm!("", options(noreturn));
    |                         ^^^^^^^^ the `noreturn` option is not meaningful for global-scoped inline assembly
 
 error: the `pure` option cannot be used with `global_asm!`
-  --> $DIR/bad-options.rs:41:25
+  --> $DIR/bad-options.rs:46:25
    |
 LL | global_asm!("", options(pure));
    |                         ^^^^ the `pure` option is not meaningful for global-scoped inline assembly
 
 error: the `nostack` option cannot be used with `global_asm!`
-  --> $DIR/bad-options.rs:43:25
+  --> $DIR/bad-options.rs:48:25
    |
 LL | global_asm!("", options(nostack));
    |                         ^^^^^^^ the `nostack` option is not meaningful for global-scoped inline assembly
 
 error: the `preserves_flags` option cannot be used with `global_asm!`
-  --> $DIR/bad-options.rs:45:25
+  --> $DIR/bad-options.rs:50:25
    |
 LL | global_asm!("", options(preserves_flags));
    |                         ^^^^^^^^^^^^^^^ the `preserves_flags` option is not meaningful for global-scoped inline assembly
 
 error: invalid ABI for `clobber_abi`
-  --> $DIR/bad-options.rs:24:18
+  --> $DIR/bad-options.rs:29:18
    |
 LL |         asm!("", clobber_abi("foo"));
    |                  ^^^^^^^^^^^^^^^^^^
    |
-   = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
+   = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, and `sysv64`
 
 error: `C` ABI specified multiple times
-  --> $DIR/bad-options.rs:28:52
+  --> $DIR/bad-options.rs:33:52
    |
 LL |         asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C"));
    |                                  ----------------  ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/asm/x86_64/bad-reg.experimental_reg.stderr b/tests/ui/asm/x86_64/bad-reg.experimental_reg.stderr
index 133921b..fe2a53a 100644
--- a/tests/ui/asm/x86_64/bad-reg.experimental_reg.stderr
+++ b/tests/ui/asm/x86_64/bad-reg.experimental_reg.stderr
@@ -4,7 +4,7 @@
 LL |         asm!("{}", in(foo) foo);
    |                    ^^^^^^^^^^^
    |
-   = note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg`
+   = note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, and `tmm_reg`
 
 error: invalid register `foo`: unknown register
   --> $DIR/bad-reg.rs:22:18
@@ -12,7 +12,7 @@
 LL |         asm!("", in("foo") foo);
    |                  ^^^^^^^^^^^^^
 
-error: invalid asm template modifier for this register class
+error: invalid asm template modifier `z` for this register class
   --> $DIR/bad-reg.rs:24:15
    |
 LL |         asm!("{:z}", in(reg) foo);
@@ -20,9 +20,9 @@
    |               |
    |               template modifier
    |
-   = note: the `reg` register class supports the following template modifiers: `l`, `x`, `e`, `r`
+   = note: the `reg` register class supports the following template modifiers: `l`, `x`, `e`, and `r`
 
-error: invalid asm template modifier for this register class
+error: invalid asm template modifier `r` for this register class
   --> $DIR/bad-reg.rs:26:15
    |
 LL |         asm!("{:r}", in(xmm_reg) foo);
@@ -30,7 +30,7 @@
    |               |
    |               template modifier
    |
-   = note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, `z`
+   = note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, and `z`
 
 error: asm template modifiers are not allowed for `const` arguments
   --> $DIR/bad-reg.rs:28:15
diff --git a/tests/ui/asm/x86_64/bad-reg.rs b/tests/ui/asm/x86_64/bad-reg.rs
index 4b3005d..cc3def9 100644
--- a/tests/ui/asm/x86_64/bad-reg.rs
+++ b/tests/ui/asm/x86_64/bad-reg.rs
@@ -1,7 +1,7 @@
 //@ add-minicore
-//@ only-x86_64
 //@ revisions: stable experimental_reg
-//@ compile-flags: -C target-feature=+avx2,+avx512f
+//@ compile-flags: --target x86_64-unknown-linux-gnu -C target-feature=+avx2,+avx512f
+//@ needs-llvm-components: x86
 #![cfg_attr(experimental_reg, feature(asm_experimental_reg))]
 
 #![crate_type = "lib"]
@@ -22,9 +22,9 @@ fn main() {
         asm!("", in("foo") foo);
         //~^ ERROR invalid register `foo`: unknown register
         asm!("{:z}", in(reg) foo);
-        //~^ ERROR invalid asm template modifier for this register class
+        //~^ ERROR invalid asm template modifier `z` for this register class
         asm!("{:r}", in(xmm_reg) foo);
-        //~^ ERROR invalid asm template modifier for this register class
+        //~^ ERROR invalid asm template modifier `r` for this register class
         asm!("{:a}", const 0);
         //~^ ERROR asm template modifiers are not allowed for `const` arguments
         asm!("{:a}", sym main);
diff --git a/tests/ui/asm/x86_64/bad-reg.stable.stderr b/tests/ui/asm/x86_64/bad-reg.stable.stderr
index a1c2792..d8a3793 100644
--- a/tests/ui/asm/x86_64/bad-reg.stable.stderr
+++ b/tests/ui/asm/x86_64/bad-reg.stable.stderr
@@ -4,7 +4,7 @@
 LL |         asm!("{}", in(foo) foo);
    |                    ^^^^^^^^^^^
    |
-   = note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg`
+   = note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, and `tmm_reg`
 
 error: invalid register `foo`: unknown register
   --> $DIR/bad-reg.rs:22:18
@@ -12,7 +12,7 @@
 LL |         asm!("", in("foo") foo);
    |                  ^^^^^^^^^^^^^
 
-error: invalid asm template modifier for this register class
+error: invalid asm template modifier `z` for this register class
   --> $DIR/bad-reg.rs:24:15
    |
 LL |         asm!("{:z}", in(reg) foo);
@@ -20,9 +20,9 @@
    |               |
    |               template modifier
    |
-   = note: the `reg` register class supports the following template modifiers: `l`, `x`, `e`, `r`
+   = note: the `reg` register class supports the following template modifiers: `l`, `x`, `e`, and `r`
 
-error: invalid asm template modifier for this register class
+error: invalid asm template modifier `r` for this register class
   --> $DIR/bad-reg.rs:26:15
    |
 LL |         asm!("{:r}", in(xmm_reg) foo);
@@ -30,7 +30,7 @@
    |               |
    |               template modifier
    |
-   = note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, `z`
+   = note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, and `z`
 
 error: asm template modifiers are not allowed for `const` arguments
   --> $DIR/bad-reg.rs:28:15
diff --git a/tests/ui/asm/x86_64/goto-block-safe.rs b/tests/ui/asm/x86_64/goto-block-safe.rs
index b739e9f..1364425 100644
--- a/tests/ui/asm/x86_64/goto-block-safe.rs
+++ b/tests/ui/asm/x86_64/goto-block-safe.rs
@@ -1,16 +1,22 @@
-//@ only-x86_64
+//@ add-minicore
+//@ compile-flags: --target x86_64-unknown-linux-gnu
+//@ needs-llvm-components: x86
 //@ needs-asm-support
-
+#![feature(no_core)]
+#![no_core]
 #![deny(unreachable_code)]
 
-use std::arch::asm;
+extern crate minicore;
+use minicore::*;
+
+unsafe fn such_unsafe() {}
 
 fn goto_fallthough() {
     unsafe {
         asm!(
             "/* {} */",
             label {
-                core::hint::unreachable_unchecked();
+                such_unsafe()
                 //~^ ERROR [E0133]
             }
         )
diff --git a/tests/ui/asm/x86_64/goto-block-safe.stderr b/tests/ui/asm/x86_64/goto-block-safe.stderr
index ee7313b..3f9afdd 100644
--- a/tests/ui/asm/x86_64/goto-block-safe.stderr
+++ b/tests/ui/asm/x86_64/goto-block-safe.stderr
@@ -1,11 +1,11 @@
-error[E0133]: call to unsafe function `unreachable_unchecked` is unsafe and requires unsafe function or block
-  --> $DIR/goto-block-safe.rs:13:17
+error[E0133]: call to unsafe function `such_unsafe` is unsafe and requires unsafe function or block
+  --> $DIR/goto-block-safe.rs:19:17
    |
 LL |     unsafe {
    |     ------ items do not inherit unsafety from separate enclosing items
 ...
-LL |                 core::hint::unreachable_unchecked();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+LL |                 such_unsafe()
+   |                 ^^^^^^^^^^^^^ call to unsafe function
    |
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
diff --git a/tests/ui/asm/x86_64/interpolated-idents.rs b/tests/ui/asm/x86_64/interpolated-idents.rs
index 4f349c5..97908026 100644
--- a/tests/ui/asm/x86_64/interpolated-idents.rs
+++ b/tests/ui/asm/x86_64/interpolated-idents.rs
@@ -1,6 +1,12 @@
-//@ only-x86_64
+//@ add-minicore
+//@ compile-flags: --target x86_64-unknown-linux-gnu
+//@ needs-llvm-components: x86
+#![crate_type = "lib"]
+#![feature(no_core)]
+#![no_core]
 
-use std::arch::asm;
+extern crate minicore;
+use minicore::*;
 
 macro_rules! m {
     ($in:ident $out:ident $lateout:ident $inout:ident $inlateout:ident $const:ident $sym:ident
diff --git a/tests/ui/asm/x86_64/interpolated-idents.stderr b/tests/ui/asm/x86_64/interpolated-idents.stderr
index a91bc76..1fb817e 100644
--- a/tests/ui/asm/x86_64/interpolated-idents.stderr
+++ b/tests/ui/asm/x86_64/interpolated-idents.stderr
@@ -1,5 +1,5 @@
 error: the `nomem` and `readonly` options are mutually exclusive
-  --> $DIR/interpolated-idents.rs:13:13
+  --> $DIR/interpolated-idents.rs:19:13
    |
 LL |               $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack, $att_syntax));
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -12,7 +12,7 @@
    = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: the `pure` and `noreturn` options are mutually exclusive
-  --> $DIR/interpolated-idents.rs:13:13
+  --> $DIR/interpolated-idents.rs:19:13
    |
 LL |               $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack, $att_syntax));
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -25,7 +25,7 @@
    = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: asm outputs are not allowed with the `noreturn` option
-  --> $DIR/interpolated-idents.rs:10:32
+  --> $DIR/interpolated-idents.rs:16:32
    |
 LL |               asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x,
    |                                  ^^^^^^^^^  ^^^^^^^^^^^^^  ^^^^^^^^^^^  ^^^^^^^^^^^^^^^
diff --git a/tests/ui/asm/x86_64/issue-82869.rs b/tests/ui/asm/x86_64/issue-82869.rs
index 448ebd9..4af09cb 100644
--- a/tests/ui/asm/x86_64/issue-82869.rs
+++ b/tests/ui/asm/x86_64/issue-82869.rs
@@ -1,10 +1,14 @@
-//@ needs-asm-support
-//@ only-x86_64
-// Make sure rustc doesn't ICE on asm! for a foreign architecture.
-
+//@ add-minicore
+//@ compile-flags: --target x86_64-unknown-linux-gnu
+//@ needs-llvm-components: x86
 #![crate_type = "rlib"]
+#![feature(no_core)]
+#![no_core]
 
-use std::arch::asm;
+extern crate minicore;
+use minicore::*;
+
+// Make sure rustc doesn't ICE on asm! for a foreign architecture.
 
 pub unsafe fn aarch64(a: f64, b: f64) -> f64 {
     let c;
diff --git a/tests/ui/asm/x86_64/issue-82869.stderr b/tests/ui/asm/x86_64/issue-82869.stderr
index 56e4909..56699ac 100644
--- a/tests/ui/asm/x86_64/issue-82869.stderr
+++ b/tests/ui/asm/x86_64/issue-82869.stderr
@@ -1,21 +1,21 @@
 error: invalid register class `vreg`: unknown register class
-  --> $DIR/issue-82869.rs:11:32
+  --> $DIR/issue-82869.rs:15:32
    |
 LL |     asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
    |                                ^^^^^^^^^^^
    |
-   = note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg`
+   = note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, and `tmm_reg`
 
 error: invalid register class `vreg`: unknown register class
-  --> $DIR/issue-82869.rs:11:45
+  --> $DIR/issue-82869.rs:15:45
    |
 LL |     asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
    |                                             ^^^^^^^^^^
    |
-   = note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg`
+   = note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, and `tmm_reg`
 
 error: invalid register `d0`: unknown register
-  --> $DIR/issue-82869.rs:11:57
+  --> $DIR/issue-82869.rs:15:57
    |
 LL |       asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
    |  _________________________________________________________^
diff --git a/tests/ui/asm/x86_64/issue-89875.rs b/tests/ui/asm/x86_64/issue-89875.rs
index 0252859..a45ef1b 100644
--- a/tests/ui/asm/x86_64/issue-89875.rs
+++ b/tests/ui/asm/x86_64/issue-89875.rs
@@ -1,9 +1,16 @@
 //@ build-pass
+//@ add-minicore
+//@ compile-flags: --target x86_64-unknown-linux-gnu
+//@ needs-llvm-components: x86
 //@ needs-asm-support
-//@ only-x86_64
+#![crate_type = "lib"]
+#![feature(no_core)]
+#![no_core]
 
-use std::arch::asm;
+extern crate minicore;
+use minicore::*;
 
+#[unsafe(no_mangle)]
 #[target_feature(enable = "avx")]
 fn foo() {
     unsafe {
@@ -13,5 +20,3 @@ fn foo() {
         );
     }
 }
-
-fn main() {}
diff --git a/tests/ui/asm/x86_64/issue-96797.rs b/tests/ui/asm/x86_64/issue-96797.rs
index 531e167..9978a48 100644
--- a/tests/ui/asm/x86_64/issue-96797.rs
+++ b/tests/ui/asm/x86_64/issue-96797.rs
@@ -1,13 +1,17 @@
+//@ add-minicore
 //@ build-pass
-//@ compile-flags: -O
-//@ needs-asm-support
-//@ only-x86_64
-//@ only-linux
+//@ compile-flags: --target x86_64-unknown-linux-gnu -O
+//@ needs-llvm-components: x86
+//@ ignore-backends: gcc
+#![crate_type = "lib"]
+#![feature(no_core)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
 
 // regression test for #96797
 
-use std::arch::global_asm;
-
 #[no_mangle]
 fn my_func() {}
 
diff --git a/tests/ui/asm/x86_64/srcloc.rs b/tests/ui/asm/x86_64/srcloc.rs
index f4ffa8c..e73854a 100644
--- a/tests/ui/asm/x86_64/srcloc.rs
+++ b/tests/ui/asm/x86_64/srcloc.rs
@@ -1,12 +1,19 @@
-//@ only-x86_64
+//@ add-minicore
 //@ build-fail
-//@ compile-flags: -Ccodegen-units=1
+//@ compile-flags: --target x86_64-unknown-linux-gnu -Ccodegen-units=1
+//@ needs-llvm-components: x86
 //@ ignore-backends: gcc
+#![crate_type = "lib"]
+#![feature(no_core)]
+#![no_core]
 
-use std::arch::asm;
+extern crate minicore;
+use minicore::*;
 
 // Checks that inline asm errors are mapped to the correct line in the source code.
 
+#[unsafe(no_mangle)]
+#[rustfmt::skip]
 fn main() {
     unsafe {
         asm!("invalid_instruction");
diff --git a/tests/ui/asm/x86_64/srcloc.stderr b/tests/ui/asm/x86_64/srcloc.stderr
index b207912..d2ab93f 100644
--- a/tests/ui/asm/x86_64/srcloc.stderr
+++ b/tests/ui/asm/x86_64/srcloc.stderr
@@ -1,5 +1,5 @@
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:12:15
+  --> $DIR/srcloc.rs:19:15
    |
 LL |         asm!("invalid_instruction");
    |               ^^^^^^^^^^^^^^^^^^^
@@ -11,7 +11,7 @@
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:16:13
+  --> $DIR/srcloc.rs:23:13
    |
 LL |             invalid_instruction
    |             ^^^^^^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@
    |             ^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:21:13
+  --> $DIR/srcloc.rs:28:13
    |
 LL |             invalid_instruction
    |             ^^^^^^^^^^^^^^^^^^^
@@ -35,18 +35,6 @@
    |             ^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:27:13
-   |
-LL |             invalid_instruction
-   |             ^^^^^^^^^^^^^^^^^^^
-   |
-note: instantiated into assembly here
-  --> <inline asm>:4:13
-   |
-LL |             invalid_instruction
-   |             ^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction'
   --> $DIR/srcloc.rs:34:13
    |
 LL |             invalid_instruction
@@ -59,7 +47,19 @@
    |             ^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:39:14
+  --> $DIR/srcloc.rs:41:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:4:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:46:14
    |
 LL |         asm!(concat!("invalid", "_", "instruction"));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,7 +71,7 @@
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: scale factor without index register is ignored
-  --> $DIR/srcloc.rs:42:15
+  --> $DIR/srcloc.rs:49:15
    |
 LL |         asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
    |               ^^^^^^^^^^^^^^^^^^^^^^^
@@ -83,7 +83,7 @@
    |                          ^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:46:14
+  --> $DIR/srcloc.rs:53:14
    |
 LL |             "invalid_instruction",
    |              ^^^^^^^^^^^^^^^^^^^
@@ -95,37 +95,25 @@
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:52:14
-   |
-LL |             "invalid_instruction",
-   |              ^^^^^^^^^^^^^^^^^^^
-   |
-note: instantiated into assembly here
-  --> <inline asm>:3:1
-   |
-LL | invalid_instruction
-   | ^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction'
   --> $DIR/srcloc.rs:59:14
    |
 LL |             "invalid_instruction",
    |              ^^^^^^^^^^^^^^^^^^^
    |
 note: instantiated into assembly here
-  --> <inline asm>:4:1
+  --> <inline asm>:3:1
    |
 LL | invalid_instruction
    | ^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:66:13
+  --> $DIR/srcloc.rs:66:14
    |
-LL |             concat!("invalid", "_", "instruction"),
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             "invalid_instruction",
+   |              ^^^^^^^^^^^^^^^^^^^
    |
 note: instantiated into assembly here
-  --> <inline asm>:3:1
+  --> <inline asm>:4:1
    |
 LL | invalid_instruction
    | ^^^^^^^^^^^^^^^^^^^
@@ -142,8 +130,20 @@
 LL | invalid_instruction
    | ^^^^^^^^^^^^^^^^^^^
 
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:80:13
+   |
+LL |             concat!("invalid", "_", "instruction"),
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:3:1
+   |
+LL | invalid_instruction
+   | ^^^^^^^^^^^^^^^^^^^
+
 error: invalid instruction mnemonic 'invalid_instruction1'
-  --> $DIR/srcloc.rs:80:14
+  --> $DIR/srcloc.rs:87:14
    |
 LL |             "invalid_instruction1",
    |              ^^^^^^^^^^^^^^^^^^^^
@@ -155,7 +155,7 @@
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction2'
-  --> $DIR/srcloc.rs:81:14
+  --> $DIR/srcloc.rs:88:14
    |
 LL |             "invalid_instruction2",
    |              ^^^^^^^^^^^^^^^^^^^^
@@ -167,7 +167,7 @@
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction1'
-  --> $DIR/srcloc.rs:87:13
+  --> $DIR/srcloc.rs:94:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction1", "\n",
@@ -182,7 +182,7 @@
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction2'
-  --> $DIR/srcloc.rs:87:13
+  --> $DIR/srcloc.rs:94:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction1", "\n",
@@ -197,7 +197,7 @@
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction1'
-  --> $DIR/srcloc.rs:96:13
+  --> $DIR/srcloc.rs:103:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction1", "\n",
@@ -212,7 +212,7 @@
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction2'
-  --> $DIR/srcloc.rs:96:13
+  --> $DIR/srcloc.rs:103:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction1", "\n",
@@ -227,7 +227,7 @@
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction3'
-  --> $DIR/srcloc.rs:100:13
+  --> $DIR/srcloc.rs:107:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction3", "\n",
@@ -242,7 +242,7 @@
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction4'
-  --> $DIR/srcloc.rs:100:13
+  --> $DIR/srcloc.rs:107:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction3", "\n",
@@ -257,7 +257,7 @@
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction1'
-  --> $DIR/srcloc.rs:111:13
+  --> $DIR/srcloc.rs:118:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction1", "\n",
@@ -272,7 +272,7 @@
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction2'
-  --> $DIR/srcloc.rs:111:13
+  --> $DIR/srcloc.rs:118:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction1", "\n",
@@ -287,7 +287,7 @@
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction3'
-  --> $DIR/srcloc.rs:115:13
+  --> $DIR/srcloc.rs:122:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction3", "\n",
@@ -302,7 +302,7 @@
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction4'
-  --> $DIR/srcloc.rs:115:13
+  --> $DIR/srcloc.rs:122:13
    |
 LL | /             concat!(
 LL | |                 "invalid", "_", "instruction3", "\n",
@@ -317,7 +317,7 @@
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: invalid instruction mnemonic 'invalid_instruction'
-  --> $DIR/srcloc.rs:128:14
+  --> $DIR/srcloc.rs:135:14
    |
 LL |             "invalid_instruction"
    |              ^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/asm/x86_64/target-feature-attr.rs b/tests/ui/asm/x86_64/target-feature-attr.rs
index 2193117..ada5fec 100644
--- a/tests/ui/asm/x86_64/target-feature-attr.rs
+++ b/tests/ui/asm/x86_64/target-feature-attr.rs
@@ -1,15 +1,20 @@
-//@ only-x86_64
+//@ add-minicore
 // Set the base cpu explicitly, in case the default has been changed.
-//@ compile-flags: -C target-cpu=x86-64
+//@ compile-flags: --target x86_64-unknown-linux-gnu -C target-cpu=x86-64
+//@ needs-llvm-components: x86
+#![crate_type = "rlib"]
+#![feature(no_core)]
+#![no_core]
 
-use std::arch::asm;
+extern crate minicore;
+use minicore::*;
 
 #[target_feature(enable = "avx")]
 unsafe fn foo() {
     let mut x = 1;
     let y = 2;
     asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
-    assert_eq!(x, 3);
+    let _ = x;
 }
 
 unsafe fn bar() {
@@ -19,7 +24,7 @@ unsafe fn bar() {
     //~^ ERROR: register class `ymm_reg` requires the `avx` target feature
     //~| ERROR: register class `ymm_reg` requires the `avx` target feature
     //~| ERROR: register class `ymm_reg` requires the `avx` target feature
-    assert_eq!(x, 3);
+    let _ = x;
 }
 
 #[target_feature(enable = "avx512bw")]
diff --git a/tests/ui/asm/x86_64/target-feature-attr.stderr b/tests/ui/asm/x86_64/target-feature-attr.stderr
index c852726..625f104 100644
--- a/tests/ui/asm/x86_64/target-feature-attr.stderr
+++ b/tests/ui/asm/x86_64/target-feature-attr.stderr
@@ -1,23 +1,23 @@
 error: register class `ymm_reg` requires the `avx` target feature
-  --> $DIR/target-feature-attr.rs:18:40
+  --> $DIR/target-feature-attr.rs:23:40
    |
 LL |     asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
    |                                        ^^^^^^^^^^^^^
 
 error: register class `ymm_reg` requires the `avx` target feature
-  --> $DIR/target-feature-attr.rs:18:55
+  --> $DIR/target-feature-attr.rs:23:55
    |
 LL |     asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
    |                                                       ^^^^^^^^^^^^^
 
 error: register class `ymm_reg` requires the `avx` target feature
-  --> $DIR/target-feature-attr.rs:18:70
+  --> $DIR/target-feature-attr.rs:23:70
    |
 LL |     asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
    |                                                                      ^^^^^^^^^^^^^^^^^^
 
 error: register class `kreg` requires at least one of the following target features: avx512bw, avx512f
-  --> $DIR/target-feature-attr.rs:33:23
+  --> $DIR/target-feature-attr.rs:38:23
    |
 LL |     asm!("/* {0} */", in(kreg) x);
    |                       ^^^^^^^^^^
diff --git a/tests/ui/asm/x86_64/x86_64_parse_error.rs b/tests/ui/asm/x86_64/x86_64_parse_error.rs
index 3df0feb..3d01141 100644
--- a/tests/ui/asm/x86_64/x86_64_parse_error.rs
+++ b/tests/ui/asm/x86_64/x86_64_parse_error.rs
@@ -1,6 +1,12 @@
-//@ only-x86_64
+//@ add-minicore
+//@ compile-flags: --target x86_64-unknown-linux-gnu
+//@ needs-llvm-components: x86
+#![crate_type = "lib"]
+#![feature(no_core)]
+#![no_core]
 
-use std::arch::asm;
+extern crate minicore;
+use minicore::*;
 
 fn main() {
     let mut foo = 0;
@@ -14,6 +20,6 @@ fn main() {
         //~^ ERROR attempt to use a non-constant value in a constant
         asm!("{1}", in("eax") foo, const bar);
         //~^ ERROR positional arguments cannot follow named arguments or explicit register arguments
-        //~^^ ERROR attempt to use a non-constant value in a constant
+        //~| ERROR attempt to use a non-constant value in a constant
     }
 }
diff --git a/tests/ui/asm/x86_64/x86_64_parse_error.stderr b/tests/ui/asm/x86_64/x86_64_parse_error.stderr
index dfa3e1d..30d2c57 100644
--- a/tests/ui/asm/x86_64/x86_64_parse_error.stderr
+++ b/tests/ui/asm/x86_64/x86_64_parse_error.stderr
@@ -1,11 +1,11 @@
 error: explicit register arguments cannot have names
-  --> $DIR/x86_64_parse_error.rs:9:18
+  --> $DIR/x86_64_parse_error.rs:15:18
    |
 LL |         asm!("", a = in("eax") foo);
    |                  ^^^^^^^^^^^^^^^^^
 
 error: positional arguments cannot follow named arguments or explicit register arguments
-  --> $DIR/x86_64_parse_error.rs:15:36
+  --> $DIR/x86_64_parse_error.rs:21:36
    |
 LL |         asm!("{1}", in("eax") foo, const bar);
    |                     -------------  ^^^^^^^^^ positional argument
@@ -13,7 +13,7 @@
    |                     explicit register argument
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/x86_64_parse_error.rs:11:46
+  --> $DIR/x86_64_parse_error.rs:17:46
    |
 LL |         asm!("{a}", in("eax") foo, a = const bar);
    |                                              ^^^ non-constant value
@@ -25,7 +25,7 @@
    |
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/x86_64_parse_error.rs:13:46
+  --> $DIR/x86_64_parse_error.rs:19:46
    |
 LL |         asm!("{a}", in("eax") foo, a = const bar);
    |                                              ^^^ non-constant value
@@ -37,7 +37,7 @@
    |
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/x86_64_parse_error.rs:15:42
+  --> $DIR/x86_64_parse_error.rs:21:42
    |
 LL |         asm!("{1}", in("eax") foo, const bar);
    |                                          ^^^ non-constant value
diff --git a/tests/ui/associated-consts/type-const-in-array-len-wrong-type.rs b/tests/ui/associated-consts/type-const-in-array-len-wrong-type.rs
index cb0b8a1..c260ab1 100644
--- a/tests/ui/associated-consts/type-const-in-array-len-wrong-type.rs
+++ b/tests/ui/associated-consts/type-const-in-array-len-wrong-type.rs
@@ -1,9 +1,6 @@
 #![feature(generic_const_exprs)]
-//~^ WARN the feature `generic_const_exprs` is incomplete
 #![feature(min_generic_const_args)]
-//~^ WARN the feature `min_generic_const_args` is incomplete
 #![feature(inherent_associated_types)]
-//~^ WARN the feature `inherent_associated_types` is incomplete
 
 struct OnDiskDirEntry<'a>(&'a ());
 
diff --git a/tests/ui/associated-consts/type-const-in-array-len-wrong-type.stderr b/tests/ui/associated-consts/type-const-in-array-len-wrong-type.stderr
index b69a1b7..a90b1f6 100644
--- a/tests/ui/associated-consts/type-const-in-array-len-wrong-type.stderr
+++ b/tests/ui/associated-consts/type-const-in-array-len-wrong-type.stderr
@@ -1,35 +1,10 @@
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/type-const-in-array-len-wrong-type.rs:1:12
-   |
-LL | #![feature(generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: the feature `min_generic_const_args` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/type-const-in-array-len-wrong-type.rs:3:12
-   |
-LL | #![feature(min_generic_const_args)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
-
-warning: the feature `inherent_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/type-const-in-array-len-wrong-type.rs:5:12
-   |
-LL | #![feature(inherent_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
-
 error: the constant `2` is not of type `usize`
-  --> $DIR/type-const-in-array-len-wrong-type.rs:13:26
+  --> $DIR/type-const-in-array-len-wrong-type.rs:10:26
    |
 LL |     fn lfn_contents() -> [char; Self::LFN_FRAGMENT_LEN] {
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `i64`
    |
    = note: the length of array `[char; 2]` must be type `usize`
 
-error: aborting due to 1 previous error; 3 warnings emitted
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/associated-consts/type-const-in-array-len.rs b/tests/ui/associated-consts/type-const-in-array-len.rs
index d33eaca..7a809cef 100644
--- a/tests/ui/associated-consts/type-const-in-array-len.rs
+++ b/tests/ui/associated-consts/type-const-in-array-len.rs
@@ -1,9 +1,7 @@
 //@ check-pass
 
 #![feature(min_generic_const_args)]
-//~^ WARN the feature `min_generic_const_args` is incomplete
 #![feature(inherent_associated_types)]
-//~^ WARN the feature `inherent_associated_types` is incomplete
 
 // Test case from #138226: generic impl with multiple type parameters
 struct Foo<A, B>(A, B);
diff --git a/tests/ui/associated-consts/type-const-in-array-len.stderr b/tests/ui/associated-consts/type-const-in-array-len.stderr
deleted file mode 100644
index 546995d..0000000
--- a/tests/ui/associated-consts/type-const-in-array-len.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-warning: the feature `min_generic_const_args` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/type-const-in-array-len.rs:3:12
-   |
-LL | #![feature(min_generic_const_args)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: the feature `inherent_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/type-const-in-array-len.rs:5:12
-   |
-LL | #![feature(inherent_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
-
-warning: 2 warnings emitted
-
diff --git a/tests/ui/associated-inherent-types/hr-do-not-blame-outlives-static-ice.rs b/tests/ui/associated-inherent-types/hr-do-not-blame-outlives-static-ice.rs
index e5c1f47..27b3b93 100644
--- a/tests/ui/associated-inherent-types/hr-do-not-blame-outlives-static-ice.rs
+++ b/tests/ui/associated-inherent-types/hr-do-not-blame-outlives-static-ice.rs
@@ -2,7 +2,6 @@
 
 // Regression test for #146467.
 #![feature(inherent_associated_types)]
-//~^ WARN the feature `inherent_associated_types` is incomplete
 
 struct Foo<T>(T);
 
diff --git a/tests/ui/associated-inherent-types/hr-do-not-blame-outlives-static-ice.stderr b/tests/ui/associated-inherent-types/hr-do-not-blame-outlives-static-ice.stderr
index 4c0726d..b06add2 100644
--- a/tests/ui/associated-inherent-types/hr-do-not-blame-outlives-static-ice.stderr
+++ b/tests/ui/associated-inherent-types/hr-do-not-blame-outlives-static-ice.stderr
@@ -1,20 +1,11 @@
-warning: the feature `inherent_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/hr-do-not-blame-outlives-static-ice.rs:4:12
-   |
-LL | #![feature(inherent_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/hr-do-not-blame-outlives-static-ice.rs:9:6
+  --> $DIR/hr-do-not-blame-outlives-static-ice.rs:8:6
    |
 LL | impl<'a> Foo<fn(&())> {
    |      ^^ unconstrained lifetime parameter
 
 error[E0308]: mismatched types
-  --> $DIR/hr-do-not-blame-outlives-static-ice.rs:14:11
+  --> $DIR/hr-do-not-blame-outlives-static-ice.rs:13:11
    |
 LL | fn foo(_: for<'a> fn(Foo<fn(&'a ())>::Assoc)) {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
@@ -23,12 +14,12 @@
               found struct `Foo<for<'a> fn(&'a ())>`
 
 error: higher-ranked subtype error
-  --> $DIR/hr-do-not-blame-outlives-static-ice.rs:14:1
+  --> $DIR/hr-do-not-blame-outlives-static-ice.rs:13:1
    |
 LL | fn foo(_: for<'a> fn(Foo<fn(&'a ())>::Assoc)) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0207, E0308.
 For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/associated-inherent-types/variance-computation-requires-equality.rs b/tests/ui/associated-inherent-types/variance-computation-requires-equality.rs
index 3f72679..b7f8586 100644
--- a/tests/ui/associated-inherent-types/variance-computation-requires-equality.rs
+++ b/tests/ui/associated-inherent-types/variance-computation-requires-equality.rs
@@ -1,7 +1,6 @@
 //@ check-pass
 
 #![feature(inherent_associated_types)]
-//~^ WARN the feature `inherent_associated_types` is incomplete
 
 struct D<T> {
   a: T
diff --git a/tests/ui/associated-inherent-types/variance-computation-requires-equality.stderr b/tests/ui/associated-inherent-types/variance-computation-requires-equality.stderr
deleted file mode 100644
index 93064f5..0000000
--- a/tests/ui/associated-inherent-types/variance-computation-requires-equality.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `inherent_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/variance-computation-requires-equality.rs:3:12
-   |
-LL | #![feature(inherent_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/associated-types/defaults-specialization.rs b/tests/ui/associated-types/defaults-specialization.rs
index 553705b..d0ed718 100644
--- a/tests/ui/associated-types/defaults-specialization.rs
+++ b/tests/ui/associated-types/defaults-specialization.rs
@@ -1,7 +1,6 @@
 //! Tests the interaction of associated type defaults and specialization.
 
 #![feature(associated_type_defaults, specialization)]
-//~^ WARN the feature `specialization` is incomplete
 
 trait Tr {
     type Ty = u8;
diff --git a/tests/ui/associated-types/defaults-specialization.stderr b/tests/ui/associated-types/defaults-specialization.stderr
index d22d9ce..2e880a7 100644
--- a/tests/ui/associated-types/defaults-specialization.stderr
+++ b/tests/ui/associated-types/defaults-specialization.stderr
@@ -1,21 +1,11 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/defaults-specialization.rs:3:38
-   |
-LL | #![feature(associated_type_defaults, specialization)]
-   |                                      ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0053]: method `make` has an incompatible type for trait
-  --> $DIR/defaults-specialization.rs:19:18
+  --> $DIR/defaults-specialization.rs:18:18
    |
 LL |     fn make() -> u8 { 0 }
    |                  ^^ expected associated type, found `u8`
    |
 note: type in trait
-  --> $DIR/defaults-specialization.rs:9:18
+  --> $DIR/defaults-specialization.rs:8:18
    |
 LL |     fn make() -> Self::Ty {
    |                  ^^^^^^^^
@@ -28,7 +18,7 @@
    |
 
 error[E0053]: method `make` has an incompatible type for trait
-  --> $DIR/defaults-specialization.rs:35:18
+  --> $DIR/defaults-specialization.rs:34:18
    |
 LL |     default type Ty = bool;
    |     --------------- associated type is `default` and may be overridden
@@ -37,7 +27,7 @@
    |                  ^^^^ expected associated type, found `bool`
    |
 note: type in trait
-  --> $DIR/defaults-specialization.rs:9:18
+  --> $DIR/defaults-specialization.rs:8:18
    |
 LL |     fn make() -> Self::Ty {
    |                  ^^^^^^^^
@@ -50,7 +40,7 @@
    |
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:10:9
+  --> $DIR/defaults-specialization.rs:9:9
    |
 LL |     type Ty = u8;
    |     ------- associated type defaults can't be assumed inside the trait defining them
@@ -64,7 +54,7 @@
                          found type `u8`
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:26:29
+  --> $DIR/defaults-specialization.rs:25:29
    |
 LL |     fn make() -> Self::Ty { 0u8 }
    |                  --------   ^^^ expected associated type, found `u8`
@@ -79,7 +69,7 @@
            see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:44:29
+  --> $DIR/defaults-specialization.rs:43:29
    |
 LL |     default type Ty = bool;
    |     --------------- associated type is `default` and may be overridden
@@ -95,7 +85,7 @@
            see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:87:32
+  --> $DIR/defaults-specialization.rs:86:32
    |
 LL |     let _: <B<()> as Tr>::Ty = 0u8;
    |            -----------------   ^^^ expected associated type, found `u8`
@@ -105,13 +95,13 @@
    = note: expected associated type `<B<()> as Tr>::Ty`
                          found type `u8`
 help: a method is available that returns `<B<()> as Tr>::Ty`
-  --> $DIR/defaults-specialization.rs:9:5
+  --> $DIR/defaults-specialization.rs:8:5
    |
 LL |     fn make() -> Self::Ty {
    |     ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:88:32
+  --> $DIR/defaults-specialization.rs:87:32
    |
 LL |     let _: <B<()> as Tr>::Ty = true;
    |            -----------------   ^^^^ expected associated type, found `bool`
@@ -121,7 +111,7 @@
    = note: expected associated type `<B<()> as Tr>::Ty`
                          found type `bool`
 help: a method is available that returns `<B<()> as Tr>::Ty`
-  --> $DIR/defaults-specialization.rs:9:5
+  --> $DIR/defaults-specialization.rs:8:5
    |
 LL |     fn make() -> Self::Ty {
    |     ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`
@@ -129,7 +119,7 @@
            see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:89:33
+  --> $DIR/defaults-specialization.rs:88:33
    |
 LL |     let _: <B2<()> as Tr>::Ty = 0u8;
    |            ------------------   ^^^ expected associated type, found `u8`
@@ -139,13 +129,13 @@
    = note: expected associated type `<B2<()> as Tr>::Ty`
                          found type `u8`
 help: a method is available that returns `<B2<()> as Tr>::Ty`
-  --> $DIR/defaults-specialization.rs:9:5
+  --> $DIR/defaults-specialization.rs:8:5
    |
 LL |     fn make() -> Self::Ty {
    |     ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:90:33
+  --> $DIR/defaults-specialization.rs:89:33
    |
 LL |     let _: <B2<()> as Tr>::Ty = true;
    |            ------------------   ^^^^ expected associated type, found `bool`
@@ -155,14 +145,14 @@
    = note: expected associated type `<B2<()> as Tr>::Ty`
                          found type `bool`
 help: a method is available that returns `<B2<()> as Tr>::Ty`
-  --> $DIR/defaults-specialization.rs:9:5
+  --> $DIR/defaults-specialization.rs:8:5
    |
 LL |     fn make() -> Self::Ty {
    |     ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`
    = note: the associated type `<B2<()> as Tr>::Ty` is defined as `bool` in the implementation, but the where-bound `B2<()>` shadows this definition
            see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information
 
-error: aborting due to 9 previous errors; 1 warning emitted
+error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0053, E0308.
 For more information about an error, try `rustc --explain E0053`.
diff --git a/tests/ui/async-await/async-drop/foreign-fundamental.rs b/tests/ui/async-await/async-drop/foreign-fundamental.rs
index 1c192fc..44be204 100644
--- a/tests/ui/async-await/async-drop/foreign-fundamental.rs
+++ b/tests/ui/async-await/async-drop/foreign-fundamental.rs
@@ -1,7 +1,6 @@
 //@ edition: 2018
 
 #![feature(async_drop)]
-//~^ WARN the feature `async_drop` is incomplete
 
 use std::future::AsyncDrop;
 use std::pin::Pin;
diff --git a/tests/ui/async-await/async-drop/foreign-fundamental.stderr b/tests/ui/async-await/async-drop/foreign-fundamental.stderr
index 7b52329..78bfdf6 100644
--- a/tests/ui/async-await/async-drop/foreign-fundamental.stderr
+++ b/tests/ui/async-await/async-drop/foreign-fundamental.stderr
@@ -1,24 +1,15 @@
-warning: the feature `async_drop` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/foreign-fundamental.rs:3:12
-   |
-LL | #![feature(async_drop)]
-   |            ^^^^^^^^^^
-   |
-   = note: see issue #126482 <https://github.com/rust-lang/rust/issues/126482> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0120]: the `AsyncDrop` trait may only be implemented for local structs, enums, and unions
-  --> $DIR/foreign-fundamental.rs:11:20
+  --> $DIR/foreign-fundamental.rs:10:20
    |
 LL | impl AsyncDrop for &Foo {
    |                    ^^^^ must be a struct, enum, or union in the current crate
 
 error[E0120]: the `AsyncDrop` trait may only be implemented for local structs, enums, and unions
-  --> $DIR/foreign-fundamental.rs:16:20
+  --> $DIR/foreign-fundamental.rs:15:20
    |
 LL | impl AsyncDrop for Pin<Foo> {
    |                    ^^^^^^^^ must be a struct, enum, or union in the current crate
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0120`.
diff --git a/tests/ui/async-await/drop-option-future.rs b/tests/ui/async-await/drop-option-future.rs
new file mode 100644
index 0000000..155b1d7
--- /dev/null
+++ b/tests/ui/async-await/drop-option-future.rs
@@ -0,0 +1,16 @@
+//! Regression test for <https://github.com/rust-lang/rust/issues/98077>.
+
+//@ edition:2018
+//@ check-pass
+
+#![allow(dead_code)]
+#![allow(unused_assignments)]
+
+async fn foo() {
+    let mut f = None;
+    let value = 0;
+    f = Some(async { value });
+    core::mem::drop(f);
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/dyn/mut-is-pointer-like.stderr b/tests/ui/async-await/dyn/mut-is-pointer-like.stderr
index 6689539..0f39052 100644
--- a/tests/ui/async-await/dyn/mut-is-pointer-like.stderr
+++ b/tests/ui/async-await/dyn/mut-is-pointer-like.stderr
@@ -1,12 +1,3 @@
-warning: the feature `async_fn_in_dyn_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/mut-is-pointer-like.rs:6:12
-   |
-LL | #![feature(async_fn_in_dyn_trait)]
-   |            ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #133119 <https://github.com/rust-lang/rust/issues/133119> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0038]: the trait `AsyncTrait` is not dyn compatible
   --> $DIR/mut-is-pointer-like.rs:35:29
    |
@@ -24,6 +15,6 @@
    |              ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async`
    = help: consider moving `async_dispatch` to another trait
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/async-await/dyn/works.stderr b/tests/ui/async-await/dyn/works.stderr
index 338479d..c7d0d14d 100644
--- a/tests/ui/async-await/dyn/works.stderr
+++ b/tests/ui/async-await/dyn/works.stderr
@@ -1,12 +1,3 @@
-warning: the feature `async_fn_in_dyn_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/works.rs:6:12
-   |
-LL | #![feature(async_fn_in_dyn_trait)]
-   |            ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #133119 <https://github.com/rust-lang/rust/issues/133119> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0038]: the trait `AsyncTrait` is not dyn compatible
   --> $DIR/works.rs:27:21
    |
@@ -24,6 +15,6 @@
    = help: consider moving `async_dispatch` to another trait
    = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/async-await/dyn/wrong-size.stderr b/tests/ui/async-await/dyn/wrong-size.stderr
index a465f91..4835c17 100644
--- a/tests/ui/async-await/dyn/wrong-size.stderr
+++ b/tests/ui/async-await/dyn/wrong-size.stderr
@@ -1,12 +1,3 @@
-warning: the feature `async_fn_in_dyn_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/wrong-size.rs:4:12
-   |
-LL | #![feature(async_fn_in_dyn_trait)]
-   |            ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #133119 <https://github.com/rust-lang/rust/issues/133119> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0038]: the trait `AsyncTrait` is not dyn compatible
   --> $DIR/wrong-size.rs:21:17
    |
@@ -24,6 +15,6 @@
    = help: consider moving `async_dispatch` to another trait
    = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead.
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/async-await/gat-is-send-across-await.rs b/tests/ui/async-await/gat-is-send-across-await.rs
new file mode 100644
index 0000000..43b7774
--- /dev/null
+++ b/tests/ui/async-await/gat-is-send-across-await.rs
@@ -0,0 +1,23 @@
+//! Regression test for <https://github.com/rust-lang/rust/issues/111852>.
+
+//@ edition:2018
+//@ check-pass
+
+#![allow(unused)]
+
+trait G: Send {
+    type Gat<'l>: Send
+    where
+        Self: 'l;
+
+    fn as_gat(&self) -> Self::Gat<'_>;
+}
+
+fn a(g: impl G) {
+    let _: &dyn Send = &async move {
+        let _gat = g.as_gat();
+        async{}.await
+    };
+}
+
+fn main() { }
diff --git a/tests/ui/attributes/malformed-reprs.stderr b/tests/ui/attributes/malformed-reprs.stderr
index 504ba91..6e77c6e 100644
--- a/tests/ui/attributes/malformed-reprs.stderr
+++ b/tests/ui/attributes/malformed-reprs.stderr
@@ -6,12 +6,6 @@
    |
    = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations>
 
-error[E0589]: invalid `repr(align)` attribute: not a power of two
-  --> $DIR/malformed-reprs.rs:9:14
-   |
-LL | #[repr(align(0))]
-   |              ^
-
 error: `repr` attribute cannot be used at crate level
   --> $DIR/malformed-reprs.rs:4:1
    |
@@ -19,7 +13,7 @@
    | ^^^^^^^^
 ...
 LL | enum Foo {}
-   |      --- the inner attribute doesn't annotate this enum
+   | ----------- the inner attribute doesn't annotate this item
    |
 help: perhaps you meant to use an outer attribute
    |
@@ -27,6 +21,12 @@
 LL + #[repr]
    |
 
+error[E0589]: invalid `repr(align)` attribute: not a power of two
+  --> $DIR/malformed-reprs.rs:9:14
+   |
+LL | #[repr(align(0))]
+   |              ^
+
 error[E0084]: unsupported representation for zero-variant enum
   --> $DIR/malformed-reprs.rs:9:1
    |
diff --git a/tests/ui/attributes/rustc_confusables_assoc_fn.rs b/tests/ui/attributes/rustc_confusables_assoc_fn.rs
new file mode 100644
index 0000000..5612ece
--- /dev/null
+++ b/tests/ui/attributes/rustc_confusables_assoc_fn.rs
@@ -0,0 +1,22 @@
+#![feature(rustc_attrs)]
+
+struct S;
+
+impl S {
+    #[rustc_confusables("bar")]
+    fn foo() {}
+
+    #[rustc_confusables("baz")]
+    fn qux(&self, x: i32) {}
+}
+
+fn main() {
+    S::bar();
+    //~^ ERROR no function or associated item named `bar`
+    //~| HELP you might have meant to use `foo`
+
+    let s = S;
+    s.baz(10);
+    //~^ ERROR no method named `baz`
+    //~| HELP you might have meant to use `qux`
+}
diff --git a/tests/ui/attributes/rustc_confusables_assoc_fn.stderr b/tests/ui/attributes/rustc_confusables_assoc_fn.stderr
new file mode 100644
index 0000000..657ca80
--- /dev/null
+++ b/tests/ui/attributes/rustc_confusables_assoc_fn.stderr
@@ -0,0 +1,33 @@
+error[E0599]: no function or associated item named `bar` found for struct `S` in the current scope
+  --> $DIR/rustc_confusables_assoc_fn.rs:14:8
+   |
+LL | struct S;
+   | -------- function or associated item `bar` not found for this struct
+...
+LL |     S::bar();
+   |        ^^^ function or associated item not found in `S`
+   |
+help: you might have meant to use `foo`
+   |
+LL -     S::bar();
+LL +     S::foo();
+   |
+
+error[E0599]: no method named `baz` found for struct `S` in the current scope
+  --> $DIR/rustc_confusables_assoc_fn.rs:19:7
+   |
+LL | struct S;
+   | -------- method `baz` not found for this struct
+...
+LL |     s.baz(10);
+   |       ^^^ method not found in `S`
+   |
+help: you might have meant to use `qux`
+   |
+LL -     s.baz(10);
+LL +     s.qux(10);
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/borrowck/generic_const_early_param.rs b/tests/ui/borrowck/generic_const_early_param.rs
index 0d07b68..e5fab59 100644
--- a/tests/ui/borrowck/generic_const_early_param.rs
+++ b/tests/ui/borrowck/generic_const_early_param.rs
@@ -1,5 +1,4 @@
 #![feature(generic_const_exprs)]
-//~^ WARN the feature `generic_const_exprs` is incomplete
 
 struct DataWrapper<'static> {
     //~^ ERROR invalid lifetime parameter name: `'static`
diff --git a/tests/ui/borrowck/generic_const_early_param.stderr b/tests/ui/borrowck/generic_const_early_param.stderr
index 6447f92..a9ee438 100644
--- a/tests/ui/borrowck/generic_const_early_param.stderr
+++ b/tests/ui/borrowck/generic_const_early_param.stderr
@@ -1,11 +1,11 @@
 error[E0262]: invalid lifetime parameter name: `'static`
-  --> $DIR/generic_const_early_param.rs:4:20
+  --> $DIR/generic_const_early_param.rs:3:20
    |
 LL | struct DataWrapper<'static> {
    |                    ^^^^^^^ 'static is a reserved lifetime name
 
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/generic_const_early_param.rs:6:12
+  --> $DIR/generic_const_early_param.rs:5:12
    |
 LL |     data: &'a [u8; Self::SIZE],
    |            ^^ undeclared lifetime
@@ -16,7 +16,7 @@
    |                    +++
 
 error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/generic_const_early_param.rs:10:18
+  --> $DIR/generic_const_early_param.rs:9:18
    |
 LL | impl DataWrapper<'a> {
    |                  ^^ undeclared lifetime
@@ -26,16 +26,7 @@
 LL | impl<'a> DataWrapper<'a> {
    |     ++++
 
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/generic_const_early_param.rs:1:12
-   |
-LL | #![feature(generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0261, E0262.
 For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr
index 06a7f47..06384c2 100644
--- a/tests/ui/check-cfg/target_feature.stderr
+++ b/tests/ui/check-cfg/target_feature.stderr
@@ -17,6 +17,7 @@
 `addsubiw`
 `adx`
 `aes`
+`allows-misaligned-mem-access`
 `altivec`
 `alu32`
 `amx-avx512`
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index efa0a7f..0ba2f0b 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -120,7 +120,7 @@
 LL |     sanitize = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `sanitize` are: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `realtime`, `safestack`, `shadow-call-stack`, and `thread`
+   = note: expected values for `sanitize` are: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `kernel-hwaddress`, `leak`, `memory`, `memtag`, `realtime`, `safestack`, `shadow-call-stack`, and `thread`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
diff --git a/tests/ui/closures/binder/const-bound.rs b/tests/ui/closures/binder/const-bound.rs
index 10d869f..e6984ed 100644
--- a/tests/ui/closures/binder/const-bound.rs
+++ b/tests/ui/closures/binder/const-bound.rs
@@ -1,5 +1,4 @@
 #![feature(closure_lifetime_binder, non_lifetime_binders)]
-//~^ WARN  is incomplete and may not be safe to use
 
 fn main()  {
     for<const N: i32> || -> () {};
diff --git a/tests/ui/closures/binder/const-bound.stderr b/tests/ui/closures/binder/const-bound.stderr
index b805879..a577880 100644
--- a/tests/ui/closures/binder/const-bound.stderr
+++ b/tests/ui/closures/binder/const-bound.stderr
@@ -1,23 +1,14 @@
 error: late-bound const parameters cannot be used currently
-  --> $DIR/const-bound.rs:5:15
+  --> $DIR/const-bound.rs:4:15
    |
 LL |     for<const N: i32> || -> () {};
    |               ^
 
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-bound.rs:1:37
-   |
-LL | #![feature(closure_lifetime_binder, non_lifetime_binders)]
-   |                                     ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: late-bound const parameter not allowed on closures
-  --> $DIR/const-bound.rs:5:9
+  --> $DIR/const-bound.rs:4:9
    |
 LL |     for<const N: i32> || -> () {};
    |         ^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/closures/binder/type-bound-2.rs b/tests/ui/closures/binder/type-bound-2.rs
index f4edcda..064fbf9 100644
--- a/tests/ui/closures/binder/type-bound-2.rs
+++ b/tests/ui/closures/binder/type-bound-2.rs
@@ -1,5 +1,4 @@
 #![feature(closure_lifetime_binder, non_lifetime_binders)]
-//~^ WARN  is incomplete and may not be safe to use
 
 fn main() {
     for<T> || -> () {};
diff --git a/tests/ui/closures/binder/type-bound-2.stderr b/tests/ui/closures/binder/type-bound-2.stderr
index 6609b326..6fd7d57 100644
--- a/tests/ui/closures/binder/type-bound-2.stderr
+++ b/tests/ui/closures/binder/type-bound-2.stderr
@@ -1,17 +1,8 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/type-bound-2.rs:1:37
-   |
-LL | #![feature(closure_lifetime_binder, non_lifetime_binders)]
-   |                                     ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: late-bound type parameter not allowed on closures
-  --> $DIR/type-bound-2.rs:5:9
+  --> $DIR/type-bound-2.rs:4:9
    |
 LL |     for<T> || -> () {};
    |         ^
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/closures/binder/type-bound.rs b/tests/ui/closures/binder/type-bound.rs
index 59a3353..9fc60b3 100644
--- a/tests/ui/closures/binder/type-bound.rs
+++ b/tests/ui/closures/binder/type-bound.rs
@@ -1,5 +1,4 @@
 #![feature(closure_lifetime_binder, non_lifetime_binders)]
-//~^ WARN  is incomplete and may not be safe to use
 
 fn main()  {
     for<T> || -> T {};
diff --git a/tests/ui/closures/binder/type-bound.stderr b/tests/ui/closures/binder/type-bound.stderr
index 2243113..11dc328 100644
--- a/tests/ui/closures/binder/type-bound.stderr
+++ b/tests/ui/closures/binder/type-bound.stderr
@@ -1,17 +1,8 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/type-bound.rs:1:37
-   |
-LL | #![feature(closure_lifetime_binder, non_lifetime_binders)]
-   |                                     ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: late-bound type parameter not allowed on closures
-  --> $DIR/type-bound.rs:5:9
+  --> $DIR/type-bound.rs:4:9
    |
 LL |     for<T> || -> T {};
    |         ^
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/codegen/freeze-on-polymorphic-projection.rs b/tests/ui/codegen/freeze-on-polymorphic-projection.rs
index f382a37..4744fa5 100644
--- a/tests/ui/codegen/freeze-on-polymorphic-projection.rs
+++ b/tests/ui/codegen/freeze-on-polymorphic-projection.rs
@@ -2,7 +2,6 @@
 //@ compile-flags: -Copt-level=1 --crate-type=lib
 
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
 
 pub unsafe trait Storage {
     type Handle;
diff --git a/tests/ui/codegen/freeze-on-polymorphic-projection.stderr b/tests/ui/codegen/freeze-on-polymorphic-projection.stderr
deleted file mode 100644
index 903cb2f..0000000
--- a/tests/ui/codegen/freeze-on-polymorphic-projection.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/freeze-on-polymorphic-projection.rs:4:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/coherence/coherence-doesnt-use-infcx-evaluate.rs b/tests/ui/coherence/coherence-doesnt-use-infcx-evaluate.rs
index 7e53695..a3dc9b5 100644
--- a/tests/ui/coherence/coherence-doesnt-use-infcx-evaluate.rs
+++ b/tests/ui/coherence/coherence-doesnt-use-infcx-evaluate.rs
@@ -5,7 +5,6 @@
 // since they are using a different infcx which doesn't preserve the intercrate flag.
 
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
 
 trait Assoc {
     type Output;
diff --git a/tests/ui/coherence/coherence-doesnt-use-infcx-evaluate.stderr b/tests/ui/coherence/coherence-doesnt-use-infcx-evaluate.stderr
deleted file mode 100644
index 56eb21c..0000000
--- a/tests/ui/coherence/coherence-doesnt-use-infcx-evaluate.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/coherence-doesnt-use-infcx-evaluate.rs:7:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs b/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs
index d74d3a2..7f0e547 100644
--- a/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs
+++ b/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs
@@ -4,7 +4,6 @@
 //
 // No we expect to run into a more user-friendly cycle error instead.
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
 
 trait Trait<T> { type Assoc; }
 //~^ ERROR E0391
diff --git a/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr b/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr
index 9f813d6..3d4d191 100644
--- a/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr
+++ b/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr
@@ -1,27 +1,17 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:6:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0391]: cycle detected when building specialization graph of trait `Trait`
-  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:9:1
+  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:8:1
    |
 LL | trait Trait<T> { type Assoc; }
    | ^^^^^^^^^^^^^^
    |
    = note: ...which immediately requires building specialization graph of trait `Trait` again
 note: cycle used when coherence checking all impls of trait `Trait`
-  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:9:1
+  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:8:1
    |
 LL | trait Trait<T> { type Assoc; }
    | ^^^^^^^^^^^^^^
    = 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; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/coherence/negative-coherence/regions-in-canonical.rs b/tests/ui/coherence/negative-coherence/regions-in-canonical.rs
index f0424e7..ff3999f 100644
--- a/tests/ui/coherence/negative-coherence/regions-in-canonical.rs
+++ b/tests/ui/coherence/negative-coherence/regions-in-canonical.rs
@@ -1,7 +1,6 @@
 //@ check-pass
 
 #![feature(adt_const_params, unsized_const_params)]
-//~^ WARN the feature `unsized_const_params` is incomplete
 #![feature(with_negative_coherence, negative_impls)]
 
 pub trait A<const K: &'static str> {}
diff --git a/tests/ui/coherence/negative-coherence/regions-in-canonical.stderr b/tests/ui/coherence/negative-coherence/regions-in-canonical.stderr
deleted file mode 100644
index 7204491..0000000
--- a/tests/ui/coherence/negative-coherence/regions-in-canonical.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/regions-in-canonical.rs:3:30
-   |
-LL | #![feature(adt_const_params, unsized_const_params)]
-   |                              ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.rs b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.rs
index e90426e..8825d53 100644
--- a/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.rs
+++ b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.rs
@@ -1,6 +1,5 @@
 //@ check-pass
 #![feature(adt_const_params, lazy_type_alias)]
-//~^ WARN: the feature `lazy_type_alias` is incomplete
 
 pub type Matrix = [usize; 1];
 const EMPTY_MATRIX: Matrix = [0; 1];
diff --git a/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.stderr b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.stderr
deleted file mode 100644
index 4f51334..0000000
--- a/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/alias_const_param_ty-1.rs:2:30
-   |
-LL | #![feature(adt_const_params, 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
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-2.rs b/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-2.rs
index 81b1ec6..9e2212b 100644
--- a/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-2.rs
+++ b/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-2.rs
@@ -2,7 +2,6 @@
 
 #![feature(adt_const_params)]
 #![feature(unsized_const_params)]
-//~^ WARN the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
 
 #[derive(Clone)]
 struct S<const L: [u8]>;
diff --git a/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-2.stderr b/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-2.stderr
index d538bb0..8112613 100644
--- a/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-2.stderr
+++ b/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-2.stderr
@@ -1,22 +1,13 @@
 error: free constant item without body
-  --> $DIR/unsized-anon-const-err-2.rs:10:1
+  --> $DIR/unsized-anon-const-err-2.rs:9:1
    |
 LL | const A: [u8];
    | ^^^^^^^^^^^^^-
    |              |
    |              help: provide a definition for the constant: `= <expr>;`
 
-warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unsized-anon-const-err-2.rs:4:12
-   |
-LL | #![feature(unsized_const_params)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/unsized-anon-const-err-2.rs:10:10
+  --> $DIR/unsized-anon-const-err-2.rs:9:10
    |
 LL | const A: [u8];
    |          ^^^^ doesn't have a size known at compile-time
@@ -25,7 +16,7 @@
    = note: statics and constants must have a statically known size
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/unsized-anon-const-err-2.rs:14:31
+  --> $DIR/unsized-anon-const-err-2.rs:13:31
    |
 LL | impl<const N: i32> Copy for S<A> {}
    |                               ^ doesn't have a size known at compile-time
@@ -34,7 +25,7 @@
    = note: statics and constants must have a statically known size
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/unsized-anon-const-err-2.rs:17:33
+  --> $DIR/unsized-anon-const-err-2.rs:16:33
    |
 LL | impl<const M: usize> Copy for S<A> {}
    |                                 ^ doesn't have a size known at compile-time
@@ -43,7 +34,7 @@
    = note: statics and constants must have a statically known size
 
 error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/unsized-anon-const-err-2.rs:14:6
+  --> $DIR/unsized-anon-const-err-2.rs:13:6
    |
 LL | impl<const N: i32> Copy for S<A> {}
    |      ^^^^^^^^^^^^ unconstrained const parameter
@@ -52,7 +43,7 @@
    = note: proving the result of expressions other than the parameter are unique is not supported
 
 error[E0207]: the const parameter `M` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/unsized-anon-const-err-2.rs:17:6
+  --> $DIR/unsized-anon-const-err-2.rs:16:6
    |
 LL | impl<const M: usize> Copy for S<A> {}
    |      ^^^^^^^^^^^^^^ unconstrained const parameter
@@ -60,7 +51,7 @@
    = 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 6 previous errors; 1 warning emitted
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0207, E0277.
 For more information about an error, try `rustc --explain E0207`.
diff --git a/tests/ui/const-generics/check_const_arg_type_in_free_alias.eager.stderr b/tests/ui/const-generics/check_const_arg_type_in_free_alias.eager.stderr
new file mode 100644
index 0000000..f62023b
--- /dev/null
+++ b/tests/ui/const-generics/check_const_arg_type_in_free_alias.eager.stderr
@@ -0,0 +1,133 @@
+error: the constant `B` is not of type `usize`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:15:1
+   |
+LL | type ArrLen<const B: bool> = [(); B];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
+   |
+   = note: the length of array `[(); B]` must be type `usize`
+
+error: the constant `B` is not of type `usize`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:19:1
+   |
+LL | type ConstArg<const B: bool> = Foo<B>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
+   |
+note: required by a const generic parameter in `Foo`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:13:12
+   |
+LL | struct Foo<const N: usize>;
+   |            ^^^^^^^^^^^^^^ required by this const generic parameter in `Foo`
+
+error: the constant `B` is not of type `usize`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:32:1
+   |
+LL | type Alias<const B: bool> = <() as IdentityWithUnused<B>>::This;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
+   |
+note: required by a const generic parameter in `IdentityWithUnused`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:24:26
+   |
+LL | trait IdentityWithUnused<const N: usize> {
+   |                          ^^^^^^^^^^^^^^ required by this const generic parameter in `IdentityWithUnused`
+
+error: the constant `B` is not of type `usize`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:38:1
+   |
+LL | type UseFree<const B: bool> = Free<B>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
+   |
+   = note: the length of array `[(); B]` must be type `usize`
+
+error: the constant `B` is not of type `usize`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:58:1
+   |
+LL | type IndirectArr<const B: bool> = Wrap<Wrap<[(); B]>>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
+   |
+   = note: the length of array `[(); B]` must be type `usize`
+
+error: the constant `B` is not of type `usize`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:62:1
+   |
+LL | type IndirectConstArg<const B: bool> = Wrap<Wrap<Foo<B>>>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
+   |
+note: required by a const generic parameter in `Foo`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:13:12
+   |
+LL | struct Foo<const N: usize>;
+   |            ^^^^^^^^^^^^^^ required by this const generic parameter in `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/check_const_arg_type_in_free_alias.rs:17:24
+   |
+LL | type AnonArrLen = [(); true];
+   |                        ^^^^ expected `usize`, found `bool`
+   |
+   = note: array length can only be `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/check_const_arg_type_in_free_alias.rs:21:25
+   |
+LL | type AnonConstArg = Foo<true>;
+   |                         ^^^^ expected `usize`, found `bool`
+   |
+note: expected because of the type of the const parameter
+  --> $DIR/check_const_arg_type_in_free_alias.rs:13:12
+   |
+LL | struct Foo<const N: usize>;
+   |            ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/check_const_arg_type_in_free_alias.rs:34:44
+   |
+LL | type AnonAlias = <() as IdentityWithUnused<true>>::This;
+   |                                            ^^^^ expected `usize`, found `bool`
+
+error[E0308]: mismatched types
+  --> $DIR/check_const_arg_type_in_free_alias.rs:40:25
+   |
+LL | type AnonUseFree = Free<true>;
+   |                         ^^^^ expected `usize`, found `bool`
+   |
+note: expected because of the type of the const parameter
+  --> $DIR/check_const_arg_type_in_free_alias.rs:37:11
+   |
+LL | type Free<const N: usize> = [(); N];
+   |           ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/check_const_arg_type_in_free_alias.rs:53:45
+   |
+LL | type AnonUseFreeIndirectlyCorrect = UseFree<1_usize>;
+   |                                             ^^^^^^^ expected `bool`, found `usize`
+   |
+note: expected because of the type of the const parameter
+  --> $DIR/check_const_arg_type_in_free_alias.rs:38:14
+   |
+LL | type UseFree<const B: bool> = Free<B>;
+   |              ^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/check_const_arg_type_in_free_alias.rs:60:39
+   |
+LL | type AnonIndirectArr = Wrap<Wrap<[(); true]>>;
+   |                                       ^^^^ expected `usize`, found `bool`
+   |
+   = note: array length can only be `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/check_const_arg_type_in_free_alias.rs:64:43
+   |
+LL | type AnonIndirectConstArg = Wrap<Wrap<Foo<true>>>;
+   |                                           ^^^^ expected `usize`, found `bool`
+   |
+note: expected because of the type of the const parameter
+  --> $DIR/check_const_arg_type_in_free_alias.rs:13:12
+   |
+LL | struct Foo<const N: usize>;
+   |            ^^^^^^^^^^^^^^
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/check_const_arg_type_in_free_alias.lazy.stderr b/tests/ui/const-generics/check_const_arg_type_in_free_alias.lazy.stderr
new file mode 100644
index 0000000..b9adb4e
--- /dev/null
+++ b/tests/ui/const-generics/check_const_arg_type_in_free_alias.lazy.stderr
@@ -0,0 +1,151 @@
+error: the constant `B` is not of type `usize`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:15:1
+   |
+LL | type ArrLen<const B: bool> = [(); B];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
+   |
+   = note: the length of array `[(); B]` must be type `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/check_const_arg_type_in_free_alias.rs:17:24
+   |
+LL | type AnonArrLen = [(); true];
+   |                        ^^^^ expected `usize`, found `bool`
+   |
+   = note: array length can only be `usize`
+
+error: the constant `B` is not of type `usize`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:19:1
+   |
+LL | type ConstArg<const B: bool> = Foo<B>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
+   |
+note: required by a const generic parameter in `Foo`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:13:12
+   |
+LL | struct Foo<const N: usize>;
+   |            ^^^^^^^^^^^^^^ required by this const generic parameter in `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/check_const_arg_type_in_free_alias.rs:21:25
+   |
+LL | type AnonConstArg = Foo<true>;
+   |                         ^^^^ expected `usize`, found `bool`
+   |
+note: expected because of the type of the const parameter
+  --> $DIR/check_const_arg_type_in_free_alias.rs:13:12
+   |
+LL | struct Foo<const N: usize>;
+   |            ^^^^^^^^^^^^^^
+
+error: the constant `B` is not of type `usize`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:32:1
+   |
+LL | type Alias<const B: bool> = <() as IdentityWithUnused<B>>::This;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
+   |
+note: required for `()` to implement `IdentityWithUnused<B>`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:28:25
+   |
+LL | impl<T, const N: usize> IdentityWithUnused<N> for T {
+   |         --------------  ^^^^^^^^^^^^^^^^^^^^^     ^
+   |         |
+   |         unsatisfied trait bound introduced here
+
+error[E0308]: mismatched types
+  --> $DIR/check_const_arg_type_in_free_alias.rs:34:44
+   |
+LL | type AnonAlias = <() as IdentityWithUnused<true>>::This;
+   |                                            ^^^^ expected `usize`, found `bool`
+
+error: the constant `B` is not of type `usize`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:38:1
+   |
+LL | type UseFree<const B: bool> = Free<B>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
+   |
+note: required by a bound on the type alias `Free`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:37:11
+   |
+LL | type Free<const N: usize> = [(); N];
+   |           ^^^^^^^^^^^^^^ required by this bound
+
+error[E0308]: mismatched types
+  --> $DIR/check_const_arg_type_in_free_alias.rs:40:25
+   |
+LL | type AnonUseFree = Free<true>;
+   |                         ^^^^ expected `usize`, found `bool`
+   |
+note: expected because of the type of the const parameter
+  --> $DIR/check_const_arg_type_in_free_alias.rs:37:11
+   |
+LL | type Free<const N: usize> = [(); N];
+   |           ^^^^^^^^^^^^^^
+
+error: the constant `N` is not of type `bool`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:51:1
+   |
+LL | type UseFreeIndirectlyCorrect<const N: usize> = UseFree<N>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `usize`
+   |
+note: required by a bound on the type alias `UseFree`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:38:14
+   |
+LL | type UseFree<const B: bool> = Free<B>;
+   |              ^^^^^^^^^^^^^ required by this bound
+
+error[E0308]: mismatched types
+  --> $DIR/check_const_arg_type_in_free_alias.rs:53:45
+   |
+LL | type AnonUseFreeIndirectlyCorrect = UseFree<1_usize>;
+   |                                             ^^^^^^^ expected `bool`, found `usize`
+   |
+note: expected because of the type of the const parameter
+  --> $DIR/check_const_arg_type_in_free_alias.rs:38:14
+   |
+LL | type UseFree<const B: bool> = Free<B>;
+   |              ^^^^^^^^^^^^^
+
+error: the constant `B` is not of type `usize`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:58:1
+   |
+LL | type IndirectArr<const B: bool> = Wrap<Wrap<[(); B]>>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
+   |
+   = note: the length of array `[(); B]` must be type `usize`
+
+error[E0308]: mismatched types
+  --> $DIR/check_const_arg_type_in_free_alias.rs:60:39
+   |
+LL | type AnonIndirectArr = Wrap<Wrap<[(); true]>>;
+   |                                       ^^^^ expected `usize`, found `bool`
+   |
+   = note: array length can only be `usize`
+
+error: the constant `B` is not of type `usize`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:62:1
+   |
+LL | type IndirectConstArg<const B: bool> = Wrap<Wrap<Foo<B>>>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
+   |
+note: required by a const generic parameter in `Foo`
+  --> $DIR/check_const_arg_type_in_free_alias.rs:13:12
+   |
+LL | struct Foo<const N: usize>;
+   |            ^^^^^^^^^^^^^^ required by this const generic parameter in `Foo`
+
+error[E0308]: mismatched types
+  --> $DIR/check_const_arg_type_in_free_alias.rs:64:43
+   |
+LL | type AnonIndirectConstArg = Wrap<Wrap<Foo<true>>>;
+   |                                           ^^^^ expected `usize`, found `bool`
+   |
+note: expected because of the type of the const parameter
+  --> $DIR/check_const_arg_type_in_free_alias.rs:13:12
+   |
+LL | struct Foo<const N: usize>;
+   |            ^^^^^^^^^^^^^^
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/check_const_arg_type_in_free_alias.rs b/tests/ui/const-generics/check_const_arg_type_in_free_alias.rs
new file mode 100644
index 0000000..12e277f
--- /dev/null
+++ b/tests/ui/const-generics/check_const_arg_type_in_free_alias.rs
@@ -0,0 +1,67 @@
+//@ revisions: eager lazy
+#![cfg_attr(lazy, feature(lazy_type_alias))]
+#![cfg_attr(lazy, expect(incomplete_features))]
+
+// We currently do not check free type aliases for well formedness.
+// However, previously we desugared all const arguments to anon
+// consts which resulted in us happening to check that they were
+// of the correct type. Nowadays we don't necessarily lower to a
+// const argument, but to continue erroring on such code we special
+// case `ConstArgHasType` clauses to be checked for free type aliases
+// even though we ignore the rest of the wf requirements.
+
+struct Foo<const N: usize>;
+
+type ArrLen<const B: bool> = [(); B];
+//~^ ERROR: the constant `B` is not of type
+type AnonArrLen = [(); true];
+//~^ ERROR: mismatched types
+type ConstArg<const B: bool> = Foo<B>;
+//~^ ERROR: the constant `B` is not of type
+type AnonConstArg = Foo<true>;
+//~^ ERROR: mismatched types
+
+trait IdentityWithUnused<const N: usize> {
+    type This;
+}
+
+impl<T, const N: usize> IdentityWithUnused<N> for T {
+    type This = T;
+}
+
+type Alias<const B: bool> = <() as IdentityWithUnused<B>>::This;
+//~^ ERROR: the constant `B` is not of type
+type AnonAlias = <() as IdentityWithUnused<true>>::This;
+//~^ ERROR: mismatched types
+
+type Free<const N: usize> = [(); N];
+type UseFree<const B: bool> = Free<B>;
+//~^ ERROR: the constant `B` is not of type
+type AnonUseFree = Free<true>;
+//~^ ERROR: mismatched types
+
+// This previously emitted an error before we stopped using
+// anon consts. Now, as free aliases don't exist after ty
+// lowering, we don't emit an error because we only see `N`
+// being used as an argument to an array length.
+//
+// Free type aliases are not allowed to have unused generic
+// parameters so this shouldn't be able to cause code to
+// pass that should error.
+type UseFreeIndirectlyCorrect<const N: usize> = UseFree<N>;
+//[lazy]~^ ERROR: the constant `N` is not of type
+type AnonUseFreeIndirectlyCorrect = UseFree<1_usize>;
+//~^ ERROR: mismatched types
+
+struct Wrap<T>(T);
+
+type IndirectArr<const B: bool> = Wrap<Wrap<[(); B]>>;
+//~^ ERROR: the constant `B` is not of type
+type AnonIndirectArr = Wrap<Wrap<[(); true]>>;
+//~^ ERROR: mismatched types
+type IndirectConstArg<const B: bool> = Wrap<Wrap<Foo<B>>>;
+//~^ ERROR: the constant `B` is not of type
+type AnonIndirectConstArg = Wrap<Wrap<Foo<true>>>;
+//~^ ERROR: mismatched types
+
+fn main() {}
diff --git a/tests/ui/const-generics/check_const_arg_type_in_trait_object.rs b/tests/ui/const-generics/check_const_arg_type_in_trait_object.rs
new file mode 100644
index 0000000..f5c5350
--- /dev/null
+++ b/tests/ui/const-generics/check_const_arg_type_in_trait_object.rs
@@ -0,0 +1,36 @@
+// We currently do not check trait objects for well formedness.
+// However, previously we desugared all const arguments to anon
+// consts which resulted in us happening to check that they were
+// of the correct type. Nowadays we don't necessarily lower to a
+// const argument, but to continue erroring on such code we special
+// case `ConstArgHasType` clauses to be checked for trait objects
+// even though we ignore the rest of the wf requirements.
+
+trait Object<const N: usize> {}
+trait Object2<T> {}
+trait Object3<'a: 'static, const N: usize> {}
+
+struct Wrap<T>(T);
+
+fn arg<const B: bool, const N: usize>(
+    param: &dyn Object<B>,
+    //~^ ERROR: the constant `B` is not of type
+    anon: &dyn Object<true>,
+    //~^ ERROR: mismatched types
+) {
+}
+
+fn indirect<const B: bool, const N: usize>(
+    param: &dyn Object2<Wrap<[(); B]>>,
+    //~^ ERROR: the constant `B` is not of type
+    anon: &dyn Object2<Wrap<[(); true]>>,
+    //~^ ERROR: mismatched types
+) {
+}
+
+// the 'a: 'static bound should *not* have its error reported (at least, until we implement checking
+// all wf things for dyn objects)
+fn binder<const B: bool>(param: &dyn for<'a> Object3<'a, B>) {}
+//~^ ERROR: the constant `B` is not of type
+
+fn main() {}
diff --git a/tests/ui/const-generics/check_const_arg_type_in_trait_object.stderr b/tests/ui/const-generics/check_const_arg_type_in_trait_object.stderr
new file mode 100644
index 0000000..4e228f6
--- /dev/null
+++ b/tests/ui/const-generics/check_const_arg_type_in_trait_object.stderr
@@ -0,0 +1,49 @@
+error[E0308]: mismatched types
+  --> $DIR/check_const_arg_type_in_trait_object.rs:18:23
+   |
+LL |     anon: &dyn Object<true>,
+   |                       ^^^^ expected `usize`, found `bool`
+
+error: the constant `B` is not of type `usize`
+  --> $DIR/check_const_arg_type_in_trait_object.rs:16:12
+   |
+LL |     param: &dyn Object<B>,
+   |            ^^^^^^^^^^^^^^ expected `usize`, found `bool`
+   |
+note: required by a const generic parameter in `Object`
+  --> $DIR/check_const_arg_type_in_trait_object.rs:9:14
+   |
+LL | trait Object<const N: usize> {}
+   |              ^^^^^^^^^^^^^^ required by this const generic parameter in `Object`
+
+error[E0308]: mismatched types
+  --> $DIR/check_const_arg_type_in_trait_object.rs:26:34
+   |
+LL |     anon: &dyn Object2<Wrap<[(); true]>>,
+   |                                  ^^^^ expected `usize`, found `bool`
+   |
+   = note: array length can only be `usize`
+
+error: the constant `B` is not of type `usize`
+  --> $DIR/check_const_arg_type_in_trait_object.rs:24:12
+   |
+LL |     param: &dyn Object2<Wrap<[(); B]>>,
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
+   |
+   = note: the length of array `[(); B]` must be type `usize`
+
+error: the constant `B` is not of type `usize`
+  --> $DIR/check_const_arg_type_in_trait_object.rs:33:33
+   |
+LL | fn binder<const B: bool>(param: &dyn for<'a> Object3<'a, B>) {}
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
+   |
+note: required by a const generic parameter in `Object3`
+  --> $DIR/check_const_arg_type_in_trait_object.rs:11:28
+   |
+LL | trait Object3<'a: 'static, const N: usize> {}
+   |                            ^^^^^^^^^^^^^^ required by this const generic parameter in `Object3`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/defaults/concrete-const-param-type.rs b/tests/ui/const-generics/defaults/concrete-const-param-type.rs
index c411f81..a2eb37b 100644
--- a/tests/ui/const-generics/defaults/concrete-const-param-type.rs
+++ b/tests/ui/const-generics/defaults/concrete-const-param-type.rs
@@ -1,6 +1,4 @@
 #![feature(generic_const_parameter_types, unsized_const_params, adt_const_params)]
-//~^ WARN the feature `generic_const_parameter_types` is incomplete
-//~| WARN the feature `unsized_const_params` is incomplete
 // Make sure that we test the const param type of default const parameters
 // if both the type of the default and the type of the parameter are concrete.
 
diff --git a/tests/ui/const-generics/defaults/concrete-const-param-type.stderr b/tests/ui/const-generics/defaults/concrete-const-param-type.stderr
index ad077f8..805d5a1 100644
--- a/tests/ui/const-generics/defaults/concrete-const-param-type.stderr
+++ b/tests/ui/const-generics/defaults/concrete-const-param-type.stderr
@@ -1,25 +1,8 @@
-warning: the feature `generic_const_parameter_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/concrete-const-param-type.rs:1:12
-   |
-LL | #![feature(generic_const_parameter_types, unsized_const_params, adt_const_params)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #137626 <https://github.com/rust-lang/rust/issues/137626> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/concrete-const-param-type.rs:1:43
-   |
-LL | #![feature(generic_const_parameter_types, unsized_const_params, adt_const_params)]
-   |                                           ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
-
 error: the constant `N` is not of type `u64`
-  --> $DIR/concrete-const-param-type.rs:9:26
+  --> $DIR/concrete-const-param-type.rs:7:26
    |
 LL | struct Foo<const N: u32, const M: u64 = N>;
    |                          ^^^^^^^^^^^^^^^^ expected `u64`, found `u32`
 
-error: aborting due to 1 previous error; 2 warnings emitted
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/const-generics/exhaustive-value.stderr b/tests/ui/const-generics/exhaustive-value.stderr
index 791bb19..3377f4c 100644
--- a/tests/ui/const-generics/exhaustive-value.stderr
+++ b/tests/ui/const-generics/exhaustive-value.stderr
@@ -4,15 +4,15 @@
 LL |     <() as Foo<N>>::test()
    |      ^^ the trait `Foo<N>` is not implemented for `()`
    |
-   = help: the following other types implement trait `Foo<N>`:
-             `()` implements `Foo<0>`
-             `()` implements `Foo<100>`
-             `()` implements `Foo<101>`
-             `()` implements `Foo<102>`
-             `()` implements `Foo<103>`
-             `()` implements `Foo<104>`
-             `()` implements `Foo<105>`
-             `()` implements `Foo<106>`
+   = help: `()` implements trait `Foo<N>`:
+             Foo<0>
+             Foo<100>
+             Foo<101>
+             Foo<102>
+             Foo<103>
+             Foo<104>
+             Foo<105>
+             Foo<106>
            and 248 others
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/const-generics/generic_const_exprs/cannot-convert-refree-ice-114463.rs b/tests/ui/const-generics/generic_const_exprs/cannot-convert-refree-ice-114463.rs
index 2ce998e..5008179 100644
--- a/tests/ui/const-generics/generic_const_exprs/cannot-convert-refree-ice-114463.rs
+++ b/tests/ui/const-generics/generic_const_exprs/cannot-convert-refree-ice-114463.rs
@@ -1,7 +1,7 @@
 // issue: rust-lang/rust#114463
 // ICE cannot convert `ReFree ..` to a region vid
 #![feature(generic_const_exprs)]
-//~^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+
 fn bug<'a>() {
     [(); (|_: &'a u8| (), 0).1];
     //~^ ERROR cannot capture late-bound lifetime in constant
diff --git a/tests/ui/const-generics/generic_const_exprs/cannot-convert-refree-ice-114463.stderr b/tests/ui/const-generics/generic_const_exprs/cannot-convert-refree-ice-114463.stderr
index e484540..a468ba6 100644
--- a/tests/ui/const-generics/generic_const_exprs/cannot-convert-refree-ice-114463.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/cannot-convert-refree-ice-114463.stderr
@@ -1,12 +1,3 @@
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/cannot-convert-refree-ice-114463.rs:3:12
-   |
-LL | #![feature(generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: cannot capture late-bound lifetime in constant
   --> $DIR/cannot-convert-refree-ice-114463.rs:6:16
    |
@@ -15,5 +6,5 @@
 LL |     [(); (|_: &'a u8| (), 0).1];
    |                ^^
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs
index a6988a4..679f6b7 100644
--- a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs
+++ b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs
@@ -1,5 +1,4 @@
 #![feature(generic_const_exprs)]
-//~^ WARN the feature `generic_const_exprs` is incomplete
 
 fn foo<T>() {
     let _ = [0u8; { const { std::mem::size_of::<T>() } }];
diff --git a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr
index db547e6..78d1540 100644
--- a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr
@@ -1,14 +1,5 @@
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-block-is-poly.rs:1:12
-   |
-LL | #![feature(generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: overly complex generic constant
-  --> $DIR/const-block-is-poly.rs:5:19
+  --> $DIR/const-block-is-poly.rs:4:19
    |
 LL |     let _ = [0u8; { const { std::mem::size_of::<T>() } }];
    |                   ^^----------------------------------^^
@@ -18,5 +9,5 @@
    = help: consider moving this anonymous constant into a `const` function
    = note: this operation may be supported in the future
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/const-generics/generic_const_exprs/double-opaque-parent-predicates.rs b/tests/ui/const-generics/generic_const_exprs/double-opaque-parent-predicates.rs
index e48d559..c5f4bbb 100644
--- a/tests/ui/const-generics/generic_const_exprs/double-opaque-parent-predicates.rs
+++ b/tests/ui/const-generics/generic_const_exprs/double-opaque-parent-predicates.rs
@@ -1,7 +1,6 @@
 //@ check-pass
 
 #![feature(generic_const_exprs)]
-//~^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use
 
 pub fn y<'a, U: 'a>() -> impl IntoIterator<Item = impl IntoIterator<Item = [u8; { 1 + 2 }]> + 'a> {
     [[[1, 2, 3]]]
diff --git a/tests/ui/const-generics/generic_const_exprs/double-opaque-parent-predicates.stderr b/tests/ui/const-generics/generic_const_exprs/double-opaque-parent-predicates.stderr
deleted file mode 100644
index faaede1..0000000
--- a/tests/ui/const-generics/generic_const_exprs/double-opaque-parent-predicates.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/double-opaque-parent-predicates.rs:3:12
-   |
-LL | #![feature(generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/const-generics/generic_const_exprs/eval-try-unify.rs b/tests/ui/const-generics/generic_const_exprs/eval-try-unify.rs
index b61d2dc..d2b8d94 100644
--- a/tests/ui/const-generics/generic_const_exprs/eval-try-unify.rs
+++ b/tests/ui/const-generics/generic_const_exprs/eval-try-unify.rs
@@ -1,7 +1,6 @@
 //@ build-pass
 
 #![feature(generic_const_exprs)]
-//~^ WARNING the feature `generic_const_exprs` is incomplete
 
 trait Generic {
     const ASSOC: usize;
diff --git a/tests/ui/const-generics/generic_const_exprs/eval-try-unify.stderr b/tests/ui/const-generics/generic_const_exprs/eval-try-unify.stderr
deleted file mode 100644
index 8eb1fcc..0000000
--- a/tests/ui/const-generics/generic_const_exprs/eval-try-unify.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/eval-try-unify.rs:3:12
-   |
-LL | #![feature(generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs
index 443d0a2..965e074 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs
+++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs
@@ -1,8 +1,6 @@
 //@ check-pass
 
 #![feature(adt_const_params, unsized_const_params, generic_const_exprs)]
-//~^ WARN the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
-//~^^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
 
 pub struct Changes<const CHANGES: &'static [&'static str]>
 where
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr
deleted file mode 100644
index b6b2975..0000000
--- a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-97047-ice-1.rs:3:30
-   |
-LL | #![feature(adt_const_params, unsized_const_params, generic_const_exprs)]
-   |                              ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-97047-ice-1.rs:3:52
-   |
-LL | #![feature(adt_const_params, unsized_const_params, generic_const_exprs)]
-   |                                                    ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-
-warning: 2 warnings emitted
-
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs
index 6a91b52..728d132 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs
+++ b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs
@@ -1,8 +1,6 @@
 //@ check-pass
 
 #![feature(adt_const_params, unsized_const_params, generic_const_exprs)]
-//~^ WARN the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
-//~^^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
 
 pub struct Changes<const CHANGES: &'static [&'static str]>
 where
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr b/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr
deleted file mode 100644
index c0c7dcc..0000000
--- a/tests/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-97047-ice-2.rs:3:30
-   |
-LL | #![feature(adt_const_params, unsized_const_params, generic_const_exprs)]
-   |                              ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-97047-ice-2.rs:3:52
-   |
-LL | #![feature(adt_const_params, unsized_const_params, generic_const_exprs)]
-   |                                                    ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-
-warning: 2 warnings emitted
-
diff --git a/tests/ui/const-generics/generic_const_exprs/mismatched-gat-subst-kind.rs b/tests/ui/const-generics/generic_const_exprs/mismatched-gat-subst-kind.rs
index 734a378..85af36e 100644
--- a/tests/ui/const-generics/generic_const_exprs/mismatched-gat-subst-kind.rs
+++ b/tests/ui/const-generics/generic_const_exprs/mismatched-gat-subst-kind.rs
@@ -1,5 +1,4 @@
 #![feature(generic_const_exprs)]
-//~^ WARN the feature `generic_const_exprs` is incomplete
 
 trait B {
     type U<T>;
diff --git a/tests/ui/const-generics/generic_const_exprs/mismatched-gat-subst-kind.stderr b/tests/ui/const-generics/generic_const_exprs/mismatched-gat-subst-kind.stderr
index 1036b72..b11eb10 100644
--- a/tests/ui/const-generics/generic_const_exprs/mismatched-gat-subst-kind.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/mismatched-gat-subst-kind.stderr
@@ -1,18 +1,9 @@
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/mismatched-gat-subst-kind.rs:1:12
-   |
-LL | #![feature(generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0747]: constant provided when a type was expected
-  --> $DIR/mismatched-gat-subst-kind.rs:8:13
+  --> $DIR/mismatched-gat-subst-kind.rs:7:13
    |
 LL | fn f<T: B<U<1i32> = ()>>() {}
    |             ^^^^
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0747`.
diff --git a/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.rs b/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.rs
index 9af351e..6e382de 100644
--- a/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.rs
+++ b/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.rs
@@ -1,6 +1,5 @@
 // Regression test for #133271.
 #![feature(generic_const_exprs)]
-//~^ WARN the feature `generic_const_exprs` is incomplete
 
 struct Foo;
 impl<'a, const NUM: usize> std::ops::Add<&'a Foo> for Foo
diff --git a/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.stderr b/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.stderr
index 37eb895..d58bc67 100644
--- a/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/post-analysis-user-facing-param-env.stderr
@@ -1,5 +1,5 @@
 error[E0407]: method `unimplemented` is not a member of trait `std::ops::Add`
-  --> $DIR/post-analysis-user-facing-param-env.rs:12:5
+  --> $DIR/post-analysis-user-facing-param-env.rs:11:5
    |
 LL | /     fn unimplemented(self, _: &Foo) -> Self::Output {
 LL | |
@@ -7,17 +7,8 @@
 LL | |     }
    | |_____^ not a member of trait `std::ops::Add`
 
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/post-analysis-user-facing-param-env.rs:2:12
-   |
-LL | #![feature(generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0046]: not all trait items implemented, missing: `Output`, `add`
-  --> $DIR/post-analysis-user-facing-param-env.rs:6:1
+  --> $DIR/post-analysis-user-facing-param-env.rs:5:1
    |
 LL | / impl<'a, const NUM: usize> std::ops::Add<&'a Foo> for Foo
 LL | |
@@ -30,7 +21,7 @@
    = help: implement the missing item: `fn add(self, _: &'a Foo) -> <Self as Add<&'a Foo>>::Output { todo!() }`
 
 error[E0207]: the const parameter `NUM` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/post-analysis-user-facing-param-env.rs:6:10
+  --> $DIR/post-analysis-user-facing-param-env.rs:5:10
    |
 LL | impl<'a, const NUM: usize> std::ops::Add<&'a Foo> for Foo
    |          ^^^^^^^^^^^^^^^^ unconstrained const parameter
@@ -38,7 +29,7 @@
    = 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; 1 warning emitted
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0046, E0207, E0407.
 For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.rs b/tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.rs
index d3ae863..d605c83 100644
--- a/tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.rs
+++ b/tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.rs
@@ -5,7 +5,6 @@
 #![feature(with_negative_coherence)]
 #![feature(min_specialization)]
 #![feature(generic_const_exprs)]
-//~^ WARNING the feature `generic_const_exprs` is incomplete
 
 #![crate_type = "lib"]
 trait Trait {}
diff --git a/tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.stderr b/tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.stderr
deleted file mode 100644
index f17b248..0000000
--- a/tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-fuzzing-ice-133639.rs:7:12
-   |
-LL | #![feature(generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.rs b/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.rs
index d3bc544..4de1616 100644
--- a/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.rs
+++ b/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.rs
@@ -1,8 +1,6 @@
 // Ensure that we actually treat `N`'s type as `&'a u32` in MIR typeck.
 
 #![feature(unsized_const_params, adt_const_params, generic_const_parameter_types)]
-//~^ WARN the feature `unsized_const_params` is incomplete
-//~| WARN the feature `generic_const_parameter_types` is incomplete
 
 fn foo<'a, const N: &'a u32>() {
     let b: &'static u32 = N;
diff --git a/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.stderr b/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.stderr
index 3dc7ce4..0b7a43a 100644
--- a/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.stderr
+++ b/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.stderr
@@ -1,27 +1,10 @@
-warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/check-type-in-mir.rs:3:12
-   |
-LL | #![feature(unsized_const_params, adt_const_params, generic_const_parameter_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: the feature `generic_const_parameter_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/check-type-in-mir.rs:3:52
-   |
-LL | #![feature(unsized_const_params, adt_const_params, generic_const_parameter_types)]
-   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #137626 <https://github.com/rust-lang/rust/issues/137626> for more information
-
 error: lifetime may not live long enough
-  --> $DIR/check-type-in-mir.rs:8:12
+  --> $DIR/check-type-in-mir.rs:6:12
    |
 LL | fn foo<'a, const N: &'a u32>() {
    |        -- lifetime `'a` defined here
 LL |     let b: &'static u32 = N;
    |            ^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
 
-error: aborting due to 1 previous error; 2 warnings emitted
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr
index 2d47797..7e61566 100644
--- a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr
+++ b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr
@@ -1,14 +1,5 @@
-warning: the feature `generic_const_parameter_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/references-parent-generics.rs:3:27
-   |
-LL | #![cfg_attr(feat, feature(generic_const_parameter_types))]
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #137626 <https://github.com/rust-lang/rust/issues/137626> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: `Self` is forbidden as the type of a const generic parameter
-  --> $DIR/references-parent-generics.rs:7:25
+  --> $DIR/references-parent-generics.rs:6:25
    |
 LL |     type Assoc<const N: Self>;
    |                         ^^^^
@@ -16,10 +7,10 @@
    = note: the only supported types are integers, `bool`, and `char`
 
 error: anonymous constants referencing generics are not yet supported
-  --> $DIR/references-parent-generics.rs:15:21
+  --> $DIR/references-parent-generics.rs:14:21
    |
 LL |     let x: T::Assoc<3>;
    |                     ^
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr
index 68ce173..ac25a4e 100644
--- a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr
+++ b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr
@@ -1,5 +1,5 @@
 error[E0770]: the type of const parameters must not depend on other generic parameters
-  --> $DIR/references-parent-generics.rs:7:25
+  --> $DIR/references-parent-generics.rs:6:25
    |
 LL |     type Assoc<const N: Self>;
    |                         ^^^^ the type must not depend on the parameter `Self`
diff --git a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs
index b91050d..6eadb60 100644
--- a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs
+++ b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs
@@ -1,7 +1,6 @@
 //@ revisions: feat nofeat
 
 #![cfg_attr(feat, feature(generic_const_parameter_types))]
-//[feat]~^ WARN the feature `generic_const_parameter_types` is incomplete
 
 trait Foo {
     type Assoc<const N: Self>;
diff --git a/tests/ui/const-generics/mgca/assoc-const-without-type_const.stderr b/tests/ui/const-generics/mgca/assoc-const-without-type_const.stderr
index 759a40c..1a5f77b 100644
--- a/tests/ui/const-generics/mgca/assoc-const-without-type_const.stderr
+++ b/tests/ui/const-generics/mgca/assoc-const-without-type_const.stderr
@@ -1,20 +1,24 @@
 error: use of `const` in the type system not defined as `type const`
   --> $DIR/assoc-const-without-type_const.rs:8:35
    |
-LL |     const SIZE: usize;
-   |     - help: add `type` before `const` for `Tr::SIZE`: `type`
-...
 LL | fn mk_array<T: Tr>(_x: T) -> [(); T::SIZE] {
    |                                   ^^^^^^^
+   |
+help: add `type` before `const` for `Tr::SIZE`
+   |
+LL |     type const SIZE: usize;
+   |     ++++
 
 error: use of `const` in the type system not defined as `type const`
   --> $DIR/assoc-const-without-type_const.rs:10:10
    |
-LL |     const SIZE: usize;
-   |     - help: add `type` before `const` for `Tr::SIZE`: `type`
-...
 LL |     [(); T::SIZE]
    |          ^^^^^^^
+   |
+help: add `type` before `const` for `Tr::SIZE`
+   |
+LL |     type const SIZE: usize;
+   |     ++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/mgca/struct-ctor-in-array-len.rs b/tests/ui/const-generics/mgca/struct-ctor-in-array-len.rs
index 715caef..c828843 100644
--- a/tests/ui/const-generics/mgca/struct-ctor-in-array-len.rs
+++ b/tests/ui/const-generics/mgca/struct-ctor-in-array-len.rs
@@ -6,7 +6,6 @@
 // It should now produce a proper type error.
 
 #![feature(min_generic_const_args)]
-//~^ WARN the feature `min_generic_const_args` is incomplete
 
 struct S;
 
diff --git a/tests/ui/const-generics/mgca/struct-ctor-in-array-len.stderr b/tests/ui/const-generics/mgca/struct-ctor-in-array-len.stderr
index baf587a..fcf02621 100644
--- a/tests/ui/const-generics/mgca/struct-ctor-in-array-len.stderr
+++ b/tests/ui/const-generics/mgca/struct-ctor-in-array-len.stderr
@@ -1,19 +1,10 @@
-warning: the feature `min_generic_const_args` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/struct-ctor-in-array-len.rs:8:12
-   |
-LL | #![feature(min_generic_const_args)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: the constant `S` is not of type `usize`
-  --> $DIR/struct-ctor-in-array-len.rs:14:14
+  --> $DIR/struct-ctor-in-array-len.rs:13:14
    |
 LL |     let _b = [0; S];
    |              ^^^^^^ expected `usize`, found `S`
    |
    = note: the length of array `[{integer}; S]` must be type `usize`
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.rs b/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.rs
index 1c3274f..4d96d23 100644
--- a/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.rs
+++ b/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.rs
@@ -1,7 +1,6 @@
 // Make sure we don't ICE when encountering an fn item during lowering in mGCA.
 
 #![feature(min_generic_const_args)]
-//~^ WARN the feature `min_generic_const_args` is incomplete
 
 trait A<T> {}
 
diff --git a/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.stderr b/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.stderr
index 89fc827..de64bf7 100644
--- a/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.stderr
+++ b/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.stderr
@@ -1,19 +1,10 @@
-warning: the feature `min_generic_const_args` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unexpected-fn-item-in-array.rs:3:12
-   |
-LL | #![feature(min_generic_const_args)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: the constant `fn_item` is not of type `usize`
-  --> $DIR/unexpected-fn-item-in-array.rs:8:6
+  --> $DIR/unexpected-fn-item-in-array.rs:7:6
    |
 LL | impl A<[usize; fn_item]> for () {}
    |      ^^^^^^^^^^^^^^^^^^^ expected `usize`, found fn item
    |
    = note: the length of array `[usize; fn_item]` must be type `usize`
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/const-generics/mgca/unmarked-free-const.stderr b/tests/ui/const-generics/mgca/unmarked-free-const.stderr
index 76875d8..dd33de4 100644
--- a/tests/ui/const-generics/mgca/unmarked-free-const.stderr
+++ b/tests/ui/const-generics/mgca/unmarked-free-const.stderr
@@ -1,11 +1,13 @@
 error: use of `const` in the type system not defined as `type const`
   --> $DIR/unmarked-free-const.rs:9:18
    |
-LL | const N: usize = 4;
-   | - help: add `type` before `const` for `N`: `type`
-...
 LL |     let x = [(); N];
    |                  ^
+   |
+help: add `type` before `const` for `N`
+   |
+LL | type const N: usize = 4;
+   | ++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr b/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr
index 9392a17..ec39cc2 100644
--- a/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr
+++ b/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr
@@ -56,7 +56,7 @@
                ff __ __ __                                     │ .░░░
            }
 
-error[E0080]: constructing invalid value: encountered 0x42, but expected a boolean
+error[E0080]: constructing invalid value of type bool: encountered 0x42, but expected a boolean
   --> $DIR/invalid-patterns.rs:42:14
    |
 LL |   get_flag::<{ unsafe { bool_raw.boolean } }, 'z'>();
@@ -67,7 +67,7 @@
                42                                              │ B
            }
 
-error[E0080]: constructing invalid value: encountered 0x42, but expected a boolean
+error[E0080]: constructing invalid value of type bool: encountered 0x42, but expected a boolean
   --> $DIR/invalid-patterns.rs:44:14
    |
 LL |   get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>();
diff --git a/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr b/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr
index 9392a17..ec39cc2 100644
--- a/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr
+++ b/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr
@@ -56,7 +56,7 @@
                ff __ __ __                                     │ .░░░
            }
 
-error[E0080]: constructing invalid value: encountered 0x42, but expected a boolean
+error[E0080]: constructing invalid value of type bool: encountered 0x42, but expected a boolean
   --> $DIR/invalid-patterns.rs:42:14
    |
 LL |   get_flag::<{ unsafe { bool_raw.boolean } }, 'z'>();
@@ -67,7 +67,7 @@
                42                                              │ B
            }
 
-error[E0080]: constructing invalid value: encountered 0x42, but expected a boolean
+error[E0080]: constructing invalid value of type bool: encountered 0x42, but expected a boolean
   --> $DIR/invalid-patterns.rs:44:14
    |
 LL |   get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>();
diff --git a/tests/ui/const-generics/occurs-check/unify-fixpoint.rs b/tests/ui/const-generics/occurs-check/unify-fixpoint.rs
index 02bc909..950757e 100644
--- a/tests/ui/const-generics/occurs-check/unify-fixpoint.rs
+++ b/tests/ui/const-generics/occurs-check/unify-fixpoint.rs
@@ -4,8 +4,7 @@
 
 //@ compile-flags: -Zunstable-options
 //@ check-pass
-#![feature(generic_const_exprs)] //~ WARN the feature `generic_const_exprs` is incomplete
-
+#![feature(generic_const_exprs)]
 
 fn bind<const N: usize>(value: [u8; N + 2]) -> [u8; N * 2] {
     todo!()
diff --git a/tests/ui/const-generics/occurs-check/unify-fixpoint.stderr b/tests/ui/const-generics/occurs-check/unify-fixpoint.stderr
deleted file mode 100644
index 8b63e8c..0000000
--- a/tests/ui/const-generics/occurs-check/unify-fixpoint.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unify-fixpoint.rs:7:12
-   |
-LL | #![feature(generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/const-ptr/forbidden_slices.stderr b/tests/ui/const-ptr/forbidden_slices.stderr
index 70ae00a..fb74be3 100644
--- a/tests/ui/const-ptr/forbidden_slices.stderr
+++ b/tests/ui/const-ptr/forbidden_slices.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value: encountered a null reference
+error[E0080]: constructing invalid value of type &[u32]: encountered a null reference
   --> $DIR/forbidden_slices.rs:16:1
    |
 LL | pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) };
@@ -9,7 +9,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered a null reference
+error[E0080]: constructing invalid value of type &[()]: encountered a null reference
   --> $DIR/forbidden_slices.rs:18:1
    |
 LL | pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) };
@@ -20,7 +20,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
+error[E0080]: constructing invalid value of type &[u32]: encountered a dangling reference (going beyond the bounds of its allocation)
   --> $DIR/forbidden_slices.rs:22:1
    |
 LL | pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 2) };
@@ -31,7 +31,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
+error[E0080]: constructing invalid value of type &[u8]: at .<deref>[0], encountered uninitialized memory, but expected an integer
   --> $DIR/forbidden_slices.rs:26:1
    |
 LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) };
@@ -42,7 +42,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
+error[E0080]: constructing invalid value of type &[u8]: at .<deref>[0], encountered a pointer, but expected an integer
   --> $DIR/forbidden_slices.rs:28:1
    |
 LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size_of::<&u32>()) };
@@ -55,7 +55,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean
+error[E0080]: constructing invalid value of type &[bool]: at .<deref>[0], encountered 0x11, but expected a boolean
   --> $DIR/forbidden_slices.rs:30:1
    |
 LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) };
@@ -66,7 +66,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<deref>[1]: encountered uninitialized memory, but expected an integer
+error[E0080]: constructing invalid value of type &[u16]: at .<deref>[1], encountered uninitialized memory, but expected an integer
   --> $DIR/forbidden_slices.rs:33:1
    |
 LL | pub static S7: &[u16] = unsafe {
@@ -77,7 +77,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
+error[E0080]: constructing invalid value of type &[u64]: encountered a dangling reference (going beyond the bounds of its allocation)
   --> $DIR/forbidden_slices.rs:41:1
    |
 LL | pub static S8: &[u64] = unsafe {
@@ -88,7 +88,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered a null reference
+error[E0080]: constructing invalid value of type &[u32]: encountered a null reference
   --> $DIR/forbidden_slices.rs:48:1
    |
 LL | pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
@@ -111,7 +111,7 @@
 LL |     from_ptr_range(ptr..ptr.add(2)) // errors inside libcore
    |                         ^^^^^^^^^^ evaluation of `R2` failed here
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
+error[E0080]: constructing invalid value of type &[u8]: at .<deref>[0], encountered uninitialized memory, but expected an integer
   --> $DIR/forbidden_slices.rs:57:1
    |
 LL | pub static R4: &[u8] = unsafe {
@@ -122,7 +122,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
+error[E0080]: constructing invalid value of type &[u8]: at .<deref>[0], encountered a pointer, but expected an integer
   --> $DIR/forbidden_slices.rs:62:1
    |
 LL | pub static R5: &[u8] = unsafe {
@@ -135,7 +135,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean
+error[E0080]: constructing invalid value of type &[bool]: at .<deref>[0], encountered 0x11, but expected a boolean
   --> $DIR/forbidden_slices.rs:67:1
    |
 LL | pub static R6: &[bool] = unsafe {
@@ -146,7 +146,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+error[E0080]: constructing invalid value of type &[u16]: encountered an unaligned reference (required 2 byte alignment but found 1)
   --> $DIR/forbidden_slices.rs:72:1
    |
 LL | pub static R7: &[u16] = unsafe {
diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr
index 239bca5..f8d6cc1 100644
--- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr
+++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.32bit.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value at .<deref>: encountered uninitialized memory, but expected an integer
+error[E0080]: constructing invalid value of type &i32: at .<deref>, encountered uninitialized memory, but expected an integer
   --> $DIR/alloc_intrinsic_uninit.rs:7:1
    |
 LL | const BAR: &i32 = unsafe {
diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr
index 3c6d66a..f7b652f 100644
--- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr
+++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_uninit.64bit.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value at .<deref>: encountered uninitialized memory, but expected an integer
+error[E0080]: constructing invalid value of type &i32: at .<deref>, encountered uninitialized memory, but expected an integer
   --> $DIR/alloc_intrinsic_uninit.rs:7:1
    |
 LL | const BAR: &i32 = unsafe {
diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr
index 152eeab..0942924 100644
--- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr
+++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_dangling.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value: encountered a dangling reference (use-after-free)
+error[E0080]: constructing invalid value of type &u8: encountered a dangling reference (use-after-free)
   --> $DIR/dealloc_intrinsic_dangling.rs:11:1
    |
 LL | const _X: &'static u8 = unsafe {
diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
index acbf19d..65f815f 100644
--- a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
+++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value at .<enum-tag>: encountered 0x00000001, but expected a valid enum tag
+error[E0080]: constructing invalid value of type Enum: at .<enum-tag>, encountered 0x00000001, but expected a valid enum tag
   --> $DIR/raw-bytes.rs:23:1
    |
 LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
@@ -9,7 +9,7 @@
                01 00 00 00                                     │ ....
            }
 
-error[E0080]: constructing invalid value at .<enum-tag>: encountered 0x00000000, but expected a valid enum tag
+error[E0080]: constructing invalid value of type Enum2: at .<enum-tag>, encountered 0x00000000, but expected a valid enum tag
   --> $DIR/raw-bytes.rs:31:1
    |
 LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
@@ -20,7 +20,7 @@
                00 00 00 00                                     │ ....
            }
 
-error[E0080]: constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
+error[E0080]: constructing invalid value of type UninhDiscriminant: at .<enum-tag>, encountered an uninhabited enum variant
   --> $DIR/raw-bytes.rs:45:1
    |
 LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
@@ -31,7 +31,7 @@
                01                                              │ .
            }
 
-error[E0080]: constructing invalid value at .<enum-tag>: encountered 0x03, but expected a valid enum tag
+error[E0080]: constructing invalid value of type UninhDiscriminant: at .<enum-tag>, encountered 0x03, but expected a valid enum tag
   --> $DIR/raw-bytes.rs:47:1
    |
 LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
@@ -42,7 +42,7 @@
                03                                              │ .
            }
 
-error[E0080]: constructing invalid value at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
+error[E0080]: constructing invalid value of type Option<(char, char)>: at .<enum-variant(Some)>.0.1, encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
   --> $DIR/raw-bytes.rs:53:1
    |
 LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
@@ -53,7 +53,7 @@
                78 00 00 00 ff ff ff ff                         │ x.......
            }
 
-error[E0080]: constructing invalid value: encountered 0, but expected something greater or equal to 1
+error[E0080]: constructing invalid value of type NonNull<u8>: encountered 0, but expected something greater or equal to 1
   --> $DIR/raw-bytes.rs:58:1
    |
 LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
@@ -64,7 +64,7 @@
                00 00 00 00                                     │ ....
            }
 
-error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
+error[E0080]: constructing invalid value of type NonZero<u8>: at .0.0, encountered 0, but expected something greater or equal to 1
   --> $DIR/raw-bytes.rs:61:1
    |
 LL | const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
@@ -75,7 +75,7 @@
                00                                              │ .
            }
 
-error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
+error[E0080]: constructing invalid value of type NonZero<usize>: at .0.0, encountered 0, but expected something greater or equal to 1
   --> $DIR/raw-bytes.rs:63:1
    |
 LL | const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };
@@ -86,7 +86,7 @@
                00 00 00 00                                     │ ....
            }
 
-error[E0080]: constructing invalid value: encountered 42, but expected something in the range 10..=30
+error[E0080]: constructing invalid value of type RestrictedRange1: encountered 42, but expected something in the range 10..=30
   --> $DIR/raw-bytes.rs:69:1
    |
 LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
@@ -97,7 +97,7 @@
                2a 00 00 00                                     │ *...
            }
 
-error[E0080]: constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30
+error[E0080]: constructing invalid value of type RestrictedRange2: encountered 20, but expected something less or equal to 10, or greater or equal to 30
   --> $DIR/raw-bytes.rs:75:1
    |
 LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
@@ -108,7 +108,7 @@
                14 00 00 00                                     │ ....
            }
 
-error[E0080]: constructing invalid value: encountered 0, but expected something greater or equal to 1
+error[E0080]: constructing invalid value of type NonNull<dyn Send>: encountered 0, but expected something greater or equal to 1
   --> $DIR/raw-bytes.rs:78:1
    |
 LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
@@ -119,7 +119,7 @@
                00 00 00 00 ╾ALLOC_ID╼                         │ ....╾──╼
            }
 
-error[E0080]: constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+error[E0080]: constructing invalid value of type &u16: encountered an unaligned reference (required 2 byte alignment but found 1)
   --> $DIR/raw-bytes.rs:85:1
    |
 LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
@@ -130,7 +130,7 @@
                ╾ALLOC_ID╼                                     │ ╾──╼
            }
 
-error[E0080]: constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1)
+error[E0080]: constructing invalid value of type Box<u16>: encountered an unaligned box (required 2 byte alignment but found 1)
   --> $DIR/raw-bytes.rs:88:1
    |
 LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
@@ -141,7 +141,7 @@
                ╾ALLOC_ID╼                                     │ ╾──╼
            }
 
-error[E0080]: constructing invalid value: encountered a null reference
+error[E0080]: constructing invalid value of type &u16: encountered a null reference
   --> $DIR/raw-bytes.rs:91:1
    |
 LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
@@ -152,7 +152,7 @@
                00 00 00 00                                     │ ....
            }
 
-error[E0080]: constructing invalid value: encountered a null box
+error[E0080]: constructing invalid value of type Box<u16>: encountered a null box
   --> $DIR/raw-bytes.rs:94:1
    |
 LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
@@ -163,7 +163,7 @@
                00 00 00 00                                     │ ....
            }
 
-error[E0080]: constructing invalid value: encountered a dangling reference (0x539[noalloc] has no provenance)
+error[E0080]: constructing invalid value of type &u8: encountered a dangling reference (0x539[noalloc] has no provenance)
   --> $DIR/raw-bytes.rs:97:1
    |
 LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
@@ -174,7 +174,7 @@
                39 05 00 00                                     │ 9...
            }
 
-error[E0080]: constructing invalid value: encountered a dangling box (0x539[noalloc] has no provenance)
+error[E0080]: constructing invalid value of type Box<u8>: encountered a dangling box (0x539[noalloc] has no provenance)
   --> $DIR/raw-bytes.rs:100:1
    |
 LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
@@ -185,7 +185,7 @@
                39 05 00 00                                     │ 9...
            }
 
-error[E0080]: constructing invalid value: encountered null pointer, but expected a function pointer
+error[E0080]: constructing invalid value of type fn(): encountered null pointer, but expected a function pointer
   --> $DIR/raw-bytes.rs:103:1
    |
 LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
@@ -196,7 +196,7 @@
                00 00 00 00                                     │ ....
            }
 
-error[E0080]: constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
+error[E0080]: constructing invalid value of type fn(): encountered 0xd[noalloc], but expected a function pointer
   --> $DIR/raw-bytes.rs:105:1
    |
 LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
@@ -207,7 +207,7 @@
                0d 00 00 00                                     │ ....
            }
 
-error[E0080]: constructing invalid value: encountered ALLOC3<imm>, but expected a function pointer
+error[E0080]: constructing invalid value of type fn(): encountered ALLOC3<imm>, but expected a function pointer
   --> $DIR/raw-bytes.rs:107:1
    |
 LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
@@ -218,7 +218,7 @@
                ╾ALLOC_ID╼                                     │ ╾──╼
            }
 
-error[E0080]: constructing invalid value: encountered a reference pointing to uninhabited type Bar
+error[E0080]: constructing invalid value of type &Bar: encountered a reference pointing to uninhabited type Bar
   --> $DIR/raw-bytes.rs:113:1
    |
 LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
@@ -229,7 +229,7 @@
                01 00 00 00                                     │ ....
            }
 
-error[E0080]: constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
+error[E0080]: constructing invalid value of type &str: encountered a dangling reference (going beyond the bounds of its allocation)
   --> $DIR/raw-bytes.rs:137:1
    |
 LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
@@ -240,7 +240,7 @@
                ╾ALLOC_ID╼ e7 03 00 00                         │ ╾──╼....
            }
 
-error[E0080]: constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object
+error[E0080]: constructing invalid value of type (&str,): at .0, encountered invalid reference metadata: slice is bigger than largest supported object
   --> $DIR/raw-bytes.rs:139:1
    |
 LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
@@ -251,7 +251,7 @@
                ╾ALLOC_ID╼ ff ff ff ff                         │ ╾──╼....
            }
 
-error[E0080]: constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
+error[E0080]: constructing invalid value of type &MyStr: encountered invalid reference metadata: slice is bigger than largest supported object
   --> $DIR/raw-bytes.rs:141:1
    |
 LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
@@ -262,7 +262,7 @@
                ╾ALLOC_ID╼ ff ff ff ff                         │ ╾──╼....
            }
 
-error[E0080]: constructing invalid value at .<deref>: encountered uninitialized memory, but expected a string
+error[E0080]: constructing invalid value of type &str: at .<deref>, encountered uninitialized memory, but expected a string
   --> $DIR/raw-bytes.rs:144:1
    |
 LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
@@ -273,7 +273,7 @@
                ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
 
-error[E0080]: constructing invalid value at .<deref>.0: encountered uninitialized memory, but expected a string
+error[E0080]: constructing invalid value of type &MyStr: at .<deref>.0, encountered uninitialized memory, but expected a string
   --> $DIR/raw-bytes.rs:146:1
    |
 LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
@@ -284,7 +284,7 @@
                ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
 
-error[E0080]: constructing invalid value at .<deref>.0: encountered a pointer, but expected a string
+error[E0080]: constructing invalid value of type &MyStr: at .<deref>.0, encountered a pointer, but expected a string
   --> $DIR/raw-bytes.rs:148:1
    |
 LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) };
@@ -297,7 +297,7 @@
                ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
 
-error[E0080]: constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
+error[E0080]: constructing invalid value of type &[u8]: encountered a dangling reference (going beyond the bounds of its allocation)
   --> $DIR/raw-bytes.rs:152:1
    |
 LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
@@ -308,7 +308,7 @@
                ╾ALLOC_ID╼ e7 03 00 00                         │ ╾──╼....
            }
 
-error[E0080]: constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
+error[E0080]: constructing invalid value of type &[u32]: encountered invalid reference metadata: slice is bigger than largest supported object
   --> $DIR/raw-bytes.rs:154:1
    |
 LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
@@ -319,7 +319,7 @@
                ╾ALLOC_ID╼ ff ff ff 7f                         │ ╾──╼....
            }
 
-error[E0080]: constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation)
+error[E0080]: constructing invalid value of type Box<[u8]>: encountered a dangling box (going beyond the bounds of its allocation)
   --> $DIR/raw-bytes.rs:157:1
    |
 LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
@@ -330,7 +330,7 @@
                ╾ALLOC_ID╼ e7 03 00 00                         │ ╾──╼....
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean
+error[E0080]: constructing invalid value of type &[bool; 1]: at .<deref>[0], encountered 0x03, but expected a boolean
   --> $DIR/raw-bytes.rs:160:1
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
@@ -347,7 +347,7 @@
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0080]: constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean
+error[E0080]: constructing invalid value of type &MySlice<[bool; 1]>: at .<deref>.0, encountered 0x03, but expected a boolean
   --> $DIR/raw-bytes.rs:164:1
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
@@ -364,7 +364,7 @@
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0080]: constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean
+error[E0080]: constructing invalid value of type &MySlice<[bool; 1]>: at .<deref>.1[0], encountered 0x03, but expected a boolean
   --> $DIR/raw-bytes.rs:167:1
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
@@ -381,7 +381,7 @@
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0080]: constructing invalid value at .0: encountered ALLOC17<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC17<imm>, but expected a vtable pointer
   --> $DIR/raw-bytes.rs:171:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
@@ -392,7 +392,7 @@
                ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
-error[E0080]: constructing invalid value at .0: encountered ALLOC19<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC19<imm>, but expected a vtable pointer
   --> $DIR/raw-bytes.rs:174:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
@@ -403,7 +403,7 @@
                ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
-error[E0080]: constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered 0x4[noalloc], but expected a vtable pointer
   --> $DIR/raw-bytes.rs:177:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
@@ -414,7 +414,7 @@
                ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
-error[E0080]: constructing invalid value at .0: encountered ALLOC22<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC22<imm>, but expected a vtable pointer
   --> $DIR/raw-bytes.rs:179:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
@@ -425,7 +425,7 @@
                ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
-error[E0080]: constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
+error[E0080]: constructing invalid value of type &dyn Trait: at .<deref>.<dyn-downcast(bool)>, encountered 0x03, but expected a boolean
   --> $DIR/raw-bytes.rs:182:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
@@ -436,7 +436,7 @@
                ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
-error[E0080]: constructing invalid value: encountered null pointer, but expected a vtable pointer
+error[E0080]: constructing invalid value of type *const dyn Trait: encountered null pointer, but expected a vtable pointer
   --> $DIR/raw-bytes.rs:185:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
@@ -447,7 +447,7 @@
                ╾ALLOC_ID╼ 00 00 00 00                         │ ╾──╼....
            }
 
-error[E0080]: constructing invalid value: encountered ALLOC27<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type *const dyn Trait: encountered ALLOC27<imm>, but expected a vtable pointer
   --> $DIR/raw-bytes.rs:187:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
@@ -458,7 +458,7 @@
                ╾ALLOC_ID╼ ╾ALLOC_ID╼                         │ ╾──╼╾──╼
            }
 
-error[E0080]: constructing invalid value: encountered a reference pointing to uninhabited type [!; 1]
+error[E0080]: constructing invalid value of type &[!; 1]: encountered a reference pointing to uninhabited type [!; 1]
   --> $DIR/raw-bytes.rs:191:1
    |
 LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
@@ -469,7 +469,7 @@
                01 00 00 00                                     │ ....
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered a value of the never type `!`
+error[E0080]: constructing invalid value of type &[!]: at .<deref>[0], encountered a value of the never type `!`
   --> $DIR/raw-bytes.rs:192:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
@@ -480,7 +480,7 @@
                01 00 00 00 01 00 00 00                         │ ........
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered a value of the never type `!`
+error[E0080]: constructing invalid value of type &[!]: at .<deref>[0], encountered a value of the never type `!`
   --> $DIR/raw-bytes.rs:193:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
@@ -491,7 +491,7 @@
                01 00 00 00 2a 00 00 00                         │ ....*...
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
+error[E0080]: constructing invalid value of type &[u8]: at .<deref>[0], encountered uninitialized memory, but expected an integer
   --> $DIR/raw-bytes.rs:196:1
    |
 LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) };
@@ -502,7 +502,7 @@
                ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
+error[E0080]: constructing invalid value of type &[u8]: at .<deref>[0], encountered a pointer, but expected an integer
   --> $DIR/raw-bytes.rs:199:1
    |
 LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem::size_of::<&u32>()) };
@@ -515,7 +515,7 @@
                ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean
+error[E0080]: constructing invalid value of type &[bool]: at .<deref>[0], encountered 0x11, but expected a boolean
   --> $DIR/raw-bytes.rs:202:1
    |
 LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) };
@@ -526,7 +526,7 @@
                ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
-error[E0080]: constructing invalid value at .<deref>[1]: encountered uninitialized memory, but expected an integer
+error[E0080]: constructing invalid value of type &[u16]: at .<deref>[1], encountered uninitialized memory, but expected an integer
   --> $DIR/raw-bytes.rs:206:1
    |
 LL | pub static S7: &[u16] = unsafe {
@@ -537,7 +537,7 @@
                ╾ALLOC_ID+0x2╼ 04 00 00 00                         │ ╾──╼....
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
+error[E0080]: constructing invalid value of type &[u8]: at .<deref>[0], encountered uninitialized memory, but expected an integer
   --> $DIR/raw-bytes.rs:213:1
    |
 LL | pub static R4: &[u8] = unsafe {
@@ -548,7 +548,7 @@
                ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
+error[E0080]: constructing invalid value of type &[u8]: at .<deref>[0], encountered a pointer, but expected an integer
   --> $DIR/raw-bytes.rs:218:1
    |
 LL | pub static R5: &[u8] = unsafe {
@@ -561,7 +561,7 @@
                ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean
+error[E0080]: constructing invalid value of type &[bool]: at .<deref>[0], encountered 0x11, but expected a boolean
   --> $DIR/raw-bytes.rs:223:1
    |
 LL | pub static R6: &[bool] = unsafe {
diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
index 52d32fd..d117de2 100644
--- a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
+++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value at .<enum-tag>: encountered 0x0000000000000001, but expected a valid enum tag
+error[E0080]: constructing invalid value of type Enum: at .<enum-tag>, encountered 0x0000000000000001, but expected a valid enum tag
   --> $DIR/raw-bytes.rs:23:1
    |
 LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
@@ -9,7 +9,7 @@
                01 00 00 00 00 00 00 00                         │ ........
            }
 
-error[E0080]: constructing invalid value at .<enum-tag>: encountered 0x0000000000000000, but expected a valid enum tag
+error[E0080]: constructing invalid value of type Enum2: at .<enum-tag>, encountered 0x0000000000000000, but expected a valid enum tag
   --> $DIR/raw-bytes.rs:31:1
    |
 LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
@@ -20,7 +20,7 @@
                00 00 00 00 00 00 00 00                         │ ........
            }
 
-error[E0080]: constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
+error[E0080]: constructing invalid value of type UninhDiscriminant: at .<enum-tag>, encountered an uninhabited enum variant
   --> $DIR/raw-bytes.rs:45:1
    |
 LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
@@ -31,7 +31,7 @@
                01                                              │ .
            }
 
-error[E0080]: constructing invalid value at .<enum-tag>: encountered 0x03, but expected a valid enum tag
+error[E0080]: constructing invalid value of type UninhDiscriminant: at .<enum-tag>, encountered 0x03, but expected a valid enum tag
   --> $DIR/raw-bytes.rs:47:1
    |
 LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
@@ -42,7 +42,7 @@
                03                                              │ .
            }
 
-error[E0080]: constructing invalid value at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
+error[E0080]: constructing invalid value of type Option<(char, char)>: at .<enum-variant(Some)>.0.1, encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
   --> $DIR/raw-bytes.rs:53:1
    |
 LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
@@ -53,7 +53,7 @@
                78 00 00 00 ff ff ff ff                         │ x.......
            }
 
-error[E0080]: constructing invalid value: encountered 0, but expected something greater or equal to 1
+error[E0080]: constructing invalid value of type NonNull<u8>: encountered 0, but expected something greater or equal to 1
   --> $DIR/raw-bytes.rs:58:1
    |
 LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
@@ -64,7 +64,7 @@
                00 00 00 00 00 00 00 00                         │ ........
            }
 
-error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
+error[E0080]: constructing invalid value of type NonZero<u8>: at .0.0, encountered 0, but expected something greater or equal to 1
   --> $DIR/raw-bytes.rs:61:1
    |
 LL | const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
@@ -75,7 +75,7 @@
                00                                              │ .
            }
 
-error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
+error[E0080]: constructing invalid value of type NonZero<usize>: at .0.0, encountered 0, but expected something greater or equal to 1
   --> $DIR/raw-bytes.rs:63:1
    |
 LL | const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };
@@ -86,7 +86,7 @@
                00 00 00 00 00 00 00 00                         │ ........
            }
 
-error[E0080]: constructing invalid value: encountered 42, but expected something in the range 10..=30
+error[E0080]: constructing invalid value of type RestrictedRange1: encountered 42, but expected something in the range 10..=30
   --> $DIR/raw-bytes.rs:69:1
    |
 LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
@@ -97,7 +97,7 @@
                2a 00 00 00                                     │ *...
            }
 
-error[E0080]: constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30
+error[E0080]: constructing invalid value of type RestrictedRange2: encountered 20, but expected something less or equal to 10, or greater or equal to 30
   --> $DIR/raw-bytes.rs:75:1
    |
 LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
@@ -108,7 +108,7 @@
                14 00 00 00                                     │ ....
            }
 
-error[E0080]: constructing invalid value: encountered 0, but expected something greater or equal to 1
+error[E0080]: constructing invalid value of type NonNull<dyn Send>: encountered 0, but expected something greater or equal to 1
   --> $DIR/raw-bytes.rs:78:1
    |
 LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
@@ -119,7 +119,7 @@
                00 00 00 00 00 00 00 00 ╾ALLOC_ID╼ │ ........╾──────╼
            }
 
-error[E0080]: constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+error[E0080]: constructing invalid value of type &u16: encountered an unaligned reference (required 2 byte alignment but found 1)
   --> $DIR/raw-bytes.rs:85:1
    |
 LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
@@ -130,7 +130,7 @@
                ╾ALLOC_ID╼                         │ ╾──────╼
            }
 
-error[E0080]: constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1)
+error[E0080]: constructing invalid value of type Box<u16>: encountered an unaligned box (required 2 byte alignment but found 1)
   --> $DIR/raw-bytes.rs:88:1
    |
 LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
@@ -141,7 +141,7 @@
                ╾ALLOC_ID╼                         │ ╾──────╼
            }
 
-error[E0080]: constructing invalid value: encountered a null reference
+error[E0080]: constructing invalid value of type &u16: encountered a null reference
   --> $DIR/raw-bytes.rs:91:1
    |
 LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
@@ -152,7 +152,7 @@
                00 00 00 00 00 00 00 00                         │ ........
            }
 
-error[E0080]: constructing invalid value: encountered a null box
+error[E0080]: constructing invalid value of type Box<u16>: encountered a null box
   --> $DIR/raw-bytes.rs:94:1
    |
 LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
@@ -163,7 +163,7 @@
                00 00 00 00 00 00 00 00                         │ ........
            }
 
-error[E0080]: constructing invalid value: encountered a dangling reference (0x539[noalloc] has no provenance)
+error[E0080]: constructing invalid value of type &u8: encountered a dangling reference (0x539[noalloc] has no provenance)
   --> $DIR/raw-bytes.rs:97:1
    |
 LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
@@ -174,7 +174,7 @@
                39 05 00 00 00 00 00 00                         │ 9.......
            }
 
-error[E0080]: constructing invalid value: encountered a dangling box (0x539[noalloc] has no provenance)
+error[E0080]: constructing invalid value of type Box<u8>: encountered a dangling box (0x539[noalloc] has no provenance)
   --> $DIR/raw-bytes.rs:100:1
    |
 LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
@@ -185,7 +185,7 @@
                39 05 00 00 00 00 00 00                         │ 9.......
            }
 
-error[E0080]: constructing invalid value: encountered null pointer, but expected a function pointer
+error[E0080]: constructing invalid value of type fn(): encountered null pointer, but expected a function pointer
   --> $DIR/raw-bytes.rs:103:1
    |
 LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
@@ -196,7 +196,7 @@
                00 00 00 00 00 00 00 00                         │ ........
            }
 
-error[E0080]: constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
+error[E0080]: constructing invalid value of type fn(): encountered 0xd[noalloc], but expected a function pointer
   --> $DIR/raw-bytes.rs:105:1
    |
 LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
@@ -207,7 +207,7 @@
                0d 00 00 00 00 00 00 00                         │ ........
            }
 
-error[E0080]: constructing invalid value: encountered ALLOC3<imm>, but expected a function pointer
+error[E0080]: constructing invalid value of type fn(): encountered ALLOC3<imm>, but expected a function pointer
   --> $DIR/raw-bytes.rs:107:1
    |
 LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
@@ -218,7 +218,7 @@
                ╾ALLOC_ID╼                         │ ╾──────╼
            }
 
-error[E0080]: constructing invalid value: encountered a reference pointing to uninhabited type Bar
+error[E0080]: constructing invalid value of type &Bar: encountered a reference pointing to uninhabited type Bar
   --> $DIR/raw-bytes.rs:113:1
    |
 LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
@@ -229,7 +229,7 @@
                01 00 00 00 00 00 00 00                         │ ........
            }
 
-error[E0080]: constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
+error[E0080]: constructing invalid value of type &str: encountered a dangling reference (going beyond the bounds of its allocation)
   --> $DIR/raw-bytes.rs:137:1
    |
 LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
@@ -240,7 +240,7 @@
                ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object
+error[E0080]: constructing invalid value of type (&str,): at .0, encountered invalid reference metadata: slice is bigger than largest supported object
   --> $DIR/raw-bytes.rs:139:1
    |
 LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
@@ -251,7 +251,7 @@
                ╾ALLOC_ID╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
            }
 
-error[E0080]: constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
+error[E0080]: constructing invalid value of type &MyStr: encountered invalid reference metadata: slice is bigger than largest supported object
   --> $DIR/raw-bytes.rs:141:1
    |
 LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
@@ -262,7 +262,7 @@
                ╾ALLOC_ID╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
            }
 
-error[E0080]: constructing invalid value at .<deref>: encountered uninitialized memory, but expected a string
+error[E0080]: constructing invalid value of type &str: at .<deref>, encountered uninitialized memory, but expected a string
   --> $DIR/raw-bytes.rs:144:1
    |
 LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
@@ -273,7 +273,7 @@
                ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: constructing invalid value at .<deref>.0: encountered uninitialized memory, but expected a string
+error[E0080]: constructing invalid value of type &MyStr: at .<deref>.0, encountered uninitialized memory, but expected a string
   --> $DIR/raw-bytes.rs:146:1
    |
 LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
@@ -284,7 +284,7 @@
                ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: constructing invalid value at .<deref>.0: encountered a pointer, but expected a string
+error[E0080]: constructing invalid value of type &MyStr: at .<deref>.0, encountered a pointer, but expected a string
   --> $DIR/raw-bytes.rs:148:1
    |
 LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) };
@@ -297,7 +297,7 @@
                ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
+error[E0080]: constructing invalid value of type &[u8]: encountered a dangling reference (going beyond the bounds of its allocation)
   --> $DIR/raw-bytes.rs:152:1
    |
 LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
@@ -308,7 +308,7 @@
                ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
+error[E0080]: constructing invalid value of type &[u32]: encountered invalid reference metadata: slice is bigger than largest supported object
   --> $DIR/raw-bytes.rs:154:1
    |
 LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
@@ -319,7 +319,7 @@
                ╾ALLOC_ID╼ ff ff ff ff ff ff ff 7f │ ╾──────╼........
            }
 
-error[E0080]: constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation)
+error[E0080]: constructing invalid value of type Box<[u8]>: encountered a dangling box (going beyond the bounds of its allocation)
   --> $DIR/raw-bytes.rs:157:1
    |
 LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
@@ -330,7 +330,7 @@
                ╾ALLOC_ID╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean
+error[E0080]: constructing invalid value of type &[bool; 1]: at .<deref>[0], encountered 0x03, but expected a boolean
   --> $DIR/raw-bytes.rs:160:1
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
@@ -347,7 +347,7 @@
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0080]: constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean
+error[E0080]: constructing invalid value of type &MySlice<[bool; 1]>: at .<deref>.0, encountered 0x03, but expected a boolean
   --> $DIR/raw-bytes.rs:164:1
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
@@ -364,7 +364,7 @@
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0080]: constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean
+error[E0080]: constructing invalid value of type &MySlice<[bool; 1]>: at .<deref>.1[0], encountered 0x03, but expected a boolean
   --> $DIR/raw-bytes.rs:167:1
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
@@ -381,7 +381,7 @@
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0080]: constructing invalid value at .0: encountered ALLOC17<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC17<imm>, but expected a vtable pointer
   --> $DIR/raw-bytes.rs:171:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
@@ -392,7 +392,7 @@
                ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
-error[E0080]: constructing invalid value at .0: encountered ALLOC19<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC19<imm>, but expected a vtable pointer
   --> $DIR/raw-bytes.rs:174:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
@@ -403,7 +403,7 @@
                ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
-error[E0080]: constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered 0x4[noalloc], but expected a vtable pointer
   --> $DIR/raw-bytes.rs:177:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
@@ -414,7 +414,7 @@
                ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: constructing invalid value at .0: encountered ALLOC22<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC22<imm>, but expected a vtable pointer
   --> $DIR/raw-bytes.rs:179:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
@@ -425,7 +425,7 @@
                ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
-error[E0080]: constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
+error[E0080]: constructing invalid value of type &dyn Trait: at .<deref>.<dyn-downcast(bool)>, encountered 0x03, but expected a boolean
   --> $DIR/raw-bytes.rs:182:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
@@ -436,7 +436,7 @@
                ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
-error[E0080]: constructing invalid value: encountered null pointer, but expected a vtable pointer
+error[E0080]: constructing invalid value of type *const dyn Trait: encountered null pointer, but expected a vtable pointer
   --> $DIR/raw-bytes.rs:185:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
@@ -447,7 +447,7 @@
                ╾ALLOC_ID╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: constructing invalid value: encountered ALLOC27<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type *const dyn Trait: encountered ALLOC27<imm>, but expected a vtable pointer
   --> $DIR/raw-bytes.rs:187:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
@@ -458,7 +458,7 @@
                ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
            }
 
-error[E0080]: constructing invalid value: encountered a reference pointing to uninhabited type [!; 1]
+error[E0080]: constructing invalid value of type &[!; 1]: encountered a reference pointing to uninhabited type [!; 1]
   --> $DIR/raw-bytes.rs:191:1
    |
 LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
@@ -469,7 +469,7 @@
                01 00 00 00 00 00 00 00                         │ ........
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered a value of the never type `!`
+error[E0080]: constructing invalid value of type &[!]: at .<deref>[0], encountered a value of the never type `!`
   --> $DIR/raw-bytes.rs:192:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
@@ -480,7 +480,7 @@
                01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 │ ................
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered a value of the never type `!`
+error[E0080]: constructing invalid value of type &[!]: at .<deref>[0], encountered a value of the never type `!`
   --> $DIR/raw-bytes.rs:193:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
@@ -491,7 +491,7 @@
                01 00 00 00 00 00 00 00 2a 00 00 00 00 00 00 00 │ ........*.......
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
+error[E0080]: constructing invalid value of type &[u8]: at .<deref>[0], encountered uninitialized memory, but expected an integer
   --> $DIR/raw-bytes.rs:196:1
    |
 LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) };
@@ -502,7 +502,7 @@
                ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
+error[E0080]: constructing invalid value of type &[u8]: at .<deref>[0], encountered a pointer, but expected an integer
   --> $DIR/raw-bytes.rs:199:1
    |
 LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem::size_of::<&u32>()) };
@@ -515,7 +515,7 @@
                ╾ALLOC_ID╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean
+error[E0080]: constructing invalid value of type &[bool]: at .<deref>[0], encountered 0x11, but expected a boolean
   --> $DIR/raw-bytes.rs:202:1
    |
 LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) };
@@ -526,7 +526,7 @@
                ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: constructing invalid value at .<deref>[1]: encountered uninitialized memory, but expected an integer
+error[E0080]: constructing invalid value of type &[u16]: at .<deref>[1], encountered uninitialized memory, but expected an integer
   --> $DIR/raw-bytes.rs:206:1
    |
 LL | pub static S7: &[u16] = unsafe {
@@ -537,7 +537,7 @@
                ╾ALLOC_ID+0x2╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
+error[E0080]: constructing invalid value of type &[u8]: at .<deref>[0], encountered uninitialized memory, but expected an integer
   --> $DIR/raw-bytes.rs:213:1
    |
 LL | pub static R4: &[u8] = unsafe {
@@ -548,7 +548,7 @@
                ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
+error[E0080]: constructing invalid value of type &[u8]: at .<deref>[0], encountered a pointer, but expected an integer
   --> $DIR/raw-bytes.rs:218:1
    |
 LL | pub static R5: &[u8] = unsafe {
@@ -561,7 +561,7 @@
                ╾ALLOC_ID╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean
+error[E0080]: constructing invalid value of type &[bool]: at .<deref>[0], encountered 0x11, but expected a boolean
   --> $DIR/raw-bytes.rs:223:1
    |
 LL | pub static R6: &[bool] = unsafe {
diff --git a/tests/ui/consts/const-eval/raw-bytes.rs b/tests/ui/consts/const-eval/raw-bytes.rs
index 274b1ae..d63e1d5 100644
--- a/tests/ui/consts/const-eval/raw-bytes.rs
+++ b/tests/ui/consts/const-eval/raw-bytes.rs
@@ -83,10 +83,10 @@ enum UninhDiscriminant {
 };
 
 const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
-//~^ ERROR constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+//~^ ERROR encountered an unaligned reference (required 2 byte alignment but found 1)
 
 const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
-//~^ ERROR constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1)
+//~^ ERROR encountered an unaligned box (required 2 byte alignment but found 1)
 
 const NULL: &u16 = unsafe { mem::transmute(0usize) };
 //~^ ERROR constructing invalid value
diff --git a/tests/ui/consts/const-eval/transmute-const.stderr b/tests/ui/consts/const-eval/transmute-const.stderr
index 53665c1..3b064c9 100644
--- a/tests/ui/consts/const-eval/transmute-const.stderr
+++ b/tests/ui/consts/const-eval/transmute-const.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value: encountered 0x03, but expected a boolean
+error[E0080]: constructing invalid value of type bool: encountered 0x03, but expected a boolean
   --> $DIR/transmute-const.rs:4:1
    |
 LL | static FOO: bool = unsafe { mem::transmute(3u8) };
diff --git a/tests/ui/consts/const-eval/ub-enum.stderr b/tests/ui/consts/const-eval/ub-enum.stderr
index da63af3..a5ac10c 100644
--- a/tests/ui/consts/const-eval/ub-enum.stderr
+++ b/tests/ui/consts/const-eval/ub-enum.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value at .<enum-tag>: encountered 0x01, but expected a valid enum tag
+error[E0080]: constructing invalid value of type Enum: at .<enum-tag>, encountered 0x01, but expected a valid enum tag
   --> $DIR/ub-enum.rs:30:1
    |
 LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
@@ -27,7 +27,7 @@
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
-error[E0080]: constructing invalid value at .<enum-tag>: encountered 0x0, but expected a valid enum tag
+error[E0080]: constructing invalid value of type Enum2: at .<enum-tag>, encountered 0x0, but expected a valid enum tag
   --> $DIR/ub-enum.rs:48:1
    |
 LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
@@ -75,7 +75,7 @@
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
-error[E0080]: constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
+error[E0080]: constructing invalid value of type UninhDiscriminant: at .<enum-tag>, encountered an uninhabited enum variant
   --> $DIR/ub-enum.rs:83:1
    |
 LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
@@ -86,7 +86,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<enum-tag>: encountered 0x03, but expected a valid enum tag
+error[E0080]: constructing invalid value of type UninhDiscriminant: at .<enum-tag>, encountered 0x03, but expected a valid enum tag
   --> $DIR/ub-enum.rs:85:1
    |
 LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
@@ -97,7 +97,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
+error[E0080]: constructing invalid value of type Option<(char, char)>: at .<enum-variant(Some)>.0.1, encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
   --> $DIR/ub-enum.rs:93:1
    |
 LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
@@ -108,13 +108,13 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
+error[E0080]: constructing invalid value of type Result<(i32, Never), (i32, !)>: at .<enum-tag>, encountered an uninhabited enum variant
   --> $DIR/ub-enum.rs:98:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
    |                                                                             ^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_UNINHABITED_WITH_DATA1` failed here
 
-error[E0080]: constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
+error[E0080]: constructing invalid value of type Result<(i32, !), (i32, Never)>: at .<enum-tag>, encountered an uninhabited enum variant
   --> $DIR/ub-enum.rs:100:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr
index 1e4d425..2d2d97d 100644
--- a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr
+++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value: encountered ALLOC1<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type &dyn Trait: encountered ALLOC1<imm>, but expected a vtable pointer
   --> $DIR/ub-incorrect-vtable.rs:18:1
    |
 LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
@@ -9,7 +9,7 @@
                ╾ALLOC0<imm>╼ ╾ALLOC1<imm>╼                         │ ╾──╼╾──╼
            }
 
-error[E0080]: constructing invalid value: encountered ALLOC3<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type &dyn Trait: encountered ALLOC3<imm>, but expected a vtable pointer
   --> $DIR/ub-incorrect-vtable.rs:22:1
    |
 LL | const INVALID_VTABLE_SIZE: &dyn Trait =
@@ -20,7 +20,7 @@
                ╾ALLOC2<imm>╼ ╾ALLOC3<imm>╼                         │ ╾──╼╾──╼
            }
 
-error[E0080]: constructing invalid value at .0: encountered ALLOC5<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC5<imm>, but expected a vtable pointer
   --> $DIR/ub-incorrect-vtable.rs:31:1
    |
 LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
@@ -31,7 +31,7 @@
                ╾ALLOC4<imm>╼ ╾ALLOC5<imm>╼                         │ ╾──╼╾──╼
            }
 
-error[E0080]: constructing invalid value at .0: encountered ALLOC7<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC7<imm>, but expected a vtable pointer
   --> $DIR/ub-incorrect-vtable.rs:35:1
    |
 LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
@@ -42,7 +42,7 @@
                ╾ALLOC6<imm>╼ ╾ALLOC7<imm>╼                         │ ╾──╼╾──╼
            }
 
-error[E0080]: constructing invalid value at .0: encountered ALLOC9<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC9<imm>, but expected a vtable pointer
   --> $DIR/ub-incorrect-vtable.rs:40:1
    |
 LL | const INVALID_VTABLE_UB: W<&dyn Trait> =
@@ -53,7 +53,7 @@
                ╾ALLOC8<imm>╼ ╾ALLOC9<imm>╼                         │ ╾──╼╾──╼
            }
 
-error[E0080]: constructing invalid value at .1: encountered a dangling reference (going beyond the bounds of its allocation)
+error[E0080]: constructing invalid value of type Wide<'_>: at .1, encountered a dangling reference (going beyond the bounds of its allocation)
   --> $DIR/ub-incorrect-vtable.rs:86:1
    |
 LL | const G: Wide = unsafe { Transmute { t: FOO }.u };
diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr
index a068991..4c8a180 100644
--- a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr
+++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value: encountered ALLOC1<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type &dyn Trait: encountered ALLOC1<imm>, but expected a vtable pointer
   --> $DIR/ub-incorrect-vtable.rs:18:1
    |
 LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
@@ -9,7 +9,7 @@
                ╾ALLOC0<imm>╼ ╾ALLOC1<imm>╼ │ ╾──────╼╾──────╼
            }
 
-error[E0080]: constructing invalid value: encountered ALLOC3<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type &dyn Trait: encountered ALLOC3<imm>, but expected a vtable pointer
   --> $DIR/ub-incorrect-vtable.rs:22:1
    |
 LL | const INVALID_VTABLE_SIZE: &dyn Trait =
@@ -20,7 +20,7 @@
                ╾ALLOC2<imm>╼ ╾ALLOC3<imm>╼ │ ╾──────╼╾──────╼
            }
 
-error[E0080]: constructing invalid value at .0: encountered ALLOC5<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC5<imm>, but expected a vtable pointer
   --> $DIR/ub-incorrect-vtable.rs:31:1
    |
 LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
@@ -31,7 +31,7 @@
                ╾ALLOC4<imm>╼ ╾ALLOC5<imm>╼ │ ╾──────╼╾──────╼
            }
 
-error[E0080]: constructing invalid value at .0: encountered ALLOC7<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC7<imm>, but expected a vtable pointer
   --> $DIR/ub-incorrect-vtable.rs:35:1
    |
 LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
@@ -42,7 +42,7 @@
                ╾ALLOC6<imm>╼ ╾ALLOC7<imm>╼ │ ╾──────╼╾──────╼
            }
 
-error[E0080]: constructing invalid value at .0: encountered ALLOC9<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC9<imm>, but expected a vtable pointer
   --> $DIR/ub-incorrect-vtable.rs:40:1
    |
 LL | const INVALID_VTABLE_UB: W<&dyn Trait> =
@@ -53,7 +53,7 @@
                ╾ALLOC8<imm>╼ ╾ALLOC9<imm>╼ │ ╾──────╼╾──────╼
            }
 
-error[E0080]: constructing invalid value at .1: encountered a dangling reference (going beyond the bounds of its allocation)
+error[E0080]: constructing invalid value of type Wide<'_>: at .1, encountered a dangling reference (going beyond the bounds of its allocation)
   --> $DIR/ub-incorrect-vtable.rs:86:1
    |
 LL | const G: Wide = unsafe { Transmute { t: FOO }.u };
diff --git a/tests/ui/consts/const-eval/ub-int-array.rs b/tests/ui/consts/const-eval/ub-int-array.rs
index eebbcca..151019c 100644
--- a/tests/ui/consts/const-eval/ub-int-array.rs
+++ b/tests/ui/consts/const-eval/ub-int-array.rs
@@ -18,7 +18,7 @@ const fn new(t: T) -> Self {
 }
 
 const UNINIT_INT_0: [u32; 3] = unsafe {
-    //~^ ERROR invalid value at [0]
+    //~^ ERROR invalid value of type [u32; 3]: at [0]
     mem::transmute([
         MaybeUninit { uninit: () },
         // Constants chosen to achieve endianness-independent hex dump.
@@ -27,7 +27,7 @@ const fn new(t: T) -> Self {
     ])
 };
 const UNINIT_INT_1: [u32; 3] = unsafe {
-    //~^ ERROR invalid value at [1]
+    //~^ ERROR invalid value of type [u32; 3]: at [1]
     mem::transmute([
         MaybeUninit::new(0u8),
         MaybeUninit::new(0u8),
@@ -44,7 +44,7 @@ const fn new(t: T) -> Self {
     ])
 };
 const UNINIT_INT_2: [u32; 3] = unsafe {
-    //~^ ERROR invalid value at [2]
+    //~^ ERROR invalid value of type [u32; 3]: at [2]
     mem::transmute([
         MaybeUninit::new(0u8),
         MaybeUninit::new(0u8),
diff --git a/tests/ui/consts/const-eval/ub-int-array.stderr b/tests/ui/consts/const-eval/ub-int-array.stderr
index 065bfd2..253358f 100644
--- a/tests/ui/consts/const-eval/ub-int-array.stderr
+++ b/tests/ui/consts/const-eval/ub-int-array.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value at [0]: encountered uninitialized memory, but expected an integer
+error[E0080]: constructing invalid value of type [u32; 3]: at [0], encountered uninitialized memory, but expected an integer
   --> $DIR/ub-int-array.rs:20:1
    |
 LL | const UNINIT_INT_0: [u32; 3] = unsafe {
@@ -9,7 +9,7 @@
                __ __ __ __ 11 11 11 11 22 22 22 22             │ ░░░░....""""
            }
 
-error[E0080]: constructing invalid value at [1]: encountered uninitialized memory, but expected an integer
+error[E0080]: constructing invalid value of type [u32; 3]: at [1], encountered uninitialized memory, but expected an integer
   --> $DIR/ub-int-array.rs:29:1
    |
 LL | const UNINIT_INT_1: [u32; 3] = unsafe {
@@ -20,7 +20,7 @@
                00 00 00 00 01 __ 01 01 02 02 __ 02             │ .....░....░.
            }
 
-error[E0080]: constructing invalid value at [2]: encountered uninitialized memory, but expected an integer
+error[E0080]: constructing invalid value of type [u32; 3]: at [2], encountered uninitialized memory, but expected an integer
   --> $DIR/ub-int-array.rs:46:1
    |
 LL | const UNINIT_INT_2: [u32; 3] = unsafe {
diff --git a/tests/ui/consts/const-eval/ub-nonnull.stderr b/tests/ui/consts/const-eval/ub-nonnull.stderr
index be5c6f7..8f18385 100644
--- a/tests/ui/consts/const-eval/ub-nonnull.stderr
+++ b/tests/ui/consts/const-eval/ub-nonnull.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value: encountered 0, but expected something greater or equal to 1
+error[E0080]: constructing invalid value of type NonNull<u8>: encountered 0, but expected something greater or equal to 1
   --> $DIR/ub-nonnull.rs:16:1
    |
 LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
@@ -15,7 +15,7 @@
 LL |     let out_of_bounds_ptr = &ptr[255];
    |                             ^^^^^^^^^ evaluation of `OUT_OF_BOUNDS_PTR` failed here
 
-error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
+error[E0080]: constructing invalid value of type NonZero<u8>: at .0.0, encountered 0, but expected something greater or equal to 1
   --> $DIR/ub-nonnull.rs:26:1
    |
 LL | const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
@@ -26,7 +26,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
+error[E0080]: constructing invalid value of type NonZero<usize>: at .0.0, encountered 0, but expected something greater or equal to 1
   --> $DIR/ub-nonnull.rs:28:1
    |
 LL | const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };
@@ -47,7 +47,7 @@
                __                                              │ ░
            }
 
-error[E0080]: constructing invalid value: encountered 42, but expected something in the range 10..=30
+error[E0080]: constructing invalid value of type RestrictedRange1: encountered 42, but expected something in the range 10..=30
   --> $DIR/ub-nonnull.rs:44:1
    |
 LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
@@ -58,7 +58,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30
+error[E0080]: constructing invalid value of type RestrictedRange2: encountered 20, but expected something less or equal to 10, or greater or equal to 30
   --> $DIR/ub-nonnull.rs:50:1
    |
 LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
@@ -69,7 +69,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered 0, but expected something greater or equal to 1
+error[E0080]: constructing invalid value of type NonNull<dyn Send>: encountered 0, but expected something greater or equal to 1
   --> $DIR/ub-nonnull.rs:53:1
    |
 LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
@@ -80,7 +80,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered a maybe-null pointer, but expected something that is definitely non-zero
+error[E0080]: constructing invalid value of type NonNull<()>: encountered a maybe-null pointer, but expected something that is definitely non-zero
   --> $DIR/ub-nonnull.rs:61:1
    |
 LL | const MAYBE_NULL_PTR: NonNull<()> = unsafe { mem::transmute((&raw const S).wrapping_add(4)) };
diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.rs b/tests/ui/consts/const-eval/ub-ref-ptr.rs
index f7421ee..5cc3277 100644
--- a/tests/ui/consts/const-eval/ub-ref-ptr.rs
+++ b/tests/ui/consts/const-eval/ub-ref-ptr.rs
@@ -16,10 +16,10 @@ union MaybeUninit<T: Copy> {
 }
 
 const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
-//~^ ERROR constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+//~^ ERROR encountered an unaligned reference (required 2 byte alignment but found 1)
 
 const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
-//~^ ERROR constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1)
+//~^ ERROR encountered an unaligned box (required 2 byte alignment but found 1)
 
 const NULL: &u16 = unsafe { mem::transmute(0usize) };
 //~^ ERROR invalid value
diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.stderr b/tests/ui/consts/const-eval/ub-ref-ptr.stderr
index 349a98f..17ddea0 100644
--- a/tests/ui/consts/const-eval/ub-ref-ptr.stderr
+++ b/tests/ui/consts/const-eval/ub-ref-ptr.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
+error[E0080]: constructing invalid value of type &u16: encountered an unaligned reference (required 2 byte alignment but found 1)
   --> $DIR/ub-ref-ptr.rs:18:1
    |
 LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
@@ -9,7 +9,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1)
+error[E0080]: constructing invalid value of type Box<u16>: encountered an unaligned box (required 2 byte alignment but found 1)
   --> $DIR/ub-ref-ptr.rs:21:1
    |
 LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
@@ -20,7 +20,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered a null reference
+error[E0080]: constructing invalid value of type &u16: encountered a null reference
   --> $DIR/ub-ref-ptr.rs:24:1
    |
 LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
@@ -31,7 +31,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered a null box
+error[E0080]: constructing invalid value of type Box<u16>: encountered a null box
   --> $DIR/ub-ref-ptr.rs:27:1
    |
 LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
@@ -42,7 +42,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered a maybe-null box
+error[E0080]: constructing invalid value of type Box<()>: encountered a maybe-null box
   --> $DIR/ub-ref-ptr.rs:30:1
    |
 LL | const MAYBE_NULL_BOX: Box<()> = unsafe { mem::transmute({
@@ -92,7 +92,7 @@
 LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
    |                                                                                     ^^^^^^^^^^^^^^^^^^^^^
 
-error[E0080]: constructing invalid value: encountered a dangling reference (0x539[noalloc] has no provenance)
+error[E0080]: constructing invalid value of type &u8: encountered a dangling reference (0x539[noalloc] has no provenance)
   --> $DIR/ub-ref-ptr.rs:48:1
    |
 LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
@@ -103,7 +103,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered a dangling box (0x539[noalloc] has no provenance)
+error[E0080]: constructing invalid value of type Box<u8>: encountered a dangling box (0x539[noalloc] has no provenance)
   --> $DIR/ub-ref-ptr.rs:51:1
    |
 LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
@@ -124,7 +124,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered null pointer, but expected a function pointer
+error[E0080]: constructing invalid value of type fn(): encountered null pointer, but expected a function pointer
   --> $DIR/ub-ref-ptr.rs:57:1
    |
 LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
@@ -145,7 +145,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
+error[E0080]: constructing invalid value of type fn(): encountered 0xd[noalloc], but expected a function pointer
   --> $DIR/ub-ref-ptr.rs:61:1
    |
 LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
@@ -156,7 +156,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered ALLOC3<imm>, but expected a function pointer
+error[E0080]: constructing invalid value of type fn(): encountered ALLOC3<imm>, but expected a function pointer
   --> $DIR/ub-ref-ptr.rs:63:1
    |
 LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
@@ -167,7 +167,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered ALLOC4+0xa, but expected a function pointer
+error[E0080]: constructing invalid value of type fn(): encountered ALLOC4+0xa, but expected a function pointer
   --> $DIR/ub-ref-ptr.rs:65:1
    |
 LL | const MAYBE_NULL_FN_PTR: fn() = unsafe { mem::transmute({
@@ -184,7 +184,7 @@
 LL |     ptr.read();
    |     ^^^^^^^^^^ evaluation of `UNALIGNED_READ` failed here
 
-error[E0080]: constructing invalid value: encountered a pointer with unknown absolute address, but expected something that is definitely greater or equal to 1000
+error[E0080]: constructing invalid value of type High: encountered a pointer with unknown absolute address, but expected something that is definitely greater or equal to 1000
   --> $DIR/ub-ref-ptr.rs:84:1
    |
 LL | const INVALID_VALUE_PTR: High = unsafe { mem::transmute(&S) };
diff --git a/tests/ui/consts/const-eval/ub-uninhabit.stderr b/tests/ui/consts/const-eval/ub-uninhabit.stderr
index aca0b13..244cb96 100644
--- a/tests/ui/consts/const-eval/ub-uninhabit.stderr
+++ b/tests/ui/consts/const-eval/ub-uninhabit.stderr
@@ -1,10 +1,10 @@
-error[E0080]: constructing invalid value: encountered a value of uninhabited type `Bar`
+error[E0080]: constructing invalid value of type Bar: encountered a value of uninhabited type `Bar`
   --> $DIR/ub-uninhabit.rs:20:35
    |
 LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init };
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_BAD_BAD` failed here
 
-error[E0080]: constructing invalid value: encountered a reference pointing to uninhabited type Bar
+error[E0080]: constructing invalid value of type &Bar: encountered a reference pointing to uninhabited type Bar
   --> $DIR/ub-uninhabit.rs:23:1
    |
 LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
@@ -15,13 +15,13 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at [0]: encountered a value of uninhabited type `Bar`
+error[E0080]: constructing invalid value of type [Bar; 1]: at [0], encountered a value of uninhabited type `Bar`
   --> $DIR/ub-uninhabit.rs:26:42
    |
 LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init };
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_BAD_ARRAY` failed here
 
-error[E0080]: constructing invalid value: encountered a value of the never type `!`
+error[E0080]: constructing invalid value of type !: encountered a value of the never type `!`
   --> $DIR/ub-uninhabit.rs:32:16
    |
 LL |     let _val = intrinsics::read_via_copy(ptr);
diff --git a/tests/ui/consts/const-eval/ub-upvars.32bit.stderr b/tests/ui/consts/const-eval/ub-upvars.32bit.stderr
index 89512c0..2e5797c 100644
--- a/tests/ui/consts/const-eval/ub-upvars.32bit.stderr
+++ b/tests/ui/consts/const-eval/ub-upvars.32bit.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value at .<deref>.<dyn-downcast>.<captured-var(bad_ref)>: encountered a null reference
+error[E0080]: constructing invalid value of type &dyn FnOnce(): at .<deref>.<dyn-downcast({closure@$DIR/ub-upvars.rs:10:5: 10:12})>.<captured-var(bad_ref)>, encountered a null reference
   --> $DIR/ub-upvars.rs:7:1
    |
 LL | const BAD_UPVAR: &dyn FnOnce() = &{
diff --git a/tests/ui/consts/const-eval/ub-upvars.64bit.stderr b/tests/ui/consts/const-eval/ub-upvars.64bit.stderr
index bf8de48..c45ad78 100644
--- a/tests/ui/consts/const-eval/ub-upvars.64bit.stderr
+++ b/tests/ui/consts/const-eval/ub-upvars.64bit.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value at .<deref>.<dyn-downcast>.<captured-var(bad_ref)>: encountered a null reference
+error[E0080]: constructing invalid value of type &dyn FnOnce(): at .<deref>.<dyn-downcast({closure@$DIR/ub-upvars.rs:10:5: 10:12})>.<captured-var(bad_ref)>, encountered a null reference
   --> $DIR/ub-upvars.rs:7:1
    |
 LL | const BAD_UPVAR: &dyn FnOnce() = &{
diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.stderr
index c505e5c..9603710 100644
--- a/tests/ui/consts/const-eval/ub-wide-ptr.stderr
+++ b/tests/ui/consts/const-eval/ub-wide-ptr.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
+error[E0080]: constructing invalid value of type &str: encountered a dangling reference (going beyond the bounds of its allocation)
   --> $DIR/ub-wide-ptr.rs:40:1
    |
 LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
@@ -9,7 +9,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object
+error[E0080]: constructing invalid value of type (&str,): at .0, encountered invalid reference metadata: slice is bigger than largest supported object
   --> $DIR/ub-wide-ptr.rs:42:1
    |
 LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
@@ -38,7 +38,7 @@
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
-error[E0080]: constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
+error[E0080]: constructing invalid value of type &MyStr: encountered invalid reference metadata: slice is bigger than largest supported object
   --> $DIR/ub-wide-ptr.rs:50:1
    |
 LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
@@ -49,7 +49,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<deref>: encountered uninitialized memory, but expected a string
+error[E0080]: constructing invalid value of type &str: at .<deref>, encountered uninitialized memory, but expected a string
   --> $DIR/ub-wide-ptr.rs:54:1
    |
 LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
@@ -60,7 +60,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<deref>.0: encountered uninitialized memory, but expected a string
+error[E0080]: constructing invalid value of type &MyStr: at .<deref>.0, encountered uninitialized memory, but expected a string
   --> $DIR/ub-wide-ptr.rs:57:1
    |
 LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
@@ -81,7 +81,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
+error[E0080]: constructing invalid value of type &[u8]: encountered a dangling reference (going beyond the bounds of its allocation)
   --> $DIR/ub-wide-ptr.rs:70:1
    |
 LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
@@ -92,7 +92,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
+error[E0080]: constructing invalid value of type &[u32]: encountered invalid reference metadata: slice is bigger than largest supported object
   --> $DIR/ub-wide-ptr.rs:73:1
    |
 LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
@@ -112,7 +112,7 @@
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
-error[E0080]: constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation)
+error[E0080]: constructing invalid value of type Box<[u8]>: encountered a dangling box (going beyond the bounds of its allocation)
   --> $DIR/ub-wide-ptr.rs:79:1
    |
 LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
@@ -132,7 +132,7 @@
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean
+error[E0080]: constructing invalid value of type &[bool; 1]: at .<deref>[0], encountered 0x03, but expected a boolean
   --> $DIR/ub-wide-ptr.rs:86:1
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
@@ -149,7 +149,7 @@
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0080]: constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean
+error[E0080]: constructing invalid value of type &MySlice<[bool; 1]>: at .<deref>.0, encountered 0x03, but expected a boolean
   --> $DIR/ub-wide-ptr.rs:92:1
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
@@ -166,7 +166,7 @@
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0080]: constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean
+error[E0080]: constructing invalid value of type &MySlice<[bool; 1]>: at .<deref>.1[0], encountered 0x03, but expected a boolean
   --> $DIR/ub-wide-ptr.rs:95:1
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
@@ -193,7 +193,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .0: encountered ALLOC12<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC12<imm>, but expected a vtable pointer
   --> $DIR/ub-wide-ptr.rs:110:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
@@ -204,7 +204,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .0: encountered ALLOC14<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC14<imm>, but expected a vtable pointer
   --> $DIR/ub-wide-ptr.rs:113:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
@@ -215,7 +215,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered 0x4[noalloc], but expected a vtable pointer
   --> $DIR/ub-wide-ptr.rs:116:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
@@ -226,7 +226,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered ALLOC17<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type &dyn Trait: encountered ALLOC17<imm>, but expected a vtable pointer
   --> $DIR/ub-wide-ptr.rs:118:1
    |
 LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
@@ -237,7 +237,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered ALLOC19<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type &dyn Trait: encountered ALLOC19<imm>, but expected a vtable pointer
   --> $DIR/ub-wide-ptr.rs:120:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
@@ -248,7 +248,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered ALLOC21<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type &dyn Trait: encountered ALLOC21<imm>, but expected a vtable pointer
   --> $DIR/ub-wide-ptr.rs:122:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
@@ -259,7 +259,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .0: encountered ALLOC23<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type W<&dyn Trait>: at .0, encountered ALLOC23<imm>, but expected a vtable pointer
   --> $DIR/ub-wide-ptr.rs:124:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
@@ -270,7 +270,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
+error[E0080]: constructing invalid value of type &dyn Trait: at .<deref>.<dyn-downcast(bool)>, encountered 0x03, but expected a boolean
   --> $DIR/ub-wide-ptr.rs:128:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
@@ -281,7 +281,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered null pointer, but expected a vtable pointer
+error[E0080]: constructing invalid value of type *const dyn Trait: encountered null pointer, but expected a vtable pointer
   --> $DIR/ub-wide-ptr.rs:132:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
@@ -292,7 +292,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered ALLOC28<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type *const dyn Trait: encountered ALLOC28<imm>, but expected a vtable pointer
   --> $DIR/ub-wide-ptr.rs:134:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
@@ -303,7 +303,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered null pointer, but expected a vtable pointer
+error[E0080]: constructing invalid value of type *const dyn Trait: encountered null pointer, but expected a vtable pointer
   --> $DIR/ub-wide-ptr.rs:141:1
    |
 LL | static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe {
@@ -314,7 +314,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered ALLOC31<imm>, but expected a vtable pointer
+error[E0080]: constructing invalid value of type *const dyn Trait: encountered ALLOC31<imm>, but expected a vtable pointer
   --> $DIR/ub-wide-ptr.rs:145:1
    |
 LL | static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe {
diff --git a/tests/ui/consts/const-eval/union-ub.32bit.stderr b/tests/ui/consts/const-eval/union-ub.32bit.stderr
index fb2311b..95960d1 100644
--- a/tests/ui/consts/const-eval/union-ub.32bit.stderr
+++ b/tests/ui/consts/const-eval/union-ub.32bit.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value: encountered 0x2a, but expected a boolean
+error[E0080]: constructing invalid value of type bool: encountered 0x2a, but expected a boolean
   --> $DIR/union-ub.rs:33:1
    |
 LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool };
diff --git a/tests/ui/consts/const-eval/union-ub.64bit.stderr b/tests/ui/consts/const-eval/union-ub.64bit.stderr
index fb2311b..95960d1 100644
--- a/tests/ui/consts/const-eval/union-ub.64bit.stderr
+++ b/tests/ui/consts/const-eval/union-ub.64bit.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value: encountered 0x2a, but expected a boolean
+error[E0080]: constructing invalid value of type bool: encountered 0x2a, but expected a boolean
   --> $DIR/union-ub.rs:33:1
    |
 LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool };
diff --git a/tests/ui/consts/const-eval/valid-const.rs b/tests/ui/consts/const-eval/valid-const.rs
index 777484c..6f92997 100644
--- a/tests/ui/consts/const-eval/valid-const.rs
+++ b/tests/ui/consts/const-eval/valid-const.rs
@@ -1,10 +1,12 @@
 //@ check-pass
 //
 // Some constants that *are* valid
+#![feature(maybe_dangling)]
 
 use std::mem;
 use std::ptr::NonNull;
 use std::num::NonZero;
+use std::mem::MaybeDangling;
 
 const NON_NULL_PTR1: NonNull<u8> = unsafe { mem::transmute(1usize) };
 const NON_NULL_PTR2: NonNull<u8> = unsafe { mem::transmute(&0) };
@@ -14,4 +16,6 @@
 
 const UNIT: () = ();
 
+const INVALID_INSIDE_MAYBE_DANGLING: MaybeDangling<&bool> = unsafe { std::mem::transmute(&5u8) };
+
 fn main() {}
diff --git a/tests/ui/consts/const-eval/validate_uninhabited_zsts.stderr b/tests/ui/consts/const-eval/validate_uninhabited_zsts.stderr
index 848c65f..cd59e7b 100644
--- a/tests/ui/consts/const-eval/validate_uninhabited_zsts.stderr
+++ b/tests/ui/consts/const-eval/validate_uninhabited_zsts.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value: encountered a value of the never type `!`
+error[E0080]: constructing invalid value of type !: encountered a value of the never type `!`
   --> $DIR/validate_uninhabited_zsts.rs:17:33
    |
 LL | const FOO: [empty::Empty; 3] = [foo(); 3];
@@ -10,7 +10,7 @@
 LL |     unsafe { std::mem::transmute(()) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^ the failure occurred here
 
-error[E0080]: constructing invalid value at .0: encountered a value of uninhabited type `Void`
+error[E0080]: constructing invalid value of type empty::Empty: at .0, encountered a value of uninhabited type `Void`
   --> $DIR/validate_uninhabited_zsts.rs:20:42
    |
 LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr b/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr
index 8f54b4e..9b289f4 100644
--- a/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr
+++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr
@@ -28,7 +28,7 @@
    |                              |           creates a temporary value which is freed while still in use
    |                              using this value as a constant requires that borrow lasts for `'static`
 
-error[E0080]: constructing invalid value: encountered mutable reference or box pointing to read-only memory
+error[E0080]: constructing invalid value of type &mut u16: encountered mutable reference or box pointing to read-only memory
   --> $DIR/mut_ref_in_final.rs:27:1
    |
 LL | const IMMUT_MUT_REF: &mut u16 = unsafe { mem::transmute(&13) };
@@ -39,7 +39,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered mutable reference or box pointing to read-only memory
+error[E0080]: constructing invalid value of type &mut u16: encountered mutable reference or box pointing to read-only memory
   --> $DIR/mut_ref_in_final.rs:29:1
    |
 LL | static IMMUT_MUT_REF_STATIC: &mut u16 = unsafe { mem::transmute(&13) };
@@ -120,7 +120,7 @@
    = note: to avoid accidentally creating global mutable state, such temporaries must be immutable
    = help: if you really want global mutable state, try replacing the temporary by an interior mutable `static` or a `static mut`
 
-error[E0080]: constructing invalid value at .<enum-variant(Some)>.0: encountered a dangling reference (0x2a[noalloc] has no provenance)
+error[E0080]: constructing invalid value of type Option<&mut i32>: at .<enum-variant(Some)>.0, encountered a dangling reference (0x2a[noalloc] has no provenance)
   --> $DIR/mut_ref_in_final.rs:86:5
    |
 LL |     const INT2PTR: Option<&mut i32> = helper_int2ptr();
@@ -131,7 +131,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<enum-variant(Some)>.0: encountered a dangling reference (0x2a[noalloc] has no provenance)
+error[E0080]: constructing invalid value of type Option<&mut i32>: at .<enum-variant(Some)>.0, encountered a dangling reference (0x2a[noalloc] has no provenance)
   --> $DIR/mut_ref_in_final.rs:87:5
    |
 LL |     static INT2PTR_STATIC: Option<&mut i32> = helper_int2ptr();
@@ -142,7 +142,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<enum-variant(Some)>.0: encountered a dangling reference (use-after-free)
+error[E0080]: constructing invalid value of type Option<&mut i32>: at .<enum-variant(Some)>.0, encountered a dangling reference (use-after-free)
   --> $DIR/mut_ref_in_final.rs:93:5
    |
 LL |     const DANGLING: Option<&mut i32> = helper_dangling();
@@ -153,7 +153,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<enum-variant(Some)>.0: encountered a dangling reference (use-after-free)
+error[E0080]: constructing invalid value of type Option<&mut i32>: at .<enum-variant(Some)>.0, encountered a dangling reference (use-after-free)
   --> $DIR/mut_ref_in_final.rs:94:5
    |
 LL |     static DANGLING_STATIC: Option<&mut i32> = helper_dangling();
diff --git a/tests/ui/consts/const_refs_to_static_fail_invalid.stderr b/tests/ui/consts/const_refs_to_static_fail_invalid.stderr
index 226a9de..b0150fc 100644
--- a/tests/ui/consts/const_refs_to_static_fail_invalid.stderr
+++ b/tests/ui/consts/const_refs_to_static_fail_invalid.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value at .<deref>: encountered 0x0a, but expected a boolean
+error[E0080]: constructing invalid value of type &bool: at .<deref>, encountered 0x0a, but expected a boolean
   --> $DIR/const_refs_to_static_fail_invalid.rs:10:5
    |
 LL |     const C: &bool = unsafe { std::mem::transmute(&S) };
diff --git a/tests/ui/consts/const_transmute_type_id7.rs b/tests/ui/consts/const_transmute_type_id7.rs
index 73b8187..6863b88 100644
--- a/tests/ui/consts/const_transmute_type_id7.rs
+++ b/tests/ui/consts/const_transmute_type_id7.rs
@@ -2,6 +2,7 @@
 //! (see <https://github.com/rust-lang/rust/issues/146748>)
 
 // Strip out raw byte dumps to make comparison platform-independent:
+//@ normalize-stderr: "\[&\(\); \d\]" -> "ARRAY"
 //@ normalize-stderr: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
 //@ normalize-stderr: "([0-9a-f][0-9a-f] |╾─*A(LLOC)?[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
 
diff --git a/tests/ui/consts/const_transmute_type_id7.stderr b/tests/ui/consts/const_transmute_type_id7.stderr
index 6649758..a1c37f2 100644
--- a/tests/ui/consts/const_transmute_type_id7.stderr
+++ b/tests/ui/consts/const_transmute_type_id7.stderr
@@ -1,5 +1,5 @@
-error[E0080]: constructing invalid value at [0]: encountered a maybe-null reference
-  --> $DIR/const_transmute_type_id7.rs:13:1
+error[E0080]: constructing invalid value of type ARRAY: at [0], encountered a maybe-null reference
+  --> $DIR/const_transmute_type_id7.rs:14:1
    |
 LL | const A: [&(); 16 / size_of::<*const ()>()] = unsafe { transmute(TypeId::of::<i32>()) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
diff --git a/tests/ui/consts/dangling-alloc-id-ice.stderr b/tests/ui/consts/dangling-alloc-id-ice.stderr
index 4b034c8..5b92bef 100644
--- a/tests/ui/consts/dangling-alloc-id-ice.stderr
+++ b/tests/ui/consts/dangling-alloc-id-ice.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value: encountered a dangling reference (use-after-free)
+error[E0080]: constructing invalid value of type &(): encountered a dangling reference (use-after-free)
   --> $DIR/dangling-alloc-id-ice.rs:12:1
    |
 LL | const FOO: &() = {
diff --git a/tests/ui/consts/dangling-zst-ice-issue-126393.stderr b/tests/ui/consts/dangling-zst-ice-issue-126393.stderr
index 248db69..0824afd 100644
--- a/tests/ui/consts/dangling-zst-ice-issue-126393.stderr
+++ b/tests/ui/consts/dangling-zst-ice-issue-126393.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value: encountered a dangling reference (use-after-free)
+error[E0080]: constructing invalid value of type &Wrapper: encountered a dangling reference (use-after-free)
   --> $DIR/dangling-zst-ice-issue-126393.rs:7:1
    |
 LL | pub static MAGIC_FFI_REF: &'static Wrapper = unsafe {
diff --git a/tests/ui/consts/escaping-bound-var.rs b/tests/ui/consts/escaping-bound-var.rs
index a538d60..03162c7 100644
--- a/tests/ui/consts/escaping-bound-var.rs
+++ b/tests/ui/consts/escaping-bound-var.rs
@@ -1,5 +1,4 @@
 #![feature(generic_const_exprs)]
-//~^ WARN the feature `generic_const_exprs` is incomplete
 
 fn test<'a>(
     _: &'a (),
diff --git a/tests/ui/consts/escaping-bound-var.stderr b/tests/ui/consts/escaping-bound-var.stderr
index bb0d285..046c58b 100644
--- a/tests/ui/consts/escaping-bound-var.stderr
+++ b/tests/ui/consts/escaping-bound-var.stderr
@@ -1,14 +1,5 @@
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/escaping-bound-var.rs:1:12
-   |
-LL | #![feature(generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: cannot capture late-bound lifetime in constant
-  --> $DIR/escaping-bound-var.rs:7:13
+  --> $DIR/escaping-bound-var.rs:6:13
    |
 LL | fn test<'a>(
    |         -- lifetime defined here
@@ -17,7 +8,7 @@
    |             ^^
 
 error[E0308]: mismatched types
-  --> $DIR/escaping-bound-var.rs:6:6
+  --> $DIR/escaping-bound-var.rs:5:6
    |
 LL |   fn test<'a>(
    |      ---- implicitly returns `()` as its body has no tail or `return` expression
@@ -33,6 +24,6 @@
     1
 }]`, found `()`
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr b/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
index 96c1666..a55a90d 100644
--- a/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
+++ b/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
@@ -1,10 +1,10 @@
-error[E0080]: constructing invalid value: encountered 0x03, but expected a boolean
+error[E0080]: constructing invalid value of type bool: encountered 0x03, but expected a boolean
   --> $DIR/detect-extra-ub.rs:30:20
    |
 LL |     let _x: bool = transmute(3u8);
    |                    ^^^^^^^^^^^^^^ evaluation of `INVALID_BOOL` failed here
 
-error[E0080]: constructing invalid value: encountered a pointer, but expected an integer
+error[E0080]: constructing invalid value of type usize: encountered a pointer, but expected an integer
   --> $DIR/detect-extra-ub.rs:35:21
    |
 LL |     let _x: usize = transmute(&3u8);
@@ -13,7 +13,7 @@
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
-error[E0080]: constructing invalid value at .<enum-tag>: encountered a pointer, but expected an integer
+error[E0080]: constructing invalid value of type PtrSizedEnum: at .<enum-tag>, encountered a pointer, but expected an integer
   --> $DIR/detect-extra-ub.rs:40:28
    |
 LL |     let _x: PtrSizedEnum = transmute(&3u8);
@@ -22,7 +22,7 @@
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
-error[E0080]: constructing invalid value at .0: encountered a pointer, but expected an integer
+error[E0080]: constructing invalid value of type (usize, usize): at .0, encountered a pointer, but expected an integer
   --> $DIR/detect-extra-ub.rs:46:30
    |
 LL |     let _x: (usize, usize) = transmute(x);
@@ -31,13 +31,13 @@
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
-error[E0080]: constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1)
+error[E0080]: constructing invalid value of type &u32: encountered an unaligned reference (required 4 byte alignment but found 1)
   --> $DIR/detect-extra-ub.rs:51:20
    |
 LL |     let _x: &u32 = transmute(&[0u8; 4]);
    |                    ^^^^^^^^^^^^^^^^^^^^ evaluation of `UNALIGNED_PTR` failed here
 
-error[E0080]: constructing invalid value: encountered a maybe-null function pointer
+error[E0080]: constructing invalid value of type fn(): encountered a maybe-null function pointer
   --> $DIR/detect-extra-ub.rs:57:20
    |
 LL |       let _x: fn() = transmute({
@@ -49,13 +49,13 @@
 LL | |     });
    | |______^ evaluation of `MAYBE_NULL_FN_PTR` failed here
 
-error[E0080]: constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
+error[E0080]: constructing invalid value of type UninhDiscriminant: at .<enum-tag>, encountered an uninhabited enum variant
   --> $DIR/detect-extra-ub.rs:68:13
    |
 LL |     let v = *addr_of!(data).cast::<UninhDiscriminant>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `UNINHABITED_VARIANT` failed here
 
-error[E0080]: constructing invalid value at [0]: encountered a partial pointer or a mix of pointers
+error[E0080]: constructing invalid value of type [*const u8; 2]: at [0], encountered a partial pointer or a mix of pointers
   --> $DIR/detect-extra-ub.rs:87:16
    |
 LL |     let _val = *(&mem as *const Align as *const [*const u8; 2]);
@@ -64,7 +64,7 @@
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
-error[E0080]: constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
+error[E0080]: constructing invalid value of type &[u8]: encountered invalid reference metadata: slice is bigger than largest supported object
   --> $DIR/detect-extra-ub.rs:101:16
    |
 LL |     let _val = &*slice;
diff --git a/tests/ui/consts/interior-mut-const-via-union.32bit.stderr b/tests/ui/consts/interior-mut-const-via-union.32bit.stderr
index 17b3238..64a178b 100644
--- a/tests/ui/consts/interior-mut-const-via-union.32bit.stderr
+++ b/tests/ui/consts/interior-mut-const-via-union.32bit.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value at .<deref>.y.<enum-variant(B)>.0: encountered `UnsafeCell` in read-only memory
+error[E0080]: constructing invalid value of type &S: at .<deref>.y.<enum-variant(B)>.0, encountered `UnsafeCell` in read-only memory
   --> $DIR/interior-mut-const-via-union.rs:34:1
    |
 LL | fn main() {
diff --git a/tests/ui/consts/interior-mut-const-via-union.64bit.stderr b/tests/ui/consts/interior-mut-const-via-union.64bit.stderr
index c4f78e7..f230156 100644
--- a/tests/ui/consts/interior-mut-const-via-union.64bit.stderr
+++ b/tests/ui/consts/interior-mut-const-via-union.64bit.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value at .<deref>.y.<enum-variant(B)>.0: encountered `UnsafeCell` in read-only memory
+error[E0080]: constructing invalid value of type &S: at .<deref>.y.<enum-variant(B)>.0, encountered `UnsafeCell` in read-only memory
   --> $DIR/interior-mut-const-via-union.rs:34:1
    |
 LL | fn main() {
diff --git a/tests/ui/consts/issue-104396.rs b/tests/ui/consts/issue-104396.rs
index f44abc3..dc0789e 100644
--- a/tests/ui/consts/issue-104396.rs
+++ b/tests/ui/consts/issue-104396.rs
@@ -2,7 +2,6 @@
 //@ check-pass
 
 #![feature(generic_const_exprs)]
-//~^ WARN the feature `generic_const_exprs` is incomplete
 
 #[inline(always)]
 fn from_fn_1<const N: usize, F: FnMut(usize) -> f32>(mut f: F) -> [f32; N] {
diff --git a/tests/ui/consts/issue-104396.stderr b/tests/ui/consts/issue-104396.stderr
deleted file mode 100644
index 5856bee..0000000
--- a/tests/ui/consts/issue-104396.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-104396.rs:4:12
-   |
-LL | #![feature(generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/consts/issue-63952.32bit.stderr b/tests/ui/consts/issue-63952.32bit.stderr
index cf97ed6..eb57a2f 100644
--- a/tests/ui/consts/issue-63952.32bit.stderr
+++ b/tests/ui/consts/issue-63952.32bit.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
+error[E0080]: constructing invalid value of type &[u8]: encountered invalid reference metadata: slice is bigger than largest supported object
   --> $DIR/issue-63952.rs:17:1
    |
 LL | const SLICE_WAY_TOO_LONG: &[u8] = unsafe {
diff --git a/tests/ui/consts/issue-63952.64bit.stderr b/tests/ui/consts/issue-63952.64bit.stderr
index 4cea967..da1d05e 100644
--- a/tests/ui/consts/issue-63952.64bit.stderr
+++ b/tests/ui/consts/issue-63952.64bit.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
+error[E0080]: constructing invalid value of type &[u8]: encountered invalid reference metadata: slice is bigger than largest supported object
   --> $DIR/issue-63952.rs:17:1
    |
 LL | const SLICE_WAY_TOO_LONG: &[u8] = unsafe {
diff --git a/tests/ui/consts/issue-64506.stderr b/tests/ui/consts/issue-64506.stderr
index 9fce07c..bd4f8f9 100644
--- a/tests/ui/consts/issue-64506.stderr
+++ b/tests/ui/consts/issue-64506.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value at .inner: encountered a value of uninhabited type `AnonPipe`
+error[E0080]: constructing invalid value of type ChildStdin: at .inner, encountered a value of uninhabited type `AnonPipe`
   --> $DIR/issue-64506.rs:16:22
    |
 LL |     let x = unsafe { Foo { b: () }.a };
diff --git a/tests/ui/consts/issue-79690.64bit.stderr b/tests/ui/consts/issue-79690.64bit.stderr
index 2653ff2..c3f89d2 100644
--- a/tests/ui/consts/issue-79690.64bit.stderr
+++ b/tests/ui/consts/issue-79690.64bit.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value at .1: encountered a dangling reference (going beyond the bounds of its allocation)
+error[E0080]: constructing invalid value of type Fat<'_>: at .1, encountered a dangling reference (going beyond the bounds of its allocation)
   --> $DIR/issue-79690.rs:30:1
    |
 LL | const G: Fat = unsafe { Transmute { t: FOO }.u };
diff --git a/tests/ui/consts/issue-90762.rs b/tests/ui/consts/issue-90762.rs
index db40e50..cc06036 100644
--- a/tests/ui/consts/issue-90762.rs
+++ b/tests/ui/consts/issue-90762.rs
@@ -27,5 +27,5 @@ fn main() {
     for (i, b) in FOO.iter().enumerate() {
         assert!(b.load(Ordering::Relaxed), "{} not set", i);
     }
-    assert_eq!(BAR.fetch_add(1, Ordering::Relaxed), usize::max_value());
+    assert_eq!(BAR.fetch_add(1, Ordering::Relaxed), usize::MAX);
 }
diff --git a/tests/ui/consts/miri_unleashed/mutable_references.stderr b/tests/ui/consts/miri_unleashed/mutable_references.stderr
index 4187a9e..68c6dd1 100644
--- a/tests/ui/consts/miri_unleashed/mutable_references.stderr
+++ b/tests/ui/consts/miri_unleashed/mutable_references.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value at .<deref>: encountered mutable reference or box pointing to read-only memory
+error[E0080]: constructing invalid value of type &&mut u32: at .<deref>, encountered mutable reference or box pointing to read-only memory
   --> $DIR/mutable_references.rs:13:1
    |
 LL | static FOO: &&mut u32 = &&mut 42;
@@ -9,7 +9,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered mutable reference or box pointing to read-only memory
+error[E0080]: constructing invalid value of type &mut i32: encountered mutable reference or box pointing to read-only memory
   --> $DIR/mutable_references.rs:15:1
    |
 LL | static OH_YES: &mut i32 = &mut 42;
@@ -32,7 +32,7 @@
 LL | static BOO: &mut Foo<()> = &mut Foo(());
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0080]: constructing invalid value: encountered mutable reference or box pointing to read-only memory
+error[E0080]: constructing invalid value of type &mut i32: encountered mutable reference or box pointing to read-only memory
   --> $DIR/mutable_references.rs:25:1
    |
 LL | const BLUNT: &mut i32 = &mut 42;
@@ -43,7 +43,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .x.<deref>: encountered `UnsafeCell` in read-only memory
+error[E0080]: constructing invalid value of type Meh: at .x.<deref>, encountered `UnsafeCell` in read-only memory
   --> $DIR/mutable_references.rs:40:1
    |
 LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) };
@@ -54,7 +54,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .x.<deref>: encountered `UnsafeCell` in read-only memory
+error[E0080]: constructing invalid value of type Meh: at .x.<deref>, encountered `UnsafeCell` in read-only memory
   --> $DIR/mutable_references.rs:45:1
    |
 LL | const MUH: Meh = Meh {
@@ -65,7 +65,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<deref>.<dyn-downcast>.x: encountered `UnsafeCell` in read-only memory
+error[E0080]: constructing invalid value of type &dyn Sync: at .<deref>.<dyn-downcast(Synced)>.x, encountered `UnsafeCell` in read-only memory
   --> $DIR/mutable_references.rs:56:1
    |
 LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
@@ -76,7 +76,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered mutable reference or box pointing to read-only memory
+error[E0080]: constructing invalid value of type &mut i32: encountered mutable reference or box pointing to read-only memory
   --> $DIR/mutable_references.rs:62:1
    |
 LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
diff --git a/tests/ui/consts/miri_unleashed/static-no-inner-mut.32bit.stderr b/tests/ui/consts/miri_unleashed/static-no-inner-mut.32bit.stderr
index d7c668a..ab21696 100644
--- a/tests/ui/consts/miri_unleashed/static-no-inner-mut.32bit.stderr
+++ b/tests/ui/consts/miri_unleashed/static-no-inner-mut.32bit.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value at .<deref>.v: encountered `UnsafeCell` in read-only memory
+error[E0080]: constructing invalid value of type &Atomic<i32>: at .<deref>.v, encountered `UnsafeCell` in read-only memory
   --> $DIR/static-no-inner-mut.rs:8:1
    |
 LL | static REF: &AtomicI32 = &AtomicI32::new(42);
@@ -9,7 +9,7 @@
                ╾ALLOC0╼                                     │ ╾──╼
            }
 
-error[E0080]: constructing invalid value: encountered mutable reference or box pointing to read-only memory
+error[E0080]: constructing invalid value of type &mut i32: encountered mutable reference or box pointing to read-only memory
   --> $DIR/static-no-inner-mut.rs:11:1
    |
 LL | static REFMUT: &mut i32 = &mut 0;
@@ -20,7 +20,7 @@
                ╾ALLOC1╼                                     │ ╾──╼
            }
 
-error[E0080]: constructing invalid value at .<deref>.v: encountered `UnsafeCell` in read-only memory
+error[E0080]: constructing invalid value of type &Atomic<i32>: at .<deref>.v, encountered `UnsafeCell` in read-only memory
   --> $DIR/static-no-inner-mut.rs:15:1
    |
 LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}};
@@ -31,7 +31,7 @@
                ╾ALLOC2╼                                     │ ╾──╼
            }
 
-error[E0080]: constructing invalid value: encountered mutable reference or box pointing to read-only memory
+error[E0080]: constructing invalid value of type &mut i32: encountered mutable reference or box pointing to read-only memory
   --> $DIR/static-no-inner-mut.rs:17:1
    |
 LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}};
diff --git a/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr b/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr
index f3bb499..673c1b3 100644
--- a/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr
+++ b/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value at .<deref>.v: encountered `UnsafeCell` in read-only memory
+error[E0080]: constructing invalid value of type &Atomic<i32>: at .<deref>.v, encountered `UnsafeCell` in read-only memory
   --> $DIR/static-no-inner-mut.rs:8:1
    |
 LL | static REF: &AtomicI32 = &AtomicI32::new(42);
@@ -9,7 +9,7 @@
                ╾ALLOC0╼                         │ ╾──────╼
            }
 
-error[E0080]: constructing invalid value: encountered mutable reference or box pointing to read-only memory
+error[E0080]: constructing invalid value of type &mut i32: encountered mutable reference or box pointing to read-only memory
   --> $DIR/static-no-inner-mut.rs:11:1
    |
 LL | static REFMUT: &mut i32 = &mut 0;
@@ -20,7 +20,7 @@
                ╾ALLOC1╼                         │ ╾──────╼
            }
 
-error[E0080]: constructing invalid value at .<deref>.v: encountered `UnsafeCell` in read-only memory
+error[E0080]: constructing invalid value of type &Atomic<i32>: at .<deref>.v, encountered `UnsafeCell` in read-only memory
   --> $DIR/static-no-inner-mut.rs:15:1
    |
 LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}};
@@ -31,7 +31,7 @@
                ╾ALLOC2╼                         │ ╾──────╼
            }
 
-error[E0080]: constructing invalid value: encountered mutable reference or box pointing to read-only memory
+error[E0080]: constructing invalid value of type &mut i32: encountered mutable reference or box pointing to read-only memory
   --> $DIR/static-no-inner-mut.rs:17:1
    |
 LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}};
diff --git a/tests/ui/consts/refs_check_const_eq-issue-88384.rs b/tests/ui/consts/refs_check_const_eq-issue-88384.rs
index 46cb627..506bec3 100644
--- a/tests/ui/consts/refs_check_const_eq-issue-88384.rs
+++ b/tests/ui/consts/refs_check_const_eq-issue-88384.rs
@@ -1,6 +1,5 @@
 #![feature(fn_traits)]
 #![feature(adt_const_params, unsized_const_params)]
-//~^ WARNING the feature `unsized_const_params` is incomplete
 
 #[derive(PartialEq, Eq)]
 struct CompileTimeSettings {
diff --git a/tests/ui/consts/refs_check_const_eq-issue-88384.stderr b/tests/ui/consts/refs_check_const_eq-issue-88384.stderr
index 62c5c52..ac4cb05 100644
--- a/tests/ui/consts/refs_check_const_eq-issue-88384.stderr
+++ b/tests/ui/consts/refs_check_const_eq-issue-88384.stderr
@@ -1,14 +1,5 @@
-warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/refs_check_const_eq-issue-88384.rs:2:30
-   |
-LL | #![feature(adt_const_params, unsized_const_params)]
-   |                              ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0741]: `CompileTimeSettings` must implement `ConstParamTy` to be used as the type of a const generic parameter
-  --> $DIR/refs_check_const_eq-issue-88384.rs:10:21
+  --> $DIR/refs_check_const_eq-issue-88384.rs:9:21
    |
 LL | struct Foo<const T: CompileTimeSettings>;
    |                     ^^^^^^^^^^^^^^^^^^^
@@ -20,7 +11,7 @@
    |
 
 error[E0741]: `CompileTimeSettings` must implement `ConstParamTy` to be used as the type of a const generic parameter
-  --> $DIR/refs_check_const_eq-issue-88384.rs:13:15
+  --> $DIR/refs_check_const_eq-issue-88384.rs:12:15
    |
 LL | impl<const T: CompileTimeSettings> Foo<T> {
    |               ^^^^^^^^^^^^^^^^^^^
@@ -31,6 +22,6 @@
 LL | struct CompileTimeSettings {
    |
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0741`.
diff --git a/tests/ui/consts/static-default-lifetime/generic-associated-const.rs b/tests/ui/consts/static-default-lifetime/generic-associated-const.rs
index 721920b..8fabaa4 100644
--- a/tests/ui/consts/static-default-lifetime/generic-associated-const.rs
+++ b/tests/ui/consts/static-default-lifetime/generic-associated-const.rs
@@ -1,6 +1,5 @@
 #![deny(elided_lifetimes_in_associated_constant)]
 #![feature(generic_const_items)]
-//~^ WARN the feature `generic_const_items` is incomplete
 
 struct A;
 impl A {
diff --git a/tests/ui/consts/static-default-lifetime/generic-associated-const.stderr b/tests/ui/consts/static-default-lifetime/generic-associated-const.stderr
index 3680ef6..fe858d6 100644
--- a/tests/ui/consts/static-default-lifetime/generic-associated-const.stderr
+++ b/tests/ui/consts/static-default-lifetime/generic-associated-const.stderr
@@ -1,5 +1,5 @@
 error[E0106]: missing lifetime specifier
-  --> $DIR/generic-associated-const.rs:15:29
+  --> $DIR/generic-associated-const.rs:14:29
    |
 LL |     const GAC_LIFETIME<'a>: &str = "";
    |                             ^ expected named lifetime parameter
@@ -9,23 +9,14 @@
 LL |     const GAC_LIFETIME<'a>: &'a str = "";
    |                              ++
 
-warning: the feature `generic_const_items` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/generic-associated-const.rs:2:12
-   |
-LL | #![feature(generic_const_items)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #113521 <https://github.com/rust-lang/rust/issues/113521> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/generic-associated-const.rs:8:29
+  --> $DIR/generic-associated-const.rs:7:29
    |
 LL |     const GAC_LIFETIME<'a>: &str = "";
    |                             ^
    |
 note: cannot automatically infer `'static` because of other lifetimes in scope
-  --> $DIR/generic-associated-const.rs:8:24
+  --> $DIR/generic-associated-const.rs:7:24
    |
 LL |     const GAC_LIFETIME<'a>: &str = "";
    |                        ^^
@@ -41,6 +32,6 @@
 LL |     const GAC_LIFETIME<'a>: &'static str = "";
    |                              +++++++
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/consts/trait_specialization.rs b/tests/ui/consts/trait_specialization.rs
index 1360fab..1ea56b5 100644
--- a/tests/ui/consts/trait_specialization.rs
+++ b/tests/ui/consts/trait_specialization.rs
@@ -4,7 +4,7 @@
 // Tests that specialization does not cause optimizations running on polymorphic MIR to resolve
 // to a `default` implementation.
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Marker {}
 
diff --git a/tests/ui/consts/trait_specialization.stderr b/tests/ui/consts/trait_specialization.stderr
deleted file mode 100644
index ce52cf1..0000000
--- a/tests/ui/consts/trait_specialization.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/trait_specialization.rs:7:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/consts/validate_never_arrays.stderr b/tests/ui/consts/validate_never_arrays.stderr
index 3c405e8..517b632 100644
--- a/tests/ui/consts/validate_never_arrays.stderr
+++ b/tests/ui/consts/validate_never_arrays.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value: encountered a reference pointing to uninhabited type [!; 1]
+error[E0080]: constructing invalid value of type &[!; 1]: encountered a reference pointing to uninhabited type [!; 1]
   --> $DIR/validate_never_arrays.rs:6:1
    |
 LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
@@ -9,7 +9,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered a value of the never type `!`
+error[E0080]: constructing invalid value of type &[!]: at .<deref>[0], encountered a value of the never type `!`
   --> $DIR/validate_never_arrays.rs:9:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
@@ -20,7 +20,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .<deref>[0]: encountered a value of the never type `!`
+error[E0080]: constructing invalid value of type &[!]: at .<deref>[0], encountered a value of the never type `!`
   --> $DIR/validate_never_arrays.rs:10:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
diff --git a/tests/ui/contracts/incomplete-feature.rs b/tests/ui/contracts/incomplete-feature.rs
index f1351e2..c10774b 100644
--- a/tests/ui/contracts/incomplete-feature.rs
+++ b/tests/ui/contracts/incomplete-feature.rs
@@ -4,6 +4,7 @@
 // This test specifically checks that the [incomplete_features] warning is
 // emitted when the `contracts` feature gate is enabled, so that it can be
 // marked as `expect`ed in other tests in order to reduce duplication.
+#![warn(incomplete_features)]
 #![feature(contracts)]
 //~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
 extern crate core;
diff --git a/tests/ui/contracts/incomplete-feature.stderr b/tests/ui/contracts/incomplete-feature.stderr
index 7683926..137b13f 100644
--- a/tests/ui/contracts/incomplete-feature.stderr
+++ b/tests/ui/contracts/incomplete-feature.stderr
@@ -1,11 +1,15 @@
 warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/incomplete-feature.rs:7:12
+  --> $DIR/incomplete-feature.rs:8:12
    |
 LL | #![feature(contracts)]
    |            ^^^^^^^^^
    |
    = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
-   = note: `#[warn(incomplete_features)]` on by default
+note: the lint level is defined here
+  --> $DIR/incomplete-feature.rs:7:9
+   |
+LL | #![warn(incomplete_features)]
+   |         ^^^^^^^^^^^^^^^^^^^
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/coverage-attr/bad-syntax.rs b/tests/ui/coverage-attr/bad-syntax.rs
index 062e82e..ef7b41d 100644
--- a/tests/ui/coverage-attr/bad-syntax.rs
+++ b/tests/ui/coverage-attr/bad-syntax.rs
@@ -6,12 +6,12 @@
 // Tests the error messages produced (or not produced) by various unusual
 // uses of the `#[coverage(..)]` attribute.
 
-#[coverage(off)] //~ ERROR multiple `coverage` attributes
 #[coverage(off)]
+#[coverage(off)] //~ ERROR multiple `coverage` attributes
 fn multiple_consistent() {}
 
-#[coverage(off)] //~ ERROR multiple `coverage` attributes
-#[coverage(on)]
+#[coverage(off)]
+#[coverage(on)] //~ ERROR multiple `coverage` attributes
 fn multiple_inconsistent() {}
 
 #[coverage] //~ ERROR malformed `coverage` attribute input
diff --git a/tests/ui/coverage-attr/bad-syntax.stderr b/tests/ui/coverage-attr/bad-syntax.stderr
index ecf3ed8..4a35622 100644
--- a/tests/ui/coverage-attr/bad-syntax.stderr
+++ b/tests/ui/coverage-attr/bad-syntax.stderr
@@ -1,26 +1,26 @@
 error: multiple `coverage` attributes
-  --> $DIR/bad-syntax.rs:9:1
+  --> $DIR/bad-syntax.rs:10:1
    |
 LL | #[coverage(off)]
    | ^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/bad-syntax.rs:10:1
+  --> $DIR/bad-syntax.rs:9:1
    |
 LL | #[coverage(off)]
    | ^^^^^^^^^^^^^^^^
 
 error: multiple `coverage` attributes
-  --> $DIR/bad-syntax.rs:13:1
-   |
-LL | #[coverage(off)]
-   | ^^^^^^^^^^^^^^^^ help: remove this attribute
-   |
-note: attribute also specified here
   --> $DIR/bad-syntax.rs:14:1
    |
 LL | #[coverage(on)]
-   | ^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+note: attribute also specified here
+  --> $DIR/bad-syntax.rs:13:1
+   |
+LL | #[coverage(off)]
+   | ^^^^^^^^^^^^^^^^
 
 error[E0539]: malformed `coverage` attribute input
   --> $DIR/bad-syntax.rs:17:1
diff --git a/tests/ui/delegation/explicit-paths-pass.rs b/tests/ui/delegation/explicit-paths-pass.rs
index dd0ee2c..7efbb37 100644
--- a/tests/ui/delegation/explicit-paths-pass.rs
+++ b/tests/ui/delegation/explicit-paths-pass.rs
@@ -17,11 +17,8 @@ impl Trait for F {}
 
 mod to_reuse {
     pub fn foo(x: i32) -> i32 { x + 1 }
-    pub fn zero_args() -> i32 { 15 }
 }
 
-reuse to_reuse::zero_args { self }
-
 struct S(F);
 impl Trait for S {
     reuse Trait::bar { self.0 }
@@ -49,5 +46,4 @@ fn main() {
     #[inline]
     reuse to_reuse::foo;
     assert_eq!(43, foo(42));
-    assert_eq!(15, zero_args());
 }
diff --git a/tests/ui/delegation/generics/const-type-ice-153433.rs b/tests/ui/delegation/generics/const-type-ice-153433.rs
new file mode 100644
index 0000000..edd6d05
--- /dev/null
+++ b/tests/ui/delegation/generics/const-type-ice-153433.rs
@@ -0,0 +1,8 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+fn main() {
+    fn foo<const N: dyn for<'a> Foo>() {}
+    //~^ ERROR: cannot find trait `Foo` in this scope
+    reuse foo as bar;
+}
diff --git a/tests/ui/delegation/generics/const-type-ice-153433.stderr b/tests/ui/delegation/generics/const-type-ice-153433.stderr
new file mode 100644
index 0000000..3b537e2
--- /dev/null
+++ b/tests/ui/delegation/generics/const-type-ice-153433.stderr
@@ -0,0 +1,9 @@
+error[E0405]: cannot find trait `Foo` in this scope
+  --> $DIR/const-type-ice-153433.rs:5:33
+   |
+LL |     fn foo<const N: dyn for<'a> Foo>() {}
+   |                                 ^^^ not found in this scope
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0405`.
diff --git a/tests/ui/delegation/generics/const-type-ice-153499.rs b/tests/ui/delegation/generics/const-type-ice-153499.rs
new file mode 100644
index 0000000..debda0d
--- /dev/null
+++ b/tests/ui/delegation/generics/const-type-ice-153499.rs
@@ -0,0 +1,13 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+trait Trait<'a, T, const F: fn(&CStr) -> usize> {
+    //~^ ERROR: cannot find type `CStr` in this scope
+    //~| ERROR: using function pointers as const generic parameters is forbidden
+    fn foo<'x: 'x, A, B>(&self) {}
+}
+
+reuse Trait::foo;
+//~^ ERROR: using function pointers as const generic parameters is forbidden
+
+fn main() {}
diff --git a/tests/ui/delegation/generics/const-type-ice-153499.stderr b/tests/ui/delegation/generics/const-type-ice-153499.stderr
new file mode 100644
index 0000000..02fd719
--- /dev/null
+++ b/tests/ui/delegation/generics/const-type-ice-153499.stderr
@@ -0,0 +1,30 @@
+error[E0425]: cannot find type `CStr` in this scope
+  --> $DIR/const-type-ice-153499.rs:4:33
+   |
+LL | trait Trait<'a, T, const F: fn(&CStr) -> usize> {
+   |                                 ^^^^ not found in this scope
+   |
+help: consider importing this struct
+   |
+LL + use std::ffi::CStr;
+   |
+
+error: using function pointers as const generic parameters is forbidden
+  --> $DIR/const-type-ice-153499.rs:4:29
+   |
+LL | trait Trait<'a, T, const F: fn(&CStr) -> usize> {
+   |                             ^^^^^^^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool`, and `char`
+
+error: using function pointers as const generic parameters is forbidden
+  --> $DIR/const-type-ice-153499.rs:10:14
+   |
+LL | reuse Trait::foo;
+   |              ^^^
+   |
+   = note: the only supported types are integers, `bool`, and `char`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/delegation/generics/mapping/free-to-free-pass.rs b/tests/ui/delegation/generics/mapping/free-to-free-pass.rs
index aafdd56..c67e4c0 100644
--- a/tests/ui/delegation/generics/mapping/free-to-free-pass.rs
+++ b/tests/ui/delegation/generics/mapping/free-to-free-pass.rs
@@ -78,18 +78,16 @@ pub fn check<T: Clone, U: Clone>() {
     }
 }
 
-// FIXME(fn_delegation): Uncomment this test when impl Traits in function params are supported
+mod test_7 {
+    fn foo<T, U>(t: T, u: U, f: impl FnOnce(T, U) -> U) -> U {
+        f(t, u)
+    }
 
-// mod test_7 {
-//     fn foo<T, U>(t: T, u: U, f: impl FnOnce(T, U) -> U) -> U {
-//         f(t, u)
-//     }
-
-//     pub fn check() {
-//         reuse foo as bar;
-//         assert_eq!(bar::<i32, i32>(1, 2, |x, y| y), 2);
-//     }
-// }
+    pub fn check() {
+        reuse foo as bar;
+        assert_eq!(bar::<i32, i32>(1, 2, |_, y| y), 2);
+    }
+}
 
 // Testing reuse of local fn with delegation parent generic params specified,
 // late-bound lifetimes + types + consts, reusing with user args,
@@ -126,7 +124,7 @@ pub fn main() {
     test_4::check::<i32, String>();
     test_5::check::<i32, String>();
     test_6::check::<i32, String>();
-    // test_7::check();
+    test_7::check();
     test_8::check::<i32, String>();
     test_9::check::<String, i32>();
 }
diff --git a/tests/ui/delegation/generics/synth-params-ice-143498.rs b/tests/ui/delegation/generics/synth-params-ice-143498.rs
new file mode 100644
index 0000000..652059b
--- /dev/null
+++ b/tests/ui/delegation/generics/synth-params-ice-143498.rs
@@ -0,0 +1,27 @@
+//@ compile-flags: -Z deduplicate-diagnostics=yes
+//@ edition:2024
+
+#![feature(fn_delegation)]
+#![feature(iter_advance_by)]
+#![feature(iter_array_chunks)]
+#![feature(iterator_try_collect)]
+#![feature(iterator_try_reduce)]
+#![feature(iter_collect_into)]
+#![feature(iter_intersperse)]
+#![feature(iter_is_partitioned)]
+#![feature(iter_map_windows)]
+#![feature(iter_next_chunk)]
+#![feature(iter_order_by)]
+#![feature(iter_partition_in_place)]
+#![feature(trusted_random_access)]
+#![feature(try_find)]
+#![allow(incomplete_features)]
+
+impl X {
+//~^ ERROR: cannot find type `X` in this scope
+    reuse< std::fmt::Debug as Iterator >::*;
+    //~^ ERROR: expected method or associated constant, found associated type `Iterator::Item`
+    //~| ERROR: expected a type, found a trait
+}
+
+pub fn main() {}
diff --git a/tests/ui/delegation/generics/synth-params-ice-143498.stderr b/tests/ui/delegation/generics/synth-params-ice-143498.stderr
new file mode 100644
index 0000000..14b0399
--- /dev/null
+++ b/tests/ui/delegation/generics/synth-params-ice-143498.stderr
@@ -0,0 +1,27 @@
+error[E0425]: cannot find type `X` in this scope
+  --> $DIR/synth-params-ice-143498.rs:20:6
+   |
+LL | impl X {
+   |      ^ not found in this scope
+
+error[E0575]: expected method or associated constant, found associated type `Iterator::Item`
+  --> $DIR/synth-params-ice-143498.rs:22:10
+   |
+LL |     reuse< std::fmt::Debug as Iterator >::*;
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a method or associated constant
+
+error[E0782]: expected a type, found a trait
+  --> $DIR/synth-params-ice-143498.rs:22:12
+   |
+LL |     reuse< std::fmt::Debug as Iterator >::*;
+   |            ^^^^^^^^^^^^^^^
+   |
+help: you can add the `dyn` keyword if you want a trait object
+   |
+LL |     reuse< dyn std::fmt::Debug as Iterator >::*;
+   |            +++
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0425, E0575, E0782.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/tests/ui/delegation/inner-attr.rs b/tests/ui/delegation/inner-attr.rs
index 6c99680..5011187 100644
--- a/tests/ui/delegation/inner-attr.rs
+++ b/tests/ui/delegation/inner-attr.rs
@@ -4,5 +4,6 @@
 fn a() {}
 
 reuse a as b { #![rustc_dummy] self } //~ ERROR an inner attribute is not permitted in this context
+//~^ ERROR: this function takes 0 arguments but 1 argument was supplied
 
 fn main() {}
diff --git a/tests/ui/delegation/inner-attr.stderr b/tests/ui/delegation/inner-attr.stderr
index 257ab76..226a48e 100644
--- a/tests/ui/delegation/inner-attr.stderr
+++ b/tests/ui/delegation/inner-attr.stderr
@@ -3,11 +3,29 @@
    |
 LL | reuse a as b { #![rustc_dummy] self }
    |                ^^^^^^^^^^^^^^^
-LL |
+...
 LL | fn main() {}
    | ------------ the inner attribute doesn't annotate this function
    |
    = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
 
-error: aborting due to 1 previous error
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+  --> $DIR/inner-attr.rs:6:7
+   |
+LL | reuse a as b { #![rustc_dummy] self }
+   |       ^                        ---- unexpected argument
+   |
+note: function defined here
+  --> $DIR/inner-attr.rs:4:4
+   |
+LL | fn a() {}
+   |    ^
+help: remove the extra argument
+   |
+LL - reuse a as b { #![rustc_dummy] self }
+LL + reuse self }
+   |
 
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/tests/ui/delegation/zero-args-delegations-ice-154332.rs b/tests/ui/delegation/zero-args-delegations-ice-154332.rs
new file mode 100644
index 0000000..c684803
--- /dev/null
+++ b/tests/ui/delegation/zero-args-delegations-ice-154332.rs
@@ -0,0 +1,30 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod test_ice {
+    fn a() {}
+
+    reuse a as b { //~ ERROR: this function takes 0 arguments but 1 argument was supplied
+        let closure = || {
+            fn foo<'a, 'b, T: Clone, const N: usize, U: Clone>(_t: &'a T, _u: &'b U) {}
+
+            reuse foo::<String, 1, String> as bar;
+            bar(&"".to_string(), &"".to_string());
+        };
+
+        closure();
+    }
+}
+
+mod test_2 {
+    mod to_reuse {
+        pub fn zero_args() -> i32 {
+            15
+        }
+    }
+
+    reuse to_reuse::zero_args { self }
+    //~^ ERROR: this function takes 0 arguments but 1 argument was supplied
+}
+
+fn main() {}
diff --git a/tests/ui/delegation/zero-args-delegations-ice-154332.stderr b/tests/ui/delegation/zero-args-delegations-ice-154332.stderr
new file mode 100644
index 0000000..dcac56e
--- /dev/null
+++ b/tests/ui/delegation/zero-args-delegations-ice-154332.stderr
@@ -0,0 +1,43 @@
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+  --> $DIR/zero-args-delegations-ice-154332.rs:7:11
+   |
+LL |       reuse a as b {
+   |  ___________^______-
+LL | |         let closure = || {
+LL | |             fn foo<'a, 'b, T: Clone, const N: usize, U: Clone>(_t: &'a T, _u: &'b U) {}
+...  |
+LL | |         closure();
+LL | |     }
+   | |_____- unexpected argument of type `()`
+   |
+note: function defined here
+  --> $DIR/zero-args-delegations-ice-154332.rs:5:8
+   |
+LL |     fn a() {}
+   |        ^
+help: remove the extra argument
+   |
+LL -     reuse a as b {
+LL +     reuse {
+   |
+
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+  --> $DIR/zero-args-delegations-ice-154332.rs:26:21
+   |
+LL |     reuse to_reuse::zero_args { self }
+   |                     ^^^^^^^^^   ---- unexpected argument
+   |
+note: function defined here
+  --> $DIR/zero-args-delegations-ice-154332.rs:21:16
+   |
+LL |         pub fn zero_args() -> i32 {
+   |                ^^^^^^^^^
+help: remove the extra argument
+   |
+LL -     reuse to_reuse::zero_args { self }
+LL +     reuse to_reuse::zero_argself }
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/tests/ui/derives/issue-36617.stderr b/tests/ui/derives/issue-36617.stderr
index 3de1d87..f76c5df 100644
--- a/tests/ui/derives/issue-36617.stderr
+++ b/tests/ui/derives/issue-36617.stderr
@@ -5,7 +5,7 @@
    | ^^^^^^^^^^^^^^^^
 ...
 LL | fn main() {}
-   |    ---- the inner attribute doesn't annotate this function
+   | ------------ the inner attribute doesn't annotate this item
    |
 help: perhaps you meant to use an outer attribute
    |
@@ -20,7 +20,7 @@
    | ^^^^^^^^
 ...
 LL | fn main() {}
-   |    ---- the inner attribute doesn't annotate this function
+   | ------------ the inner attribute doesn't annotate this item
    |
 help: perhaps you meant to use an outer attribute
    |
@@ -35,7 +35,7 @@
    | ^^^^^^^^^^^^^
 ...
 LL | fn main() {}
-   |    ---- the inner attribute doesn't annotate this function
+   | ------------ the inner attribute doesn't annotate this item
    |
 help: perhaps you meant to use an outer attribute
    |
@@ -50,7 +50,7 @@
    | ^^^^^^^^^
 ...
 LL | fn main() {}
-   |    ---- the inner attribute doesn't annotate this function
+   | ------------ the inner attribute doesn't annotate this item
    |
 help: perhaps you meant to use an outer attribute
    |
@@ -65,7 +65,7 @@
    | ^^^^^^^^^^^^^^^^^^^^
 ...
 LL | fn main() {}
-   |    ---- the inner attribute doesn't annotate this function
+   | ------------ the inner attribute doesn't annotate this item
    |
 help: perhaps you meant to use an outer attribute
    |
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 e64e60f..09c2a05 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
@@ -26,12 +26,15 @@ impl Bar for i32 {}
 // cannot use special rustc_on_unimplement symbols
 // in the format string
 #[diagnostic::on_unimplemented(
-    message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+    message = "{from_desugaring}{direct}{cause}{integral}{integer}{struct}{enum}{union}",
     //~^WARN there is no parameter `from_desugaring` on trait `Baz`
     //~|WARN there is no parameter `direct` on trait `Baz`
     //~|WARN there is no parameter `cause` on trait `Baz`
     //~|WARN there is no parameter `integral` on trait `Baz`
     //~|WARN there is no parameter `integer` on trait `Baz`
+    //~|WARN there is no parameter `r#struct` on trait `Baz`
+    //~|WARN there is no parameter `r#enum` on trait `Baz`
+    //~|WARN there is no parameter `union` on trait `Baz`
     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
     //~^WARN there is no parameter `float` on trait `Baz`
     //~|WARN there is no parameter `_Self` on trait `Baz`
@@ -52,5 +55,5 @@ fn main() {
     takes_bar(());
     //~^ERROR the trait bound `(): Bar` is not satisfied
     takes_baz(());
-    //~^ERROR {from_desugaring}{direct}{cause}{integral}{integer}
+    //~^ERROR {from_desugaring}{direct}{cause}{integral}{integer}{struct}{enum}{union}
 }
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 862f805..58d2bdb 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
@@ -9,7 +9,7 @@
 warning: there is no parameter `from_desugaring` on trait `Baz`
   --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:17
    |
-LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}{struct}{enum}{union}",
    |                 ^^^^^^^^^^^^^^^
    |
    = help: expect either a generic argument name or `{Self}` as format argument
@@ -18,7 +18,7 @@
 warning: there is no parameter `direct` on trait `Baz`
   --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:34
    |
-LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}{struct}{enum}{union}",
    |                                  ^^^^^^
    |
    = help: expect either a generic argument name or `{Self}` as format argument
@@ -26,7 +26,7 @@
 warning: there is no parameter `cause` on trait `Baz`
   --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:42
    |
-LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}{struct}{enum}{union}",
    |                                          ^^^^^
    |
    = help: expect either a generic argument name or `{Self}` as format argument
@@ -34,7 +34,7 @@
 warning: there is no parameter `integral` on trait `Baz`
   --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:49
    |
-LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}{struct}{enum}{union}",
    |                                                 ^^^^^^^^
    |
    = help: expect either a generic argument name or `{Self}` as format argument
@@ -42,13 +42,37 @@
 warning: there is no parameter `integer` on trait `Baz`
   --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:59
    |
-LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}",
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}{struct}{enum}{union}",
    |                                                           ^^^^^^^
    |
    = help: expect either a generic argument name or `{Self}` as format argument
 
+warning: there is no parameter `r#struct` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:68
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}{struct}{enum}{union}",
+   |                                                                    ^^^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `r#enum` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:76
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}{struct}{enum}{union}",
+   |                                                                            ^^^^
+   |
+   = help: expect either a generic argument name or `{Self}` as format argument
+
+warning: there is no parameter `union` on trait `Baz`
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:29:82
+   |
+LL |     message = "{from_desugaring}{direct}{cause}{integral}{integer}{struct}{enum}{union}",
+   |                                                                                  ^^^^^
+   |
+   = 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:35:15
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:38:15
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
    |               ^^^^^
@@ -56,7 +80,7 @@
    = 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:35:22
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:38:22
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
    |                      ^^^^^
@@ -64,7 +88,7 @@
    = 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:35:29
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:38:29
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
    |                             ^^^^^^^^^^^
@@ -72,7 +96,7 @@
    = 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:35:42
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:38:42
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
    |                                          ^^^^^
@@ -80,7 +104,7 @@
    = 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:35:49
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:38:49
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
    |                                                 ^^^^^^^^^^^
@@ -88,7 +112,7 @@
    = help: expect either a generic argument name or `{Self}` as format argument
 
 warning: there is no parameter `This` on trait `Baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:35:62
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:38:62
    |
 LL |     label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
    |                                                              ^^^^
@@ -129,7 +153,7 @@
    = help: only `message`, `note` and `label` are allowed as options
 
 error[E0277]: trait has `()` and `i32` as params
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:50:15
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:53:15
    |
 LL |     takes_foo(());
    |     --------- ^^ trait has `()` and `i32` as params
@@ -144,13 +168,13 @@
 LL | trait Foo<T> {}
    | ^^^^^^^^^^^^
 note: required by a bound in `takes_foo`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:45:22
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:48:22
    |
 LL | fn takes_foo(_: impl Foo<i32>) {}
    |                      ^^^^^^^^ required by this bound in `takes_foo`
 
 error[E0277]: the trait bound `(): Bar` is not satisfied
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:52:15
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:55:15
    |
 LL |     takes_bar(());
    |     --------- ^^ the trait `Bar` is not implemented for `()`
@@ -163,13 +187,13 @@
 LL | impl Bar for i32 {}
    | ^^^^^^^^^^^^^^^^
 note: required by a bound in `takes_bar`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:46:22
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:49:22
    |
 LL | fn takes_bar(_: impl Bar) {}
    |                      ^^^ required by this bound in `takes_bar`
 
-error[E0277]: {from_desugaring}{direct}{cause}{integral}{integer}
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:54:15
+error[E0277]: {from_desugaring}{direct}{cause}{integral}{integer}{struct}{enum}{union}
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:57:15
    |
 LL |     takes_baz(());
    |     --------- ^^ {float}{_Self}{crate_local}{Trait}{ItemContext}{This}
@@ -178,16 +202,16 @@
    |
    = 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:43:1
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:46:1
    |
 LL | trait Baz {}
    | ^^^^^^^^^
 note: required by a bound in `takes_baz`
-  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:47:22
+  --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:50:22
    |
 LL | fn takes_baz(_: impl Baz) {}
    |                      ^^^ required by this bound in `takes_baz`
 
-error: aborting due to 3 previous errors; 16 warnings emitted
+error: aborting due to 3 previous errors; 19 warnings emitted
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr
index 4a38546..0c07e5a 100644
--- a/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr
+++ b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr
@@ -11,14 +11,14 @@
    |
 LL | struct Bar;
    | ^^^^^^^^^^
-help: the following other types implement trait `Foo<A>`
+help: `Bar` implements trait `Foo<A>`
   --> $DIR/issue-21659-show-relevant-trait-impls-1.rs:15:1
    |
 LL | impl Foo<i32> for Bar {}
-   | ^^^^^^^^^^^^^^^^^^^^^ `Bar` implements `Foo<i32>`
+   | ^^^^^^^^^^^^^^^^^^^^^ `Foo<i32>`
 LL |
 LL | impl Foo<u8> for Bar {}
-   | ^^^^^^^^^^^^^^^^^^^^ `Bar` implements `Foo<u8>`
+   | ^^^^^^^^^^^^^^^^^^^^ `Foo<u8>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
index 8d1c05e..cb4ca90 100644
--- a/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
+++ b/tests/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
@@ -11,13 +11,13 @@
    |
 LL | struct Bar;
    | ^^^^^^^^^^
-   = help: the following other types implement trait `Foo<A>`:
-             `Bar` implements `Foo<i16>`
-             `Bar` implements `Foo<i32>`
-             `Bar` implements `Foo<i8>`
-             `Bar` implements `Foo<u16>`
-             `Bar` implements `Foo<u32>`
-             `Bar` implements `Foo<u8>`
+   = help: `Bar` implements trait `Foo<A>`:
+             Foo<i16>
+             Foo<i32>
+             Foo<i8>
+             Foo<u16>
+             Foo<u32>
+             Foo<u8>
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
index 8bacae9..4bb816b 100644
--- a/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
+++ b/tests/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
@@ -6,12 +6,12 @@
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the following other types implement trait `Foo<B>`:
-             `i8` implements `Foo<bool>`
-             `i8` implements `Foo<u16>`
-             `i8` implements `Foo<u32>`
-             `i8` implements `Foo<u64>`
-             `i8` implements `Foo<u8>`
+   = help: `i8` implements trait `Foo<B>`:
+             Foo<bool>
+             Foo<u16>
+             Foo<u32>
+             Foo<u64>
+             Foo<u8>
 
 error[E0277]: the trait bound `u8: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:25:21
@@ -21,17 +21,17 @@
    |     |
    |     required by a bound introduced by this call
    |
-help: the following other types implement trait `Foo<B>`
+help: `u8` implements trait `Foo<B>`
   --> $DIR/issue-39802-show-5-trait-impls.rs:11:1
    |
 LL | impl Foo<u16> for u8 {}
-   | ^^^^^^^^^^^^^^^^^^^^ `u8` implements `Foo<u16>`
+   | ^^^^^^^^^^^^^^^^^^^^ `Foo<u16>`
 LL | impl Foo<u32> for u8 {}
-   | ^^^^^^^^^^^^^^^^^^^^ `u8` implements `Foo<u32>`
+   | ^^^^^^^^^^^^^^^^^^^^ `Foo<u32>`
 LL | impl Foo<u64> for u8 {}
-   | ^^^^^^^^^^^^^^^^^^^^ `u8` implements `Foo<u64>`
+   | ^^^^^^^^^^^^^^^^^^^^ `Foo<u64>`
 LL | impl Foo<bool> for u8 {}
-   | ^^^^^^^^^^^^^^^^^^^^^ `u8` implements `Foo<bool>`
+   | ^^^^^^^^^^^^^^^^^^^^^ `Foo<bool>`
 
 error[E0277]: the trait bound `bool: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:26:21
@@ -41,13 +41,13 @@
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the following other types implement trait `Foo<B>`:
-             `bool` implements `Foo<bool>`
-             `bool` implements `Foo<i8>`
-             `bool` implements `Foo<u16>`
-             `bool` implements `Foo<u32>`
-             `bool` implements `Foo<u64>`
-             `bool` implements `Foo<u8>`
+   = help: `bool` implements trait `Foo<B>`:
+             Foo<bool>
+             Foo<i8>
+             Foo<u16>
+             Foo<u32>
+             Foo<u64>
+             Foo<u8>
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/error-codes/E0520.rs b/tests/ui/error-codes/E0520.rs
index ead78b7..b746ca6 100644
--- a/tests/ui/error-codes/E0520.rs
+++ b/tests/ui/error-codes/E0520.rs
@@ -1,5 +1,4 @@
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
 
 trait SpaceLlama {
     fn fly(&self);
diff --git a/tests/ui/error-codes/E0520.stderr b/tests/ui/error-codes/E0520.stderr
index 8331920..c47b3e7 100644
--- a/tests/ui/error-codes/E0520.stderr
+++ b/tests/ui/error-codes/E0520.stderr
@@ -1,15 +1,5 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/E0520.rs:1:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0520]: `fly` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/E0520.rs:17:5
+  --> $DIR/E0520.rs:16:5
    |
 LL | impl<T: Clone> SpaceLlama for T {
    | ------------------------------- parent `impl` is here
@@ -19,6 +9,6 @@
    |
    = note: to specialize, `fly` in the parent `impl` must be marked `default`
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0520`.
diff --git a/tests/ui/error-codes/E0771.rs b/tests/ui/error-codes/E0771.rs
index a932c5e..6d86d4a 100644
--- a/tests/ui/error-codes/E0771.rs
+++ b/tests/ui/error-codes/E0771.rs
@@ -1,5 +1,4 @@
 #![feature(adt_const_params, unsized_const_params)]
-//~^ WARN the feature `unsized_const_params` is incomplete
 
 fn function_with_str<'a, const STRING: &'a str>() {} //~ ERROR E0770
 
diff --git a/tests/ui/error-codes/E0771.stderr b/tests/ui/error-codes/E0771.stderr
index dfeaa34..9378207 100644
--- a/tests/ui/error-codes/E0771.stderr
+++ b/tests/ui/error-codes/E0771.stderr
@@ -1,18 +1,9 @@
 error[E0770]: the type of const parameters must not depend on other generic parameters
-  --> $DIR/E0771.rs:4:41
+  --> $DIR/E0771.rs:3:41
    |
 LL | fn function_with_str<'a, const STRING: &'a str>() {}
    |                                         ^^ the type must not depend on the parameter `'a`
 
-warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/E0771.rs:1:30
-   |
-LL | #![feature(adt_const_params, unsized_const_params)]
-   |                              ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0770`.
diff --git a/tests/ui/feature-gates/feature-gate-effective-target-features.default.stderr b/tests/ui/feature-gates/feature-gate-effective-target-features.default.stderr
index 34a56fe..e699c5d 100644
--- a/tests/ui/feature-gates/feature-gate-effective-target-features.default.stderr
+++ b/tests/ui/feature-gates/feature-gate-effective-target-features.default.stderr
@@ -1,5 +1,5 @@
 error[E0658]: the `#[force_target_feature]` attribute is an experimental feature
-  --> $DIR/feature-gate-effective-target-features.rs:13:5
+  --> $DIR/feature-gate-effective-target-features.rs:14:5
    |
 LL |     #[unsafe(force_target_feature(enable = "avx2"))]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: `#[target_feature(..)]` cannot be applied to safe trait method
-  --> $DIR/feature-gate-effective-target-features.rs:21:5
+  --> $DIR/feature-gate-effective-target-features.rs:22:5
    |
 LL |     #[target_feature(enable = "avx2")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method
@@ -18,13 +18,13 @@
    |     ------------- not an `unsafe` function
 
 error[E0053]: method `foo` has an incompatible type for trait
-  --> $DIR/feature-gate-effective-target-features.rs:23:5
+  --> $DIR/feature-gate-effective-target-features.rs:24:5
    |
 LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^ expected safe fn, found unsafe fn
    |
 note: type in trait
-  --> $DIR/feature-gate-effective-target-features.rs:7:5
+  --> $DIR/feature-gate-effective-target-features.rs:8:5
    |
 LL |     fn foo(&self);
    |     ^^^^^^^^^^^^^^
diff --git a/tests/ui/feature-gates/feature-gate-effective-target-features.feature.stderr b/tests/ui/feature-gates/feature-gate-effective-target-features.feature.stderr
index d51956f..bf9f5d7 100644
--- a/tests/ui/feature-gates/feature-gate-effective-target-features.feature.stderr
+++ b/tests/ui/feature-gates/feature-gate-effective-target-features.feature.stderr
@@ -1,14 +1,18 @@
 warning: the feature `effective_target_features` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/feature-gate-effective-target-features.rs:3:30
+  --> $DIR/feature-gate-effective-target-features.rs:4:30
    |
 LL | #![cfg_attr(feature, feature(effective_target_features))]
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #143352 <https://github.com/rust-lang/rust/issues/143352> for more information
-   = note: `#[warn(incomplete_features)]` on by default
+note: the lint level is defined here
+  --> $DIR/feature-gate-effective-target-features.rs:3:9
+   |
+LL | #![warn(incomplete_features)]
+   |         ^^^^^^^^^^^^^^^^^^^
 
 error: `#[target_feature(..)]` cannot be applied to safe trait method
-  --> $DIR/feature-gate-effective-target-features.rs:21:5
+  --> $DIR/feature-gate-effective-target-features.rs:22:5
    |
 LL |     #[target_feature(enable = "avx2")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method
@@ -17,13 +21,13 @@
    |     ------------- not an `unsafe` function
 
 error[E0053]: method `foo` has an incompatible type for trait
-  --> $DIR/feature-gate-effective-target-features.rs:23:5
+  --> $DIR/feature-gate-effective-target-features.rs:24:5
    |
 LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^ expected safe fn, found unsafe fn
    |
 note: type in trait
-  --> $DIR/feature-gate-effective-target-features.rs:7:5
+  --> $DIR/feature-gate-effective-target-features.rs:8:5
    |
 LL |     fn foo(&self);
    |     ^^^^^^^^^^^^^^
diff --git a/tests/ui/feature-gates/feature-gate-effective-target-features.rs b/tests/ui/feature-gates/feature-gate-effective-target-features.rs
index d383897..a8be611 100644
--- a/tests/ui/feature-gates/feature-gate-effective-target-features.rs
+++ b/tests/ui/feature-gates/feature-gate-effective-target-features.rs
@@ -1,5 +1,6 @@
 //@ revisions: default feature
 //@ only-x86_64
+#![warn(incomplete_features)]
 #![cfg_attr(feature, feature(effective_target_features))]
 //[feature]~^ WARN the feature `effective_target_features` is incomplete and may not be safe to use and/or cause compiler crashes
 
diff --git a/tests/ui/feature-gates/feature-gate-macro-guard-matcher.rs b/tests/ui/feature-gates/feature-gate-macro-guard-matcher.rs
new file mode 100644
index 0000000..662161f
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-macro-guard-matcher.rs
@@ -0,0 +1,5 @@
+fn main() {
+    macro_rules! m {
+        ($x:guard) => {}; //~ ERROR `guard` fragments in macro are unstable
+    }
+}
diff --git a/tests/ui/feature-gates/feature-gate-macro-guard-matcher.stderr b/tests/ui/feature-gates/feature-gate-macro-guard-matcher.stderr
new file mode 100644
index 0000000..0977f94
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-macro-guard-matcher.stderr
@@ -0,0 +1,13 @@
+error[E0658]: `guard` fragments in macro are unstable
+  --> $DIR/feature-gate-macro-guard-matcher.rs:3:10
+   |
+LL |         ($x:guard) => {};
+   |          ^^^^^^^^
+   |
+   = note: see issue #153104 <https://github.com/rust-lang/rust/issues/153104> for more information
+   = help: add `#![feature(macro_guard_matcher)]` 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-unsafe_fields.rs b/tests/ui/feature-gates/feature-gate-unsafe_fields.rs
index 2b0bbaa..27e8b51 100644
--- a/tests/ui/feature-gates/feature-gate-unsafe_fields.rs
+++ b/tests/ui/feature-gates/feature-gate-unsafe_fields.rs
@@ -1,7 +1,7 @@
 //@ compile-flags: --crate-type=lib
 //@ revisions: with_gate without_gate
 //@ [with_gate] check-pass
-
+#![warn(incomplete_features)]
 #![cfg_attr(with_gate, feature(unsafe_fields))] //[with_gate]~ WARNING
 
 #[cfg(false)]
diff --git a/tests/ui/feature-gates/feature-gate-unsafe_fields.with_gate.stderr b/tests/ui/feature-gates/feature-gate-unsafe_fields.with_gate.stderr
index a7deeb0..4220930 100644
--- a/tests/ui/feature-gates/feature-gate-unsafe_fields.with_gate.stderr
+++ b/tests/ui/feature-gates/feature-gate-unsafe_fields.with_gate.stderr
@@ -5,7 +5,11 @@
    |                                ^^^^^^^^^^^^^
    |
    = note: see issue #132922 <https://github.com/rust-lang/rust/issues/132922> for more information
-   = note: `#[warn(incomplete_features)]` on by default
+note: the lint level is defined here
+  --> $DIR/feature-gate-unsafe_fields.rs:4:9
+   |
+LL | #![warn(incomplete_features)]
+   |         ^^^^^^^^^^^^^^^^^^^
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr b/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr
index 912c274..c51d615 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr
@@ -5,7 +5,7 @@
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL | fn main() {}
-   |    ---- the inner attribute doesn't annotate this function
+   | ------------ the inner attribute doesn't annotate this item
    |
 help: perhaps you meant to use an outer attribute
    |
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
index 1560f2b..66d36d9 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
@@ -37,7 +37,7 @@
 #[inline]
 //~^ ERROR attribute cannot be used on
 mod inline {
-    //~^ NOTE the inner attribute doesn't annotate this module
+    //~^ NOTE the inner attribute doesn't annotate this item
 
     mod inner { #![inline] }
     //~^ ERROR attribute cannot be used on
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
index 662776e..db56f22 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
@@ -24,6 +24,21 @@
    |
    = help: `#[rustc_main]` can only be applied to functions
 
+error: `repr` attribute cannot be used at crate level
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:16:1
+   |
+LL | #![repr()]
+   | ^^^^^^^^^^
+...
+LL | mod inline {
+   | ------------ the inner attribute doesn't annotate this item
+   |
+help: perhaps you meant to use an outer attribute
+   |
+LL - #![repr()]
+LL + #[repr()]
+   |
+
 error: `#[path]` attribute cannot be used on crates
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:20:1
    |
@@ -243,21 +258,6 @@
 LL - #![no_mangle]
    |
 
-error: `repr` attribute cannot be used at crate level
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:16:1
-   |
-LL | #![repr()]
-   | ^^^^^^^^^^
-...
-LL | mod inline {
-   |     ------ the inner attribute doesn't annotate this module
-   |
-help: perhaps you meant to use an outer attribute
-   |
-LL - #![repr()]
-LL + #[repr()]
-   |
-
 error[E0517]: attribute should be applied to a struct, enum, or union
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:127:25
    |
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-test.stderr b/tests/ui/feature-gates/issue-43106-gating-of-test.stderr
index 6e706b1..8af140b 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-test.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-test.stderr
@@ -5,7 +5,7 @@
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL | fn main() {}
-   |    ---- the inner attribute doesn't annotate this function
+   | ------------ the inner attribute doesn't annotate this item
    |
 help: perhaps you meant to use an outer attribute
    |
diff --git a/tests/ui/generic-associated-types/issue-87429-specialization.rs b/tests/ui/generic-associated-types/issue-87429-specialization.rs
index 87e9116..4a1e6aa 100644
--- a/tests/ui/generic-associated-types/issue-87429-specialization.rs
+++ b/tests/ui/generic-associated-types/issue-87429-specialization.rs
@@ -1,7 +1,6 @@
 //@ check-fail
 
 #![feature(specialization)]
-//~^ WARN incomplete
 
 trait Family {
     type Member<'a>: for<'b> PartialEq<Self::Member<'b>>;
diff --git a/tests/ui/generic-associated-types/issue-87429-specialization.stderr b/tests/ui/generic-associated-types/issue-87429-specialization.stderr
index 44f871e..dbe97bd 100644
--- a/tests/ui/generic-associated-types/issue-87429-specialization.stderr
+++ b/tests/ui/generic-associated-types/issue-87429-specialization.stderr
@@ -1,22 +1,12 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-87429-specialization.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0277]: can't compare `Foo` with `Foo`
-  --> $DIR/issue-87429-specialization.rs:20:31
+  --> $DIR/issue-87429-specialization.rs:19:31
    |
 LL |     default type Member<'a> = Foo;
    |                               ^^^ no implementation for `Foo == Foo`
    |
    = help: the trait `PartialEq` is not implemented for `Foo`
 note: required by a bound in `Family::Member`
-  --> $DIR/issue-87429-specialization.rs:7:22
+  --> $DIR/issue-87429-specialization.rs:6:22
    |
 LL |     type Member<'a>: for<'b> PartialEq<Self::Member<'b>>;
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Family::Member`
@@ -26,6 +16,6 @@
 LL | struct Foo;
    |
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-restriction/recover-incorrect-impl-restriction.rs b/tests/ui/impl-restriction/recover-incorrect-impl-restriction.rs
index d6490d5..dc47eba 100644
--- a/tests/ui/impl-restriction/recover-incorrect-impl-restriction.rs
+++ b/tests/ui/impl-restriction/recover-incorrect-impl-restriction.rs
@@ -1,5 +1,6 @@
 //@ compile-flags: --crate-type=lib
 //@ revisions: with_gate without_gate
+#![warn(incomplete_features)]
 #![cfg_attr(with_gate, feature(impl_restriction))]
 //[with_gate]~^ WARN the feature `impl_restriction` is incomplete and may not be safe to use and/or cause compiler crashes
 #![feature(auto_traits, const_trait_impl)]
diff --git a/tests/ui/impl-restriction/recover-incorrect-impl-restriction.with_gate.stderr b/tests/ui/impl-restriction/recover-incorrect-impl-restriction.with_gate.stderr
index ad183b2..834cc99 100644
--- a/tests/ui/impl-restriction/recover-incorrect-impl-restriction.with_gate.stderr
+++ b/tests/ui/impl-restriction/recover-incorrect-impl-restriction.with_gate.stderr
@@ -1,5 +1,5 @@
 error: incorrect `impl` restriction
-  --> $DIR/recover-incorrect-impl-restriction.rs:8:14
+  --> $DIR/recover-incorrect-impl-restriction.rs:9:14
    |
 LL |     pub impl(crate::foo) trait Baz {}
    |              ^^^^^^^^^^
@@ -15,7 +15,7 @@
    |              ++
 
 error: incorrect `impl` restriction
-  --> $DIR/recover-incorrect-impl-restriction.rs:10:21
+  --> $DIR/recover-incorrect-impl-restriction.rs:11:21
    |
 LL |     pub unsafe impl(crate::foo) trait BazUnsafe {}
    |                     ^^^^^^^^^^
@@ -31,7 +31,7 @@
    |                     ++
 
 error: incorrect `impl` restriction
-  --> $DIR/recover-incorrect-impl-restriction.rs:12:19
+  --> $DIR/recover-incorrect-impl-restriction.rs:13:19
    |
 LL |     pub auto impl(crate::foo) trait BazAuto {}
    |                   ^^^^^^^^^^
@@ -47,7 +47,7 @@
    |                   ++
 
 error: incorrect `impl` restriction
-  --> $DIR/recover-incorrect-impl-restriction.rs:14:20
+  --> $DIR/recover-incorrect-impl-restriction.rs:15:20
    |
 LL |     pub const impl(crate::foo) trait BazConst {}
    |                    ^^^^^^^^^^
@@ -63,7 +63,7 @@
    |                    ++
 
 error: incorrect `impl` restriction
-  --> $DIR/recover-incorrect-impl-restriction.rs:16:27
+  --> $DIR/recover-incorrect-impl-restriction.rs:17:27
    |
 LL |     pub const unsafe impl(crate::foo) trait BazConstUnsafe {}
    |                           ^^^^^^^^^^
@@ -79,7 +79,7 @@
    |                           ++
 
 error: incorrect `impl` restriction
-  --> $DIR/recover-incorrect-impl-restriction.rs:18:26
+  --> $DIR/recover-incorrect-impl-restriction.rs:19:26
    |
 LL |     pub unsafe auto impl(crate::foo) trait BazUnsafeAuto {}
    |                          ^^^^^^^^^^
@@ -95,13 +95,17 @@
    |                          ++
 
 warning: the feature `impl_restriction` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/recover-incorrect-impl-restriction.rs:3:32
+  --> $DIR/recover-incorrect-impl-restriction.rs:4:32
    |
 LL | #![cfg_attr(with_gate, feature(impl_restriction))]
    |                                ^^^^^^^^^^^^^^^^
    |
    = note: see issue #105077 <https://github.com/rust-lang/rust/issues/105077> for more information
-   = note: `#[warn(incomplete_features)]` on by default
+note: the lint level is defined here
+  --> $DIR/recover-incorrect-impl-restriction.rs:3:9
+   |
+LL | #![warn(incomplete_features)]
+   |         ^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 6 previous errors; 1 warning emitted
 
diff --git a/tests/ui/impl-restriction/recover-incorrect-impl-restriction.without_gate.stderr b/tests/ui/impl-restriction/recover-incorrect-impl-restriction.without_gate.stderr
index d949172..223a7cd 100644
--- a/tests/ui/impl-restriction/recover-incorrect-impl-restriction.without_gate.stderr
+++ b/tests/ui/impl-restriction/recover-incorrect-impl-restriction.without_gate.stderr
@@ -1,5 +1,5 @@
 error: incorrect `impl` restriction
-  --> $DIR/recover-incorrect-impl-restriction.rs:8:14
+  --> $DIR/recover-incorrect-impl-restriction.rs:9:14
    |
 LL |     pub impl(crate::foo) trait Baz {}
    |              ^^^^^^^^^^
@@ -15,7 +15,7 @@
    |              ++
 
 error: incorrect `impl` restriction
-  --> $DIR/recover-incorrect-impl-restriction.rs:10:21
+  --> $DIR/recover-incorrect-impl-restriction.rs:11:21
    |
 LL |     pub unsafe impl(crate::foo) trait BazUnsafe {}
    |                     ^^^^^^^^^^
@@ -31,7 +31,7 @@
    |                     ++
 
 error: incorrect `impl` restriction
-  --> $DIR/recover-incorrect-impl-restriction.rs:12:19
+  --> $DIR/recover-incorrect-impl-restriction.rs:13:19
    |
 LL |     pub auto impl(crate::foo) trait BazAuto {}
    |                   ^^^^^^^^^^
@@ -47,7 +47,7 @@
    |                   ++
 
 error: incorrect `impl` restriction
-  --> $DIR/recover-incorrect-impl-restriction.rs:14:20
+  --> $DIR/recover-incorrect-impl-restriction.rs:15:20
    |
 LL |     pub const impl(crate::foo) trait BazConst {}
    |                    ^^^^^^^^^^
@@ -63,7 +63,7 @@
    |                    ++
 
 error: incorrect `impl` restriction
-  --> $DIR/recover-incorrect-impl-restriction.rs:16:27
+  --> $DIR/recover-incorrect-impl-restriction.rs:17:27
    |
 LL |     pub const unsafe impl(crate::foo) trait BazConstUnsafe {}
    |                           ^^^^^^^^^^
@@ -79,7 +79,7 @@
    |                           ++
 
 error: incorrect `impl` restriction
-  --> $DIR/recover-incorrect-impl-restriction.rs:18:26
+  --> $DIR/recover-incorrect-impl-restriction.rs:19:26
    |
 LL |     pub unsafe auto impl(crate::foo) trait BazUnsafeAuto {}
    |                          ^^^^^^^^^^
@@ -95,7 +95,7 @@
    |                          ++
 
 error[E0658]: `impl` restrictions are experimental
-  --> $DIR/recover-incorrect-impl-restriction.rs:8:9
+  --> $DIR/recover-incorrect-impl-restriction.rs:9:9
    |
 LL |     pub impl(crate::foo) trait Baz {}
    |         ^^^^^^^^^^^^^^^^
@@ -105,7 +105,7 @@
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `impl` restrictions are experimental
-  --> $DIR/recover-incorrect-impl-restriction.rs:10:16
+  --> $DIR/recover-incorrect-impl-restriction.rs:11:16
    |
 LL |     pub unsafe impl(crate::foo) trait BazUnsafe {}
    |                ^^^^^^^^^^^^^^^^
@@ -115,7 +115,7 @@
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `impl` restrictions are experimental
-  --> $DIR/recover-incorrect-impl-restriction.rs:12:14
+  --> $DIR/recover-incorrect-impl-restriction.rs:13:14
    |
 LL |     pub auto impl(crate::foo) trait BazAuto {}
    |              ^^^^^^^^^^^^^^^^
@@ -125,7 +125,7 @@
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `impl` restrictions are experimental
-  --> $DIR/recover-incorrect-impl-restriction.rs:14:15
+  --> $DIR/recover-incorrect-impl-restriction.rs:15:15
    |
 LL |     pub const impl(crate::foo) trait BazConst {}
    |               ^^^^^^^^^^^^^^^^
@@ -135,7 +135,7 @@
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `impl` restrictions are experimental
-  --> $DIR/recover-incorrect-impl-restriction.rs:16:22
+  --> $DIR/recover-incorrect-impl-restriction.rs:17:22
    |
 LL |     pub const unsafe impl(crate::foo) trait BazConstUnsafe {}
    |                      ^^^^^^^^^^^^^^^^
@@ -145,7 +145,7 @@
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `impl` restrictions are experimental
-  --> $DIR/recover-incorrect-impl-restriction.rs:18:21
+  --> $DIR/recover-incorrect-impl-restriction.rs:19:21
    |
 LL |     pub unsafe auto impl(crate::foo) trait BazUnsafeAuto {}
    |                     ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-restriction/trait-alias-cannot-be-impl-restricted.rs b/tests/ui/impl-restriction/trait-alias-cannot-be-impl-restricted.rs
index 62622e1..ce36a49 100644
--- a/tests/ui/impl-restriction/trait-alias-cannot-be-impl-restricted.rs
+++ b/tests/ui/impl-restriction/trait-alias-cannot-be-impl-restricted.rs
@@ -1,5 +1,6 @@
 //@ compile-flags: --crate-type=lib
 //@ revisions: with_gate without_gate
+#![warn(incomplete_features)]
 #![cfg_attr(with_gate, feature(impl_restriction))]
 //[with_gate]~^ WARN the feature `impl_restriction` is incomplete and may not be safe to use and/or cause compiler crashes
 #![feature(auto_traits, const_trait_impl, trait_alias)]
diff --git a/tests/ui/impl-restriction/trait-alias-cannot-be-impl-restricted.with_gate.stderr b/tests/ui/impl-restriction/trait-alias-cannot-be-impl-restricted.with_gate.stderr
index 70287ac..7be0300 100644
--- a/tests/ui/impl-restriction/trait-alias-cannot-be-impl-restricted.with_gate.stderr
+++ b/tests/ui/impl-restriction/trait-alias-cannot-be-impl-restricted.with_gate.stderr
@@ -1,83 +1,87 @@
 error: trait aliases cannot be `impl`-restricted
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:7:1
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:8:1
    |
 LL | impl(crate) trait Alias = Copy;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `impl`-restricted
 
 error: trait aliases cannot be `auto`
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:9:1
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:10:1
    |
 LL | auto impl(in crate) trait AutoAlias = Copy;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `auto`
 
 error: trait aliases cannot be `impl`-restricted
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:9:1
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:10:1
    |
 LL | auto impl(in crate) trait AutoAlias = Copy;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `impl`-restricted
 
 error: trait aliases cannot be `unsafe`
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:12:1
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:13:1
    |
 LL | unsafe impl(self) trait UnsafeAlias = Copy;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `unsafe`
 
 error: trait aliases cannot be `impl`-restricted
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:12:1
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:13:1
    |
 LL | unsafe impl(self) trait UnsafeAlias = Copy;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `impl`-restricted
 
 error: trait aliases cannot be `impl`-restricted
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:15:1
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:16:1
    |
 LL | const impl(in self) trait ConstAlias = Copy;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `impl`-restricted
 
 error: trait aliases cannot be `impl`-restricted
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:19:5
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:20:5
    |
 LL |     impl(super) trait InnerAlias = Copy;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `impl`-restricted
 
 error: trait aliases cannot be `unsafe`
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:21:5
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:22:5
    |
 LL |     const unsafe impl(in crate::foo) trait InnerConstUnsafeAlias = Copy;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `unsafe`
 
 error: trait aliases cannot be `impl`-restricted
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:21:5
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:22:5
    |
 LL |     const unsafe impl(in crate::foo) trait InnerConstUnsafeAlias = Copy;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `impl`-restricted
 
 error: trait aliases cannot be `auto`
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:24:5
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:25:5
    |
 LL |     unsafe auto impl(in crate::foo) trait InnerUnsafeAutoAlias = Copy;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `auto`
 
 error: trait aliases cannot be `unsafe`
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:24:5
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:25:5
    |
 LL |     unsafe auto impl(in crate::foo) trait InnerUnsafeAutoAlias = Copy;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `unsafe`
 
 error: trait aliases cannot be `impl`-restricted
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:24:5
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:25:5
    |
 LL |     unsafe auto impl(in crate::foo) trait InnerUnsafeAutoAlias = Copy;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `impl`-restricted
 
 warning: the feature `impl_restriction` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:3:32
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:4:32
    |
 LL | #![cfg_attr(with_gate, feature(impl_restriction))]
    |                                ^^^^^^^^^^^^^^^^
    |
    = note: see issue #105077 <https://github.com/rust-lang/rust/issues/105077> for more information
-   = note: `#[warn(incomplete_features)]` on by default
+note: the lint level is defined here
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:3:9
+   |
+LL | #![warn(incomplete_features)]
+   |         ^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 12 previous errors; 1 warning emitted
 
diff --git a/tests/ui/impl-restriction/trait-alias-cannot-be-impl-restricted.without_gate.stderr b/tests/ui/impl-restriction/trait-alias-cannot-be-impl-restricted.without_gate.stderr
index 7bff903..c99bfce 100644
--- a/tests/ui/impl-restriction/trait-alias-cannot-be-impl-restricted.without_gate.stderr
+++ b/tests/ui/impl-restriction/trait-alias-cannot-be-impl-restricted.without_gate.stderr
@@ -1,77 +1,77 @@
 error: trait aliases cannot be `impl`-restricted
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:7:1
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:8:1
    |
 LL | impl(crate) trait Alias = Copy;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `impl`-restricted
 
 error: trait aliases cannot be `auto`
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:9:1
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:10:1
    |
 LL | auto impl(in crate) trait AutoAlias = Copy;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `auto`
 
 error: trait aliases cannot be `impl`-restricted
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:9:1
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:10:1
    |
 LL | auto impl(in crate) trait AutoAlias = Copy;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `impl`-restricted
 
 error: trait aliases cannot be `unsafe`
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:12:1
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:13:1
    |
 LL | unsafe impl(self) trait UnsafeAlias = Copy;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `unsafe`
 
 error: trait aliases cannot be `impl`-restricted
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:12:1
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:13:1
    |
 LL | unsafe impl(self) trait UnsafeAlias = Copy;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `impl`-restricted
 
 error: trait aliases cannot be `impl`-restricted
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:15:1
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:16:1
    |
 LL | const impl(in self) trait ConstAlias = Copy;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `impl`-restricted
 
 error: trait aliases cannot be `impl`-restricted
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:19:5
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:20:5
    |
 LL |     impl(super) trait InnerAlias = Copy;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `impl`-restricted
 
 error: trait aliases cannot be `unsafe`
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:21:5
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:22:5
    |
 LL |     const unsafe impl(in crate::foo) trait InnerConstUnsafeAlias = Copy;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `unsafe`
 
 error: trait aliases cannot be `impl`-restricted
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:21:5
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:22:5
    |
 LL |     const unsafe impl(in crate::foo) trait InnerConstUnsafeAlias = Copy;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `impl`-restricted
 
 error: trait aliases cannot be `auto`
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:24:5
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:25:5
    |
 LL |     unsafe auto impl(in crate::foo) trait InnerUnsafeAutoAlias = Copy;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `auto`
 
 error: trait aliases cannot be `unsafe`
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:24:5
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:25:5
    |
 LL |     unsafe auto impl(in crate::foo) trait InnerUnsafeAutoAlias = Copy;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `unsafe`
 
 error: trait aliases cannot be `impl`-restricted
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:24:5
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:25:5
    |
 LL |     unsafe auto impl(in crate::foo) trait InnerUnsafeAutoAlias = Copy;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `impl`-restricted
 
 error[E0658]: `impl` restrictions are experimental
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:7:1
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:8:1
    |
 LL | impl(crate) trait Alias = Copy;
    | ^^^^^^^^^^^
@@ -81,7 +81,7 @@
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `impl` restrictions are experimental
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:9:6
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:10:6
    |
 LL | auto impl(in crate) trait AutoAlias = Copy;
    |      ^^^^^^^^^^^^^^
@@ -91,7 +91,7 @@
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `impl` restrictions are experimental
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:12:8
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:13:8
    |
 LL | unsafe impl(self) trait UnsafeAlias = Copy;
    |        ^^^^^^^^^^
@@ -101,7 +101,7 @@
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `impl` restrictions are experimental
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:15:7
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:16:7
    |
 LL | const impl(in self) trait ConstAlias = Copy;
    |       ^^^^^^^^^^^^^
@@ -111,7 +111,7 @@
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `impl` restrictions are experimental
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:19:5
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:20:5
    |
 LL |     impl(super) trait InnerAlias = Copy;
    |     ^^^^^^^^^^^
@@ -121,7 +121,7 @@
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `impl` restrictions are experimental
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:21:18
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:22:18
    |
 LL |     const unsafe impl(in crate::foo) trait InnerConstUnsafeAlias = Copy;
    |                  ^^^^^^^^^^^^^^^^^^^
@@ -131,7 +131,7 @@
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `impl` restrictions are experimental
-  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:24:17
+  --> $DIR/trait-alias-cannot-be-impl-restricted.rs:25:17
    |
 LL |     unsafe auto impl(in crate::foo) trait InnerUnsafeAutoAlias = Copy;
    |                 ^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/equality-rpass.rs b/tests/ui/impl-trait/equality-rpass.rs
index da750f4..d5cac80 100644
--- a/tests/ui/impl-trait/equality-rpass.rs
+++ b/tests/ui/impl-trait/equality-rpass.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Foo: std::fmt::Debug + Eq {}
 
diff --git a/tests/ui/impl-trait/equality-rpass.stderr b/tests/ui/impl-trait/equality-rpass.stderr
deleted file mode 100644
index bde8362..0000000
--- a/tests/ui/impl-trait/equality-rpass.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/equality-rpass.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/impl-trait/equality.rs b/tests/ui/impl-trait/equality.rs
index 07fc4a5..4a31563 100644
--- a/tests/ui/impl-trait/equality.rs
+++ b/tests/ui/impl-trait/equality.rs
@@ -1,6 +1,6 @@
 //@ dont-require-annotations: NOTE
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Foo: Copy + ToString {}
 
diff --git a/tests/ui/impl-trait/equality.stderr b/tests/ui/impl-trait/equality.stderr
index 7f965b9..3c765da 100644
--- a/tests/ui/impl-trait/equality.stderr
+++ b/tests/ui/impl-trait/equality.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/equality.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0308]: mismatched types
   --> $DIR/equality.rs:17:5
    |
@@ -48,7 +38,7 @@
    = note: `&u32` implements `Add`
    = note: this error originates in the macro `add_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/equality2.rs b/tests/ui/impl-trait/equality2.rs
index 808c600..44d356e 100644
--- a/tests/ui/impl-trait/equality2.rs
+++ b/tests/ui/impl-trait/equality2.rs
@@ -1,6 +1,6 @@
 //@ dont-require-annotations: NOTE
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Foo: Copy + ToString {}
 
diff --git a/tests/ui/impl-trait/equality2.stderr b/tests/ui/impl-trait/equality2.stderr
index 2fa7eb2..ce0ccea 100644
--- a/tests/ui/impl-trait/equality2.stderr
+++ b/tests/ui/impl-trait/equality2.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/equality2.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0308]: mismatched types
   --> $DIR/equality2.rs:27:18
    |
@@ -72,6 +62,6 @@
               found opaque type `impl Foo` (`u32`)
    = note: distinct uses of `impl Trait` result in different opaque types
 
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs
index 351cdad..ba6dfd4 100644
--- a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs
+++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs
@@ -1,7 +1,6 @@
 //@ compile-flags: -Znext-solver
 
 #![feature(lazy_type_alias)]
-//~^ WARN the feature `lazy_type_alias` is incomplete
 
 trait Foo {}
 
diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr
index a95670c..03c5d7a 100644
--- a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr
+++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr
@@ -1,53 +1,44 @@
-warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/alias-bounds-when-not-wf.rs:3: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[E0277]: the trait bound `usize: Foo` is not satisfied
-  --> $DIR/alias-bounds-when-not-wf.rs:16:15
+  --> $DIR/alias-bounds-when-not-wf.rs:15:15
    |
 LL | fn hello(_: W<A<usize>>) {}
    |               ^^^^^^^^ the trait `Foo` is not implemented for `usize`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/alias-bounds-when-not-wf.rs:6:1
+  --> $DIR/alias-bounds-when-not-wf.rs:5:1
    |
 LL | trait Foo {}
    | ^^^^^^^^^
 note: required by a bound in `A`
-  --> $DIR/alias-bounds-when-not-wf.rs:8:11
+  --> $DIR/alias-bounds-when-not-wf.rs:7:11
    |
 LL | type A<T: Foo> = T;
    |           ^^^ required by this bound in `A`
 
 error[E0277]: the trait bound `usize: Foo` is not satisfied
-  --> $DIR/alias-bounds-when-not-wf.rs:16:10
+  --> $DIR/alias-bounds-when-not-wf.rs:15:10
    |
 LL | fn hello(_: W<A<usize>>) {}
    |          ^ the trait `Foo` is not implemented for `usize`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/alias-bounds-when-not-wf.rs:6:1
+  --> $DIR/alias-bounds-when-not-wf.rs:5:1
    |
 LL | trait Foo {}
    | ^^^^^^^^^
 
 error[E0277]: the trait bound `usize: Foo` is not satisfied
-  --> $DIR/alias-bounds-when-not-wf.rs:16:1
+  --> $DIR/alias-bounds-when-not-wf.rs:15:1
    |
 LL | fn hello(_: W<A<usize>>) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `usize`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/alias-bounds-when-not-wf.rs:6:1
+  --> $DIR/alias-bounds-when-not-wf.rs:5:1
    |
 LL | trait Foo {}
    | ^^^^^^^^^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/imports/inconsistent-resolution-153842.rs b/tests/ui/imports/inconsistent-resolution-153842.rs
new file mode 100644
index 0000000..85fff36
--- /dev/null
+++ b/tests/ui/imports/inconsistent-resolution-153842.rs
@@ -0,0 +1,17 @@
+mod a {
+    pub use crate::s::Trait as s;
+    //~^ ERROR cannot determine resolution for the import
+    //~| ERROR cannot determine resolution for the import
+    //~| ERROR unresolved imports `crate::s::Trait`, `a::s`
+}
+
+mod b {
+    pub mod s {
+        pub trait Trait {}
+    }
+}
+
+use a::s;
+use b::*;
+
+fn main() {}
diff --git a/tests/ui/imports/inconsistent-resolution-153842.stderr b/tests/ui/imports/inconsistent-resolution-153842.stderr
new file mode 100644
index 0000000..2b686ff
--- /dev/null
+++ b/tests/ui/imports/inconsistent-resolution-153842.stderr
@@ -0,0 +1,26 @@
+error: cannot determine resolution for the import
+  --> $DIR/inconsistent-resolution-153842.rs:2:13
+   |
+LL |     pub use crate::s::Trait as s;
+   |             ^^^^^^^^^^^^^^^^^^^^
+
+error: cannot determine resolution for the import
+  --> $DIR/inconsistent-resolution-153842.rs:2:13
+   |
+LL |     pub use crate::s::Trait as s;
+   |             ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0432]: unresolved imports `crate::s::Trait`, `a::s`
+  --> $DIR/inconsistent-resolution-153842.rs:2:13
+   |
+LL |     pub use crate::s::Trait as s;
+   |             ^^^^^^^^^^^^^^^^^^^^
+...
+LL | use a::s;
+   |     ^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/indexing/index-help.stderr b/tests/ui/indexing/index-help.stderr
index 8fc91c1..65faaec 100644
--- a/tests/ui/indexing/index-help.stderr
+++ b/tests/ui/indexing/index-help.stderr
@@ -5,13 +5,13 @@
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32`
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
    = note: required for `Vec<{integer}>` to implement `Index<i32>`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/indexing/indexing-integral-types.stderr b/tests/ui/indexing/indexing-integral-types.stderr
index 3dfc5f5..6041613 100644
--- a/tests/ui/indexing/indexing-integral-types.stderr
+++ b/tests/ui/indexing/indexing-integral-types.stderr
@@ -5,13 +5,13 @@
    |       ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `u8`
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
    = note: required for `Vec<isize>` to implement `Index<u8>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `i8`
@@ -21,13 +21,13 @@
    |       ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `i8`
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
    = note: required for `Vec<isize>` to implement `Index<i8>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `u32`
@@ -37,13 +37,13 @@
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `u32`
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
    = note: required for `Vec<isize>` to implement `Index<u32>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `i32`
@@ -53,13 +53,13 @@
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `i32`
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
    = note: required for `Vec<isize>` to implement `Index<i32>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `u8`
@@ -69,13 +69,13 @@
    |                  ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `u8`
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
    = note: required for `[u8]` to implement `Index<u8>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `i8`
@@ -85,13 +85,13 @@
    |                  ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `i8`
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
    = note: required for `[u8]` to implement `Index<i8>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `u32`
@@ -101,13 +101,13 @@
    |                  ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `u32`
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
    = note: required for `[u8]` to implement `Index<u32>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `i32`
@@ -117,13 +117,13 @@
    |                  ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `i32`
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
    = note: required for `[u8]` to implement `Index<i32>`
 
 error: aborting due to 8 previous errors
diff --git a/tests/ui/indexing/indexing-requires-a-uint.stderr b/tests/ui/indexing/indexing-requires-a-uint.stderr
index e5f9f78..9e974c8 100644
--- a/tests/ui/indexing/indexing-requires-a-uint.stderr
+++ b/tests/ui/indexing/indexing-requires-a-uint.stderr
@@ -5,13 +5,13 @@
    |         ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8`
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
    = note: required for `[{integer}]` to implement `Index<u8>`
 
 error[E0308]: mismatched types
diff --git a/tests/ui/issues/issue-25901.rs b/tests/ui/issues/issue-25901.rs
deleted file mode 100644
index d40b869..0000000
--- a/tests/ui/issues/issue-25901.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-struct A;
-struct B;
-
-static S: &'static B = &A;
-//~^ ERROR the trait bound `A: const Deref` is not satisfied
-
-use std::ops::Deref;
-
-impl Deref for A {
-    type Target = B;
-    fn deref(&self)->&B { static B_: B = B; &B_ }
-}
-
-fn main(){}
diff --git a/tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668.rs b/tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668.rs
deleted file mode 100644
index 0e1f19a..0000000
--- a/tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-struct P { child: Option<Box<P>> }
-trait PTrait {
-   fn getChildOption(&self) -> Option<Box<P>>;
-}
-
-impl PTrait for P {
-   fn getChildOption(&self) -> Option<Box<P>> {
-       static childVal: Box<P> = self.child.get();
-       //~^ ERROR attempt to use a non-constant value in a constant
-       panic!();
-   }
-}
-
-fn main() {}
diff --git a/tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668.stderr b/tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668.stderr
deleted file mode 100644
index 06e0192..0000000
--- a/tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/issue-3668.rs:8:34
-   |
-LL |        static childVal: Box<P> = self.child.get();
-   |                                  ^^^^ non-constant value
-   |
-help: consider using `let` instead of `static`
-   |
-LL -        static childVal: Box<P> = self.child.get();
-LL +        let childVal: Box<P> = self.child.get();
-   |
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0435`.
diff --git a/tests/ui/issues/issue-39367.rs b/tests/ui/issues/issue-39367.rs
deleted file mode 100644
index 68b4d28..0000000
--- a/tests/ui/issues/issue-39367.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-//@ run-pass
-
-use std::ops::Deref;
-
-struct ArenaSet<U: Deref, V=<U as Deref>::Target>(U, &'static V)
-    where V: 'static + ?Sized;
-
-static Z: [u8; 4] = [1,2,3,4];
-
-fn arena() -> &'static ArenaSet<Vec<u8>> {
-    fn __static_ref_initialize() -> ArenaSet<Vec<u8>> {
-        ArenaSet(vec![], &Z)
-    }
-    unsafe {
-        use std::sync::Once;
-        fn require_sync<T: Sync>(_: &T) { }
-        unsafe fn __stability() -> &'static ArenaSet<Vec<u8>> {
-            use std::mem::transmute;
-            static mut DATA: *const ArenaSet<Vec<u8>> = std::ptr::null_mut();
-
-            static mut ONCE: Once = Once::new();
-            ONCE.call_once(|| {
-            //~^ WARN creating a shared reference to mutable static [static_mut_refs]
-                DATA = transmute
-                    ::<Box<ArenaSet<Vec<u8>>>, *const ArenaSet<Vec<u8>>>
-                    (Box::new(__static_ref_initialize()));
-            });
-
-            &*DATA
-        }
-        let static_ref = __stability();
-        require_sync(static_ref);
-        static_ref
-    }
-}
-
-fn main() {
-    let &ArenaSet(ref u, v) = arena();
-    assert!(u.is_empty());
-    assert_eq!(v, Z);
-}
diff --git a/tests/ui/iterators/auxiliary/rangefrom-overflow-2crates-ocno.rs b/tests/ui/iterators/auxiliary/rangefrom-overflow-2crates-ocno.rs
new file mode 100644
index 0000000..ebba4ae
--- /dev/null
+++ b/tests/ui/iterators/auxiliary/rangefrom-overflow-2crates-ocno.rs
@@ -0,0 +1,10 @@
+//@ compile-flags: -C overflow-checks=no
+
+#![crate_type = "lib"]
+#![feature(new_range_api)]
+
+use std::range::RangeFromIter;
+
+pub fn next(iter: &mut RangeFromIter<u8>) -> u8 {
+    iter.next().unwrap()
+}
diff --git a/tests/ui/iterators/auxiliary/rangefrom-overflow-2crates-ocyes.rs b/tests/ui/iterators/auxiliary/rangefrom-overflow-2crates-ocyes.rs
new file mode 100644
index 0000000..8eb5392
--- /dev/null
+++ b/tests/ui/iterators/auxiliary/rangefrom-overflow-2crates-ocyes.rs
@@ -0,0 +1,10 @@
+//@ compile-flags: -C overflow-checks=yes
+
+#![crate_type = "lib"]
+#![feature(new_range_api)]
+
+use std::range::RangeFromIter;
+
+pub fn next(iter: &mut RangeFromIter<u8>) -> u8 {
+    iter.next().unwrap()
+}
diff --git a/tests/ui/iterators/invalid-iterator-chain-fixable.stderr b/tests/ui/iterators/invalid-iterator-chain-fixable.stderr
index 99bff6b..f22fc21 100644
--- a/tests/ui/iterators/invalid-iterator-chain-fixable.stderr
+++ b/tests/ui/iterators/invalid-iterator-chain-fixable.stderr
@@ -33,13 +33,13 @@
    |                           required by a bound introduced by this call
    |
    = help: the trait `Sum<()>` is not implemented for `i32`
-help: the following other types implement trait `Sum<A>`
+help: `i32` implements trait `Sum<A>`
   --> $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum`
+   = note: `Sum`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum<&i32>`
+   = note: `Sum<&i32>`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
    = note: in this macro invocation
@@ -74,13 +74,13 @@
    |              required by a bound introduced by this call
    |
    = help: the trait `Sum<()>` is not implemented for `i32`
-help: the following other types implement trait `Sum<A>`
+help: `i32` implements trait `Sum<A>`
   --> $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum`
+   = note: `Sum`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum<&i32>`
+   = note: `Sum<&i32>`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
    = note: in this macro invocation
@@ -115,13 +115,13 @@
    |                                                      required by a bound introduced by this call
    |
    = help: the trait `Sum<()>` is not implemented for `i32`
-help: the following other types implement trait `Sum<A>`
+help: `i32` implements trait `Sum<A>`
   --> $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum`
+   = note: `Sum`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum<&i32>`
+   = note: `Sum<&i32>`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
    = note: in this macro invocation
diff --git a/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr
index c94b716..82269f6 100644
--- a/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr
+++ b/tests/ui/iterators/invalid-iterator-chain-with-int-infer.stderr
@@ -7,13 +7,13 @@
    |                                         required by a bound introduced by this call
    |
    = help: the trait `Sum<{integer}>` is not implemented for `f32`
-help: the following other types implement trait `Sum<A>`
+help: `f32` implements trait `Sum<A>`
   --> $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `f32` implements `Sum`
+   = note: `Sum`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `f32` implements `Sum<&f32>`
+   = note: `Sum<&f32>`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
    = note: in this macro invocation
diff --git a/tests/ui/iterators/invalid-iterator-chain.stderr b/tests/ui/iterators/invalid-iterator-chain.stderr
index 7f0c154..d58fe43 100644
--- a/tests/ui/iterators/invalid-iterator-chain.stderr
+++ b/tests/ui/iterators/invalid-iterator-chain.stderr
@@ -33,13 +33,13 @@
    |                           required by a bound introduced by this call
    |
    = help: the trait `Sum<()>` is not implemented for `i32`
-help: the following other types implement trait `Sum<A>`
+help: `i32` implements trait `Sum<A>`
   --> $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum`
+   = note: `Sum`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum<&i32>`
+   = note: `Sum<&i32>`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
    = note: in this macro invocation
@@ -73,13 +73,13 @@
    |              required by a bound introduced by this call
    |
    = help: the trait `Sum<()>` is not implemented for `i32`
-help: the following other types implement trait `Sum<A>`
+help: `i32` implements trait `Sum<A>`
   --> $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum`
+   = note: `Sum`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum<&i32>`
+   = note: `Sum<&i32>`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
    = note: in this macro invocation
@@ -120,13 +120,13 @@
    |              required by a bound introduced by this call
    |
    = help: the trait `Sum<f64>` is not implemented for `i32`
-help: the following other types implement trait `Sum<A>`
+help: `i32` implements trait `Sum<A>`
   --> $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum`
+   = note: `Sum`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum<&i32>`
+   = note: `Sum<&i32>`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
    = note: in this macro invocation
@@ -158,13 +158,13 @@
    |                                                      required by a bound introduced by this call
    |
    = help: the trait `Sum<()>` is not implemented for `i32`
-help: the following other types implement trait `Sum<A>`
+help: `i32` implements trait `Sum<A>`
   --> $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum`
+   = note: `Sum`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum<&i32>`
+   = note: `Sum<&i32>`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
    = note: in this macro invocation
@@ -194,13 +194,13 @@
    |                                        required by a bound introduced by this call
    |
    = help: the trait `Sum<&()>` is not implemented for `i32`
-help: the following other types implement trait `Sum<A>`
+help: `i32` implements trait `Sum<A>`
   --> $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum`
+   = note: `Sum`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum<&i32>`
+   = note: `Sum<&i32>`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
    = note: in this macro invocation
diff --git a/tests/ui/iterators/rangefrom-overflow-2crates.rs b/tests/ui/iterators/rangefrom-overflow-2crates.rs
new file mode 100644
index 0000000..c35c96f
--- /dev/null
+++ b/tests/ui/iterators/rangefrom-overflow-2crates.rs
@@ -0,0 +1,40 @@
+//@ run-pass
+//@ needs-unwind
+//@ aux-build:rangefrom-overflow-2crates-ocno.rs
+//@ aux-build:rangefrom-overflow-2crates-ocyes.rs
+
+// For #154124
+// Test that two crates with different overflow-checks have the same results,
+// even when the iterator is passed between them.
+
+#![feature(new_range_api)]
+
+extern crate rangefrom_overflow_2crates_ocno;
+extern crate rangefrom_overflow_2crates_ocyes;
+
+use rangefrom_overflow_2crates_ocno::next as next_ocno;
+use rangefrom_overflow_2crates_ocyes::next as next_ocyes;
+
+fn main() {
+    let mut iter_ocyes = std::range::RangeFrom::from(0_u8..).into_iter();
+    let mut iter_ocno = iter_ocyes.clone();
+
+    for n in 0_u8..=255 {
+        assert_eq!(n, next_ocno(&mut iter_ocyes.clone()));
+        assert_eq!(n, next_ocyes(&mut iter_ocyes));
+        assert_eq!(n, next_ocyes(&mut iter_ocno.clone()));
+        assert_eq!(n, next_ocno(&mut iter_ocno));
+    }
+
+    // `iter_ocno` should have wrapped
+    assert_eq!(0, next_ocyes(&mut iter_ocno.clone()));
+    assert_eq!(0, next_ocno(&mut iter_ocno));
+    // `iter_ocyes` should be exhausted,
+    // which will wrap when called without overflow-checks
+    assert_eq!(0, next_ocno(&mut iter_ocyes.clone()));
+    // and panic when called with overflow-checks
+    let r = std::panic::catch_unwind(move || {
+        let _ = next_ocyes(&mut iter_ocyes);
+    });
+    assert!(r.is_err());
+}
diff --git a/tests/ui/layout/gce-rigid-const-in-array-len.rs b/tests/ui/layout/gce-rigid-const-in-array-len.rs
index 8e57907..d8cc415 100644
--- a/tests/ui/layout/gce-rigid-const-in-array-len.rs
+++ b/tests/ui/layout/gce-rigid-const-in-array-len.rs
@@ -12,7 +12,7 @@
 //! constant.
 
 #![feature(rustc_attrs)]
-#![feature(generic_const_exprs)] //~ WARNING: the feature `generic_const_exprs` is incomplete
+#![feature(generic_const_exprs)]
 #![feature(trivial_bounds)]
 
 #![crate_type = "lib"]
diff --git a/tests/ui/layout/gce-rigid-const-in-array-len.stderr b/tests/ui/layout/gce-rigid-const-in-array-len.stderr
index 6149deb..9038563 100644
--- a/tests/ui/layout/gce-rigid-const-in-array-len.stderr
+++ b/tests/ui/layout/gce-rigid-const-in-array-len.stderr
@@ -1,17 +1,8 @@
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/gce-rigid-const-in-array-len.rs:15:12
-   |
-LL | #![feature(generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: the type `[u8; <u8 as A>::B]` has an unknown layout
   --> $DIR/gce-rigid-const-in-array-len.rs:25:1
    |
 LL | struct S([u8; <u8 as A>::B])
    | ^^^^^^^^
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/lazy-type-alias/bad-lazy-type-alias.rs b/tests/ui/lazy-type-alias/bad-lazy-type-alias.rs
index 6ded911..e9e7de8 100644
--- a/tests/ui/lazy-type-alias/bad-lazy-type-alias.rs
+++ b/tests/ui/lazy-type-alias/bad-lazy-type-alias.rs
@@ -1,7 +1,6 @@
 // regression test for #127351
 
 #![feature(lazy_type_alias)]
-//~^ WARN the feature `lazy_type_alias` is incomplete
 
 type ExplicitTypeOutlives<T> = T;
 
diff --git a/tests/ui/lazy-type-alias/bad-lazy-type-alias.stderr b/tests/ui/lazy-type-alias/bad-lazy-type-alias.stderr
index 3a5ded6..7aa34a2 100644
--- a/tests/ui/lazy-type-alias/bad-lazy-type-alias.stderr
+++ b/tests/ui/lazy-type-alias/bad-lazy-type-alias.stderr
@@ -1,20 +1,11 @@
-warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/bad-lazy-type-alias.rs:3: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[E0107]: missing generics for type alias `ExplicitTypeOutlives`
-  --> $DIR/bad-lazy-type-alias.rs:9:24
+  --> $DIR/bad-lazy-type-alias.rs:8:24
    |
 LL |     _significant_drop: ExplicitTypeOutlives,
    |                        ^^^^^^^^^^^^^^^^^^^^ expected 1 generic argument
    |
 note: type alias defined here, with 1 generic parameter: `T`
-  --> $DIR/bad-lazy-type-alias.rs:6:6
+  --> $DIR/bad-lazy-type-alias.rs:5:6
    |
 LL | type ExplicitTypeOutlives<T> = T;
    |      ^^^^^^^^^^^^^^^^^^^^ -
@@ -23,6 +14,6 @@
 LL |     _significant_drop: ExplicitTypeOutlives<T>,
    |                                            +++
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/lazy-type-alias/coerce-behind-lazy.current.stderr b/tests/ui/lazy-type-alias/coerce-behind-lazy.current.stderr
deleted file mode 100644
index 78dd05b..0000000
--- a/tests/ui/lazy-type-alias/coerce-behind-lazy.current.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/coerce-behind-lazy.rs:6: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
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/lazy-type-alias/coerce-behind-lazy.next.stderr b/tests/ui/lazy-type-alias/coerce-behind-lazy.next.stderr
deleted file mode 100644
index 78dd05b..0000000
--- a/tests/ui/lazy-type-alias/coerce-behind-lazy.next.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/coerce-behind-lazy.rs:6: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
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/lazy-type-alias/coerce-behind-lazy.rs b/tests/ui/lazy-type-alias/coerce-behind-lazy.rs
index 7873ff4..a69e39b 100644
--- a/tests/ui/lazy-type-alias/coerce-behind-lazy.rs
+++ b/tests/ui/lazy-type-alias/coerce-behind-lazy.rs
@@ -4,7 +4,6 @@
 //@[next] compile-flags: -Znext-solver
 
 #![feature(lazy_type_alias)]
-//~^ WARN the feature `lazy_type_alias` is incomplete
 
 use std::any::Any;
 
diff --git a/tests/ui/lazy-type-alias/enum-variant.rs b/tests/ui/lazy-type-alias/enum-variant.rs
index d9b7dff..236e193 100644
--- a/tests/ui/lazy-type-alias/enum-variant.rs
+++ b/tests/ui/lazy-type-alias/enum-variant.rs
@@ -2,7 +2,6 @@
 //@ check-pass
 
 #![feature(lazy_type_alias)]
-//~^ WARN the feature `lazy_type_alias` is incomplete and may not be safe to use
 
 enum Enum {
     Unit,
diff --git a/tests/ui/lazy-type-alias/enum-variant.stderr b/tests/ui/lazy-type-alias/enum-variant.stderr
deleted file mode 100644
index 4360db9..0000000
--- a/tests/ui/lazy-type-alias/enum-variant.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/enum-variant.rs:4: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
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/lazy-type-alias/trailing-where-clause.stderr b/tests/ui/lazy-type-alias/trailing-where-clause.stderr
index 93cd314..170bc3b 100644
--- a/tests/ui/lazy-type-alias/trailing-where-clause.stderr
+++ b/tests/ui/lazy-type-alias/trailing-where-clause.stderr
@@ -4,13 +4,13 @@
 LL |     let _: Alias<()>;
    |                  ^^ the trait `From<()>` is not implemented for `String`
    |
-   = help: the following other types implement trait `From<T>`:
-             `String` implements `From<&String>`
-             `String` implements `From<&mut str>`
-             `String` implements `From<&str>`
-             `String` implements `From<Box<str>>`
-             `String` implements `From<Cow<'_, str>>`
-             `String` implements `From<char>`
+   = help: `String` implements trait `From<T>`:
+             From<&String>
+             From<&mut str>
+             From<&str>
+             From<Box<str>>
+             From<Cow<'_, str>>
+             From<char>
 note: required by a bound in `Alias`
   --> $DIR/trailing-where-clause.rs:8:13
    |
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.rs
index f5fb164..d9251f6 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.rs
@@ -1,11 +1,11 @@
 //@ only-windows
 #[link(name = "foo", kind = "raw-dylib")]
 extern "C" {
-    #[link_ordinal(1)] //~ ERROR multiple `link_ordinal` attributes
-    #[link_ordinal(2)]
+    #[link_ordinal(1)]
+    #[link_ordinal(2)] //~ ERROR multiple `link_ordinal` attributes
     fn foo();
-    #[link_ordinal(1)] //~ ERROR multiple `link_ordinal` attributes
-    #[link_ordinal(2)]
+    #[link_ordinal(1)]
+    #[link_ordinal(2)] //~ ERROR multiple `link_ordinal` attributes
     static mut imported_variable: i32;
 }
 
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.stderr
index 2e6cf37..26d7351 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.stderr
@@ -1,25 +1,25 @@
 error: multiple `link_ordinal` attributes
-  --> $DIR/link-ordinal-multiple.rs:4:5
-   |
-LL |     #[link_ordinal(1)]
-   |     ^^^^^^^^^^^^^^^^^^ help: remove this attribute
-   |
-note: attribute also specified here
   --> $DIR/link-ordinal-multiple.rs:5:5
    |
 LL |     #[link_ordinal(2)]
-   |     ^^^^^^^^^^^^^^^^^^
-
-error: multiple `link_ordinal` attributes
-  --> $DIR/link-ordinal-multiple.rs:7:5
-   |
-LL |     #[link_ordinal(1)]
    |     ^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
+  --> $DIR/link-ordinal-multiple.rs:4:5
+   |
+LL |     #[link_ordinal(1)]
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: multiple `link_ordinal` attributes
   --> $DIR/link-ordinal-multiple.rs:8:5
    |
 LL |     #[link_ordinal(2)]
+   |     ^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+note: attribute also specified here
+  --> $DIR/link-ordinal-multiple.rs:7:5
+   |
+LL |     #[link_ordinal(1)]
    |     ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/lint/unused/unused-attr-duplicate.rs b/tests/ui/lint/unused/unused-attr-duplicate.rs
index a334c49..2b29fde 100644
--- a/tests/ui/lint/unused/unused-attr-duplicate.rs
+++ b/tests/ui/lint/unused/unused-attr-duplicate.rs
@@ -61,7 +61,7 @@ macro_rules! foo {
 fn t1() {}
 
 #[must_use]
-#[must_use = "some message"] //~ ERROR unused attribute
+#[must_use = "some message"]  //~ ERROR unused attribute
 //~^ WARN this was previously accepted
 // No warnings for #[repr], would require more logic.
 #[repr(C)]
@@ -89,15 +89,15 @@ pub fn xyz() {}
 #[link(name = "rust_test_helpers", kind = "static")]
 #[link(name = "rust_test_helpers", kind = "static")]
 extern "C" {
-    #[link_name = "this_does_not_exist"] //~ ERROR unused attribute
+    #[link_name = "this_does_not_exist"]
+    #[link_name = "rust_dbg_extern_identity_u32"] //~ ERROR unused attribute
     //~^ WARN this was previously accepted
-    #[link_name = "rust_dbg_extern_identity_u32"]
     pub fn name_in_rust(v: u32) -> u32;
 }
 
-#[export_name = "exported_symbol_name"] //~ ERROR unused attribute
+#[export_name = "exported_symbol_name"]
+#[export_name = "exported_symbol_name2"]  //~ ERROR unused attribute
 //~^ WARN this was previously accepted
-#[export_name = "exported_symbol_name2"]
 pub fn export_test() {}
 
 #[no_mangle]
@@ -109,9 +109,9 @@ pub fn no_mangle_test() {}
 static FOO: u32 = 0;
 
 #[link_section = ".text"]
+#[link_section = ".bss"]
 //~^ ERROR unused attribute
 //~| WARN this was previously accepted
-#[link_section = ".bss"]
 pub extern "C" fn example() {}
 
 fn main() {}
diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr
index 351645f..1942249 100644
--- a/tests/ui/lint/unused/unused-attr-duplicate.stderr
+++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr
@@ -165,29 +165,29 @@
    | ^^^^^^^^^^^^^^^
 
 error: unused attribute
+  --> $DIR/unused-attr-duplicate.rs:93:5
+   |
+LL |     #[link_name = "rust_dbg_extern_identity_u32"]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+note: attribute also specified here
   --> $DIR/unused-attr-duplicate.rs:92:5
    |
 LL |     #[link_name = "this_does_not_exist"]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
-   |
-note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:94:5
-   |
-LL |     #[link_name = "rust_dbg_extern_identity_u32"]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 error: unused attribute
+  --> $DIR/unused-attr-duplicate.rs:99:1
+   |
+LL | #[export_name = "exported_symbol_name2"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+note: attribute also specified here
   --> $DIR/unused-attr-duplicate.rs:98:1
    |
 LL | #[export_name = "exported_symbol_name"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
-   |
-note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:100:1
-   |
-LL | #[export_name = "exported_symbol_name2"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 error: unused attribute
@@ -215,16 +215,16 @@
    | ^^^^^^^
 
 error: unused attribute
+  --> $DIR/unused-attr-duplicate.rs:112:1
+   |
+LL | #[link_section = ".bss"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+note: attribute also specified here
   --> $DIR/unused-attr-duplicate.rs:111:1
    |
 LL | #[link_section = ".text"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
-   |
-note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:114:1
-   |
-LL | #[link_section = ".bss"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 error: unused attribute
diff --git a/tests/ui/lowering/issue-121108.stderr b/tests/ui/lowering/issue-121108.stderr
index f68655a..e1aa153 100644
--- a/tests/ui/lowering/issue-121108.stderr
+++ b/tests/ui/lowering/issue-121108.stderr
@@ -5,7 +5,7 @@
    | ^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL | use std::ptr::addr_of;
-   |               ------- the inner attribute doesn't annotate this import
+   | ---------------------- the inner attribute doesn't annotate this item
    |
 help: perhaps you meant to use an outer attribute
    |
diff --git a/tests/ui/issues/issue-44056.rs b/tests/ui/lto/lto-avx-target-feature.rs
similarity index 72%
rename from tests/ui/issues/issue-44056.rs
rename to tests/ui/lto/lto-avx-target-feature.rs
index 37d7b00..37a8ce6 100644
--- a/tests/ui/issues/issue-44056.rs
+++ b/tests/ui/lto/lto-avx-target-feature.rs
@@ -1,3 +1,4 @@
+//! regression test for <https://github.com/rust-lang/rust/issues/44056>
 //@ build-pass (FIXME(55996): should be run on targets supporting avx)
 //@ only-x86_64
 //@ no-prefer-dynamic
diff --git a/tests/ui/issues/issue-51947.rs b/tests/ui/lto/lto-weak-merge-functions.rs
similarity index 82%
rename from tests/ui/issues/issue-51947.rs
rename to tests/ui/lto/lto-weak-merge-functions.rs
index eda48aa..bf16fbc 100644
--- a/tests/ui/issues/issue-51947.rs
+++ b/tests/ui/lto/lto-weak-merge-functions.rs
@@ -1,3 +1,4 @@
+//! regression test for <https://github.com/rust-lang/rust/issues/51947>
 //@ build-pass
 
 #![crate_type = "lib"]
diff --git a/tests/ui/macros/attr-expr.rs b/tests/ui/macros/attr-expr.rs
new file mode 100644
index 0000000..a2bee87
--- /dev/null
+++ b/tests/ui/macros/attr-expr.rs
@@ -0,0 +1,19 @@
+macro_rules! foo {
+    ($e:expr) => {
+        #[$e]
+        //~^ ERROR expected identifier, found metavariable
+        fn foo() {}
+    };
+}
+foo!(inline);
+
+macro_rules! bar {
+    ($e:expr) => {
+        #[inline($e)]
+        //~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `expr` metavariable
+        fn bar() {}
+    };
+}
+bar!(always);
+
+fn main() {}
diff --git a/tests/ui/macros/attr-expr.stderr b/tests/ui/macros/attr-expr.stderr
new file mode 100644
index 0000000..eaad41c
--- /dev/null
+++ b/tests/ui/macros/attr-expr.stderr
@@ -0,0 +1,24 @@
+error: expected identifier, found metavariable
+  --> $DIR/attr-expr.rs:3:11
+   |
+LL |         #[$e]
+   |           ^^ expected identifier, found metavariable
+...
+LL | foo!(inline);
+   | ------------ in this macro invocation
+   |
+   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `expr` metavariable
+  --> $DIR/attr-expr.rs:12:18
+   |
+LL |         #[inline($e)]
+   |                  ^^
+...
+LL | bar!(always);
+   | ------------ in this macro invocation
+   |
+   = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/macros/cfg-expr.rs b/tests/ui/macros/cfg-expr.rs
new file mode 100644
index 0000000..e9ca6e3
--- /dev/null
+++ b/tests/ui/macros/cfg-expr.rs
@@ -0,0 +1,44 @@
+//@ run-pass
+macro_rules! foo {
+    ($e:expr, $n:ident) => {
+        #[cfg($e)]
+        macro_rules! $n {
+            () => {}
+        }
+
+        #[cfg_attr($e, allow(non_snake_case))]
+        #[cfg($e)]
+        fn $n() {
+            #[cfg($e)]
+            $n!();
+        }
+
+        #[cfg_attr(not($e), allow(unused))]
+        #[cfg(not($e))]
+        fn $n() {
+            panic!()
+        }
+    }
+}
+foo!(true, BAR);
+foo!(any(true, unix, target_pointer_width = "64"), baz);
+foo!(target_pointer_width = "64", quux);
+foo!(false, haha);
+
+fn main() {
+    BAR();
+    BAR!();
+    baz();
+    baz!();
+    #[cfg(target_pointer_width = "64")]
+    quux();
+    #[cfg(target_pointer_width = "64")]
+    quux!();
+    #[cfg(panic = "unwind")]
+    {
+        let result = std::panic::catch_unwind(|| {
+            haha();
+        });
+        assert!(result.is_err());
+    }
+}
diff --git a/tests/ui/macros/cfg_attr-expr.rs b/tests/ui/macros/cfg_attr-expr.rs
new file mode 100644
index 0000000..1dab2ca
--- /dev/null
+++ b/tests/ui/macros/cfg_attr-expr.rs
@@ -0,0 +1,9 @@
+macro_rules! foo {
+    ($e:expr) => {
+        #[cfg_attr(true, $e)]
+        //~^ ERROR expected identifier, found metavariable
+        fn foo() {}
+    }
+}
+foo!(inline);
+fn main() {}
diff --git a/tests/ui/macros/cfg_attr-expr.stderr b/tests/ui/macros/cfg_attr-expr.stderr
new file mode 100644
index 0000000..a46ea10
--- /dev/null
+++ b/tests/ui/macros/cfg_attr-expr.stderr
@@ -0,0 +1,17 @@
+error: expected identifier, found metavariable
+  --> $DIR/cfg_attr-expr.rs:3:26
+   |
+LL |         #[cfg_attr(true, $e)]
+   |         -----------------^^--
+   |         |                |
+   |         |                expected identifier, found metavariable
+   |         help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]`
+...
+LL | foo!(inline);
+   | ------------ in this macro invocation
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
+   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/macros/cfg_select-expr.rs b/tests/ui/macros/cfg_select-expr.rs
new file mode 100644
index 0000000..90e8945
--- /dev/null
+++ b/tests/ui/macros/cfg_select-expr.rs
@@ -0,0 +1,57 @@
+//@ run-pass
+#![allow(unreachable_cfg_select_predicates)]
+
+macro_rules! foo {
+    ($e:expr, $n:ident) => {
+        cfg_select! {
+            $e => {
+                macro_rules! $n {
+                    () => {}
+                }
+            }
+            _ => {}
+        }
+
+        cfg_select! {
+            $e => {
+                #[cfg_attr($e, allow(non_snake_case))]
+                fn $n() {
+                    cfg_select! {
+                        $e => {
+                            $n!();
+                        }
+                        _ => {}
+                    }
+                }
+            }
+            not($e) => {
+                #[cfg_attr(not($e), allow(unused))]
+                fn $n() {
+                    panic!()
+                }
+            }
+        }
+    }
+}
+foo!(true, BAR);
+foo!(any(true, unix, target_pointer_width = "64"), baz);
+foo!(target_pointer_width = "64", quux);
+foo!(false, haha);
+
+fn main() {
+    BAR();
+    BAR!();
+    baz();
+    baz!();
+    #[cfg(target_pointer_width = "64")]
+    quux();
+    #[cfg(target_pointer_width = "64")]
+    quux!();
+    #[cfg(panic = "unwind")]
+    {
+        let result = std::panic::catch_unwind(|| {
+            haha();
+        });
+        assert!(result.is_err());
+    }
+}
diff --git a/tests/ui/macros/die-macro-2.rs b/tests/ui/macros/die-macro-2.rs
deleted file mode 100644
index d802f18..0000000
--- a/tests/ui/macros/die-macro-2.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ run-fail
-//@ error-pattern:test
-//@ needs-subprocess
-
-fn main() {
-    panic!("test");
-}
diff --git a/tests/ui/macros/die-macro-expr.rs b/tests/ui/macros/die-macro-expr.rs
deleted file mode 100644
index f4fefb0..0000000
--- a/tests/ui/macros/die-macro-expr.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ run-fail
-//@ error-pattern:test
-//@ needs-subprocess
-
-fn main() {
-    let __isize: isize = panic!("test");
-}
diff --git a/tests/ui/macros/die-macro-pure.rs b/tests/ui/macros/die-macro-pure.rs
deleted file mode 100644
index d847877..0000000
--- a/tests/ui/macros/die-macro-pure.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ run-fail
-//@ error-pattern:test
-//@ needs-subprocess
-
-fn f() {
-    panic!("test");
-}
-
-fn main() {
-    f();
-}
diff --git a/tests/ui/macros/die-macro.rs b/tests/ui/macros/die-macro.rs
deleted file mode 100644
index b717eed..0000000
--- a/tests/ui/macros/die-macro.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//@ run-pass
-#![allow(dead_code)]
-// Just testing that panic!() type checks in statement or expr
-
-
-#![allow(unreachable_code)]
-
-fn f() {
-    panic!();
-
-    let _x: isize = panic!();
-}
-
-pub fn main() {
-
-}
diff --git a/tests/ui/macros/issue-2804.rs b/tests/ui/macros/issue-2804.rs
index 0b6f948..9f45df4 100644
--- a/tests/ui/macros/issue-2804.rs
+++ b/tests/ui/macros/issue-2804.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 
 #![allow(non_camel_case_types)]
 #![allow(dead_code)]
diff --git a/tests/ui/macros/issue-33185.rs b/tests/ui/macros/issue-33185.rs
index 8d7e305..5771b40 100644
--- a/tests/ui/macros/issue-33185.rs
+++ b/tests/ui/macros/issue-33185.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(dead_code)]
 
 #[macro_export]
diff --git a/tests/ui/macros/issue-40469.rs b/tests/ui/macros/issue-40469.rs
index faa4c65..4529e44 100644
--- a/tests/ui/macros/issue-40469.rs
+++ b/tests/ui/macros/issue-40469.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 
 #![allow(dead_code)]
 
diff --git a/tests/ui/macros/issue-40770.rs b/tests/ui/macros/issue-40770.rs
index d90294a..028bd48 100644
--- a/tests/ui/macros/issue-40770.rs
+++ b/tests/ui/macros/issue-40770.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(unused_macros)]
 macro_rules! m {
     ($e:expr) => {
diff --git a/tests/ui/macros/macro-attribute-expansion.rs b/tests/ui/macros/macro-attribute-expansion.rs
index be682b3..255400e 100644
--- a/tests/ui/macros/macro-attribute-expansion.rs
+++ b/tests/ui/macros/macro-attribute-expansion.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 macro_rules! descriptions {
     ($name:ident is $desc:expr) => {
         // Check that we will correctly expand attributes
diff --git a/tests/ui/macros/macro-attributes.rs b/tests/ui/macros/macro-attributes.rs
index 976d2cb..a25ed2b 100644
--- a/tests/ui/macros/macro-attributes.rs
+++ b/tests/ui/macros/macro-attributes.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 
 macro_rules! compiles_fine {
     (#[$at:meta]) => {
diff --git a/tests/ui/macros/macro-delimiter-significance.rs b/tests/ui/macros/macro-delimiter-significance.rs
index 8b532e1..1947ecf 100644
--- a/tests/ui/macros/macro-delimiter-significance.rs
+++ b/tests/ui/macros/macro-delimiter-significance.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 fn main() {
     vec![1_usize, 2, 3].len();
 }
diff --git a/tests/ui/macros/macro-doc-comments.rs b/tests/ui/macros/macro-doc-comments.rs
index 47740e2..4622c37 100644
--- a/tests/ui/macros/macro-doc-comments.rs
+++ b/tests/ui/macros/macro-doc-comments.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(non_snake_case)]
 
 macro_rules! doc {
diff --git a/tests/ui/macros/macro-doc-escapes.rs b/tests/ui/macros/macro-doc-escapes.rs
index 81c8d33..77d9a5c 100644
--- a/tests/ui/macros/macro-doc-escapes.rs
+++ b/tests/ui/macros/macro-doc-escapes.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 // When expanding a macro, documentation attributes (including documentation comments) must be
 // passed "as is" without being parsed. Otherwise, some text will be incorrectly interpreted as
 // escape sequences, leading to an ICE.
diff --git a/tests/ui/macros/macro-follow-rpass.rs b/tests/ui/macros/macro-follow-rpass.rs
index 8551b18..3103e86 100644
--- a/tests/ui/macros/macro-follow-rpass.rs
+++ b/tests/ui/macros/macro-follow-rpass.rs
@@ -1,15 +1,16 @@
 //@ edition:2015..2021
-//@ run-pass
+//@ check-pass
 #![allow(unused_macros)]
 // Check the macro follow sets (see corresponding cfail test).
 
-// FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), Ident(in)}
+// FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), MetaVarDecl(Guard), Ident(in)}
 macro_rules! follow_pat {
     ($p:pat =>) => {};
     ($p:pat ,) => {};
     ($p:pat =) => {};
     ($p:pat |) => {};
     ($p:pat if) => {};
+    ($p:pat if let) => {};
     ($p:pat in) => {};
 }
 // FOLLOW(expr) = {FatArrow, Comma, Semicolon}
diff --git a/tests/ui/macros/macro-follow.rs b/tests/ui/macros/macro-follow.rs
index 923c9bd..874bad6 100644
--- a/tests/ui/macros/macro-follow.rs
+++ b/tests/ui/macros/macro-follow.rs
@@ -2,9 +2,10 @@
 //
 // Check the macro follow sets (see corresponding rpass test).
 
+#![feature(macro_guard_matcher)]
 #![allow(unused_macros)]
 
-// FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), Ident(in)}
+// FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), MetaVarDecl(Guard), Ident(in)}
 macro_rules! follow_pat {
     ($p:pat ()) => {};       //~ERROR  `$p:pat` is followed by `(`
     ($p:pat []) => {};       //~ERROR  `$p:pat` is followed by `[`
@@ -47,6 +48,7 @@ macro_rules! follow_expr {
     ($e:expr $t:tt) => {};    //~ERROR `$e:expr` is followed by `$t:tt`
     ($e:expr $i:item) => {};  //~ERROR `$e:expr` is followed by `$i:item`
     ($e:expr $m:meta) => {};  //~ERROR `$e:expr` is followed by `$m:meta`
+    ($e:expr $g:guard) => {}; //~ERROR `$e:expr` is followed by `$g:guard`
 }
 // FOLLOW(ty) = {OpenDelim(Brace), Comma, FatArrow, Colon, Eq, Gt, Semi, Or,
 //               Ident(as), Ident(where), OpenDelim(Bracket), Nonterminal(Block)}
@@ -66,6 +68,7 @@ macro_rules! follow_ty {
     ($t:ty $r:tt) => {};    //~ERROR `$t:ty` is followed by `$r:tt`
     ($t:ty $i:item) => {};  //~ERROR `$t:ty` is followed by `$i:item`
     ($t:ty $m:meta) => {};  //~ERROR `$t:ty` is followed by `$m:meta`
+    ($t:ty $g:guard) => {}; //~ERROR `$t:ty` is followed by `$g:guard`
 }
 // FOLLOW(stmt) = FOLLOW(expr)
 macro_rules! follow_stmt {
@@ -90,6 +93,7 @@ macro_rules! follow_stmt {
     ($s:stmt $t:tt) => {};    //~ERROR `$s:stmt` is followed by `$t:tt`
     ($s:stmt $i:item) => {};  //~ERROR `$s:stmt` is followed by `$i:item`
     ($s:stmt $m:meta) => {};  //~ERROR `$s:stmt` is followed by `$m:meta`
+    ($s:stmt $g:guard) => {}; //~ERROR `$s:stmt` is followed by `$g:guard`
 }
 // FOLLOW(path) = FOLLOW(ty)
 macro_rules! follow_path {
@@ -108,6 +112,7 @@ macro_rules! follow_path {
     ($p:path $t:tt) => {};    //~ERROR `$p:path` is followed by `$t:tt`
     ($p:path $i:item) => {};  //~ERROR `$p:path` is followed by `$i:item`
     ($p:path $m:meta) => {};  //~ERROR `$p:path` is followed by `$m:meta`
+    ($p:path $g:guard) => {}; //~ERROR `$p:path` is followed by `$g:guard`
 }
 // FOLLOW(block) = any token
 // FOLLOW(ident) = any token
diff --git a/tests/ui/macros/macro-follow.stderr b/tests/ui/macros/macro-follow.stderr
index 92491dc..78d167a 100644
--- a/tests/ui/macros/macro-follow.stderr
+++ b/tests/ui/macros/macro-follow.stderr
@@ -1,141 +1,141 @@
 error: `$p:pat` is followed by `(`, which is not allowed for `pat` fragments
-  --> $DIR/macro-follow.rs:9:13
+  --> $DIR/macro-follow.rs:10:13
    |
 LL |     ($p:pat ()) => {};
    |             ^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$p:pat` is followed by `[`, which is not allowed for `pat` fragments
-  --> $DIR/macro-follow.rs:10:13
+  --> $DIR/macro-follow.rs:11:13
    |
 LL |     ($p:pat []) => {};
    |             ^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$p:pat` is followed by `{`, which is not allowed for `pat` fragments
-  --> $DIR/macro-follow.rs:11:13
+  --> $DIR/macro-follow.rs:12:13
    |
 LL |     ($p:pat {}) => {};
    |             ^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$p:pat` is followed by `:`, which is not allowed for `pat` fragments
-  --> $DIR/macro-follow.rs:12:13
+  --> $DIR/macro-follow.rs:13:13
    |
 LL |     ($p:pat :) => {};
    |             ^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$p:pat` is followed by `>`, which is not allowed for `pat` fragments
-  --> $DIR/macro-follow.rs:13:13
+  --> $DIR/macro-follow.rs:14:13
    |
 LL |     ($p:pat >) => {};
    |             ^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$p:pat` is followed by `+`, which is not allowed for `pat` fragments
-  --> $DIR/macro-follow.rs:14:13
+  --> $DIR/macro-follow.rs:15:13
    |
 LL |     ($p:pat +) => {};
    |             ^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$p:pat` is followed by `ident`, which is not allowed for `pat` fragments
-  --> $DIR/macro-follow.rs:15:13
+  --> $DIR/macro-follow.rs:16:13
    |
 LL |     ($p:pat ident) => {};
    |             ^^^^^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$p:pat` is followed by `$q:pat`, which is not allowed for `pat` fragments
-  --> $DIR/macro-follow.rs:16:13
+  --> $DIR/macro-follow.rs:17:13
    |
 LL |     ($p:pat $q:pat) => {};
    |             ^^^^^^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$p:pat` is followed by `$e:expr`, which is not allowed for `pat` fragments
-  --> $DIR/macro-follow.rs:17:13
+  --> $DIR/macro-follow.rs:18:13
    |
 LL |     ($p:pat $e:expr) => {};
    |             ^^^^^^^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$p:pat` is followed by `$t:ty`, which is not allowed for `pat` fragments
-  --> $DIR/macro-follow.rs:18:13
+  --> $DIR/macro-follow.rs:19:13
    |
 LL |     ($p:pat $t:ty) => {};
    |             ^^^^^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$p:pat` is followed by `$s:stmt`, which is not allowed for `pat` fragments
-  --> $DIR/macro-follow.rs:19:13
+  --> $DIR/macro-follow.rs:20:13
    |
 LL |     ($p:pat $s:stmt) => {};
    |             ^^^^^^^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$p:pat` is followed by `$q:path`, which is not allowed for `pat` fragments
-  --> $DIR/macro-follow.rs:20:13
+  --> $DIR/macro-follow.rs:21:13
    |
 LL |     ($p:pat $q:path) => {};
    |             ^^^^^^^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$p:pat` is followed by `$b:block`, which is not allowed for `pat` fragments
-  --> $DIR/macro-follow.rs:21:13
+  --> $DIR/macro-follow.rs:22:13
    |
 LL |     ($p:pat $b:block) => {};
    |             ^^^^^^^^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$p:pat` is followed by `$i:ident`, which is not allowed for `pat` fragments
-  --> $DIR/macro-follow.rs:22:13
+  --> $DIR/macro-follow.rs:23:13
    |
 LL |     ($p:pat $i:ident) => {};
    |             ^^^^^^^^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$p:pat` is followed by `$t:tt`, which is not allowed for `pat` fragments
-  --> $DIR/macro-follow.rs:23:13
+  --> $DIR/macro-follow.rs:24:13
    |
 LL |     ($p:pat $t:tt) => {};
    |             ^^^^^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$p:pat` is followed by `$i:item`, which is not allowed for `pat` fragments
-  --> $DIR/macro-follow.rs:24:13
+  --> $DIR/macro-follow.rs:25:13
    |
 LL |     ($p:pat $i:item) => {};
    |             ^^^^^^^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$p:pat` is followed by `$m:meta`, which is not allowed for `pat` fragments
-  --> $DIR/macro-follow.rs:25:13
+  --> $DIR/macro-follow.rs:26:13
    |
 LL |     ($p:pat $m:meta) => {};
    |             ^^^^^^^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$e:expr` is followed by `(`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:29:14
+  --> $DIR/macro-follow.rs:30:14
    |
 LL |     ($e:expr ()) => {};
    |              ^ not allowed after `expr` fragments
@@ -143,7 +143,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `[`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:30:14
+  --> $DIR/macro-follow.rs:31:14
    |
 LL |     ($e:expr []) => {};
    |              ^ not allowed after `expr` fragments
@@ -151,7 +151,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `{`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:31:14
+  --> $DIR/macro-follow.rs:32:14
    |
 LL |     ($e:expr {}) => {};
    |              ^ not allowed after `expr` fragments
@@ -159,7 +159,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `=`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:32:14
+  --> $DIR/macro-follow.rs:33:14
    |
 LL |     ($e:expr =) => {};
    |              ^ not allowed after `expr` fragments
@@ -167,7 +167,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `|`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:33:14
+  --> $DIR/macro-follow.rs:34:14
    |
 LL |     ($e:expr |) => {};
    |              ^ not allowed after `expr` fragments
@@ -175,7 +175,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `:`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:34:14
+  --> $DIR/macro-follow.rs:35:14
    |
 LL |     ($e:expr :) => {};
    |              ^ not allowed after `expr` fragments
@@ -183,7 +183,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `>`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:35:14
+  --> $DIR/macro-follow.rs:36:14
    |
 LL |     ($e:expr >) => {};
    |              ^ not allowed after `expr` fragments
@@ -191,7 +191,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `+`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:36:14
+  --> $DIR/macro-follow.rs:37:14
    |
 LL |     ($e:expr +) => {};
    |              ^ not allowed after `expr` fragments
@@ -199,7 +199,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `ident`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:37:14
+  --> $DIR/macro-follow.rs:38:14
    |
 LL |     ($e:expr ident) => {};
    |              ^^^^^ not allowed after `expr` fragments
@@ -207,7 +207,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `if`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:38:14
+  --> $DIR/macro-follow.rs:39:14
    |
 LL |     ($e:expr if) => {};
    |              ^^ not allowed after `expr` fragments
@@ -215,7 +215,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `in`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:39:14
+  --> $DIR/macro-follow.rs:40:14
    |
 LL |     ($e:expr in) => {};
    |              ^^ not allowed after `expr` fragments
@@ -223,7 +223,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `$p:pat`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:40:14
+  --> $DIR/macro-follow.rs:41:14
    |
 LL |     ($e:expr $p:pat) => {};
    |              ^^^^^^ not allowed after `expr` fragments
@@ -231,7 +231,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `$f:expr`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:41:14
+  --> $DIR/macro-follow.rs:42:14
    |
 LL |     ($e:expr $f:expr) => {};
    |              ^^^^^^^ not allowed after `expr` fragments
@@ -239,7 +239,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `$t:ty`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:42:14
+  --> $DIR/macro-follow.rs:43:14
    |
 LL |     ($e:expr $t:ty) => {};
    |              ^^^^^ not allowed after `expr` fragments
@@ -247,7 +247,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `$s:stmt`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:43:14
+  --> $DIR/macro-follow.rs:44:14
    |
 LL |     ($e:expr $s:stmt) => {};
    |              ^^^^^^^ not allowed after `expr` fragments
@@ -255,7 +255,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `$p:path`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:44:14
+  --> $DIR/macro-follow.rs:45:14
    |
 LL |     ($e:expr $p:path) => {};
    |              ^^^^^^^ not allowed after `expr` fragments
@@ -263,7 +263,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `$b:block`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:45:14
+  --> $DIR/macro-follow.rs:46:14
    |
 LL |     ($e:expr $b:block) => {};
    |              ^^^^^^^^ not allowed after `expr` fragments
@@ -271,7 +271,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `$i:ident`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:46:14
+  --> $DIR/macro-follow.rs:47:14
    |
 LL |     ($e:expr $i:ident) => {};
    |              ^^^^^^^^ not allowed after `expr` fragments
@@ -279,7 +279,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `$t:tt`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:47:14
+  --> $DIR/macro-follow.rs:48:14
    |
 LL |     ($e:expr $t:tt) => {};
    |              ^^^^^ not allowed after `expr` fragments
@@ -287,7 +287,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `$i:item`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:48:14
+  --> $DIR/macro-follow.rs:49:14
    |
 LL |     ($e:expr $i:item) => {};
    |              ^^^^^^^ not allowed after `expr` fragments
@@ -295,15 +295,23 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$e:expr` is followed by `$m:meta`, which is not allowed for `expr` fragments
-  --> $DIR/macro-follow.rs:49:14
+  --> $DIR/macro-follow.rs:50:14
    |
 LL |     ($e:expr $m:meta) => {};
    |              ^^^^^^^ not allowed after `expr` fragments
    |
    = note: allowed there are: `=>`, `,` or `;`
 
+error: `$e:expr` is followed by `$g:guard`, which is not allowed for `expr` fragments
+  --> $DIR/macro-follow.rs:51:14
+   |
+LL |     ($e:expr $g:guard) => {};
+   |              ^^^^^^^^ not allowed after `expr` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
 error: `$t:ty` is followed by `(`, which is not allowed for `ty` fragments
-  --> $DIR/macro-follow.rs:54:12
+  --> $DIR/macro-follow.rs:56:12
    |
 LL |     ($t:ty ()) => {};
    |            ^ not allowed after `ty` fragments
@@ -311,7 +319,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$t:ty` is followed by `+`, which is not allowed for `ty` fragments
-  --> $DIR/macro-follow.rs:56:12
+  --> $DIR/macro-follow.rs:58:12
    |
 LL |     ($t:ty +) => {};
    |            ^ not allowed after `ty` fragments
@@ -319,7 +327,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$t:ty` is followed by `ident`, which is not allowed for `ty` fragments
-  --> $DIR/macro-follow.rs:57:12
+  --> $DIR/macro-follow.rs:59:12
    |
 LL |     ($t:ty ident) => {};
    |            ^^^^^ not allowed after `ty` fragments
@@ -327,7 +335,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$t:ty` is followed by `if`, which is not allowed for `ty` fragments
-  --> $DIR/macro-follow.rs:58:12
+  --> $DIR/macro-follow.rs:60:12
    |
 LL |     ($t:ty if) => {};
    |            ^^ not allowed after `ty` fragments
@@ -335,7 +343,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$t:ty` is followed by `$p:pat`, which is not allowed for `ty` fragments
-  --> $DIR/macro-follow.rs:59:12
+  --> $DIR/macro-follow.rs:61:12
    |
 LL |     ($t:ty $p:pat) => {};
    |            ^^^^^^ not allowed after `ty` fragments
@@ -343,7 +351,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$t:ty` is followed by `$e:expr`, which is not allowed for `ty` fragments
-  --> $DIR/macro-follow.rs:60:12
+  --> $DIR/macro-follow.rs:62:12
    |
 LL |     ($t:ty $e:expr) => {};
    |            ^^^^^^^ not allowed after `ty` fragments
@@ -351,7 +359,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$t:ty` is followed by `$r:ty`, which is not allowed for `ty` fragments
-  --> $DIR/macro-follow.rs:61:12
+  --> $DIR/macro-follow.rs:63:12
    |
 LL |     ($t:ty $r:ty) => {};
    |            ^^^^^ not allowed after `ty` fragments
@@ -359,7 +367,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$t:ty` is followed by `$s:stmt`, which is not allowed for `ty` fragments
-  --> $DIR/macro-follow.rs:62:12
+  --> $DIR/macro-follow.rs:64:12
    |
 LL |     ($t:ty $s:stmt) => {};
    |            ^^^^^^^ not allowed after `ty` fragments
@@ -367,7 +375,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$t:ty` is followed by `$p:path`, which is not allowed for `ty` fragments
-  --> $DIR/macro-follow.rs:63:12
+  --> $DIR/macro-follow.rs:65:12
    |
 LL |     ($t:ty $p:path) => {};
    |            ^^^^^^^ not allowed after `ty` fragments
@@ -375,7 +383,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$t:ty` is followed by `$i:ident`, which is not allowed for `ty` fragments
-  --> $DIR/macro-follow.rs:65:12
+  --> $DIR/macro-follow.rs:67:12
    |
 LL |     ($t:ty $i:ident) => {};
    |            ^^^^^^^^ not allowed after `ty` fragments
@@ -383,7 +391,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$t:ty` is followed by `$r:tt`, which is not allowed for `ty` fragments
-  --> $DIR/macro-follow.rs:66:12
+  --> $DIR/macro-follow.rs:68:12
    |
 LL |     ($t:ty $r:tt) => {};
    |            ^^^^^ not allowed after `ty` fragments
@@ -391,7 +399,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$t:ty` is followed by `$i:item`, which is not allowed for `ty` fragments
-  --> $DIR/macro-follow.rs:67:12
+  --> $DIR/macro-follow.rs:69:12
    |
 LL |     ($t:ty $i:item) => {};
    |            ^^^^^^^ not allowed after `ty` fragments
@@ -399,15 +407,23 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$t:ty` is followed by `$m:meta`, which is not allowed for `ty` fragments
-  --> $DIR/macro-follow.rs:68:12
+  --> $DIR/macro-follow.rs:70:12
    |
 LL |     ($t:ty $m:meta) => {};
    |            ^^^^^^^ not allowed after `ty` fragments
    |
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
+error: `$t:ty` is followed by `$g:guard`, which is not allowed for `ty` fragments
+  --> $DIR/macro-follow.rs:71:12
+   |
+LL |     ($t:ty $g:guard) => {};
+   |            ^^^^^^^^ not allowed after `ty` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
 error: `$s:stmt` is followed by `(`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:72:14
+  --> $DIR/macro-follow.rs:75:14
    |
 LL |     ($s:stmt ()) => {};
    |              ^ not allowed after `stmt` fragments
@@ -415,7 +431,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `[`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:73:14
+  --> $DIR/macro-follow.rs:76:14
    |
 LL |     ($s:stmt []) => {};
    |              ^ not allowed after `stmt` fragments
@@ -423,7 +439,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `{`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:74:14
+  --> $DIR/macro-follow.rs:77:14
    |
 LL |     ($s:stmt {}) => {};
    |              ^ not allowed after `stmt` fragments
@@ -431,7 +447,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `=`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:75:14
+  --> $DIR/macro-follow.rs:78:14
    |
 LL |     ($s:stmt =) => {};
    |              ^ not allowed after `stmt` fragments
@@ -439,7 +455,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `|`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:76:14
+  --> $DIR/macro-follow.rs:79:14
    |
 LL |     ($s:stmt |) => {};
    |              ^ not allowed after `stmt` fragments
@@ -447,7 +463,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `:`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:77:14
+  --> $DIR/macro-follow.rs:80:14
    |
 LL |     ($s:stmt :) => {};
    |              ^ not allowed after `stmt` fragments
@@ -455,7 +471,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `>`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:78:14
+  --> $DIR/macro-follow.rs:81:14
    |
 LL |     ($s:stmt >) => {};
    |              ^ not allowed after `stmt` fragments
@@ -463,7 +479,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `+`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:79:14
+  --> $DIR/macro-follow.rs:82:14
    |
 LL |     ($s:stmt +) => {};
    |              ^ not allowed after `stmt` fragments
@@ -471,7 +487,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `ident`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:80:14
+  --> $DIR/macro-follow.rs:83:14
    |
 LL |     ($s:stmt ident) => {};
    |              ^^^^^ not allowed after `stmt` fragments
@@ -479,7 +495,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `if`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:81:14
+  --> $DIR/macro-follow.rs:84:14
    |
 LL |     ($s:stmt if) => {};
    |              ^^ not allowed after `stmt` fragments
@@ -487,7 +503,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `in`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:82:14
+  --> $DIR/macro-follow.rs:85:14
    |
 LL |     ($s:stmt in) => {};
    |              ^^ not allowed after `stmt` fragments
@@ -495,7 +511,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `$p:pat`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:83:14
+  --> $DIR/macro-follow.rs:86:14
    |
 LL |     ($s:stmt $p:pat) => {};
    |              ^^^^^^ not allowed after `stmt` fragments
@@ -503,7 +519,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `$e:expr`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:84:14
+  --> $DIR/macro-follow.rs:87:14
    |
 LL |     ($s:stmt $e:expr) => {};
    |              ^^^^^^^ not allowed after `stmt` fragments
@@ -511,7 +527,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `$t:ty`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:85:14
+  --> $DIR/macro-follow.rs:88:14
    |
 LL |     ($s:stmt $t:ty) => {};
    |              ^^^^^ not allowed after `stmt` fragments
@@ -519,7 +535,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `$t:stmt`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:86:14
+  --> $DIR/macro-follow.rs:89:14
    |
 LL |     ($s:stmt $t:stmt) => {};
    |              ^^^^^^^ not allowed after `stmt` fragments
@@ -527,7 +543,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `$p:path`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:87:14
+  --> $DIR/macro-follow.rs:90:14
    |
 LL |     ($s:stmt $p:path) => {};
    |              ^^^^^^^ not allowed after `stmt` fragments
@@ -535,7 +551,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `$b:block`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:88:14
+  --> $DIR/macro-follow.rs:91:14
    |
 LL |     ($s:stmt $b:block) => {};
    |              ^^^^^^^^ not allowed after `stmt` fragments
@@ -543,7 +559,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `$i:ident`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:89:14
+  --> $DIR/macro-follow.rs:92:14
    |
 LL |     ($s:stmt $i:ident) => {};
    |              ^^^^^^^^ not allowed after `stmt` fragments
@@ -551,7 +567,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `$t:tt`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:90:14
+  --> $DIR/macro-follow.rs:93:14
    |
 LL |     ($s:stmt $t:tt) => {};
    |              ^^^^^ not allowed after `stmt` fragments
@@ -559,7 +575,7 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `$i:item`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:91:14
+  --> $DIR/macro-follow.rs:94:14
    |
 LL |     ($s:stmt $i:item) => {};
    |              ^^^^^^^ not allowed after `stmt` fragments
@@ -567,23 +583,31 @@
    = note: allowed there are: `=>`, `,` or `;`
 
 error: `$s:stmt` is followed by `$m:meta`, which is not allowed for `stmt` fragments
-  --> $DIR/macro-follow.rs:92:14
+  --> $DIR/macro-follow.rs:95:14
    |
 LL |     ($s:stmt $m:meta) => {};
    |              ^^^^^^^ not allowed after `stmt` fragments
    |
    = note: allowed there are: `=>`, `,` or `;`
 
-error: `$p:path` is followed by `(`, which is not allowed for `path` fragments
+error: `$s:stmt` is followed by `$g:guard`, which is not allowed for `stmt` fragments
   --> $DIR/macro-follow.rs:96:14
    |
+LL |     ($s:stmt $g:guard) => {};
+   |              ^^^^^^^^ not allowed after `stmt` fragments
+   |
+   = note: allowed there are: `=>`, `,` or `;`
+
+error: `$p:path` is followed by `(`, which is not allowed for `path` fragments
+  --> $DIR/macro-follow.rs:100:14
+   |
 LL |     ($p:path ()) => {};
    |              ^ not allowed after `path` fragments
    |
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$p:path` is followed by `+`, which is not allowed for `path` fragments
-  --> $DIR/macro-follow.rs:98:14
+  --> $DIR/macro-follow.rs:102:14
    |
 LL |     ($p:path +) => {};
    |              ^ not allowed after `path` fragments
@@ -591,7 +615,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$p:path` is followed by `ident`, which is not allowed for `path` fragments
-  --> $DIR/macro-follow.rs:99:14
+  --> $DIR/macro-follow.rs:103:14
    |
 LL |     ($p:path ident) => {};
    |              ^^^^^ not allowed after `path` fragments
@@ -599,7 +623,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$p:path` is followed by `if`, which is not allowed for `path` fragments
-  --> $DIR/macro-follow.rs:100:14
+  --> $DIR/macro-follow.rs:104:14
    |
 LL |     ($p:path if) => {};
    |              ^^ not allowed after `path` fragments
@@ -607,7 +631,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$p:path` is followed by `$q:pat`, which is not allowed for `path` fragments
-  --> $DIR/macro-follow.rs:101:14
+  --> $DIR/macro-follow.rs:105:14
    |
 LL |     ($p:path $q:pat) => {};
    |              ^^^^^^ not allowed after `path` fragments
@@ -615,7 +639,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$p:path` is followed by `$e:expr`, which is not allowed for `path` fragments
-  --> $DIR/macro-follow.rs:102:14
+  --> $DIR/macro-follow.rs:106:14
    |
 LL |     ($p:path $e:expr) => {};
    |              ^^^^^^^ not allowed after `path` fragments
@@ -623,7 +647,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$p:path` is followed by `$t:ty`, which is not allowed for `path` fragments
-  --> $DIR/macro-follow.rs:103:14
+  --> $DIR/macro-follow.rs:107:14
    |
 LL |     ($p:path $t:ty) => {};
    |              ^^^^^ not allowed after `path` fragments
@@ -631,7 +655,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$p:path` is followed by `$s:stmt`, which is not allowed for `path` fragments
-  --> $DIR/macro-follow.rs:104:14
+  --> $DIR/macro-follow.rs:108:14
    |
 LL |     ($p:path $s:stmt) => {};
    |              ^^^^^^^ not allowed after `path` fragments
@@ -639,7 +663,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$p:path` is followed by `$q:path`, which is not allowed for `path` fragments
-  --> $DIR/macro-follow.rs:105:14
+  --> $DIR/macro-follow.rs:109:14
    |
 LL |     ($p:path $q:path) => {};
    |              ^^^^^^^ not allowed after `path` fragments
@@ -647,7 +671,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$p:path` is followed by `$i:ident`, which is not allowed for `path` fragments
-  --> $DIR/macro-follow.rs:107:14
+  --> $DIR/macro-follow.rs:111:14
    |
 LL |     ($p:path $i:ident) => {};
    |              ^^^^^^^^ not allowed after `path` fragments
@@ -655,7 +679,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$p:path` is followed by `$t:tt`, which is not allowed for `path` fragments
-  --> $DIR/macro-follow.rs:108:14
+  --> $DIR/macro-follow.rs:112:14
    |
 LL |     ($p:path $t:tt) => {};
    |              ^^^^^ not allowed after `path` fragments
@@ -663,7 +687,7 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$p:path` is followed by `$i:item`, which is not allowed for `path` fragments
-  --> $DIR/macro-follow.rs:109:14
+  --> $DIR/macro-follow.rs:113:14
    |
 LL |     ($p:path $i:item) => {};
    |              ^^^^^^^ not allowed after `path` fragments
@@ -671,12 +695,20 @@
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
 error: `$p:path` is followed by `$m:meta`, which is not allowed for `path` fragments
-  --> $DIR/macro-follow.rs:110:14
+  --> $DIR/macro-follow.rs:114:14
    |
 LL |     ($p:path $m:meta) => {};
    |              ^^^^^^^ not allowed after `path` fragments
    |
    = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
 
-error: aborting due to 85 previous errors
+error: `$p:path` is followed by `$g:guard`, which is not allowed for `path` fragments
+  --> $DIR/macro-follow.rs:115:14
+   |
+LL |     ($p:path $g:guard) => {};
+   |              ^^^^^^^^ not allowed after `path` fragments
+   |
+   = note: allowed there are: `{`, `[`, `=>`, `,`, `>`, `=`, `:`, `;`, `|`, `as` or `where`
+
+error: aborting due to 89 previous errors
 
diff --git a/tests/ui/macros/macro-followed-by-seq.rs b/tests/ui/macros/macro-followed-by-seq.rs
index f4756d4..3643836 100644
--- a/tests/ui/macros/macro-followed-by-seq.rs
+++ b/tests/ui/macros/macro-followed-by-seq.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(unused_macros)]
 // Regression test for issue #25436: check that things which can be
 // followed by any token also permit X* to come afterwards.
diff --git a/tests/ui/macros/macro-guard-matcher.rs b/tests/ui/macros/macro-guard-matcher.rs
new file mode 100644
index 0000000..81a4412
--- /dev/null
+++ b/tests/ui/macros/macro-guard-matcher.rs
@@ -0,0 +1,17 @@
+#![feature(macro_guard_matcher)]
+
+fn main() {
+    macro_rules! m {
+        ($x:guard) => {};
+    }
+
+    // Accepts
+    m!(if true);
+    m!(if let Some(x) = Some(1));
+    m!(if let Some(x) = Some(1) && x == 1);
+    m!(if let Some(x) = Some(Some(1)) && let Some(1) = x);
+    m!(if let Some(x) = Some(Some(1)) && let Some(y) = x && y == 1);
+
+    // Rejects
+    m!(let Some(x) = Some(1)); //~ERROR no rules expected keyword `let`
+}
diff --git a/tests/ui/macros/macro-guard-matcher.stderr b/tests/ui/macros/macro-guard-matcher.stderr
new file mode 100644
index 0000000..eddb0de
--- /dev/null
+++ b/tests/ui/macros/macro-guard-matcher.stderr
@@ -0,0 +1,17 @@
+error: no rules expected keyword `let`
+  --> $DIR/macro-guard-matcher.rs:16:8
+   |
+LL |     macro_rules! m {
+   |     -------------- when calling this macro
+...
+LL |     m!(let Some(x) = Some(1));
+   |        ^^^ no rules expected this token in macro call
+   |
+note: while trying to match meta-variable `$x:guard`
+  --> $DIR/macro-guard-matcher.rs:5:10
+   |
+LL |         ($x:guard) => {};
+   |          ^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/macros/macro-in-fn.rs b/tests/ui/macros/macro-in-fn.rs
index 2ffa6b2..48085b8 100644
--- a/tests/ui/macros/macro-in-fn.rs
+++ b/tests/ui/macros/macro-in-fn.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![feature(decl_macro)]
 
 pub fn moo() {
diff --git a/tests/ui/macros/macro-input-future-proofing.stderr b/tests/ui/macros/macro-input-future-proofing.stderr
index 11960db..a12cc9f 100644
--- a/tests/ui/macros/macro-input-future-proofing.stderr
+++ b/tests/ui/macros/macro-input-future-proofing.stderr
@@ -20,7 +20,7 @@
 LL |     ($pa:pat >) => ();
    |              ^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$pa:pat` is followed by `$pb:pat`, which is not allowed for `pat` fragments
   --> $DIR/macro-input-future-proofing.rs:14:14
@@ -28,7 +28,7 @@
 LL |     ($pa:pat $pb:pat $ty:ty ,) => ();
    |              ^^^^^^^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$pb:pat` is followed by `$ty:ty`, which is not allowed for `pat` fragments
   --> $DIR/macro-input-future-proofing.rs:14:22
@@ -36,7 +36,7 @@
 LL |     ($pa:pat $pb:pat $ty:ty ,) => ();
    |                      ^^^^^^ not allowed after `pat` fragments
    |
-   = note: allowed there are: `=>`, `,`, `=`, `|`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `|`, `if`, `if let` or `in`
 
 error: `$ty:ty` is followed by `-`, which is not allowed for `ty` fragments
   --> $DIR/macro-input-future-proofing.rs:17:17
diff --git a/tests/ui/macros/macro-invocation-in-count-expr-fixed-array-type.rs b/tests/ui/macros/macro-invocation-in-count-expr-fixed-array-type.rs
index e80c712..ed8974c 100644
--- a/tests/ui/macros/macro-invocation-in-count-expr-fixed-array-type.rs
+++ b/tests/ui/macros/macro-invocation-in-count-expr-fixed-array-type.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 
 macro_rules! four {
     () => (4)
diff --git a/tests/ui/macros/macro-multiple-items.rs b/tests/ui/macros/macro-multiple-items.rs
index c746d1b..46b561af 100644
--- a/tests/ui/macros/macro-multiple-items.rs
+++ b/tests/ui/macros/macro-multiple-items.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 macro_rules! make_foo {
     () => (
         struct Foo;
diff --git a/tests/ui/macros/macro-named-default.rs b/tests/ui/macros/macro-named-default.rs
index bca0e00..c7eac83 100644
--- a/tests/ui/macros/macro-named-default.rs
+++ b/tests/ui/macros/macro-named-default.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 macro_rules! default {
     ($($x:tt)*) => { $($x)* }
 }
diff --git a/tests/ui/macros/macro-nt-list.rs b/tests/ui/macros/macro-nt-list.rs
index b7b260c..56ea917 100644
--- a/tests/ui/macros/macro-nt-list.rs
+++ b/tests/ui/macros/macro-nt-list.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 
 macro_rules! list {
     ( ($($id:ident),*) ) => (());
diff --git a/tests/ui/macros/macro-pat-follow-2018.rs b/tests/ui/macros/macro-pat-follow-2018.rs
index 6dcb841..b2a556f 100644
--- a/tests/ui/macros/macro-pat-follow-2018.rs
+++ b/tests/ui/macros/macro-pat-follow-2018.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 //@ edition:2018
 
 macro_rules! pat_bar {
diff --git a/tests/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr b/tests/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr
index a06487b..9179fbc 100644
--- a/tests/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr
+++ b/tests/ui/macros/macro-pat-pattern-followed-by-or-in-2021.stderr
@@ -6,7 +6,7 @@
    |                     |
    |                     help: try a `pat_param` fragment specifier instead: `$x:pat_param`
    |
-   = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `if`, `if let` or `in`
 
 error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments
   --> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:4:32
@@ -16,7 +16,7 @@
    |                       |
    |                       help: try a `pat_param` fragment specifier instead: `$x:pat_param`
    |
-   = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `if`, `if let` or `in`
 
 error: `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments
   --> $DIR/macro-pat-pattern-followed-by-or-in-2021.rs:7:36
@@ -26,7 +26,7 @@
    |                          |
    |                          help: try a `pat_param` fragment specifier instead: `$pat:pat_param`
    |
-   = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `if`, `if let` or `in`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/macros/macro-pat2021-pattern-followed-by-or.stderr b/tests/ui/macros/macro-pat2021-pattern-followed-by-or.stderr
index c3754dd..af76e3f 100644
--- a/tests/ui/macros/macro-pat2021-pattern-followed-by-or.stderr
+++ b/tests/ui/macros/macro-pat2021-pattern-followed-by-or.stderr
@@ -6,7 +6,7 @@
    |                     |
    |                     help: try a `pat_param` fragment specifier instead: `$x:pat_param`
    |
-   = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `if`, `if let` or `in`
 
 error: `$x:pat` is followed by `|`, which is not allowed for `pat` fragments
   --> $DIR/macro-pat2021-pattern-followed-by-or.rs:7:28
@@ -16,7 +16,7 @@
    |                     |
    |                     help: try a `pat_param` fragment specifier instead: `$x:pat_param`
    |
-   = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `if`, `if let` or `in`
 
 error: `$pat:pat` may be followed by `|`, which is not allowed for `pat` fragments
   --> $DIR/macro-pat2021-pattern-followed-by-or.rs:9:35
@@ -26,7 +26,7 @@
    |                          |
    |                          help: try a `pat_param` fragment specifier instead: `$pat:pat_param`
    |
-   = note: allowed there are: `=>`, `,`, `=`, `if` or `in`
+   = note: allowed there are: `=>`, `,`, `=`, `if`, `if let` or `in`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/macros/macro-pub-matcher.rs b/tests/ui/macros/macro-pub-matcher.rs
index e0b03db..20cacab 100644
--- a/tests/ui/macros/macro-pub-matcher.rs
+++ b/tests/ui/macros/macro-pub-matcher.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(dead_code, unused_imports, unused_macro_rules)]
 
 /**
diff --git a/tests/ui/macros/macro-seq-followed-by-seq.rs b/tests/ui/macros/macro-seq-followed-by-seq.rs
index 3661744..cf5a1c1 100644
--- a/tests/ui/macros/macro-seq-followed-by-seq.rs
+++ b/tests/ui/macros/macro-seq-followed-by-seq.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 // Test of allowing two sequences repetitions in a row,
 // functionality added as byproduct of RFC amendment #1384
 //   https://github.com/rust-lang/rfcs/pull/1384
diff --git a/tests/ui/macros/macro-use-all-and-none.rs b/tests/ui/macros/macro-use-all-and-none.rs
index f1acff4..53d450e 100644
--- a/tests/ui/macros/macro-use-all-and-none.rs
+++ b/tests/ui/macros/macro-use-all-and-none.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 //@ aux-build:two_macros-rpass.rs
 
 #![warn(unused_attributes)]
diff --git a/tests/ui/macros/macro-use-all.rs b/tests/ui/macros/macro-use-all.rs
index a7fd3df..06b96da 100644
--- a/tests/ui/macros/macro-use-all.rs
+++ b/tests/ui/macros/macro-use-all.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 //@ aux-build:two_macros.rs
 
 #[macro_use]
diff --git a/tests/ui/macros/macro-use-both.rs b/tests/ui/macros/macro-use-both.rs
index e49f346..c417975 100644
--- a/tests/ui/macros/macro-use-both.rs
+++ b/tests/ui/macros/macro-use-both.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 //@ aux-build:two_macros.rs
 
 #[macro_use(macro_one, macro_two)]
diff --git a/tests/ui/macros/macro-use-one.rs b/tests/ui/macros/macro-use-one.rs
index 2b04865..93f7c21 100644
--- a/tests/ui/macros/macro-use-one.rs
+++ b/tests/ui/macros/macro-use-one.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 //@ aux-build:two_macros.rs
 
 #[macro_use(macro_two)]
diff --git a/tests/ui/macros/panic-macro-basic.rs b/tests/ui/macros/panic-macro-basic.rs
new file mode 100644
index 0000000..96ed426
--- /dev/null
+++ b/tests/ui/macros/panic-macro-basic.rs
@@ -0,0 +1,14 @@
+//@ run-fail
+//@ error-pattern:test
+//@ needs-subprocess
+// Just testing that panic!() type checks in statement or expr
+
+fn f() {
+    let __isize: isize = panic!("test");
+
+    panic!();
+}
+
+fn main() {
+    f();
+}
diff --git a/tests/ui/macros/parse-complex-macro-invoc-op.rs b/tests/ui/macros/parse-complex-macro-invoc-op.rs
index 2c384bd..bbb01fa 100644
--- a/tests/ui/macros/parse-complex-macro-invoc-op.rs
+++ b/tests/ui/macros/parse-complex-macro-invoc-op.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(unused_must_use)]
 #![allow(dead_code)]
 #![allow(unused_assignments)]
diff --git a/tests/ui/macros/pub-item-inside-macro.rs b/tests/ui/macros/pub-item-inside-macro.rs
index c37945a..679987a 100644
--- a/tests/ui/macros/pub-item-inside-macro.rs
+++ b/tests/ui/macros/pub-item-inside-macro.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 // Issue #14660
 
 
diff --git a/tests/ui/macros/pub-method-inside-macro.rs b/tests/ui/macros/pub-method-inside-macro.rs
index dd4e6fd..23d8c45 100644
--- a/tests/ui/macros/pub-method-inside-macro.rs
+++ b/tests/ui/macros/pub-method-inside-macro.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 // Issue #17436
 
 
diff --git a/tests/ui/macros/semi-after-macro-ty.rs b/tests/ui/macros/semi-after-macro-ty.rs
index 60afc3b..ff026c5 100644
--- a/tests/ui/macros/semi-after-macro-ty.rs
+++ b/tests/ui/macros/semi-after-macro-ty.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 macro_rules! foo {
     ($t:ty; $p:path;) => {}
 }
diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs
index 3f331b0..af2ba7a 100644
--- a/tests/ui/macros/stringify.rs
+++ b/tests/ui/macros/stringify.rs
@@ -14,6 +14,7 @@
 #![feature(trait_alias)]
 #![feature(try_blocks)]
 #![feature(yeet_expr)]
+#![feature(macro_guard_matcher)]
 #![deny(unused_macros)]
 
 // These macros force the use of AST pretty-printing by converting the input to
@@ -27,6 +28,7 @@
 macro_rules! stmt { ($stmt:stmt) => { stringify!($stmt) }; }
 macro_rules! ty { ($ty:ty) => { stringify!($ty) }; }
 macro_rules! vis { ($vis:vis) => { stringify!($vis) }; }
+macro_rules! guard { ($guard:guard) => { stringify!($guard) }; }
 
 macro_rules! c1 {
     ($frag:ident, [$($tt:tt)*], $s:literal) => {
@@ -792,6 +794,21 @@ fn test_vis() {
     // Attributes are not allowed on visibilities.
 }
 
+#[test]
+fn test_guard() {
+    c1!(guard, [ if true ], "if true");
+    c1!(guard, [ if let Some(x) = Some(1) ], "if let Some(x) = Some(1)");
+    c1!(guard, [ if let Some(x) = Some(1) && x == 1 ], "if let Some(x) = Some(1) && x == 1");
+    c1!(guard,
+        [ if let Some(x) = Some(Some(1)) && let Some(1) = x ],
+        "if let Some(x) = Some(Some(1)) && let Some(1) = x"
+    );
+    c1!(guard,
+        [ if let Some(x) = Some(Some(1)) && let Some(y) = x && y == 1 ],
+        "if let Some(x) = Some(Some(1)) && let Some(y) = x && y == 1"
+    );
+}
+
 macro_rules! p {
     ([$($tt:tt)*], $s:literal) => {
         assert_eq!(stringify!($($tt)*), $s);
diff --git a/tests/ui/macros/two-macro-use.rs b/tests/ui/macros/two-macro-use.rs
index 8bb3c9d..733853f 100644
--- a/tests/ui/macros/two-macro-use.rs
+++ b/tests/ui/macros/two-macro-use.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 //@ aux-build:two_macros.rs
 
 #[macro_use(macro_one)]
diff --git a/tests/ui/macros/type-macros-simple.rs b/tests/ui/macros/type-macros-simple.rs
index d189b88..800a796 100644
--- a/tests/ui/macros/type-macros-simple.rs
+++ b/tests/ui/macros/type-macros-simple.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(dead_code)]
 #![allow(unused_variables)]
 #![allow(non_local_definitions)]
diff --git a/tests/ui/macros/use-macro-self.rs b/tests/ui/macros/use-macro-self.rs
index 1d15b83..cf5a410 100644
--- a/tests/ui/macros/use-macro-self.rs
+++ b/tests/ui/macros/use-macro-self.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(unused_imports)]
 //@ aux-build:use-macro-self.rs
 
diff --git a/tests/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.rs b/tests/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.rs
index a9f0cda..cd2eaa5 100644
--- a/tests/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.rs
+++ b/tests/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 
 #![feature(marker_trait_attr)]
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 #[marker]
 trait MyMarker {}
diff --git a/tests/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr b/tests/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr
deleted file mode 100644
index 649e589..0000000
--- a/tests/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/overlap-doesnt-conflict-with-specialization.rs:4:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/missing/undeclared-generic-parameter.rs b/tests/ui/missing/undeclared-generic-parameter.rs
new file mode 100644
index 0000000..eebae21
--- /dev/null
+++ b/tests/ui/missing/undeclared-generic-parameter.rs
@@ -0,0 +1,5 @@
+struct A;
+impl A<B> {}
+//~^ ERROR cannot find type `B` in this scope
+//~| ERROR struct takes 0 generic arguments but 1 generic argument was supplied
+fn main() {}
diff --git a/tests/ui/missing/undeclared-generic-parameter.stderr b/tests/ui/missing/undeclared-generic-parameter.stderr
new file mode 100644
index 0000000..101a579
--- /dev/null
+++ b/tests/ui/missing/undeclared-generic-parameter.stderr
@@ -0,0 +1,36 @@
+error[E0425]: cannot find type `B` in this scope
+  --> $DIR/undeclared-generic-parameter.rs:2:8
+   |
+LL | struct A;
+   | --------- similarly named struct `A` defined here
+LL | impl A<B> {}
+   |        ^
+   |
+help: a struct with a similar name exists
+   |
+LL - impl A<B> {}
+LL + impl A<A> {}
+   |
+help: you might be missing a type parameter
+   |
+LL | impl<B> A<B> {}
+   |     +++
+
+error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied
+  --> $DIR/undeclared-generic-parameter.rs:2:6
+   |
+LL | impl A<B> {}
+   |      ^--- help: remove the unnecessary generics
+   |      |
+   |      expected 0 generic arguments
+   |
+note: struct defined here, with 0 generic parameters
+  --> $DIR/undeclared-generic-parameter.rs:1:8
+   |
+LL | struct A;
+   |        ^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0107, E0425.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/on-unimplemented/self-types.rs b/tests/ui/on-unimplemented/self-types.rs
new file mode 100644
index 0000000..736d3ba
--- /dev/null
+++ b/tests/ui/on-unimplemented/self-types.rs
@@ -0,0 +1,30 @@
+#![feature(rustc_attrs)]
+
+#[rustc_on_unimplemented(
+    on(Self = "{union}", message = "union self type"),
+    on(Self = "{enum}", message = "enum self type"),
+    on(Self = "{struct}", message = "struct self type"),
+    message = "fallback self type `{Self}`"
+)]
+trait Trait {}
+
+union Union {
+    value: u8,
+}
+
+enum Enum {
+    Variant,
+}
+
+struct Struct;
+
+fn needs_trait<T: Trait>() {}
+
+fn main() {
+    needs_trait::<Union>();
+    //~^ ERROR union self type
+    needs_trait::<Enum>();
+    //~^ ERROR enum self type
+    needs_trait::<Struct>();
+    //~^ ERROR struct self type
+}
diff --git a/tests/ui/on-unimplemented/self-types.stderr b/tests/ui/on-unimplemented/self-types.stderr
new file mode 100644
index 0000000..ea40ac5
--- /dev/null
+++ b/tests/ui/on-unimplemented/self-types.stderr
@@ -0,0 +1,69 @@
+error[E0277]: union self type
+  --> $DIR/self-types.rs:24:19
+   |
+LL |     needs_trait::<Union>();
+   |                   ^^^^^ unsatisfied trait bound
+   |
+help: the trait `Trait` is not implemented for `Union`
+  --> $DIR/self-types.rs:11:1
+   |
+LL | union Union {
+   | ^^^^^^^^^^^
+help: this trait has no implementations, consider adding one
+  --> $DIR/self-types.rs:9:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
+note: required by a bound in `needs_trait`
+  --> $DIR/self-types.rs:21:19
+   |
+LL | fn needs_trait<T: Trait>() {}
+   |                   ^^^^^ required by this bound in `needs_trait`
+
+error[E0277]: enum self type
+  --> $DIR/self-types.rs:26:19
+   |
+LL |     needs_trait::<Enum>();
+   |                   ^^^^ unsatisfied trait bound
+   |
+help: the trait `Trait` is not implemented for `Enum`
+  --> $DIR/self-types.rs:15:1
+   |
+LL | enum Enum {
+   | ^^^^^^^^^
+help: this trait has no implementations, consider adding one
+  --> $DIR/self-types.rs:9:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
+note: required by a bound in `needs_trait`
+  --> $DIR/self-types.rs:21:19
+   |
+LL | fn needs_trait<T: Trait>() {}
+   |                   ^^^^^ required by this bound in `needs_trait`
+
+error[E0277]: struct self type
+  --> $DIR/self-types.rs:28:19
+   |
+LL |     needs_trait::<Struct>();
+   |                   ^^^^^^ unsatisfied trait bound
+   |
+help: the trait `Trait` is not implemented for `Struct`
+  --> $DIR/self-types.rs:19:1
+   |
+LL | struct Struct;
+   | ^^^^^^^^^^^^^
+help: this trait has no implementations, consider adding one
+  --> $DIR/self-types.rs:9:1
+   |
+LL | trait Trait {}
+   | ^^^^^^^^^^^
+note: required by a bound in `needs_trait`
+  --> $DIR/self-types.rs:21:19
+   |
+LL | fn needs_trait<T: Trait>() {}
+   |                   ^^^^^ required by this bound in `needs_trait`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr
index 67b72bd..61d4866 100644
--- a/tests/ui/on-unimplemented/slice-index.stderr
+++ b/tests/ui/on-unimplemented/slice-index.stderr
@@ -5,13 +5,13 @@
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[i32]>` is not implemented for `i32`
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
    = note: required for `[i32]` to implement `Index<i32>`
 
 error[E0277]: the type `[i32]` cannot be indexed by `RangeTo<i32>`
@@ -21,19 +21,19 @@
    |       ^^^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo<i32>`
-help: the following other types implement trait `SliceIndex<T>`
+help: `RangeTo<usize>` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `RangeTo<usize>` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `RangeTo<usize>` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
   ::: $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
    = note: in this macro invocation
   --> $SRC_DIR/core/src/str/traits.rs:LL:COL
    |
-   = note: `RangeTo<usize>` implements `SliceIndex<str>`
+   = note: `SliceIndex<str>`
    = note: required for `[i32]` to implement `Index<RangeTo<i32>>`
    = note: this error originates in the macro `impl_slice_index` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.rs b/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.rs
index aaaf4d3..2c89863 100644
--- a/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.rs
+++ b/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.rs
@@ -5,7 +5,7 @@ fn from(_: (u8,)) -> Self {
         todo!()
     }
 }
-impl From<(u8, u8)> for Tuple { //~ HELP the following other types implement trait `From<T>`
+impl From<(u8, u8)> for Tuple { //~ HELP `Tuple` implements trait `From<T>`
     fn from(_: (u8, u8)) -> Self {
         todo!()
     }
diff --git a/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.stderr b/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.stderr
index cf15ac1..f07db05 100644
--- a/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.stderr
+++ b/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.stderr
@@ -11,17 +11,17 @@
    |
 LL | struct Tuple;
    | ^^^^^^^^^^^^
-help: the following other types implement trait `From<T>`
+help: `Tuple` implements trait `From<T>`
   --> $DIR/suggest_tuple_wrap_root_obligation.rs:3:1
    |
 LL | impl From<(u8,)> for Tuple {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `Tuple` implements `From<(u8,)>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `From<(u8,)>`
 ...
 LL | impl From<(u8, u8)> for Tuple {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Tuple` implements `From<(u8, u8)>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `From<(u8, u8)>`
 ...
 LL | impl From<(u8, u8, u8)> for Tuple {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Tuple` implements `From<(u8, u8, u8)>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `From<(u8, u8, u8)>`
    = note: required for `u8` to implement `Into<Tuple>`
 note: required by a bound in `convert_into_tuple`
   --> $DIR/suggest_tuple_wrap_root_obligation.rs:19:32
diff --git a/tests/ui/on-unimplemented/sum.stderr b/tests/ui/on-unimplemented/sum.stderr
index 5e82948..56257079 100644
--- a/tests/ui/on-unimplemented/sum.stderr
+++ b/tests/ui/on-unimplemented/sum.stderr
@@ -7,13 +7,13 @@
    |                         required by a bound introduced by this call
    |
    = help: the trait `Sum<&()>` is not implemented for `i32`
-help: the following other types implement trait `Sum<A>`
+help: `i32` implements trait `Sum<A>`
   --> $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum`
+   = note: `Sum`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Sum<&i32>`
+   = note: `Sum<&i32>`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
    = note: in this macro invocation
@@ -37,13 +37,13 @@
    |                         required by a bound introduced by this call
    |
    = help: the trait `Product<&()>` is not implemented for `i32`
-help: the following other types implement trait `Product<A>`
+help: `i32` implements trait `Product<A>`
   --> $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Product`
+   = note: `Product`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
-   = note: `i32` implements `Product<&i32>`
+   = note: `Product<&i32>`
   ::: $SRC_DIR/core/src/iter/traits/accum.rs:LL:COL
    |
    = note: in this macro invocation
diff --git a/tests/ui/parser/assoc/assoc-static-semantic-fail.rs b/tests/ui/parser/assoc/assoc-static-semantic-fail.rs
index 403160f..de0cee6 100644
--- a/tests/ui/parser/assoc/assoc-static-semantic-fail.rs
+++ b/tests/ui/parser/assoc/assoc-static-semantic-fail.rs
@@ -1,7 +1,6 @@
 // Semantically, we do not allow e.g., `static X: u8 = 0;` as an associated item.
 
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
 
 fn main() {}
 
diff --git a/tests/ui/parser/assoc/assoc-static-semantic-fail.stderr b/tests/ui/parser/assoc/assoc-static-semantic-fail.stderr
index cc21df7..4ac3528 100644
--- a/tests/ui/parser/assoc/assoc-static-semantic-fail.stderr
+++ b/tests/ui/parser/assoc/assoc-static-semantic-fail.stderr
@@ -1,17 +1,17 @@
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:10:5
+  --> $DIR/assoc-static-semantic-fail.rs:9:5
    |
 LL |     static IA: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:12:5
+  --> $DIR/assoc-static-semantic-fail.rs:11:5
    |
 LL |     static IB: u8;
    |     ^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:15:5
+  --> $DIR/assoc-static-semantic-fail.rs:14:5
    |
 LL |     default static IC: u8 = 0;
    |     ^^^^^^^ `default` because of this
@@ -19,13 +19,13 @@
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:15:5
+  --> $DIR/assoc-static-semantic-fail.rs:14:5
    |
 LL |     default static IC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:18:16
+  --> $DIR/assoc-static-semantic-fail.rs:17:16
    |
 LL |     pub(crate) default static ID: u8;
    |                ^^^^^^^ `default` because of this
@@ -33,25 +33,25 @@
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:18:5
+  --> $DIR/assoc-static-semantic-fail.rs:17:5
    |
 LL |     pub(crate) default static ID: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:25:5
+  --> $DIR/assoc-static-semantic-fail.rs:24:5
    |
 LL |     static TA: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:27:5
+  --> $DIR/assoc-static-semantic-fail.rs:26:5
    |
 LL |     static TB: u8;
    |     ^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:29:5
+  --> $DIR/assoc-static-semantic-fail.rs:28:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^ `default` because of this
@@ -59,13 +59,13 @@
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:29:5
+  --> $DIR/assoc-static-semantic-fail.rs:28:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:32:16
+  --> $DIR/assoc-static-semantic-fail.rs:31:16
    |
 LL |     pub(crate) default static TD: u8;
    |                ^^^^^^^ `default` because of this
@@ -73,25 +73,25 @@
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:32:5
+  --> $DIR/assoc-static-semantic-fail.rs:31:5
    |
 LL |     pub(crate) default static TD: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:39:5
+  --> $DIR/assoc-static-semantic-fail.rs:38:5
    |
 LL |     static TA: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:41:5
+  --> $DIR/assoc-static-semantic-fail.rs:40:5
    |
 LL |     static TB: u8;
    |     ^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:44:5
+  --> $DIR/assoc-static-semantic-fail.rs:43:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^ `default` because of this
@@ -99,13 +99,13 @@
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:44:5
+  --> $DIR/assoc-static-semantic-fail.rs:43:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:47:9
+  --> $DIR/assoc-static-semantic-fail.rs:46:9
    |
 LL |     pub default static TD: u8;
    |         ^^^^^^^ `default` because of this
@@ -113,13 +113,13 @@
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:47:5
+  --> $DIR/assoc-static-semantic-fail.rs:46:5
    |
 LL |     pub default static TD: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated constant in `impl` without body
-  --> $DIR/assoc-static-semantic-fail.rs:12:5
+  --> $DIR/assoc-static-semantic-fail.rs:11:5
    |
 LL |     static IB: u8;
    |     ^^^^^^^^^^^^^-
@@ -127,7 +127,7 @@
    |                  help: provide a definition for the constant: `= <expr>;`
 
 error: associated constant in `impl` without body
-  --> $DIR/assoc-static-semantic-fail.rs:18:5
+  --> $DIR/assoc-static-semantic-fail.rs:17:5
    |
 LL |     pub(crate) default static ID: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -135,7 +135,7 @@
    |                                     help: provide a definition for the constant: `= <expr>;`
 
 error[E0449]: visibility qualifiers are not permitted here
-  --> $DIR/assoc-static-semantic-fail.rs:32:5
+  --> $DIR/assoc-static-semantic-fail.rs:31:5
    |
 LL |     pub(crate) default static TD: u8;
    |     ^^^^^^^^^^ help: remove the qualifier
@@ -143,7 +143,7 @@
    = note: trait items always share the visibility of their trait
 
 error: associated constant in `impl` without body
-  --> $DIR/assoc-static-semantic-fail.rs:41:5
+  --> $DIR/assoc-static-semantic-fail.rs:40:5
    |
 LL |     static TB: u8;
    |     ^^^^^^^^^^^^^-
@@ -151,7 +151,7 @@
    |                  help: provide a definition for the constant: `= <expr>;`
 
 error: associated constant in `impl` without body
-  --> $DIR/assoc-static-semantic-fail.rs:47:5
+  --> $DIR/assoc-static-semantic-fail.rs:46:5
    |
 LL |     pub default static TD: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -159,23 +159,13 @@
    |                              help: provide a definition for the constant: `= <expr>;`
 
 error[E0449]: visibility qualifiers are not permitted here
-  --> $DIR/assoc-static-semantic-fail.rs:47:5
+  --> $DIR/assoc-static-semantic-fail.rs:46:5
    |
 LL |     pub default static TD: u8;
    |     ^^^ help: remove the qualifier
    |
    = note: trait items always share the visibility of their trait
 
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/assoc-static-semantic-fail.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-error: aborting due to 24 previous errors; 1 warning emitted
+error: aborting due to 24 previous errors
 
 For more information about this error, try `rustc --explain E0449`.
diff --git a/tests/ui/parser/default.rs b/tests/ui/parser/default.rs
index d1058ce..81821ce 100644
--- a/tests/ui/parser/default.rs
+++ b/tests/ui/parser/default.rs
@@ -1,7 +1,6 @@
 // Test successful and unsuccessful parsing of the `default` contextual keyword
 
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
 
 trait Foo {
     fn foo<T: Default>() -> T;
diff --git a/tests/ui/parser/default.stderr b/tests/ui/parser/default.stderr
index c420e5a..1f2312d 100644
--- a/tests/ui/parser/default.stderr
+++ b/tests/ui/parser/default.stderr
@@ -1,5 +1,5 @@
 error: `default` is not followed by an item
-  --> $DIR/default.rs:23:5
+  --> $DIR/default.rs:22:5
    |
 LL |     default pub fn foo<T: Default>() -> T { T::default() }
    |     ^^^^^^^ the `default` qualifier
@@ -7,7 +7,7 @@
    = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
 
 error: non-item in item list
-  --> $DIR/default.rs:23:13
+  --> $DIR/default.rs:22:13
    |
 LL | impl Foo for u32 {
    |                  - item list starts here
@@ -18,25 +18,15 @@
    | - item list ends here
 
 error[E0449]: visibility qualifiers are not permitted here
-  --> $DIR/default.rs:17:5
+  --> $DIR/default.rs:16:5
    |
 LL |     pub default fn foo<T: Default>() -> T {
    |     ^^^ help: remove the qualifier
    |
    = note: trait items always share the visibility of their trait
 
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/default.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0046]: not all trait items implemented, missing: `foo`
-  --> $DIR/default.rs:22:1
+  --> $DIR/default.rs:21:1
    |
 LL |     fn foo<T: Default>() -> T;
    |     -------------------------- `foo` from trait
@@ -44,7 +34,7 @@
 LL | impl Foo for u32 {
    | ^^^^^^^^^^^^^^^^ missing `foo` in implementation
 
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0046, E0449.
 For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/parser/defaultness-invalid-places-fail-semantic.rs b/tests/ui/parser/defaultness-invalid-places-fail-semantic.rs
index bff53f6..f274040 100644
--- a/tests/ui/parser/defaultness-invalid-places-fail-semantic.rs
+++ b/tests/ui/parser/defaultness-invalid-places-fail-semantic.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 fn main() {}
 
diff --git a/tests/ui/parser/defaultness-invalid-places-fail-semantic.stderr b/tests/ui/parser/defaultness-invalid-places-fail-semantic.stderr
index 41fad3a..4adb0ab 100644
--- a/tests/ui/parser/defaultness-invalid-places-fail-semantic.stderr
+++ b/tests/ui/parser/defaultness-invalid-places-fail-semantic.stderr
@@ -70,15 +70,5 @@
    | |
    | `default` because of this
 
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/defaultness-invalid-places-fail-semantic.rs:1:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-error: aborting due to 9 previous errors; 1 warning emitted
+error: aborting due to 9 previous errors
 
diff --git a/tests/ui/parser/recover/array-type-no-semi.stderr b/tests/ui/parser/recover/array-type-no-semi.stderr
index 45f39fe..56c78b0 100644
--- a/tests/ui/parser/recover/array-type-no-semi.stderr
+++ b/tests/ui/parser/recover/array-type-no-semi.stderr
@@ -17,7 +17,12 @@
    |          -     ^ expected `;` or `]`
    |          |
    |          while parsing the type for `a`
-   |          help: use `=` if you meant to assign
+   |
+help: use `=` if you meant to assign
+   |
+LL -     let a: [i32, ];
+LL +     let a = [i32, ];
+   |
 
 error: expected `;` or `]`, found `,`
   --> $DIR/array-type-no-semi.rs:12:16
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 15c27bb..94e5d44 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
@@ -13,7 +13,12 @@
    |          -                     ^ expected one of `!`, `+`, `->`, `::`, `;`, or `=`
    |          |
    |          while parsing the type for `_`
-   |          help: use `=` if you meant to assign
+   |
+help: use `=` if you meant to assign
+   |
+LL -     let _: std::env::temp_dir().join("foo");
+LL +     let _ = std::env::temp_dir().join("foo");
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/shebang/multiline-attrib.rs b/tests/ui/parser/shebang/multiline-attrib.rs
index 2d2e029..d67ba5f 100644
--- a/tests/ui/parser/shebang/multiline-attrib.rs
+++ b/tests/ui/parser/shebang/multiline-attrib.rs
@@ -1,7 +1,7 @@
 #!
 [allow(unused_variables)]
 //@ check-pass
-//@ reference: input.shebang.inner-attribute
+//@ reference: shebang.syntax-description
 
 fn main() {
     let x = 5;
diff --git a/tests/ui/parser/shebang/regular-attrib.rs b/tests/ui/parser/shebang/regular-attrib.rs
index c2ac256..f711b81 100644
--- a/tests/ui/parser/shebang/regular-attrib.rs
+++ b/tests/ui/parser/shebang/regular-attrib.rs
@@ -1,6 +1,6 @@
 #![allow(unused_variables)]
 //@ check-pass
-//@ reference: input.shebang.inner-attribute
+//@ reference: shebang.syntax-description
 fn main() {
     let x = 5;
 }
diff --git a/tests/ui/parser/shebang/shebang-and-attrib.rs b/tests/ui/parser/shebang/shebang-and-attrib.rs
index d73db6b..e3e52b5 100644
--- a/tests/ui/parser/shebang/shebang-and-attrib.rs
+++ b/tests/ui/parser/shebang/shebang-and-attrib.rs
@@ -1,7 +1,7 @@
 #!/usr/bin/env run-cargo-script
 
 //@ check-pass
-//@ reference: input.shebang.inner-attribute
+//@ reference: shebang.syntax-description
 #![allow(unused_variables)]
 
 
diff --git a/tests/ui/parser/shebang/shebang-doc-comment.rs b/tests/ui/parser/shebang/shebang-doc-comment.rs
index 4992c75..976a2b3 100644
--- a/tests/ui/parser/shebang/shebang-doc-comment.rs
+++ b/tests/ui/parser/shebang/shebang-doc-comment.rs
@@ -2,4 +2,4 @@
 [allow(unused_variables)]
 //~^ ERROR expected item, found `[`
 
-//@ reference: input.shebang.inner-attribute
+//@ reference: shebang.syntax-description
diff --git a/tests/ui/parser/shebang/sneaky-attrib.rs b/tests/ui/parser/shebang/sneaky-attrib.rs
index e22c45c..b9c4adb 100644
--- a/tests/ui/parser/shebang/sneaky-attrib.rs
+++ b/tests/ui/parser/shebang/sneaky-attrib.rs
@@ -11,7 +11,7 @@
 [allow(unused_variables)]
 
 //@ check-pass
-//@ reference: input.shebang.inner-attribute
+//@ reference: shebang.syntax-description
 fn main() {
     let x = 5;
 }
diff --git a/tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.rs b/tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.rs
index 83ad8c7..21edb9c 100644
--- a/tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.rs
+++ b/tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.rs
@@ -6,6 +6,7 @@
 #![expect(incomplete_features)]
 
 fn good_fn_item(((x if x) | x): bool) -> bool { x }
+//~^ ERROR: used binding `x` is possibly-uninitialized [E0381]
 
 fn bad_fn_item_1(x: bool, ((y if x) | y): bool) {}
 //~^ ERROR cannot find value `x` in this scope
diff --git a/tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.stderr b/tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.stderr
index 44e42f1..a95ffdd 100644
--- a/tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.stderr
+++ b/tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.stderr
@@ -1,5 +1,5 @@
 error[E0408]: variable `y` is not bound in all patterns
-  --> $DIR/name-resolution.rs:37:10
+  --> $DIR/name-resolution.rs:38:10
    |
 LL |         ((Ok(x) if y) | (Err(y) if x),) => x && y,
    |          ^^^^^^^^^^^^        - variable not in all patterns
@@ -13,7 +13,7 @@
    |
 
 error[E0408]: variable `x` is not bound in all patterns
-  --> $DIR/name-resolution.rs:37:25
+  --> $DIR/name-resolution.rs:38:25
    |
 LL |         ((Ok(x) if y) | (Err(y) if x),) => x && y,
    |              -          ^^^^^^^^^^^^^ pattern doesn't bind `x`
@@ -27,7 +27,7 @@
    |
 
 error[E0408]: variable `x` is not bound in all patterns
-  --> $DIR/name-resolution.rs:63:28
+  --> $DIR/name-resolution.rs:64:28
    |
 LL |         Some(x if x > 0) | None => {}
    |              -             ^^^^ pattern doesn't bind `x`
@@ -35,7 +35,7 @@
    |              variable not in all patterns
 
 error[E0425]: cannot find value `x` in this scope
-  --> $DIR/name-resolution.rs:10:34
+  --> $DIR/name-resolution.rs:11:34
    |
 LL | fn bad_fn_item_1(x: bool, ((y if x) | y): bool) {}
    |                                  ^
@@ -47,7 +47,7 @@
    |
 
 error[E0425]: cannot find value `y` in this scope
-  --> $DIR/name-resolution.rs:12:25
+  --> $DIR/name-resolution.rs:13:25
    |
 LL | fn bad_fn_item_2(((x if y) | x): bool, y: bool) {}
    |                         ^
@@ -59,7 +59,7 @@
    |
 
 error[E0425]: cannot find value `x` in this scope
-  --> $DIR/name-resolution.rs:20:18
+  --> $DIR/name-resolution.rs:21:18
    |
 LL |         (x, y if x) => x && y,
    |                  ^
@@ -71,7 +71,7 @@
    |
 
 error[E0425]: cannot find value `y` in this scope
-  --> $DIR/name-resolution.rs:22:15
+  --> $DIR/name-resolution.rs:23:15
    |
 LL |         (x if y, y) => x && y,
    |               ^
@@ -83,7 +83,7 @@
    |
 
 error[E0425]: cannot find value `x` in this scope
-  --> $DIR/name-resolution.rs:29:20
+  --> $DIR/name-resolution.rs:30:20
    |
 LL |         (x @ (y if x),) => x && y,
    |                    ^
@@ -95,7 +95,7 @@
    |
 
 error[E0425]: cannot find value `y` in this scope
-  --> $DIR/name-resolution.rs:37:20
+  --> $DIR/name-resolution.rs:38:20
    |
 LL |         ((Ok(x) if y) | (Err(y) if x),) => x && y,
    |                    ^
@@ -107,7 +107,7 @@
    |
 
 error[E0425]: cannot find value `x` in this scope
-  --> $DIR/name-resolution.rs:37:36
+  --> $DIR/name-resolution.rs:38:36
    |
 LL |         ((Ok(x) if y) | (Err(y) if x),) => x && y,
    |                                    ^
@@ -119,13 +119,13 @@
    |
 
 error[E0425]: cannot find value `nonexistent` in this scope
-  --> $DIR/name-resolution.rs:44:15
+  --> $DIR/name-resolution.rs:45:15
    |
 LL |     let (_ if nonexistent) = true;
    |               ^^^^^^^^^^^ not found in this scope
 
 error[E0425]: cannot find value `x` in this scope
-  --> $DIR/name-resolution.rs:46:22
+  --> $DIR/name-resolution.rs:47:22
    |
 LL |     if let ((x, y if x) | (x if y, y)) = (true, true) { x && y; }
    |                      ^
@@ -137,7 +137,7 @@
    |
 
 error[E0425]: cannot find value `y` in this scope
-  --> $DIR/name-resolution.rs:46:33
+  --> $DIR/name-resolution.rs:47:33
    |
 LL |     if let ((x, y if x) | (x if y, y)) = (true, true) { x && y; }
    |                                 ^
@@ -149,7 +149,7 @@
    |
 
 error[E0425]: cannot find value `x` in this scope
-  --> $DIR/name-resolution.rs:49:25
+  --> $DIR/name-resolution.rs:50:25
    |
 LL |     while let ((x, y if x) | (x if y, y)) = (true, true) { x && y; }
    |                         ^
@@ -161,7 +161,7 @@
    |
 
 error[E0425]: cannot find value `y` in this scope
-  --> $DIR/name-resolution.rs:49:36
+  --> $DIR/name-resolution.rs:50:36
    |
 LL |     while let ((x, y if x) | (x if y, y)) = (true, true) { x && y; }
    |                                    ^
@@ -173,7 +173,7 @@
    |
 
 error[E0425]: cannot find value `x` in this scope
-  --> $DIR/name-resolution.rs:52:19
+  --> $DIR/name-resolution.rs:53:19
    |
 LL |     for ((x, y if x) | (x if y, y)) in [(true, true)] { x && y; }
    |                   ^
@@ -185,7 +185,7 @@
    |
 
 error[E0425]: cannot find value `y` in this scope
-  --> $DIR/name-resolution.rs:52:30
+  --> $DIR/name-resolution.rs:53:30
    |
 LL |     for ((x, y if x) | (x if y, y)) in [(true, true)] { x && y; }
    |                              ^
@@ -197,7 +197,7 @@
    |
 
 error[E0425]: cannot find value `y` in this scope
-  --> $DIR/name-resolution.rs:57:13
+  --> $DIR/name-resolution.rs:58:13
    |
 LL |     (|(x if y), (y if x)| x && y)(true, true);
    |             ^
@@ -209,7 +209,7 @@
    |
 
 error[E0425]: cannot find value `x` in this scope
-  --> $DIR/name-resolution.rs:57:23
+  --> $DIR/name-resolution.rs:58:23
    |
 LL |     (|(x if y), (y if x)| x && y)(true, true);
    |                       ^
@@ -221,7 +221,7 @@
    |
 
 error[E0308]: mismatched types
-  --> $DIR/name-resolution.rs:75:18
+  --> $DIR/name-resolution.rs:76:18
    |
 LL |         local if local => 0,
    |                  ^^^^^ expected `bool`, found `({integer}, {integer})`
@@ -229,7 +229,16 @@
    = note: expected type `bool`
              found tuple `({integer}, {integer})`
 
-error: aborting due to 20 previous errors
+error[E0381]: used binding `x` is possibly-uninitialized
+  --> $DIR/name-resolution.rs:8:49
+   |
+LL | fn good_fn_item(((x if x) | x): bool) -> bool { x }
+   |                   -         -                   ^ `x` used here but it is possibly-uninitialized
+   |                   |         |
+   |                   |         binding initialized here in some conditions
+   |                   binding declared here but left uninitialized
 
-Some errors have detailed explanations: E0308, E0408, E0425.
+error: aborting due to 21 previous errors
+
+Some errors have detailed explanations: E0308, E0381, E0408, E0425.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr
index d26ba93..75a633c 100644
--- a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr
@@ -1,5 +1,5 @@
 error: unreachable pattern
-  --> $DIR/empty-types.rs:48:9
+  --> $DIR/empty-types.rs:47:9
    |
 LL |         _ => {}
    |         ^------
@@ -9,13 +9,13 @@
    |
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
-  --> $DIR/empty-types.rs:14:9
+  --> $DIR/empty-types.rs:13:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:51:9
+  --> $DIR/empty-types.rs:50:9
    |
 LL |         _x => {}
    |         ^^------
@@ -26,7 +26,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `&!` is non-empty
-  --> $DIR/empty-types.rs:55:11
+  --> $DIR/empty-types.rs:54:11
    |
 LL |     match ref_never {}
    |           ^^^^^^^^^
@@ -41,7 +41,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:69:9
+  --> $DIR/empty-types.rs:68:9
    |
 LL |         (_, _) => {}
    |         ^^^^^^------
@@ -52,7 +52,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:75:9
+  --> $DIR/empty-types.rs:74:9
    |
 LL |         _ => {}
    |         ^------
@@ -63,7 +63,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:78:9
+  --> $DIR/empty-types.rs:77:9
    |
 LL |         (_, _) => {}
    |         ^^^^^^------
@@ -74,7 +74,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:82:9
+  --> $DIR/empty-types.rs:81:9
    |
 LL |         _ => {}
    |         ^------
@@ -85,7 +85,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
-  --> $DIR/empty-types.rs:86:11
+  --> $DIR/empty-types.rs:85:11
    |
 LL |     match res_u32_never {}
    |           ^^^^^^^^^^^^^ pattern `Ok(_)` not covered
@@ -104,7 +104,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:93:9
+  --> $DIR/empty-types.rs:92:9
    |
 LL |         Err(_) => {}
    |         ^^^^^^------
@@ -115,7 +115,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:98:9
+  --> $DIR/empty-types.rs:97:9
    |
 LL |         Err(_) => {}
    |         ^^^^^^------
@@ -126,7 +126,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
-  --> $DIR/empty-types.rs:95:11
+  --> $DIR/empty-types.rs:94:11
    |
 LL |     match res_u32_never {
    |           ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered
@@ -144,7 +144,7 @@
    |
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:101:9
+  --> $DIR/empty-types.rs:100:9
    |
 LL |     let Ok(_x) = res_u32_never.as_ref();
    |         ^^^^^^ pattern `Err(_)` not covered
@@ -158,7 +158,7 @@
    |                                         ++++++++++++++++
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:111:9
+  --> $DIR/empty-types.rs:110:9
    |
 LL |         _ => {}
    |         ^------
@@ -169,7 +169,18 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:114:9
+  --> $DIR/empty-types.rs:113:9
+   |
+LL |         Ok(_) => {}
+   |         ^^^^^------
+   |         |
+   |         matches no values because `Result<!, !>` is uninhabited
+   |         help: remove the match arm
+   |
+   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:116:9
    |
 LL |         Ok(_) => {}
    |         ^^^^^------
@@ -182,17 +193,6 @@
 error: unreachable pattern
   --> $DIR/empty-types.rs:117:9
    |
-LL |         Ok(_) => {}
-   |         ^^^^^------
-   |         |
-   |         matches no values because `Result<!, !>` is uninhabited
-   |         help: remove the match arm
-   |
-   = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
-
-error: unreachable pattern
-  --> $DIR/empty-types.rs:118:9
-   |
 LL |         _ => {}
    |         ^------
    |         |
@@ -202,7 +202,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:121:9
+  --> $DIR/empty-types.rs:120:9
    |
 LL |         Ok(_) => {}
    |         ^^^^^------
@@ -213,7 +213,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:122:9
+  --> $DIR/empty-types.rs:121:9
    |
 LL |         Err(_) => {}
    |         ^^^^^^------
@@ -224,7 +224,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:131:13
+  --> $DIR/empty-types.rs:130:13
    |
 LL |             _ => {}
    |             ^------
@@ -235,7 +235,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:134:13
+  --> $DIR/empty-types.rs:133:13
    |
 LL |             _ if false => {}
    |             ^---------------
@@ -246,7 +246,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:142:13
+  --> $DIR/empty-types.rs:141:13
    |
 LL |             Some(_) => {}
    |             ^^^^^^^------
@@ -257,7 +257,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:146:13
+  --> $DIR/empty-types.rs:145:13
    |
 LL |             None => {}
    |             ---- matches all the relevant values
@@ -265,7 +265,7 @@
    |             ^ no value can reach this
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:198:13
+  --> $DIR/empty-types.rs:197:13
    |
 LL |             _ => {}
    |             ^------
@@ -276,7 +276,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:203:13
+  --> $DIR/empty-types.rs:202:13
    |
 LL |             _ => {}
    |             ^------
@@ -287,7 +287,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:208:13
+  --> $DIR/empty-types.rs:207:13
    |
 LL |             _ => {}
    |             ^------
@@ -298,7 +298,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:213:13
+  --> $DIR/empty-types.rs:212:13
    |
 LL |             _ => {}
    |             ^------
@@ -309,7 +309,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:219:13
+  --> $DIR/empty-types.rs:218:13
    |
 LL |             _ => {}
    |             ^------
@@ -320,7 +320,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:280:9
+  --> $DIR/empty-types.rs:279:9
    |
 LL |         _ => {}
    |         ^------
@@ -331,7 +331,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:283:9
+  --> $DIR/empty-types.rs:282:9
    |
 LL |         (_, _) => {}
    |         ^^^^^^------
@@ -342,7 +342,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:286:9
+  --> $DIR/empty-types.rs:285:9
    |
 LL |         Ok(_) => {}
    |         ^^^^^------
@@ -353,7 +353,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:287:9
+  --> $DIR/empty-types.rs:286:9
    |
 LL |         Err(_) => {}
    |         ^^^^^^------
@@ -364,7 +364,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
-  --> $DIR/empty-types.rs:326:11
+  --> $DIR/empty-types.rs:325:11
    |
 LL |     match slice_never {}
    |           ^^^^^^^^^^^
@@ -378,7 +378,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&[]` not covered
-  --> $DIR/empty-types.rs:337:11
+  --> $DIR/empty-types.rs:336:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ pattern `&[]` not covered
@@ -391,7 +391,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&[]` not covered
-  --> $DIR/empty-types.rs:351:11
+  --> $DIR/empty-types.rs:350:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ pattern `&[]` not covered
@@ -405,7 +405,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
-  --> $DIR/empty-types.rs:358:11
+  --> $DIR/empty-types.rs:357:11
    |
 LL |     match *slice_never {}
    |           ^^^^^^^^^^^^
@@ -419,7 +419,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:367:9
+  --> $DIR/empty-types.rs:366:9
    |
 LL |         _ => {}
    |         ^------
@@ -430,7 +430,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:370:9
+  --> $DIR/empty-types.rs:369:9
    |
 LL |         [_, _, _] => {}
    |         ^^^^^^^^^------
@@ -441,7 +441,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:373:9
+  --> $DIR/empty-types.rs:372:9
    |
 LL |         [_, ..] => {}
    |         ^^^^^^^------
@@ -452,7 +452,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
-  --> $DIR/empty-types.rs:387:11
+  --> $DIR/empty-types.rs:386:11
    |
 LL |     match array_0_never {}
    |           ^^^^^^^^^^^^^
@@ -466,7 +466,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:394:9
+  --> $DIR/empty-types.rs:393:9
    |
 LL |         [] => {}
    |         -- matches all the relevant values
@@ -474,7 +474,7 @@
    |         ^ no value can reach this
 
 error[E0004]: non-exhaustive patterns: `[]` not covered
-  --> $DIR/empty-types.rs:396:11
+  --> $DIR/empty-types.rs:395:11
    |
 LL |     match array_0_never {
    |           ^^^^^^^^^^^^^ pattern `[]` not covered
@@ -488,7 +488,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:415:9
+  --> $DIR/empty-types.rs:414:9
    |
 LL |         Some(_) => {}
    |         ^^^^^^^------
@@ -499,7 +499,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:420:9
+  --> $DIR/empty-types.rs:419:9
    |
 LL |         Some(_a) => {}
    |         ^^^^^^^^------
@@ -510,7 +510,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:425:9
+  --> $DIR/empty-types.rs:424:9
    |
 LL |         None => {}
    |         ---- matches all the relevant values
@@ -519,7 +519,7 @@
    |         ^ no value can reach this
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:430:9
+  --> $DIR/empty-types.rs:429:9
    |
 LL |         None => {}
    |         ---- matches all the relevant values
@@ -528,7 +528,7 @@
    |         ^^ no value can reach this
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:602:9
+  --> $DIR/empty-types.rs:601:9
    |
 LL |         _ => {}
    |         ^------
@@ -539,7 +539,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:605:9
+  --> $DIR/empty-types.rs:604:9
    |
 LL |         _x => {}
    |         ^^------
@@ -550,7 +550,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:608:9
+  --> $DIR/empty-types.rs:607:9
    |
 LL |         _ if false => {}
    |         ^---------------
@@ -561,7 +561,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:611:9
+  --> $DIR/empty-types.rs:610:9
    |
 LL |         _x if false => {}
    |         ^^---------------
diff --git a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr
index 55d6eb8..046c0d5 100644
--- a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr
+++ b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr
@@ -1,14 +1,5 @@
-warning: the feature `never_patterns` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/empty-types.rs:11:33
-   |
-LL | #![cfg_attr(never_pats, feature(never_patterns))]
-   |                                 ^^^^^^^^^^^^^^
-   |
-   = note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: unreachable pattern
-  --> $DIR/empty-types.rs:48:9
+  --> $DIR/empty-types.rs:47:9
    |
 LL |         _ => {}
    |         ^------
@@ -18,13 +9,13 @@
    |
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
-  --> $DIR/empty-types.rs:14:9
+  --> $DIR/empty-types.rs:13:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:51:9
+  --> $DIR/empty-types.rs:50:9
    |
 LL |         _x => {}
    |         ^^------
@@ -35,7 +26,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `&!` is non-empty
-  --> $DIR/empty-types.rs:55:11
+  --> $DIR/empty-types.rs:54:11
    |
 LL |     match ref_never {}
    |           ^^^^^^^^^
@@ -50,7 +41,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:82:9
+  --> $DIR/empty-types.rs:81:9
    |
 LL |         _ => {}
    |         ^------
@@ -61,7 +52,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
-  --> $DIR/empty-types.rs:86:11
+  --> $DIR/empty-types.rs:85:11
    |
 LL |     match res_u32_never {}
    |           ^^^^^^^^^^^^^ pattern `Ok(_)` not covered
@@ -80,7 +71,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
-  --> $DIR/empty-types.rs:95:11
+  --> $DIR/empty-types.rs:94:11
    |
 LL |     match res_u32_never {
    |           ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered
@@ -98,7 +89,7 @@
    |
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:101:9
+  --> $DIR/empty-types.rs:100:9
    |
 LL |     let Ok(_x) = res_u32_never.as_ref();
    |         ^^^^^^ pattern `Err(_)` not covered
@@ -112,7 +103,7 @@
    |                                         ++++++++++++++++
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:105:9
+  --> $DIR/empty-types.rs:104:9
    |
 LL |     let Ok(_x) = &res_u32_never;
    |         ^^^^^^ pattern `&Err(!)` not covered
@@ -126,7 +117,7 @@
    |                                 ++++++++++++++++
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:131:13
+  --> $DIR/empty-types.rs:130:13
    |
 LL |             _ => {}
    |             ^------
@@ -137,7 +128,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:134:13
+  --> $DIR/empty-types.rs:133:13
    |
 LL |             _ if false => {}
    |             ^---------------
@@ -148,7 +139,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Some(!)` not covered
-  --> $DIR/empty-types.rs:155:15
+  --> $DIR/empty-types.rs:154:15
    |
 LL |         match *ref_opt_void {
    |               ^^^^^^^^^^^^^ pattern `Some(!)` not covered
@@ -167,7 +158,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:198:13
+  --> $DIR/empty-types.rs:197:13
    |
 LL |             _ => {}
    |             ^------
@@ -178,7 +169,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:203:13
+  --> $DIR/empty-types.rs:202:13
    |
 LL |             _ => {}
    |             ^------
@@ -189,7 +180,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:208:13
+  --> $DIR/empty-types.rs:207:13
    |
 LL |             _ => {}
    |             ^------
@@ -200,7 +191,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:213:13
+  --> $DIR/empty-types.rs:212:13
    |
 LL |             _ => {}
    |             ^------
@@ -211,7 +202,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:219:13
+  --> $DIR/empty-types.rs:218:13
    |
 LL |             _ => {}
    |             ^------
@@ -222,7 +213,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:280:9
+  --> $DIR/empty-types.rs:279:9
    |
 LL |         _ => {}
    |         ^------
@@ -233,7 +224,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:296:13
+  --> $DIR/empty-types.rs:295:13
    |
 LL |         let Ok(_) = *ptr_result_never_err;
    |             ^^^^^ pattern `Err(!)` not covered
@@ -247,7 +238,7 @@
    |         ++                                   +++++++++++
 
 error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
-  --> $DIR/empty-types.rs:315:11
+  --> $DIR/empty-types.rs:314:11
    |
 LL |     match *x {}
    |           ^^
@@ -261,7 +252,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
-  --> $DIR/empty-types.rs:317:11
+  --> $DIR/empty-types.rs:316:11
    |
 LL |     match *x {}
    |           ^^
@@ -275,7 +266,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Ok(!)` and `Err(!)` not covered
-  --> $DIR/empty-types.rs:319:11
+  --> $DIR/empty-types.rs:318:11
    |
 LL |     match *x {}
    |           ^^ patterns `Ok(!)` and `Err(!)` not covered
@@ -297,7 +288,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
-  --> $DIR/empty-types.rs:321:11
+  --> $DIR/empty-types.rs:320:11
    |
 LL |     match *x {}
    |           ^^
@@ -311,7 +302,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
-  --> $DIR/empty-types.rs:326:11
+  --> $DIR/empty-types.rs:325:11
    |
 LL |     match slice_never {}
    |           ^^^^^^^^^^^
@@ -325,7 +316,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&[!, ..]` not covered
-  --> $DIR/empty-types.rs:328:11
+  --> $DIR/empty-types.rs:327:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ pattern `&[!, ..]` not covered
@@ -339,7 +330,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&[]`, `&[!]` and `&[!, !]` not covered
-  --> $DIR/empty-types.rs:337:11
+  --> $DIR/empty-types.rs:336:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ patterns `&[]`, `&[!]` and `&[!, !]` not covered
@@ -352,7 +343,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&[]` and `&[!, ..]` not covered
-  --> $DIR/empty-types.rs:351:11
+  --> $DIR/empty-types.rs:350:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ patterns `&[]` and `&[!, ..]` not covered
@@ -366,7 +357,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
-  --> $DIR/empty-types.rs:358:11
+  --> $DIR/empty-types.rs:357:11
    |
 LL |     match *slice_never {}
    |           ^^^^^^^^^^^^
@@ -380,7 +371,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
-  --> $DIR/empty-types.rs:387:11
+  --> $DIR/empty-types.rs:386:11
    |
 LL |     match array_0_never {}
    |           ^^^^^^^^^^^^^
@@ -394,7 +385,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:394:9
+  --> $DIR/empty-types.rs:393:9
    |
 LL |         [] => {}
    |         -- matches all the relevant values
@@ -402,7 +393,7 @@
    |         ^ no value can reach this
 
 error[E0004]: non-exhaustive patterns: `[]` not covered
-  --> $DIR/empty-types.rs:396:11
+  --> $DIR/empty-types.rs:395:11
    |
 LL |     match array_0_never {
    |           ^^^^^^^^^^^^^ pattern `[]` not covered
@@ -416,7 +407,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&Some(!)` not covered
-  --> $DIR/empty-types.rs:450:11
+  --> $DIR/empty-types.rs:449:11
    |
 LL |     match ref_opt_never {
    |           ^^^^^^^^^^^^^ pattern `&Some(!)` not covered
@@ -435,7 +426,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Some(!)` not covered
-  --> $DIR/empty-types.rs:491:11
+  --> $DIR/empty-types.rs:490:11
    |
 LL |     match *ref_opt_never {
    |           ^^^^^^^^^^^^^^ pattern `Some(!)` not covered
@@ -454,7 +445,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Err(!)` not covered
-  --> $DIR/empty-types.rs:539:11
+  --> $DIR/empty-types.rs:538:11
    |
 LL |     match *ref_res_never {
    |           ^^^^^^^^^^^^^^ pattern `Err(!)` not covered
@@ -473,7 +464,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Err(!)` not covered
-  --> $DIR/empty-types.rs:550:11
+  --> $DIR/empty-types.rs:549:11
    |
 LL |     match *ref_res_never {
    |           ^^^^^^^^^^^^^^ pattern `Err(!)` not covered
@@ -492,7 +483,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
-  --> $DIR/empty-types.rs:569:11
+  --> $DIR/empty-types.rs:568:11
    |
 LL |     match *ref_tuple_half_never {}
    |           ^^^^^^^^^^^^^^^^^^^^^
@@ -506,7 +497,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:602:9
+  --> $DIR/empty-types.rs:601:9
    |
 LL |         _ => {}
    |         ^------
@@ -517,7 +508,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:605:9
+  --> $DIR/empty-types.rs:604:9
    |
 LL |         _x => {}
    |         ^^------
@@ -528,7 +519,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:608:9
+  --> $DIR/empty-types.rs:607:9
    |
 LL |         _ if false => {}
    |         ^---------------
@@ -539,7 +530,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:611:9
+  --> $DIR/empty-types.rs:610:9
    |
 LL |         _x if false => {}
    |         ^^---------------
@@ -550,7 +541,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `&!` not covered
-  --> $DIR/empty-types.rs:636:11
+  --> $DIR/empty-types.rs:635:11
    |
 LL |     match ref_never {
    |           ^^^^^^^^^ pattern `&!` not covered
@@ -566,7 +557,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Ok(!)` not covered
-  --> $DIR/empty-types.rs:652:11
+  --> $DIR/empty-types.rs:651:11
    |
 LL |     match *ref_result_never {
    |           ^^^^^^^^^^^^^^^^^ pattern `Ok(!)` not covered
@@ -585,7 +576,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Some(!)` not covered
-  --> $DIR/empty-types.rs:672:11
+  --> $DIR/empty-types.rs:671:11
    |
 LL |     match *x {
    |           ^^ pattern `Some(!)` not covered
@@ -603,7 +594,7 @@
 LL +         Some(!)
    |
 
-error: aborting due to 42 previous errors; 1 warning emitted
+error: aborting due to 42 previous errors
 
 Some errors have detailed explanations: E0004, E0005.
 For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-types.normal.stderr b/tests/ui/pattern/usefulness/empty-types.normal.stderr
index 0ed8c21..ba158c1 100644
--- a/tests/ui/pattern/usefulness/empty-types.normal.stderr
+++ b/tests/ui/pattern/usefulness/empty-types.normal.stderr
@@ -1,5 +1,5 @@
 error: unreachable pattern
-  --> $DIR/empty-types.rs:48:9
+  --> $DIR/empty-types.rs:47:9
    |
 LL |         _ => {}
    |         ^------
@@ -9,13 +9,13 @@
    |
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 note: the lint level is defined here
-  --> $DIR/empty-types.rs:14:9
+  --> $DIR/empty-types.rs:13:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:51:9
+  --> $DIR/empty-types.rs:50:9
    |
 LL |         _x => {}
    |         ^^------
@@ -26,7 +26,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: type `&!` is non-empty
-  --> $DIR/empty-types.rs:55:11
+  --> $DIR/empty-types.rs:54:11
    |
 LL |     match ref_never {}
    |           ^^^^^^^^^
@@ -41,7 +41,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:82:9
+  --> $DIR/empty-types.rs:81:9
    |
 LL |         _ => {}
    |         ^------
@@ -52,7 +52,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
-  --> $DIR/empty-types.rs:86:11
+  --> $DIR/empty-types.rs:85:11
    |
 LL |     match res_u32_never {}
    |           ^^^^^^^^^^^^^ pattern `Ok(_)` not covered
@@ -71,7 +71,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
-  --> $DIR/empty-types.rs:95:11
+  --> $DIR/empty-types.rs:94:11
    |
 LL |     match res_u32_never {
    |           ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered
@@ -89,7 +89,7 @@
    |
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:101:9
+  --> $DIR/empty-types.rs:100:9
    |
 LL |     let Ok(_x) = res_u32_never.as_ref();
    |         ^^^^^^ pattern `Err(_)` not covered
@@ -103,7 +103,7 @@
    |                                         ++++++++++++++++
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:105:9
+  --> $DIR/empty-types.rs:104:9
    |
 LL |     let Ok(_x) = &res_u32_never;
    |         ^^^^^^ pattern `&Err(_)` not covered
@@ -117,7 +117,7 @@
    |                                 ++++++++++++++++
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:131:13
+  --> $DIR/empty-types.rs:130:13
    |
 LL |             _ => {}
    |             ^------
@@ -128,7 +128,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:134:13
+  --> $DIR/empty-types.rs:133:13
    |
 LL |             _ if false => {}
    |             ^---------------
@@ -139,7 +139,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `Some(_)` not covered
-  --> $DIR/empty-types.rs:155:15
+  --> $DIR/empty-types.rs:154:15
    |
 LL |         match *ref_opt_void {
    |               ^^^^^^^^^^^^^ pattern `Some(_)` not covered
@@ -158,7 +158,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:198:13
+  --> $DIR/empty-types.rs:197:13
    |
 LL |             _ => {}
    |             ^------
@@ -169,7 +169,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:203:13
+  --> $DIR/empty-types.rs:202:13
    |
 LL |             _ => {}
    |             ^------
@@ -180,7 +180,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:208:13
+  --> $DIR/empty-types.rs:207:13
    |
 LL |             _ => {}
    |             ^------
@@ -191,7 +191,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:213:13
+  --> $DIR/empty-types.rs:212:13
    |
 LL |             _ => {}
    |             ^------
@@ -202,7 +202,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:219:13
+  --> $DIR/empty-types.rs:218:13
    |
 LL |             _ => {}
    |             ^------
@@ -213,7 +213,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:280:9
+  --> $DIR/empty-types.rs:279:9
    |
 LL |         _ => {}
    |         ^------
@@ -224,7 +224,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:296:13
+  --> $DIR/empty-types.rs:295:13
    |
 LL |         let Ok(_) = *ptr_result_never_err;
    |             ^^^^^ pattern `Err(_)` not covered
@@ -238,7 +238,7 @@
    |         ++                                   +++++++++++
 
 error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
-  --> $DIR/empty-types.rs:315:11
+  --> $DIR/empty-types.rs:314:11
    |
 LL |     match *x {}
    |           ^^
@@ -252,7 +252,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
-  --> $DIR/empty-types.rs:317:11
+  --> $DIR/empty-types.rs:316:11
    |
 LL |     match *x {}
    |           ^^
@@ -266,7 +266,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered
-  --> $DIR/empty-types.rs:319:11
+  --> $DIR/empty-types.rs:318:11
    |
 LL |     match *x {}
    |           ^^ patterns `Ok(_)` and `Err(_)` not covered
@@ -288,7 +288,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
-  --> $DIR/empty-types.rs:321:11
+  --> $DIR/empty-types.rs:320:11
    |
 LL |     match *x {}
    |           ^^
@@ -302,7 +302,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
-  --> $DIR/empty-types.rs:326:11
+  --> $DIR/empty-types.rs:325:11
    |
 LL |     match slice_never {}
    |           ^^^^^^^^^^^
@@ -316,7 +316,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
-  --> $DIR/empty-types.rs:328:11
+  --> $DIR/empty-types.rs:327:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ pattern `&[_, ..]` not covered
@@ -330,7 +330,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&[]`, `&[_]` and `&[_, _]` not covered
-  --> $DIR/empty-types.rs:337:11
+  --> $DIR/empty-types.rs:336:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ patterns `&[]`, `&[_]` and `&[_, _]` not covered
@@ -343,7 +343,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered
-  --> $DIR/empty-types.rs:351:11
+  --> $DIR/empty-types.rs:350:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ patterns `&[]` and `&[_, ..]` not covered
@@ -357,7 +357,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
-  --> $DIR/empty-types.rs:358:11
+  --> $DIR/empty-types.rs:357:11
    |
 LL |     match *slice_never {}
    |           ^^^^^^^^^^^^
@@ -371,7 +371,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
-  --> $DIR/empty-types.rs:387:11
+  --> $DIR/empty-types.rs:386:11
    |
 LL |     match array_0_never {}
    |           ^^^^^^^^^^^^^
@@ -385,7 +385,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:394:9
+  --> $DIR/empty-types.rs:393:9
    |
 LL |         [] => {}
    |         -- matches all the relevant values
@@ -393,7 +393,7 @@
    |         ^ no value can reach this
 
 error[E0004]: non-exhaustive patterns: `[]` not covered
-  --> $DIR/empty-types.rs:396:11
+  --> $DIR/empty-types.rs:395:11
    |
 LL |     match array_0_never {
    |           ^^^^^^^^^^^^^ pattern `[]` not covered
@@ -407,7 +407,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `&Some(_)` not covered
-  --> $DIR/empty-types.rs:450:11
+  --> $DIR/empty-types.rs:449:11
    |
 LL |     match ref_opt_never {
    |           ^^^^^^^^^^^^^ pattern `&Some(_)` not covered
@@ -426,7 +426,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Some(_)` not covered
-  --> $DIR/empty-types.rs:491:11
+  --> $DIR/empty-types.rs:490:11
    |
 LL |     match *ref_opt_never {
    |           ^^^^^^^^^^^^^^ pattern `Some(_)` not covered
@@ -445,7 +445,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Err(_)` not covered
-  --> $DIR/empty-types.rs:539:11
+  --> $DIR/empty-types.rs:538:11
    |
 LL |     match *ref_res_never {
    |           ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
@@ -464,7 +464,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Err(_)` not covered
-  --> $DIR/empty-types.rs:550:11
+  --> $DIR/empty-types.rs:549:11
    |
 LL |     match *ref_res_never {
    |           ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
@@ -483,7 +483,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
-  --> $DIR/empty-types.rs:569:11
+  --> $DIR/empty-types.rs:568:11
    |
 LL |     match *ref_tuple_half_never {}
    |           ^^^^^^^^^^^^^^^^^^^^^
@@ -497,7 +497,7 @@
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:602:9
+  --> $DIR/empty-types.rs:601:9
    |
 LL |         _ => {}
    |         ^------
@@ -508,7 +508,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:605:9
+  --> $DIR/empty-types.rs:604:9
    |
 LL |         _x => {}
    |         ^^------
@@ -519,7 +519,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:608:9
+  --> $DIR/empty-types.rs:607:9
    |
 LL |         _ if false => {}
    |         ^---------------
@@ -530,7 +530,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:611:9
+  --> $DIR/empty-types.rs:610:9
    |
 LL |         _x if false => {}
    |         ^^---------------
@@ -541,7 +541,7 @@
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error[E0004]: non-exhaustive patterns: `&_` not covered
-  --> $DIR/empty-types.rs:636:11
+  --> $DIR/empty-types.rs:635:11
    |
 LL |     match ref_never {
    |           ^^^^^^^^^ pattern `&_` not covered
@@ -557,7 +557,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
-  --> $DIR/empty-types.rs:652:11
+  --> $DIR/empty-types.rs:651:11
    |
 LL |     match *ref_result_never {
    |           ^^^^^^^^^^^^^^^^^ pattern `Ok(_)` not covered
@@ -576,7 +576,7 @@
    |
 
 error[E0004]: non-exhaustive patterns: `Some(_)` not covered
-  --> $DIR/empty-types.rs:672:11
+  --> $DIR/empty-types.rs:671:11
    |
 LL |     match *x {
    |           ^^ pattern `Some(_)` not covered
diff --git a/tests/ui/pattern/usefulness/empty-types.rs b/tests/ui/pattern/usefulness/empty-types.rs
index a503295..d4fdb7c 100644
--- a/tests/ui/pattern/usefulness/empty-types.rs
+++ b/tests/ui/pattern/usefulness/empty-types.rs
@@ -9,7 +9,6 @@
 #![feature(never_type)]
 #![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
 #![cfg_attr(never_pats, feature(never_patterns))]
-//[never_pats]~^ WARN the feature `never_patterns` is incomplete
 #![allow(dead_code, unreachable_code)]
 #![deny(unreachable_patterns)]
 
diff --git a/tests/ui/pin-ergonomics/coerce-non-pointer-pin.rs b/tests/ui/pin-ergonomics/coerce-non-pointer-pin.rs
index a95665f..b5a0c6e 100644
--- a/tests/ui/pin-ergonomics/coerce-non-pointer-pin.rs
+++ b/tests/ui/pin-ergonomics/coerce-non-pointer-pin.rs
@@ -1,7 +1,6 @@
 //@ check-pass
 
 #![feature(pin_ergonomics)]
-//~^ WARN the feature `pin_ergonomics` is incomplete
 
 use std::pin::Pin;
 
diff --git a/tests/ui/pin-ergonomics/coerce-non-pointer-pin.stderr b/tests/ui/pin-ergonomics/coerce-non-pointer-pin.stderr
deleted file mode 100644
index 2deb5b0..0000000
--- a/tests/ui/pin-ergonomics/coerce-non-pointer-pin.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `pin_ergonomics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/coerce-non-pointer-pin.rs:3:12
-   |
-LL | #![feature(pin_ergonomics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #130494 <https://github.com/rust-lang/rust/issues/130494> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/privacy/private-in-public-warn.rs b/tests/ui/privacy/private-in-public-warn.rs
index 6a0ac2b..299fe9a 100644
--- a/tests/ui/privacy/private-in-public-warn.rs
+++ b/tests/ui/privacy/private-in-public-warn.rs
@@ -49,10 +49,10 @@ pub trait Tr3 {
         fn f<T: PrivTr>(arg: T) {}
         //~^ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::f`
         fn g() -> impl PrivTr;
-        //~^ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::g::{anon_assoc#0}`
+        //~^ ERROR private trait `traits::PrivTr` in public interface
         //~| ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::g::{anon_assoc#0}`
         fn h() -> impl PrivTr {}
-        //~^ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::h::{anon_assoc#0}`
+        //~^ ERROR private trait `traits::PrivTr` in public interface
         //~| ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::h::{anon_assoc#0}`
     }
     impl<T: PrivTr> Pub<T> {} //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Pub<T>`
@@ -93,13 +93,13 @@ pub trait Tr4: PubTr<Pub<Priv>> {} //~ ERROR type `generics::Priv` is more priva
 
     pub trait Tr5 {
         fn required() -> impl PrivTr<Priv<()>>;
-        //~^ ERROR trait `generics::PrivTr<generics::Priv<()>>` is more private than the item `Tr5::required::{anon_assoc#0}`
-        //~| ERROR type `generics::Priv<()>` is more private than the item `Tr5::required::{anon_assoc#0}`
+        //~^ ERROR private trait `generics::PrivTr<generics::Priv<()>>` in public interface
+        //~| ERROR private type `generics::Priv<()>` in public interface
         //~| ERROR trait `generics::PrivTr<generics::Priv<()>>` is more private than the item `Tr5::required::{anon_assoc#0}`
         //~| ERROR type `generics::Priv<()>` is more private than the item `Tr5::required::{anon_assoc#0}`
         fn provided() -> impl PrivTr<Priv<()>> {}
-        //~^ ERROR trait `generics::PrivTr<generics::Priv<()>>` is more private than the item `Tr5::provided::{anon_assoc#0}`
-        //~| ERROR type `generics::Priv<()>` is more private than the item `Tr5::provided::{anon_assoc#0}`
+        //~^ ERROR private trait `generics::PrivTr<generics::Priv<()>>` in public interface
+        //~| ERROR private type `generics::Priv<()>` in public interface
         //~| ERROR trait `generics::PrivTr<generics::Priv<()>>` is more private than the item `Tr5::provided::{anon_assoc#0}`
         //~| ERROR type `generics::Priv<()>` is more private than the item `Tr5::provided::{anon_assoc#0}`
     }
diff --git a/tests/ui/privacy/private-in-public-warn.stderr b/tests/ui/privacy/private-in-public-warn.stderr
index 1fd648f..649b117 100644
--- a/tests/ui/privacy/private-in-public-warn.stderr
+++ b/tests/ui/privacy/private-in-public-warn.stderr
@@ -194,17 +194,14 @@
 LL |     trait PrivTr {}
    |     ^^^^^^^^^^^^
 
-error: trait `traits::PrivTr` is more private than the item `traits::Tr3::g::{anon_assoc#0}`
+error[E0446]: private trait `traits::PrivTr` in public interface
   --> $DIR/private-in-public-warn.rs:51:19
    |
-LL |         fn g() -> impl PrivTr;
-   |                   ^^^^^^^^^^^ opaque type `traits::Tr3::g::{anon_assoc#0}` is reachable at visibility `pub(crate)`
-   |
-note: but trait `traits::PrivTr` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:37:5
-   |
 LL |     trait PrivTr {}
-   |     ^^^^^^^^^^^^
+   |     ------------ `traits::PrivTr` declared as private
+...
+LL |         fn g() -> impl PrivTr;
+   |                   ^^^^^^^^^^^ can't leak private trait
 
 error: trait `traits::PrivTr` is more private than the item `traits::Tr3::g::{anon_assoc#0}`
   --> $DIR/private-in-public-warn.rs:51:19
@@ -218,17 +215,14 @@
 LL |     trait PrivTr {}
    |     ^^^^^^^^^^^^
 
-error: trait `traits::PrivTr` is more private than the item `traits::Tr3::h::{anon_assoc#0}`
+error[E0446]: private trait `traits::PrivTr` in public interface
   --> $DIR/private-in-public-warn.rs:54:19
    |
-LL |         fn h() -> impl PrivTr {}
-   |                   ^^^^^^^^^^^ opaque type `traits::Tr3::h::{anon_assoc#0}` is reachable at visibility `pub(crate)`
-   |
-note: but trait `traits::PrivTr` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:37:5
-   |
 LL |     trait PrivTr {}
-   |     ^^^^^^^^^^^^
+   |     ------------ `traits::PrivTr` declared as private
+...
+LL |         fn h() -> impl PrivTr {}
+   |                   ^^^^^^^^^^^ can't leak private trait
 
 error: trait `traits::PrivTr` is more private than the item `traits::Tr3::h::{anon_assoc#0}`
   --> $DIR/private-in-public-warn.rs:54:19
@@ -350,29 +344,23 @@
 LL |     struct Priv<T = u8>(T);
    |     ^^^^^^^^^^^^^^^^^^^
 
-error: trait `generics::PrivTr<generics::Priv<()>>` is more private than the item `Tr5::required::{anon_assoc#0}`
+error[E0446]: private trait `generics::PrivTr<generics::Priv<()>>` in public interface
   --> $DIR/private-in-public-warn.rs:95:26
    |
-LL |         fn required() -> impl PrivTr<Priv<()>>;
-   |                          ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::required::{anon_assoc#0}` is reachable at visibility `pub(crate)`
-   |
-note: but trait `generics::PrivTr<generics::Priv<()>>` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:84:5
-   |
 LL |     trait PrivTr<T> {}
-   |     ^^^^^^^^^^^^^^^
+   |     --------------- `generics::PrivTr<generics::Priv<()>>` declared as private
+...
+LL |         fn required() -> impl PrivTr<Priv<()>>;
+   |                          ^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
-error: type `generics::Priv<()>` is more private than the item `Tr5::required::{anon_assoc#0}`
+error[E0446]: private type `generics::Priv<()>` in public interface
   --> $DIR/private-in-public-warn.rs:95:26
    |
-LL |         fn required() -> impl PrivTr<Priv<()>>;
-   |                          ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::required::{anon_assoc#0}` is reachable at visibility `pub(crate)`
-   |
-note: but type `generics::Priv<()>` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:82:5
-   |
 LL |     struct Priv<T = u8>(T);
-   |     ^^^^^^^^^^^^^^^^^^^
+   |     ------------------- `generics::Priv<()>` declared as private
+...
+LL |         fn required() -> impl PrivTr<Priv<()>>;
+   |                          ^^^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error: trait `generics::PrivTr<generics::Priv<()>>` is more private than the item `Tr5::required::{anon_assoc#0}`
   --> $DIR/private-in-public-warn.rs:95:26
@@ -398,29 +386,23 @@
 LL |     struct Priv<T = u8>(T);
    |     ^^^^^^^^^^^^^^^^^^^
 
-error: trait `generics::PrivTr<generics::Priv<()>>` is more private than the item `Tr5::provided::{anon_assoc#0}`
+error[E0446]: private trait `generics::PrivTr<generics::Priv<()>>` in public interface
   --> $DIR/private-in-public-warn.rs:100:26
    |
-LL |         fn provided() -> impl PrivTr<Priv<()>> {}
-   |                          ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::provided::{anon_assoc#0}` is reachable at visibility `pub(crate)`
-   |
-note: but trait `generics::PrivTr<generics::Priv<()>>` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:84:5
-   |
 LL |     trait PrivTr<T> {}
-   |     ^^^^^^^^^^^^^^^
+   |     --------------- `generics::PrivTr<generics::Priv<()>>` declared as private
+...
+LL |         fn provided() -> impl PrivTr<Priv<()>> {}
+   |                          ^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
-error: type `generics::Priv<()>` is more private than the item `Tr5::provided::{anon_assoc#0}`
+error[E0446]: private type `generics::Priv<()>` in public interface
   --> $DIR/private-in-public-warn.rs:100:26
    |
-LL |         fn provided() -> impl PrivTr<Priv<()>> {}
-   |                          ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::provided::{anon_assoc#0}` is reachable at visibility `pub(crate)`
-   |
-note: but type `generics::Priv<()>` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:82:5
-   |
 LL |     struct Priv<T = u8>(T);
-   |     ^^^^^^^^^^^^^^^^^^^
+   |     ------------------- `generics::Priv<()>` declared as private
+...
+LL |         fn provided() -> impl PrivTr<Priv<()>> {}
+   |                          ^^^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error: trait `generics::PrivTr<generics::Priv<()>>` is more private than the item `Tr5::provided::{anon_assoc#0}`
   --> $DIR/private-in-public-warn.rs:100:26
diff --git a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr
index 0990816..1d7b5ab 100644
--- a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr
+++ b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr
@@ -5,7 +5,7 @@
    | ^^^^^^^^^^^^^^^^^
 LL | #[allow(dead_code)]
 LL | struct Test {}
-   |        ---- the inner attribute doesn't annotate this struct
+   | -------------- the inner attribute doesn't annotate this item
    |
 help: perhaps you meant to use an outer attribute
    |
diff --git a/tests/ui/resolve/auxiliary/open-ns-mod-my_api.rs b/tests/ui/resolve/auxiliary/open-ns-mod-my_api.rs
new file mode 100644
index 0000000..dc8b572
--- /dev/null
+++ b/tests/ui/resolve/auxiliary/open-ns-mod-my_api.rs
@@ -0,0 +1,9 @@
+pub mod utils {
+    pub fn root_helper() {
+        println!("root_helper");
+    }
+}
+
+pub fn root_function() -> String {
+    "my_api root!".to_string()
+}
diff --git a/tests/ui/resolve/auxiliary/open-ns-my_api.rs b/tests/ui/resolve/auxiliary/open-ns-my_api.rs
new file mode 100644
index 0000000..be4bf31
--- /dev/null
+++ b/tests/ui/resolve/auxiliary/open-ns-my_api.rs
@@ -0,0 +1,3 @@
+pub fn root_function() -> String {
+    "my_api root!".to_string()
+}
diff --git a/tests/ui/resolve/auxiliary/open-ns-my_api_core.rs b/tests/ui/resolve/auxiliary/open-ns-my_api_core.rs
new file mode 100644
index 0000000..41418f1
--- /dev/null
+++ b/tests/ui/resolve/auxiliary/open-ns-my_api_core.rs
@@ -0,0 +1,15 @@
+// #![crate_name = "my_api::core"]
+
+pub mod util {
+    pub fn core_mod_fn() -> String {
+        format!("core_fn from my_api::core::util",)
+    }
+}
+
+pub fn core_fn() -> String {
+    format!("core_fn from my_api::core!",)
+}
+
+pub fn core_fn2() -> String {
+    format!("core_fn2 from my_api::core!",)
+}
diff --git a/tests/ui/resolve/auxiliary/open-ns-my_api_utils.rs b/tests/ui/resolve/auxiliary/open-ns-my_api_utils.rs
new file mode 100644
index 0000000..d2af207
--- /dev/null
+++ b/tests/ui/resolve/auxiliary/open-ns-my_api_utils.rs
@@ -0,0 +1,13 @@
+pub mod util {
+    pub fn util_mod_helper() -> String {
+        format!("Helper from my_api::utils::util",)
+    }
+}
+
+pub fn utils_helper() -> String {
+    format!("Helper from my_api::utils!",)
+}
+
+pub fn get_u32() -> u32 {
+    1
+}
diff --git a/tests/ui/resolve/open-ns-1.rs b/tests/ui/resolve/open-ns-1.rs
new file mode 100644
index 0000000..e77ddbe
--- /dev/null
+++ b/tests/ui/resolve/open-ns-1.rs
@@ -0,0 +1,19 @@
+//@ aux-crate:my_api=open-ns-my_api.rs
+//@ aux-crate:my_api::utils=open-ns-my_api_utils.rs
+//@ aux-crate:my_api::core=open-ns-my_api_core.rs
+//@ compile-flags: -Z namespaced-crates
+//@ edition: 2024
+
+use my_api::root_function;
+use my_api::utils::util;
+//~^ ERROR unresolved import `my_api::utils`
+
+fn main() {
+    let _ = root_function();
+    let _ = my_api::root_function();
+    let _ = my_api::utils::utils_helper();
+    //~^ ERROR cannot find `utils` in `my_api` [E0433]
+    let _ = util::util_mod_helper();
+    let _ = my_api::core::core_fn();
+    //~^ ERROR cannot find `core` in `my_api` [E0433]
+}
diff --git a/tests/ui/resolve/open-ns-1.stderr b/tests/ui/resolve/open-ns-1.stderr
new file mode 100644
index 0000000..65b9c6a
--- /dev/null
+++ b/tests/ui/resolve/open-ns-1.stderr
@@ -0,0 +1,22 @@
+error[E0432]: unresolved import `my_api::utils`
+  --> $DIR/open-ns-1.rs:8:13
+   |
+LL | use my_api::utils::util;
+   |             ^^^^^ could not find `utils` in `my_api`
+
+error[E0433]: cannot find `utils` in `my_api`
+  --> $DIR/open-ns-1.rs:14:21
+   |
+LL |     let _ = my_api::utils::utils_helper();
+   |                     ^^^^^ could not find `utils` in `my_api`
+
+error[E0433]: cannot find `core` in `my_api`
+  --> $DIR/open-ns-1.rs:17:21
+   |
+LL |     let _ = my_api::core::core_fn();
+   |                     ^^^^ could not find `core` in `my_api`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0432, E0433.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/tests/ui/resolve/open-ns-10.rs b/tests/ui/resolve/open-ns-10.rs
new file mode 100644
index 0000000..b05a0ab
--- /dev/null
+++ b/tests/ui/resolve/open-ns-10.rs
@@ -0,0 +1,8 @@
+// Tests that namespaced crate names are limited to two segments
+
+//@ aux-crate: nscrate::three::segments=open-ns-my_api_utils.rs
+//@ compile-flags: -Z namespaced-crates
+//@ edition: 2024
+//~? ERROR crate name `nscrate::three::segments` passed to `--extern` can have at most two segments.
+
+fn main() {}
diff --git a/tests/ui/resolve/open-ns-10.stderr b/tests/ui/resolve/open-ns-10.stderr
new file mode 100644
index 0000000..fdef748
--- /dev/null
+++ b/tests/ui/resolve/open-ns-10.stderr
@@ -0,0 +1,2 @@
+error: crate name `nscrate::three::segments` passed to `--extern` can have at most two segments.
+
diff --git a/tests/ui/resolve/open-ns-11.rs b/tests/ui/resolve/open-ns-11.rs
new file mode 100644
index 0000000..90e85a9
--- /dev/null
+++ b/tests/ui/resolve/open-ns-11.rs
@@ -0,0 +1,12 @@
+// Tests that std has higher precedence than an open module with the same name.
+
+//@ aux-crate: std::utils=open-ns-my_api_utils.rs
+//@ compile-flags: -Z namespaced-crates
+//@ edition: 2024
+
+use std::utils::get_u32;
+//~^ ERROR unresolved import `std::utils`
+
+fn main() {
+    let _ = get_u32();
+}
diff --git a/tests/ui/resolve/open-ns-11.stderr b/tests/ui/resolve/open-ns-11.stderr
new file mode 100644
index 0000000..cb073bc
--- /dev/null
+++ b/tests/ui/resolve/open-ns-11.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `std::utils`
+  --> $DIR/open-ns-11.rs:7:10
+   |
+LL | use std::utils::get_u32;
+   |          ^^^^^ could not find `utils` in `std`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/resolve/open-ns-2.rs b/tests/ui/resolve/open-ns-2.rs
new file mode 100644
index 0000000..6165a41
--- /dev/null
+++ b/tests/ui/resolve/open-ns-2.rs
@@ -0,0 +1,18 @@
+//@ aux-crate: my_api=open-ns-my_api.rs
+//@ aux-crate: my_api::utils=open-ns-my_api_utils.rs
+//@ aux-crate: my_api::core=open-ns-my_api_core.rs
+//@ compile-flags: -Z namespaced-crates
+//@ edition: 2024
+
+use my_api::core::{core_fn, core_fn2};
+//~^ ERROR unresolved import `my_api::core` [E0432]
+use my_api::utils::*;
+//~^ ERROR unresolved import `my_api::utils` [E0432]
+use my_api::*;
+
+fn main() {
+    let _ = root_function();
+    let _ = utils_helper();
+    let _ = core_fn();
+    let _ = core_fn2();
+}
diff --git a/tests/ui/resolve/open-ns-2.stderr b/tests/ui/resolve/open-ns-2.stderr
new file mode 100644
index 0000000..0e22123
--- /dev/null
+++ b/tests/ui/resolve/open-ns-2.stderr
@@ -0,0 +1,15 @@
+error[E0432]: unresolved import `my_api::core`
+  --> $DIR/open-ns-2.rs:7:13
+   |
+LL | use my_api::core::{core_fn, core_fn2};
+   |             ^^^^ could not find `core` in `my_api`
+
+error[E0432]: unresolved import `my_api::utils`
+  --> $DIR/open-ns-2.rs:9:13
+   |
+LL | use my_api::utils::*;
+   |             ^^^^^ could not find `utils` in `my_api`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/resolve/open-ns-3.rs b/tests/ui/resolve/open-ns-3.rs
new file mode 100644
index 0000000..9c78999
--- /dev/null
+++ b/tests/ui/resolve/open-ns-3.rs
@@ -0,0 +1,14 @@
+// This test should fail with `utils_helper` being unresolvable in `my_api::utils`.
+// If a crate contains a module that overlaps with a namespaced crate name, then
+// the namespaced crate will not be used in name resolution.
+
+//@ aux-crate: my_api::utils=open-ns-my_api_utils.rs
+//@ aux-crate: my_api=open-ns-mod-my_api.rs
+//@ compile-flags: -Z namespaced-crates
+//@ edition: 2024
+
+fn main() {
+    let _ = my_api::utils::root_helper();
+    let _ = my_api::utils::utils_helper();
+    //~^ ERROR cannot find function `utils_helper` in module `my_api::utils` [E0425]
+}
diff --git a/tests/ui/resolve/open-ns-3.stderr b/tests/ui/resolve/open-ns-3.stderr
new file mode 100644
index 0000000..8ae261a
--- /dev/null
+++ b/tests/ui/resolve/open-ns-3.stderr
@@ -0,0 +1,19 @@
+error[E0425]: cannot find function `utils_helper` in module `my_api::utils`
+  --> $DIR/open-ns-3.rs:12:28
+   |
+LL |     let _ = my_api::utils::utils_helper();
+   |                            ^^^^^^^^^^^^ not found in `my_api::utils`
+   |
+help: consider importing this function
+   |
+LL + use my_api::utils::utils_helper;
+   |
+help: if you import `utils_helper`, refer to it directly
+   |
+LL -     let _ = my_api::utils::utils_helper();
+LL +     let _ = utils_helper();
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/resolve/open-ns-4.rs b/tests/ui/resolve/open-ns-4.rs
new file mode 100644
index 0000000..4db3ad4
--- /dev/null
+++ b/tests/ui/resolve/open-ns-4.rs
@@ -0,0 +1,12 @@
+// This tests that namespaced crates are shadowed.
+
+//@ aux-crate: my_api=open-ns-my_api.rs
+//@ aux-crate: my_api::utils=open-ns-my_api_utils.rs
+//@ compile-flags: -Z namespaced-crates
+//@ edition: 2024
+
+fn main() {
+    let _ = my_api::root_function();
+    let _ = my_api::utils::utils_helper();
+    //~^ ERROR cannot find `utils` in `my_api` [E0433]
+}
diff --git a/tests/ui/resolve/open-ns-4.stderr b/tests/ui/resolve/open-ns-4.stderr
new file mode 100644
index 0000000..2e6872c
--- /dev/null
+++ b/tests/ui/resolve/open-ns-4.stderr
@@ -0,0 +1,9 @@
+error[E0433]: cannot find `utils` in `my_api`
+  --> $DIR/open-ns-4.rs:10:21
+   |
+LL |     let _ = my_api::utils::utils_helper();
+   |                     ^^^^^ could not find `utils` in `my_api`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/resolve/open-ns-5.rs b/tests/ui/resolve/open-ns-5.rs
new file mode 100644
index 0000000..8776da3
--- /dev/null
+++ b/tests/ui/resolve/open-ns-5.rs
@@ -0,0 +1,18 @@
+// Tests that namespaced crate names work inside macros.
+
+//@ aux-crate: my_api::utils=open-ns-my_api_utils.rs
+//@ compile-flags: -Z namespaced-crates
+//@ edition: 2024
+//@ check-pass
+
+macro_rules! import_and_call {
+    ($import_path:path, $fn_name:ident) => {{
+        use $import_path;
+        $fn_name();
+    }};
+}
+
+fn main() {
+    import_and_call!(my_api::utils::utils_helper, utils_helper);
+    let _x = 4 + 5;
+}
diff --git a/tests/ui/resolve/open-ns-6.rs b/tests/ui/resolve/open-ns-6.rs
new file mode 100644
index 0000000..856858a
--- /dev/null
+++ b/tests/ui/resolve/open-ns-6.rs
@@ -0,0 +1,13 @@
+// Tests that open modules are resolvable.
+
+//@ aux-crate: my_api::utils=open-ns-my_api_utils.rs
+//@ compile-flags: -Z namespaced-crates
+//@ edition: 2024
+//@ check-pass
+
+use my_api;
+use my_api::utils::utils_helper;
+
+fn main() {
+    let _ = utils_helper();
+}
diff --git a/tests/ui/resolve/open-ns-7.rs b/tests/ui/resolve/open-ns-7.rs
new file mode 100644
index 0000000..cf16c59
--- /dev/null
+++ b/tests/ui/resolve/open-ns-7.rs
@@ -0,0 +1,14 @@
+// Tests that namespaced crates cannot be resolved if shadowed.
+
+//@ aux-crate: my_api=open-ns-my_api.rs
+//@ aux-crate: my_api::utils=open-ns-my_api_utils.rs
+//@ compile-flags: -Z namespaced-crates
+//@ edition: 2024
+
+use my_api::utils::utils_helper;
+//~^ ERROR unresolved import `my_api::utils` [E0432]
+
+fn main() {
+    let _ = my_api::utils::utils_helper();
+    //~^ ERROR cannot find `utils` in `my_api` [E0433]
+}
diff --git a/tests/ui/resolve/open-ns-7.stderr b/tests/ui/resolve/open-ns-7.stderr
new file mode 100644
index 0000000..b008547
--- /dev/null
+++ b/tests/ui/resolve/open-ns-7.stderr
@@ -0,0 +1,16 @@
+error[E0432]: unresolved import `my_api::utils`
+  --> $DIR/open-ns-7.rs:8:13
+   |
+LL | use my_api::utils::utils_helper;
+   |             ^^^^^ could not find `utils` in `my_api`
+
+error[E0433]: cannot find `utils` in `my_api`
+  --> $DIR/open-ns-7.rs:12:21
+   |
+LL |     let _ = my_api::utils::utils_helper();
+   |                     ^^^^^ could not find `utils` in `my_api`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0432, E0433.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/tests/ui/resolve/open-ns-8.rs b/tests/ui/resolve/open-ns-8.rs
new file mode 100644
index 0000000..46aafb6
--- /dev/null
+++ b/tests/ui/resolve/open-ns-8.rs
@@ -0,0 +1,23 @@
+// Tests that a macro-generated item has higher precendence than a namespaced crate
+//@ aux-crate: my_api::utils=open-ns-my_api_utils.rs
+//@ compile-flags: -Z namespaced-crates
+//@ edition: 2024
+//@ check-pass
+
+macro_rules! define {
+    () => {
+        pub mod my_api {
+            pub mod utils {
+                pub fn get_u32() -> u32 {
+                    2
+                }
+            }
+        }
+    };
+}
+
+fn main() {
+    define!();
+    let res = my_api::utils::get_u32();
+    assert_eq!(res, 2);
+}
diff --git a/tests/ui/resolve/open-ns-9.rs b/tests/ui/resolve/open-ns-9.rs
new file mode 100644
index 0000000..7ded0b3
--- /dev/null
+++ b/tests/ui/resolve/open-ns-9.rs
@@ -0,0 +1,25 @@
+//@ aux-crate: my_api::utils=open-ns-my_api_utils.rs
+//@ compile-flags: -Z namespaced-crates
+//@ edition: 2024
+
+use my_api::utils::get_u32;
+//~^ ERROR `my_api` is ambiguous [E0659]
+
+macro_rules! define {
+    () => {
+        pub mod my_api {
+            pub mod utils {
+                pub fn get_u32() -> u32 {
+                    2
+                }
+            }
+        }
+    };
+}
+
+define!();
+
+fn main() {
+    let val = get_u32();
+    assert_eq!(val, 2);
+}
diff --git a/tests/ui/resolve/open-ns-9.stderr b/tests/ui/resolve/open-ns-9.stderr
new file mode 100644
index 0000000..675f487
--- /dev/null
+++ b/tests/ui/resolve/open-ns-9.stderr
@@ -0,0 +1,27 @@
+error[E0659]: `my_api` is ambiguous
+  --> $DIR/open-ns-9.rs:5:5
+   |
+LL | use my_api::utils::get_u32;
+   |     ^^^^^^ ambiguous name
+   |
+   = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
+   = note: `my_api` could refer to a namespaced crate passed with `--extern`
+note: `my_api` could also refer to the module defined here
+  --> $DIR/open-ns-9.rs:10:9
+   |
+LL | /         pub mod my_api {
+LL | |             pub mod utils {
+LL | |                 pub fn get_u32() -> u32 {
+LL | |                     2
+...  |
+LL | |         }
+   | |_________^
+...
+LL |   define!();
+   |   --------- in this macro invocation
+   = help: use `crate::my_api` to refer to this module unambiguously
+   = note: this error originates in the macro `define` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/never-pattern-is-a-read.rs b/tests/ui/rfcs/rfc-0000-never_patterns/never-pattern-is-a-read.rs
index a66c446..8dff48d 100644
--- a/tests/ui/rfcs/rfc-0000-never_patterns/never-pattern-is-a-read.rs
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/never-pattern-is-a-read.rs
@@ -1,7 +1,6 @@
 // Make sure we consider `!` to be a union read.
 
 #![feature(never_type, never_patterns)]
-//~^ WARN the feature `never_patterns` is incomplete
 
 union U {
     a: !,
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/never-pattern-is-a-read.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/never-pattern-is-a-read.stderr
index d7dc7a4..c415e26 100644
--- a/tests/ui/rfcs/rfc-0000-never_patterns/never-pattern-is-a-read.stderr
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/never-pattern-is-a-read.stderr
@@ -1,20 +1,11 @@
-warning: the feature `never_patterns` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/never-pattern-is-a-read.rs:3:24
-   |
-LL | #![feature(never_type, never_patterns)]
-   |                        ^^^^^^^^^^^^^^
-   |
-   = note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/never-pattern-is-a-read.rs:12:16
+  --> $DIR/never-pattern-is-a-read.rs:11:16
    |
 LL |     let U { a: ! } = u;
    |                ^ access to union field
    |
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/sanitize-attr/invalid-sanitize.rs b/tests/ui/sanitize-attr/invalid-sanitize.rs
index 6846b6f..5574661 100644
--- a/tests/ui/sanitize-attr/invalid-sanitize.rs
+++ b/tests/ui/sanitize-attr/invalid-sanitize.rs
@@ -4,12 +4,12 @@
 #[sanitize(brontosaurus = "off")] //~ ERROR malformed `sanitize` attribute input
 fn main() {}
 
-#[sanitize(address = "off")] //~ ERROR multiple `sanitize` attributes
 #[sanitize(address = "off")]
+#[sanitize(address = "off")] //~ ERROR multiple `sanitize` attributes
 fn multiple_consistent() {}
 
-#[sanitize(address = "on")] //~ ERROR multiple `sanitize` attributes
-#[sanitize(address = "off")]
+#[sanitize(address = "on")]
+#[sanitize(address = "off")] //~ ERROR multiple `sanitize` attributes
 fn multiple_inconsistent() {}
 
 #[sanitize(address = "bogus")] //~ ERROR malformed `sanitize` attribute input
diff --git a/tests/ui/sanitize-attr/invalid-sanitize.stderr b/tests/ui/sanitize-attr/invalid-sanitize.stderr
index 00bb774..699902f 100644
--- a/tests/ui/sanitize-attr/invalid-sanitize.stderr
+++ b/tests/ui/sanitize-attr/invalid-sanitize.stderr
@@ -4,31 +4,31 @@
 LL | #[sanitize(brontosaurus = "off")]
    | ^^^^^^^^^^^------------^^^^^^^^^^
    |            |
-   |            valid arguments are "address", "kernel_address", "cfi", "kcfi", "memory", "memtag", "shadow_call_stack", "thread", "hwaddress" or "realtime"
+   |            valid arguments are "address", "kernel_address", "cfi", "kcfi", "memory", "memtag", "shadow_call_stack", "thread", "hwaddress", "kernel_hwaddress" or "realtime"
 
 error: multiple `sanitize` attributes
-  --> $DIR/invalid-sanitize.rs:7:1
+  --> $DIR/invalid-sanitize.rs:8:1
    |
 LL | #[sanitize(address = "off")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/invalid-sanitize.rs:8:1
+  --> $DIR/invalid-sanitize.rs:7:1
    |
 LL | #[sanitize(address = "off")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: multiple `sanitize` attributes
-  --> $DIR/invalid-sanitize.rs:11:1
-   |
-LL | #[sanitize(address = "on")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
-   |
-note: attribute also specified here
   --> $DIR/invalid-sanitize.rs:12:1
    |
 LL | #[sanitize(address = "off")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+note: attribute also specified here
+  --> $DIR/invalid-sanitize.rs:11:1
+   |
+LL | #[sanitize(address = "on")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0539]: malformed `sanitize` attribute input
   --> $DIR/invalid-sanitize.rs:15:1
diff --git a/tests/ui/sanitizer/cfg-khwasan.rs b/tests/ui/sanitizer/cfg-khwasan.rs
new file mode 100644
index 0000000..27a2f60
--- /dev/null
+++ b/tests/ui/sanitizer/cfg-khwasan.rs
@@ -0,0 +1,20 @@
+// Verifies that when compiling with -Zsanitizer=kernel-hwaddress,
+// the `#[cfg(sanitize = "hwaddress")]` attribute is configured.
+
+//@ add-minicore
+//@ check-pass
+//@ compile-flags: -Zsanitizer=kernel-hwaddress --target aarch64-unknown-none
+//@ needs-llvm-components: aarch64
+//@ ignore-backends: gcc
+
+#![crate_type = "rlib"]
+#![feature(cfg_sanitize, no_core)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+const _: fn() -> () = main;
+
+#[cfg(sanitize = "hwaddress")]
+fn main() {}
diff --git a/tests/ui/sanitizer/incompatible-khwasan.rs b/tests/ui/sanitizer/incompatible-khwasan.rs
new file mode 100644
index 0000000..eb6a5d3
--- /dev/null
+++ b/tests/ui/sanitizer/incompatible-khwasan.rs
@@ -0,0 +1,9 @@
+//@ compile-flags: -Z sanitizer=kernel-hwaddress -Z sanitizer=kernel-address --target aarch64-unknown-none
+//@ needs-llvm-components: aarch64
+//@ ignore-backends: gcc
+
+#![feature(no_core)]
+#![no_core]
+#![no_main]
+
+//~? ERROR `-Zsanitizer=kernel-address` is incompatible with `-Zsanitizer=kernel-hwaddress`
diff --git a/tests/ui/sanitizer/incompatible-khwasan.stderr b/tests/ui/sanitizer/incompatible-khwasan.stderr
new file mode 100644
index 0000000..35246fb
--- /dev/null
+++ b/tests/ui/sanitizer/incompatible-khwasan.stderr
@@ -0,0 +1,4 @@
+error: `-Zsanitizer=kernel-address` is incompatible with `-Zsanitizer=kernel-hwaddress`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/sanitizer/unsupported-target-khwasan.rs b/tests/ui/sanitizer/unsupported-target-khwasan.rs
new file mode 100644
index 0000000..bef6d95
--- /dev/null
+++ b/tests/ui/sanitizer/unsupported-target-khwasan.rs
@@ -0,0 +1,9 @@
+//@ compile-flags: -Z sanitizer=kernel-hwaddress --target x86_64-unknown-none
+//@ needs-llvm-components: x86
+//@ ignore-backends: gcc
+
+#![feature(no_core)]
+#![no_core]
+#![no_main]
+
+//~? ERROR kernel-hwaddress sanitizer is not supported for this target
diff --git a/tests/ui/sanitizer/unsupported-target-khwasan.stderr b/tests/ui/sanitizer/unsupported-target-khwasan.stderr
new file mode 100644
index 0000000..8b122a6
--- /dev/null
+++ b/tests/ui/sanitizer/unsupported-target-khwasan.stderr
@@ -0,0 +1,4 @@
+error: kernel-hwaddress sanitizer is not supported for this target
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/span/issue-43927-non-ADT-derive.stderr b/tests/ui/span/issue-43927-non-ADT-derive.stderr
index 27ed561..8742f34 100644
--- a/tests/ui/span/issue-43927-non-ADT-derive.stderr
+++ b/tests/ui/span/issue-43927-non-ADT-derive.stderr
@@ -5,7 +5,7 @@
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL | struct DerivedOn;
-   |        --------- the inner attribute doesn't annotate this struct
+   | ----------------- the inner attribute doesn't annotate this item
    |
 help: perhaps you meant to use an outer attribute
    |
diff --git a/tests/ui/specialization/assoc-ty-graph-cycle.rs b/tests/ui/specialization/assoc-ty-graph-cycle.rs
index 083b030..16be58e 100644
--- a/tests/ui/specialization/assoc-ty-graph-cycle.rs
+++ b/tests/ui/specialization/assoc-ty-graph-cycle.rs
@@ -2,7 +2,7 @@
 
 // Make sure we don't crash with a cycle error during coherence.
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Trait<T> {
     type Assoc;
diff --git a/tests/ui/specialization/assoc-ty-graph-cycle.stderr b/tests/ui/specialization/assoc-ty-graph-cycle.stderr
deleted file mode 100644
index f5529c2..0000000
--- a/tests/ui/specialization/assoc-ty-graph-cycle.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/assoc-ty-graph-cycle.rs:5:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs
index 1691530..a0073d5 100644
--- a/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs
+++ b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs
@@ -1,5 +1,5 @@
 // regression test for #118987
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Assoc {
     type Output;
diff --git a/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr
index e950268..8ccf0c2 100644
--- a/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr
+++ b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/default-impl-normalization-ambig-2.rs:2:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0277]: the trait bound `u16: Assoc` is not satisfied
   --> $DIR/default-impl-normalization-ambig-2.rs:17:14
    |
@@ -20,6 +10,6 @@
 LL | impl Assoc for u8 {}
    | ^^^^^^^^^^^^^^^^^
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs
index af7cf33..24142a4 100644
--- a/tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs
+++ b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs
@@ -1,5 +1,5 @@
 // regression test for #73299.
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait X {
     type U;
diff --git a/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr
index a15151c..f45c4e5 100644
--- a/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr
+++ b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/default-item-normalization-ambig-1.rs:2:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0119]: conflicting implementations of trait `Y` for type `<() as X>::U`
   --> $DIR/default-item-normalization-ambig-1.rs:20:1
    |
@@ -16,6 +6,6 @@
 LL | impl Y for <i32 as X>::U {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<() as X>::U`
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/specialization/cross-crate-defaults.rs b/tests/ui/specialization/cross-crate-defaults.rs
index c920446..0a2d6e9 100644
--- a/tests/ui/specialization/cross-crate-defaults.rs
+++ b/tests/ui/specialization/cross-crate-defaults.rs
@@ -2,7 +2,7 @@
 
 //@ aux-build:cross_crates_defaults.rs
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 extern crate cross_crates_defaults;
 
diff --git a/tests/ui/specialization/cross-crate-defaults.stderr b/tests/ui/specialization/cross-crate-defaults.stderr
deleted file mode 100644
index ee5c77a..0000000
--- a/tests/ui/specialization/cross-crate-defaults.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/cross-crate-defaults.rs:5:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/ctfe/default-assoc-const.rs b/tests/ui/specialization/ctfe/default-assoc-const.rs
index 083aede..644e56f 100644
--- a/tests/ui/specialization/ctfe/default-assoc-const.rs
+++ b/tests/ui/specialization/ctfe/default-assoc-const.rs
@@ -1,7 +1,6 @@
 //! Regression test for revealing associated types through specialization during const eval.
 //@ check-pass
 #![feature(specialization)]
-//~^ WARNING the feature `specialization` is incomplete and may not be safe to use
 
 trait Foo {
     const ASSOC: usize;
diff --git a/tests/ui/specialization/ctfe/default-assoc-const.stderr b/tests/ui/specialization/ctfe/default-assoc-const.stderr
deleted file mode 100644
index 933b6dc..0000000
--- a/tests/ui/specialization/ctfe/default-assoc-const.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/default-assoc-const.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/ctfe/default-assoc-type.rs b/tests/ui/specialization/ctfe/default-assoc-type.rs
index 0ceba2d..0415cd3 100644
--- a/tests/ui/specialization/ctfe/default-assoc-type.rs
+++ b/tests/ui/specialization/ctfe/default-assoc-type.rs
@@ -2,7 +2,6 @@
 //! even if they rely on specialization.
 //@ check-pass
 #![feature(specialization)]
-//~^ WARNING the feature `specialization` is incomplete and may not be safe to use
 
 trait Foo {
     type Assoc: Trait;
diff --git a/tests/ui/specialization/ctfe/default-assoc-type.stderr b/tests/ui/specialization/ctfe/default-assoc-type.stderr
deleted file mode 100644
index 23fa213..0000000
--- a/tests/ui/specialization/ctfe/default-assoc-type.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/default-assoc-type.rs:4:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/default-associated-type-bound-1.rs b/tests/ui/specialization/default-associated-type-bound-1.rs
index c043114..8e889a6 100644
--- a/tests/ui/specialization/default-associated-type-bound-1.rs
+++ b/tests/ui/specialization/default-associated-type-bound-1.rs
@@ -2,7 +2,6 @@
 // bounds on them.
 
 #![feature(specialization)]
-//~^ WARNING `specialization` is incomplete
 
 trait X {
     type U: Clone;
diff --git a/tests/ui/specialization/default-associated-type-bound-1.stderr b/tests/ui/specialization/default-associated-type-bound-1.stderr
index aa6f695..7040814 100644
--- a/tests/ui/specialization/default-associated-type-bound-1.stderr
+++ b/tests/ui/specialization/default-associated-type-bound-1.stderr
@@ -1,15 +1,5 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/default-associated-type-bound-1.rs:4:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0277]: the trait bound `str: Clone` is not satisfied
-  --> $DIR/default-associated-type-bound-1.rs:18:22
+  --> $DIR/default-associated-type-bound-1.rs:17:22
    |
 LL |     default type U = str;
    |                      ^^^ the trait `Clone` is not implemented for `str`
@@ -17,11 +7,11 @@
 help: the trait `Clone` is implemented for `String`
   --> $SRC_DIR/alloc/src/string.rs:LL:COL
 note: required by a bound in `X::U`
-  --> $DIR/default-associated-type-bound-1.rs:8:13
+  --> $DIR/default-associated-type-bound-1.rs:7:13
    |
 LL |     type U: Clone;
    |             ^^^^^ required by this bound in `X::U`
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/specialization/default-associated-type-bound-2.rs b/tests/ui/specialization/default-associated-type-bound-2.rs
index 0a21b1f..9ea31f3 100644
--- a/tests/ui/specialization/default-associated-type-bound-2.rs
+++ b/tests/ui/specialization/default-associated-type-bound-2.rs
@@ -1,6 +1,5 @@
 // Check that generic predicates are also checked for default associated types.
 #![feature(specialization)]
-//~^ WARNING `specialization` is incomplete
 
 trait X<T> {
     type U: PartialEq<T>;
diff --git a/tests/ui/specialization/default-associated-type-bound-2.stderr b/tests/ui/specialization/default-associated-type-bound-2.stderr
index e02a945..3d3fdba 100644
--- a/tests/ui/specialization/default-associated-type-bound-2.stderr
+++ b/tests/ui/specialization/default-associated-type-bound-2.stderr
@@ -1,22 +1,12 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/default-associated-type-bound-2.rs:2:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0277]: can't compare `&'static B` with `B`
-  --> $DIR/default-associated-type-bound-2.rs:16:22
+  --> $DIR/default-associated-type-bound-2.rs:15:22
    |
 LL |     default type U = &'static B;
    |                      ^^^^^^^^^^ no implementation for `&'static B == B`
    |
    = help: the trait `PartialEq<B>` is not implemented for `&'static B`
 note: required by a bound in `X::U`
-  --> $DIR/default-associated-type-bound-2.rs:6:13
+  --> $DIR/default-associated-type-bound-2.rs:5:13
    |
 LL |     type U: PartialEq<T>;
    |             ^^^^^^^^^^^^ required by this bound in `X::U`
@@ -25,6 +15,6 @@
 LL | impl<B: 'static, T> X<B> for T where &'static B: PartialEq<B> {
    |                                ++++++++++++++++++++++++++++++
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/specialization/default-generic-associated-type-bound.rs b/tests/ui/specialization/default-generic-associated-type-bound.rs
index 31a0685..7cdb6c2 100644
--- a/tests/ui/specialization/default-generic-associated-type-bound.rs
+++ b/tests/ui/specialization/default-generic-associated-type-bound.rs
@@ -1,7 +1,6 @@
 // Check that default generics associated types are validated.
 
 #![feature(specialization)]
-//~^ WARNING `specialization` is incomplete
 
 trait X {
     type U<'a>: PartialEq<&'a Self> where Self: 'a;
diff --git a/tests/ui/specialization/default-generic-associated-type-bound.stderr b/tests/ui/specialization/default-generic-associated-type-bound.stderr
index 57d67ac..7c2bde8 100644
--- a/tests/ui/specialization/default-generic-associated-type-bound.stderr
+++ b/tests/ui/specialization/default-generic-associated-type-bound.stderr
@@ -1,22 +1,12 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/default-generic-associated-type-bound.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0277]: can't compare `T` with `T`
-  --> $DIR/default-generic-associated-type-bound.rs:17:26
+  --> $DIR/default-generic-associated-type-bound.rs:16:26
    |
 LL |     default type U<'a> = &'a T;
    |                          ^^^^^ no implementation for `T == T`
    |
    = note: required for `&'a T` to implement `PartialEq`
 note: required by a bound in `X::U`
-  --> $DIR/default-generic-associated-type-bound.rs:7:17
+  --> $DIR/default-generic-associated-type-bound.rs:6:17
    |
 LL |     type U<'a>: PartialEq<&'a Self> where Self: 'a;
    |                 ^^^^^^^^^^^^^^^^^^^ required by this bound in `X::U`
@@ -25,6 +15,6 @@
 LL | impl<T: 'static + std::cmp::PartialEq> X for T {
    |                 +++++++++++++++++++++
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/specialization/defaultimpl/allowed-cross-crate.rs b/tests/ui/specialization/defaultimpl/allowed-cross-crate.rs
index 697a62c..1a6c383 100644
--- a/tests/ui/specialization/defaultimpl/allowed-cross-crate.rs
+++ b/tests/ui/specialization/defaultimpl/allowed-cross-crate.rs
@@ -5,7 +5,7 @@
 
 //@ aux-build:go_trait.rs
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 extern crate go_trait;
 
diff --git a/tests/ui/specialization/defaultimpl/allowed-cross-crate.stderr b/tests/ui/specialization/defaultimpl/allowed-cross-crate.stderr
deleted file mode 100644
index 02f13d4..0000000
--- a/tests/ui/specialization/defaultimpl/allowed-cross-crate.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/allowed-cross-crate.rs:8:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/defaultimpl/out-of-order.rs b/tests/ui/specialization/defaultimpl/out-of-order.rs
index 2274946..bd3bfe2 100644
--- a/tests/ui/specialization/defaultimpl/out-of-order.rs
+++ b/tests/ui/specialization/defaultimpl/out-of-order.rs
@@ -2,7 +2,7 @@
 
 // Test that you can list the more specific impl before the more general one.
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Foo {
     type Out;
diff --git a/tests/ui/specialization/defaultimpl/out-of-order.stderr b/tests/ui/specialization/defaultimpl/out-of-order.stderr
deleted file mode 100644
index 2cf1ac9..0000000
--- a/tests/ui/specialization/defaultimpl/out-of-order.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/out-of-order.rs:5:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/defaultimpl/overlap-projection.rs b/tests/ui/specialization/defaultimpl/overlap-projection.rs
index da466e6..1af1040 100644
--- a/tests/ui/specialization/defaultimpl/overlap-projection.rs
+++ b/tests/ui/specialization/defaultimpl/overlap-projection.rs
@@ -4,7 +4,7 @@
 // projections involve specialization, so long as the associated type is
 // provided by the most specialized impl.
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Assoc {
     type Output;
diff --git a/tests/ui/specialization/defaultimpl/overlap-projection.stderr b/tests/ui/specialization/defaultimpl/overlap-projection.stderr
deleted file mode 100644
index 75fdfaf..0000000
--- a/tests/ui/specialization/defaultimpl/overlap-projection.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/overlap-projection.rs:7:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/defaultimpl/projection.rs b/tests/ui/specialization/defaultimpl/projection.rs
index 7a77c76..9a2fc8d 100644
--- a/tests/ui/specialization/defaultimpl/projection.rs
+++ b/tests/ui/specialization/defaultimpl/projection.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 #![allow(dead_code)]
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 // Make sure we *can* project non-defaulted associated types
 // cf ui/specialization/specialization-default-projection.rs
diff --git a/tests/ui/specialization/defaultimpl/projection.stderr b/tests/ui/specialization/defaultimpl/projection.stderr
deleted file mode 100644
index cc3fe82..0000000
--- a/tests/ui/specialization/defaultimpl/projection.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/projection.rs:4:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/defaultimpl/specialization-no-default.rs b/tests/ui/specialization/defaultimpl/specialization-no-default.rs
index ddc3233..a3b1d09 100644
--- a/tests/ui/specialization/defaultimpl/specialization-no-default.rs
+++ b/tests/ui/specialization/defaultimpl/specialization-no-default.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 // Check a number of scenarios in which one impl tries to override another,
 // without correctly using `default`.
diff --git a/tests/ui/specialization/defaultimpl/specialization-no-default.stderr b/tests/ui/specialization/defaultimpl/specialization-no-default.stderr
index f9e62a9..60c489d 100644
--- a/tests/ui/specialization/defaultimpl/specialization-no-default.stderr
+++ b/tests/ui/specialization/defaultimpl/specialization-no-default.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-no-default.rs:1:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
   --> $DIR/specialization-no-default.rs:20:5
    |
@@ -63,6 +53,6 @@
    |
    = note: to specialize, `redundant` in the parent `impl` must be marked `default`
 
-error: aborting due to 5 previous errors; 1 warning emitted
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0520`.
diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs
index eb4ecf2..b88bf52 100644
--- a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs
+++ b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs
@@ -3,7 +3,7 @@
 // Tests that we can combine a default impl that supplies one method with a
 // full impl that supplies the other, and they can invoke one another.
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Foo {
     fn foo_one(&self) -> &'static str;
diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr
deleted file mode 100644
index 407c1ab..0000000
--- a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-trait-item-not-implemented-rpass.rs:6:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs
index 3c54144..2a121e6 100644
--- a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs
+++ b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs
@@ -1,6 +1,6 @@
 // Tests that default impls do not have to supply all items but regular impls do.
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Foo {
     fn foo_one(&self) -> &'static str;
diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr
index d3441b0..ae336da 100644
--- a/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr
+++ b/tests/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-trait-item-not-implemented.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0046]: not all trait items implemented, missing: `foo_two`
   --> $DIR/specialization-trait-item-not-implemented.rs:18:1
    |
@@ -17,6 +7,6 @@
 LL | impl Foo for MyStruct {}
    | ^^^^^^^^^^^^^^^^^^^^^ missing `foo_two` in implementation
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
index 344dd7b..2867a00 100644
--- a/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
+++ b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
@@ -2,7 +2,7 @@
 // - default impls do not have to supply all items and
 // - a default impl does not count as an impl (in this case, an incomplete default impl).
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Foo {
     fn foo_one(&self) -> &'static str;
diff --git a/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
index 74f81bb..7cec84b 100644
--- a/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
+++ b/tests/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-trait-not-implemented.rs:5:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0599]: no method named `foo_one` found for struct `MyStruct` in the current scope
   --> $DIR/specialization-trait-not-implemented.rs:22:29
    |
@@ -24,6 +14,6 @@
 LL | trait Foo {
    | ^^^^^^^^^
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/specialization/defaultimpl/specialization-wfcheck.rs b/tests/ui/specialization/defaultimpl/specialization-wfcheck.rs
index eb18d6e..51b63f0 100644
--- a/tests/ui/specialization/defaultimpl/specialization-wfcheck.rs
+++ b/tests/ui/specialization/defaultimpl/specialization-wfcheck.rs
@@ -1,6 +1,6 @@
 // Tests that a default impl still has to have a WF trait ref.
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Foo<'a, T: Eq + 'a> { }
 
diff --git a/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr
index 4a51a7d..aaf0204 100644
--- a/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr
+++ b/tests/ui/specialization/defaultimpl/specialization-wfcheck.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-wfcheck.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0277]: the trait bound `U: Eq` is not satisfied
   --> $DIR/specialization-wfcheck.rs:7:17
    |
@@ -24,6 +14,6 @@
 LL | default impl<U: std::cmp::Eq> Foo<'static, U> for () {}
    |               ++++++++++++++
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/specialization/defaultimpl/validation.rs b/tests/ui/specialization/defaultimpl/validation.rs
index 78f6099..3504d3e 100644
--- a/tests/ui/specialization/defaultimpl/validation.rs
+++ b/tests/ui/specialization/defaultimpl/validation.rs
@@ -1,5 +1,5 @@
 #![feature(negative_impls)]
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 struct S;
 struct Z;
diff --git a/tests/ui/specialization/defaultimpl/validation.stderr b/tests/ui/specialization/defaultimpl/validation.stderr
index a8dfef2..99ae6de 100644
--- a/tests/ui/specialization/defaultimpl/validation.stderr
+++ b/tests/ui/specialization/defaultimpl/validation.stderr
@@ -8,16 +8,6 @@
    |
    = note: only trait implementations may be annotated with `default`
 
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/validation.rs:2:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0367]: `!Send` impl requires `Z: Send` but the struct it is implemented for does not
   --> $DIR/validation.rs:12:1
    |
@@ -58,7 +48,7 @@
 LL | default impl !Tr for S {}
    | ^^^^^^^      ^
 
-error: aborting due to 6 previous errors; 1 warning emitted
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0367, E0750.
 For more information about an error, try `rustc --explain E0367`.
diff --git a/tests/ui/specialization/fuzzed/fuzzing-ice-134905.rs b/tests/ui/specialization/fuzzed/fuzzing-ice-134905.rs
index 559c234..f0a40ef 100644
--- a/tests/ui/specialization/fuzzed/fuzzing-ice-134905.rs
+++ b/tests/ui/specialization/fuzzed/fuzzing-ice-134905.rs
@@ -1,7 +1,7 @@
 // This test previously tried to use a tainted `EvalCtxt` when emitting
 // an error during coherence.
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
+
 trait Iterate<'a> {
     type Ty: Valid;
 }
diff --git a/tests/ui/specialization/fuzzed/fuzzing-ice-134905.stderr b/tests/ui/specialization/fuzzed/fuzzing-ice-134905.stderr
index 611fef1..5db98e7 100644
--- a/tests/ui/specialization/fuzzed/fuzzing-ice-134905.stderr
+++ b/tests/ui/specialization/fuzzed/fuzzing-ice-134905.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/fuzzing-ice-134905.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0277]: the trait bound `(): Valid` is not satisfied
   --> $DIR/fuzzing-ice-134905.rs:12:23
    |
@@ -34,7 +24,7 @@
    = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0210, E0277.
 For more information about an error, try `rustc --explain E0210`.
diff --git a/tests/ui/specialization/issue-35376.rs b/tests/ui/specialization/issue-35376.rs
index 786f229..df4361b 100644
--- a/tests/ui/specialization/issue-35376.rs
+++ b/tests/ui/specialization/issue-35376.rs
@@ -1,6 +1,5 @@
 //@ check-pass
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
 
 fn main() {}
 
diff --git a/tests/ui/specialization/issue-35376.stderr b/tests/ui/specialization/issue-35376.stderr
deleted file mode 100644
index 6c4167f..0000000
--- a/tests/ui/specialization/issue-35376.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-35376.rs:2:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/issue-36804.rs b/tests/ui/specialization/issue-36804.rs
index 5ed0c1a..c0c188f 100644
--- a/tests/ui/specialization/issue-36804.rs
+++ b/tests/ui/specialization/issue-36804.rs
@@ -1,5 +1,5 @@
 //@ check-pass
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 pub struct Cloned<I>(I);
 
diff --git a/tests/ui/specialization/issue-36804.stderr b/tests/ui/specialization/issue-36804.stderr
deleted file mode 100644
index c2113b2..0000000
--- a/tests/ui/specialization/issue-36804.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-36804.rs:2:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/issue-38091-2.rs b/tests/ui/specialization/issue-38091-2.rs
index da27603..bd62a08 100644
--- a/tests/ui/specialization/issue-38091-2.rs
+++ b/tests/ui/specialization/issue-38091-2.rs
@@ -2,7 +2,6 @@
 //~^ ERROR overflow evaluating the requirement `i32: Check`
 
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
 
 trait Iterate<'a> {
     type Ty: Valid;
diff --git a/tests/ui/specialization/issue-38091-2.stderr b/tests/ui/specialization/issue-38091-2.stderr
index 828a8e93..d0a15e6 100644
--- a/tests/ui/specialization/issue-38091-2.stderr
+++ b/tests/ui/specialization/issue-38091-2.stderr
@@ -1,17 +1,7 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-38091-2.rs:4:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0275]: overflow evaluating the requirement `i32: Check`
    |
 note: required for `i32` to implement `Iterate<'_>`
-  --> $DIR/issue-38091-2.rs:11:13
+  --> $DIR/issue-38091-2.rs:10:13
    |
 LL | impl<'a, T> Iterate<'a> for T
    |             ^^^^^^^^^^^     ^
@@ -19,6 +9,6 @@
 LL |     T: Check,
    |        ----- unsatisfied trait bound introduced here
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/specialization/issue-38091.rs b/tests/ui/specialization/issue-38091.rs
index 5b39836..06236aa 100644
--- a/tests/ui/specialization/issue-38091.rs
+++ b/tests/ui/specialization/issue-38091.rs
@@ -1,5 +1,4 @@
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
 
 trait Iterate<'a> {
     type Ty: Valid;
diff --git a/tests/ui/specialization/issue-38091.stderr b/tests/ui/specialization/issue-38091.stderr
index eb64383..91ea3db 100644
--- a/tests/ui/specialization/issue-38091.stderr
+++ b/tests/ui/specialization/issue-38091.stderr
@@ -1,30 +1,20 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-38091.rs:1:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0277]: the trait bound `(): Valid` is not satisfied
-  --> $DIR/issue-38091.rs:12:23
+  --> $DIR/issue-38091.rs:11:23
    |
 LL |     default type Ty = ();
    |                       ^^ the trait `Valid` is not implemented for `()`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/issue-38091.rs:20:1
+  --> $DIR/issue-38091.rs:19:1
    |
 LL | trait Valid {}
    | ^^^^^^^^^^^
 note: required by a bound in `Iterate::Ty`
-  --> $DIR/issue-38091.rs:5:14
+  --> $DIR/issue-38091.rs:4:14
    |
 LL |     type Ty: Valid;
    |              ^^^^^ required by this bound in `Iterate::Ty`
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/specialization/issue-39448.rs b/tests/ui/specialization/issue-39448.rs
index 1c8843d..4d07b11 100644
--- a/tests/ui/specialization/issue-39448.rs
+++ b/tests/ui/specialization/issue-39448.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 // Regression test for a specialization-related ICE (#39448).
 
diff --git a/tests/ui/specialization/issue-39448.stderr b/tests/ui/specialization/issue-39448.stderr
index e2c5f8c..09f2ced 100644
--- a/tests/ui/specialization/issue-39448.stderr
+++ b/tests/ui/specialization/issue-39448.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-39448.rs:1:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0391]: cycle detected when computing whether impls specialize one another
   --> $DIR/issue-39448.rs:24:1
    |
@@ -23,6 +13,6 @@
    | ^^^^^^^^^^^^^^
    = 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; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/specialization/issue-39618.rs b/tests/ui/specialization/issue-39618.rs
index 14a6fcf..d6346a9 100644
--- a/tests/ui/specialization/issue-39618.rs
+++ b/tests/ui/specialization/issue-39618.rs
@@ -2,7 +2,7 @@
 // FIXME(JohnTitor): Centril pointed out this looks suspicions, we should revisit here.
 // More context: https://github.com/rust-lang/rust/pull/69192#discussion_r379846796
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Foo {
     fn foo(&self);
diff --git a/tests/ui/specialization/issue-39618.stderr b/tests/ui/specialization/issue-39618.stderr
index 756162c..ca3c250 100644
--- a/tests/ui/specialization/issue-39618.stderr
+++ b/tests/ui/specialization/issue-39618.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-39618.rs:5:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0391]: cycle detected when computing whether impls specialize one another
   --> $DIR/issue-39618.rs:19:1
    |
@@ -23,6 +13,6 @@
    | ^^^^^^^^^
    = 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; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/specialization/issue-50452-fail.rs b/tests/ui/specialization/issue-50452-fail.rs
index fe21e9b..3096ac3 100644
--- a/tests/ui/specialization/issue-50452-fail.rs
+++ b/tests/ui/specialization/issue-50452-fail.rs
@@ -1,5 +1,4 @@
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
 
 pub trait Foo {
     fn foo();
diff --git a/tests/ui/specialization/issue-50452-fail.stderr b/tests/ui/specialization/issue-50452-fail.stderr
index 7ac4b39..5bca4cc 100644
--- a/tests/ui/specialization/issue-50452-fail.stderr
+++ b/tests/ui/specialization/issue-50452-fail.stderr
@@ -1,15 +1,5 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-50452-fail.rs:1:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/issue-50452-fail.rs:10:5
+  --> $DIR/issue-50452-fail.rs:9:5
    |
 LL |     fn foo() {}
    |     ^^^^^^^^ cannot specialize default item `foo`
@@ -19,6 +9,6 @@
    |
    = note: to specialize, `foo` in the parent `impl` must be marked `default`
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0520`.
diff --git a/tests/ui/specialization/issue-50452.rs b/tests/ui/specialization/issue-50452.rs
index c379825..629ae80 100644
--- a/tests/ui/specialization/issue-50452.rs
+++ b/tests/ui/specialization/issue-50452.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 pub trait Foo {
     fn foo();
diff --git a/tests/ui/specialization/issue-50452.stderr b/tests/ui/specialization/issue-50452.stderr
deleted file mode 100644
index 48cab9d..0000000
--- a/tests/ui/specialization/issue-50452.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-50452.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/issue-52050.rs b/tests/ui/specialization/issue-52050.rs
index 8046587..1e1bfe9 100644
--- a/tests/ui/specialization/issue-52050.rs
+++ b/tests/ui/specialization/issue-52050.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 // Regression test for #52050: when inserting the blanket impl `I`
 // into the tree, we had to replace the child node for `Foo`, which
diff --git a/tests/ui/specialization/issue-52050.stderr b/tests/ui/specialization/issue-52050.stderr
index 3b0cac5..b8368c6 100644
--- a/tests/ui/specialization/issue-52050.stderr
+++ b/tests/ui/specialization/issue-52050.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-52050.rs:1:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0119]: conflicting implementations of trait `IntoPyDictPointer` for type `()`
   --> $DIR/issue-52050.rs:28:1
    |
@@ -21,6 +11,6 @@
    |
    = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/specialization/issue-63716-parse-async.rs b/tests/ui/specialization/issue-63716-parse-async.rs
index 00c0b29..26fd84b 100644
--- a/tests/ui/specialization/issue-63716-parse-async.rs
+++ b/tests/ui/specialization/issue-63716-parse-async.rs
@@ -4,7 +4,7 @@
 //@ check-pass
 //@ edition:2018
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 fn main() {}
 
diff --git a/tests/ui/specialization/issue-63716-parse-async.stderr b/tests/ui/specialization/issue-63716-parse-async.stderr
deleted file mode 100644
index a00572d..0000000
--- a/tests/ui/specialization/issue-63716-parse-async.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-63716-parse-async.rs:7:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/issue-70442.rs b/tests/ui/specialization/issue-70442.rs
index fb82b0d..c2168b3 100644
--- a/tests/ui/specialization/issue-70442.rs
+++ b/tests/ui/specialization/issue-70442.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 //@ check-pass
 
diff --git a/tests/ui/specialization/issue-70442.stderr b/tests/ui/specialization/issue-70442.stderr
deleted file mode 100644
index aa72c32..0000000
--- a/tests/ui/specialization/issue-70442.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-70442.rs:1:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/non-defaulted-item-fail.rs b/tests/ui/specialization/non-defaulted-item-fail.rs
index b7d6ac8..403f718 100644
--- a/tests/ui/specialization/non-defaulted-item-fail.rs
+++ b/tests/ui/specialization/non-defaulted-item-fail.rs
@@ -1,5 +1,4 @@
 #![feature(specialization, associated_type_defaults)]
-//~^ WARN the feature `specialization` is incomplete
 
 // Test that attempting to override a non-default method or one not in the
 // parent impl causes an error.
diff --git a/tests/ui/specialization/non-defaulted-item-fail.stderr b/tests/ui/specialization/non-defaulted-item-fail.stderr
index 9d62a35..739f171 100644
--- a/tests/ui/specialization/non-defaulted-item-fail.stderr
+++ b/tests/ui/specialization/non-defaulted-item-fail.stderr
@@ -1,15 +1,5 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/non-defaulted-item-fail.rs:1:12
-   |
-LL | #![feature(specialization, associated_type_defaults)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:30:5
+  --> $DIR/non-defaulted-item-fail.rs:29:5
    |
 LL | impl<T> Foo for Box<T> {
    | ---------------------- parent `impl` is here
@@ -20,7 +10,7 @@
    = note: to specialize, `Ty` in the parent `impl` must be marked `default`
 
 error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:32:5
+  --> $DIR/non-defaulted-item-fail.rs:31:5
    |
 LL | impl<T> Foo for Box<T> {
    | ---------------------- parent `impl` is here
@@ -31,7 +21,7 @@
    = note: to specialize, `CONST` in the parent `impl` must be marked `default`
 
 error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:34:5
+  --> $DIR/non-defaulted-item-fail.rs:33:5
    |
 LL | impl<T> Foo for Box<T> {
    | ---------------------- parent `impl` is here
@@ -42,7 +32,7 @@
    = note: to specialize, `foo` in the parent `impl` must be marked `default`
 
 error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:46:5
+  --> $DIR/non-defaulted-item-fail.rs:45:5
    |
 LL | impl<T> Foo for Vec<T> {}
    | ---------------------- parent `impl` is here
@@ -53,7 +43,7 @@
    = note: to specialize, `Ty` in the parent `impl` must be marked `default`
 
 error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:48:5
+  --> $DIR/non-defaulted-item-fail.rs:47:5
    |
 LL | impl<T> Foo for Vec<T> {}
    | ---------------------- parent `impl` is here
@@ -64,7 +54,7 @@
    = note: to specialize, `CONST` in the parent `impl` must be marked `default`
 
 error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:50:5
+  --> $DIR/non-defaulted-item-fail.rs:49:5
    |
 LL | impl<T> Foo for Vec<T> {}
    | ---------------------- parent `impl` is here
@@ -74,6 +64,6 @@
    |
    = note: to specialize, `foo` in the parent `impl` must be marked `default`
 
-error: aborting due to 6 previous errors; 1 warning emitted
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0520`.
diff --git a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs
index 578a46c..0cf6092 100644
--- a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs
+++ b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs
@@ -1,8 +1,6 @@
 // Regression test for #140571. The compiler used to ICE
 
 #![feature(min_generic_const_args, specialization)]
-//~^ WARN the feature `specialization` is incomplete
-//~| WARN the feature `min_generic_const_args` is incomplete
 
 pub trait IsVoid {
 
diff --git a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr
index 9361f7d..3ec3e83 100644
--- a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr
+++ b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr
@@ -1,29 +1,11 @@
-warning: the feature `min_generic_const_args` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/overlap-due-to-unsatisfied-const-bound.rs:3:12
-   |
-LL | #![feature(min_generic_const_args, specialization)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/overlap-due-to-unsatisfied-const-bound.rs:3:36
-   |
-LL | #![feature(min_generic_const_args, specialization)]
-   |                                    ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-
 error[E0119]: conflicting implementations of trait `Maybe<()>` for type `()`
-  --> $DIR/overlap-due-to-unsatisfied-const-bound.rs:20:1
+  --> $DIR/overlap-due-to-unsatisfied-const-bound.rs:18:1
    |
 LL | impl<T> Maybe<T> for T {}
    | ---------------------- first implementation here
 LL | impl<T> Maybe<T> for () where T: NotVoid + ?Sized {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
 
-error: aborting due to 1 previous error; 2 warnings emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/specialization/prefer-specializing-impl-over-default.current.stderr b/tests/ui/specialization/prefer-specializing-impl-over-default.current.stderr
deleted file mode 100644
index 7e3df0c..0000000
--- a/tests/ui/specialization/prefer-specializing-impl-over-default.current.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/prefer-specializing-impl-over-default.rs:5:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/prefer-specializing-impl-over-default.next.stderr b/tests/ui/specialization/prefer-specializing-impl-over-default.next.stderr
deleted file mode 100644
index 7e3df0c..0000000
--- a/tests/ui/specialization/prefer-specializing-impl-over-default.next.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/prefer-specializing-impl-over-default.rs:5:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/prefer-specializing-impl-over-default.rs b/tests/ui/specialization/prefer-specializing-impl-over-default.rs
index af6837b..4fa5b3e 100644
--- a/tests/ui/specialization/prefer-specializing-impl-over-default.rs
+++ b/tests/ui/specialization/prefer-specializing-impl-over-default.rs
@@ -3,7 +3,6 @@
 //@[next] compile-flags: -Znext-solver
 //@ check-pass
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
 
 trait WithAssoc: 'static {
     type Assoc;
diff --git a/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.next.stderr b/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.next.stderr
deleted file mode 100644
index 17918a7..0000000
--- a/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.next.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/source-impl-requires-constraining-predicates-ambig.rs:14:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.rs b/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.rs
index 2296cd8..ff56965 100644
--- a/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.rs
+++ b/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.rs
@@ -12,7 +12,6 @@
 // is ambiguous.
 
 #![feature(specialization)]
-//[next]~^ WARN the feature `specialization` is incomplete
 
 trait Spec {
     type Assoc;
diff --git a/tests/ui/specialization/source-impl-requires-constraining-predicates.current.stderr b/tests/ui/specialization/source-impl-requires-constraining-predicates.current.stderr
deleted file mode 100644
index 3442e5b..0000000
--- a/tests/ui/specialization/source-impl-requires-constraining-predicates.current.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/source-impl-requires-constraining-predicates.rs:9:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/source-impl-requires-constraining-predicates.next.stderr b/tests/ui/specialization/source-impl-requires-constraining-predicates.next.stderr
deleted file mode 100644
index 3442e5b..0000000
--- a/tests/ui/specialization/source-impl-requires-constraining-predicates.next.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/source-impl-requires-constraining-predicates.rs:9:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/source-impl-requires-constraining-predicates.rs b/tests/ui/specialization/source-impl-requires-constraining-predicates.rs
index 532fc36..690649d 100644
--- a/tests/ui/specialization/source-impl-requires-constraining-predicates.rs
+++ b/tests/ui/specialization/source-impl-requires-constraining-predicates.rs
@@ -7,7 +7,6 @@
 // `[u32; 0]: IntoIterator<Item = ?U>` predicate to constrain the `?U` impl arg.
 
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
 
 trait Spec {
     type Assoc;
diff --git a/tests/ui/specialization/specialization-allowed-cross-crate.rs b/tests/ui/specialization/specialization-allowed-cross-crate.rs
index 697a62c..1a6c383 100644
--- a/tests/ui/specialization/specialization-allowed-cross-crate.rs
+++ b/tests/ui/specialization/specialization-allowed-cross-crate.rs
@@ -5,7 +5,7 @@
 
 //@ aux-build:go_trait.rs
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 extern crate go_trait;
 
diff --git a/tests/ui/specialization/specialization-allowed-cross-crate.stderr b/tests/ui/specialization/specialization-allowed-cross-crate.stderr
deleted file mode 100644
index 3eea4a5..0000000
--- a/tests/ui/specialization/specialization-allowed-cross-crate.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-allowed-cross-crate.rs:8:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/specialization-assoc-fns.rs b/tests/ui/specialization/specialization-assoc-fns.rs
index 75f0b0d..596b1c9 100644
--- a/tests/ui/specialization/specialization-assoc-fns.rs
+++ b/tests/ui/specialization/specialization-assoc-fns.rs
@@ -2,7 +2,7 @@
 
 // Test that non-method associated functions can be specialized
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Foo {
     fn mk() -> Self;
diff --git a/tests/ui/specialization/specialization-assoc-fns.stderr b/tests/ui/specialization/specialization-assoc-fns.stderr
deleted file mode 100644
index 69f7cec..0000000
--- a/tests/ui/specialization/specialization-assoc-fns.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-assoc-fns.rs:5:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/specialization-basics.rs b/tests/ui/specialization/specialization-basics.rs
index dc320b2..76cba35 100644
--- a/tests/ui/specialization/specialization-basics.rs
+++ b/tests/ui/specialization/specialization-basics.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 // Tests a variety of basic specialization scenarios and method
 // dispatch for them.
diff --git a/tests/ui/specialization/specialization-basics.stderr b/tests/ui/specialization/specialization-basics.stderr
deleted file mode 100644
index 7714d4a..0000000
--- a/tests/ui/specialization/specialization-basics.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-basics.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/specialization-cross-crate.rs b/tests/ui/specialization/specialization-cross-crate.rs
index 6daf48b..3900181 100644
--- a/tests/ui/specialization/specialization-cross-crate.rs
+++ b/tests/ui/specialization/specialization-cross-crate.rs
@@ -2,7 +2,7 @@
 
 //@ aux-build:specialization_cross_crate.rs
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 extern crate specialization_cross_crate;
 
diff --git a/tests/ui/specialization/specialization-cross-crate.stderr b/tests/ui/specialization/specialization-cross-crate.stderr
deleted file mode 100644
index 06818bb..0000000
--- a/tests/ui/specialization/specialization-cross-crate.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-cross-crate.rs:5:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/specialization-default-methods.rs b/tests/ui/specialization/specialization-default-methods.rs
index 7058c03..1699fad 100644
--- a/tests/ui/specialization/specialization-default-methods.rs
+++ b/tests/ui/specialization/specialization-default-methods.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 // Test that default methods are cascaded correctly
 
diff --git a/tests/ui/specialization/specialization-default-methods.stderr b/tests/ui/specialization/specialization-default-methods.stderr
deleted file mode 100644
index d78d30b..0000000
--- a/tests/ui/specialization/specialization-default-methods.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-default-methods.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/specialization-default-projection.current.stderr b/tests/ui/specialization/specialization-default-projection.current.stderr
index b88c1a9..859f83e 100644
--- a/tests/ui/specialization/specialization-default-projection.current.stderr
+++ b/tests/ui/specialization/specialization-default-projection.current.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-default-projection.rs:5:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0308]: mismatched types
   --> $DIR/specialization-default-projection.rs:25:5
    |
@@ -42,6 +32,6 @@
    = note: the associated type `<() as Foo>::Assoc` is defined as `()` in the implementation, but the where-bound `()` shadows this definition
            see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/specialization/specialization-default-projection.next.stderr b/tests/ui/specialization/specialization-default-projection.next.stderr
index a385b16..1a5869f 100644
--- a/tests/ui/specialization/specialization-default-projection.next.stderr
+++ b/tests/ui/specialization/specialization-default-projection.next.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-default-projection.rs:5:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0308]: mismatched types
   --> $DIR/specialization-default-projection.rs:25:5
    |
@@ -42,6 +32,6 @@
    = note: the associated type `<() as Foo>::Assoc` is defined as `()` in the implementation, but the where-bound `()` shadows this definition
            see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/specialization/specialization-default-projection.rs b/tests/ui/specialization/specialization-default-projection.rs
index 4f69ccb..36f20b6 100644
--- a/tests/ui/specialization/specialization-default-projection.rs
+++ b/tests/ui/specialization/specialization-default-projection.rs
@@ -2,7 +2,7 @@
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 // Make sure we can't project defaulted associated types
 
diff --git a/tests/ui/specialization/specialization-default-types.current.stderr b/tests/ui/specialization/specialization-default-types.current.stderr
index 8df170c..2447669 100644
--- a/tests/ui/specialization/specialization-default-types.current.stderr
+++ b/tests/ui/specialization/specialization-default-types.current.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-default-types.rs:9:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0308]: mismatched types
   --> $DIR/specialization-default-types.rs:19:9
    |
@@ -38,6 +28,6 @@
    = note: the associated type `<T as Example>::Output` is defined as `Box<T>` in the implementation, but the where-bound `T` shadows this definition
            see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/specialization/specialization-default-types.next.stderr b/tests/ui/specialization/specialization-default-types.next.stderr
index 4ea9b99..b6f61b4 100644
--- a/tests/ui/specialization/specialization-default-types.next.stderr
+++ b/tests/ui/specialization/specialization-default-types.next.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-default-types.rs:9:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0308]: mismatched types
   --> $DIR/specialization-default-types.rs:19:9
    |
@@ -38,6 +28,6 @@
    = note: the associated type `<T as Example>::Output` is defined as `Box<T>` in the implementation, but the where-bound `T` shadows this definition
            see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/specialization/specialization-default-types.rs b/tests/ui/specialization/specialization-default-types.rs
index 77817ab..ffbe856 100644
--- a/tests/ui/specialization/specialization-default-types.rs
+++ b/tests/ui/specialization/specialization-default-types.rs
@@ -6,7 +6,7 @@
 // associated type in the impl defining it -- otherwise, what happens
 // if it's overridden?
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Example {
     type Output;
diff --git a/tests/ui/specialization/specialization-no-default.rs b/tests/ui/specialization/specialization-no-default.rs
index ae739b2..57346b2 100644
--- a/tests/ui/specialization/specialization-no-default.rs
+++ b/tests/ui/specialization/specialization-no-default.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 // Check a number of scenarios in which one impl tries to override another,
 // without correctly using `default`.
diff --git a/tests/ui/specialization/specialization-no-default.stderr b/tests/ui/specialization/specialization-no-default.stderr
index 695a3f6..07c3529 100644
--- a/tests/ui/specialization/specialization-no-default.stderr
+++ b/tests/ui/specialization/specialization-no-default.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-no-default.rs:1:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
   --> $DIR/specialization-no-default.rs:20:5
    |
@@ -63,6 +53,6 @@
    |
    = note: to specialize, `redundant` in the parent `impl` must be marked `default`
 
-error: aborting due to 5 previous errors; 1 warning emitted
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0520`.
diff --git a/tests/ui/specialization/specialization-on-projection.rs b/tests/ui/specialization/specialization-on-projection.rs
index 876439c..f5fc131 100644
--- a/tests/ui/specialization/specialization-on-projection.rs
+++ b/tests/ui/specialization/specialization-on-projection.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 #![allow(dead_code)]
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 // Ensure that specialization works for impls defined directly on a projection
 
diff --git a/tests/ui/specialization/specialization-on-projection.stderr b/tests/ui/specialization/specialization-on-projection.stderr
deleted file mode 100644
index 00fc7ff..0000000
--- a/tests/ui/specialization/specialization-on-projection.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-on-projection.rs:4:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/specialization-out-of-order.rs b/tests/ui/specialization/specialization-out-of-order.rs
index 4f4d40f..72b2856 100644
--- a/tests/ui/specialization/specialization-out-of-order.rs
+++ b/tests/ui/specialization/specialization-out-of-order.rs
@@ -2,7 +2,7 @@
 
 // Test that you can list the more specific impl before the more general one.
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Foo {
     type Out;
diff --git a/tests/ui/specialization/specialization-out-of-order.stderr b/tests/ui/specialization/specialization-out-of-order.stderr
deleted file mode 100644
index b524e00..0000000
--- a/tests/ui/specialization/specialization-out-of-order.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-out-of-order.rs:5:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/specialization-overlap-negative.rs b/tests/ui/specialization/specialization-overlap-negative.rs
index 244f21c..d5cf51e 100644
--- a/tests/ui/specialization/specialization-overlap-negative.rs
+++ b/tests/ui/specialization/specialization-overlap-negative.rs
@@ -1,5 +1,5 @@
 #![feature(negative_impls)]
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait MyTrait {}
 
diff --git a/tests/ui/specialization/specialization-overlap-negative.stderr b/tests/ui/specialization/specialization-overlap-negative.stderr
index 4874e89..3e1cf40 100644
--- a/tests/ui/specialization/specialization-overlap-negative.stderr
+++ b/tests/ui/specialization/specialization-overlap-negative.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-overlap-negative.rs:2:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0751]: found both positive and negative implementation of trait `Send` for type `TestType<_>`:
   --> $DIR/specialization-overlap-negative.rs:9:1
    |
@@ -28,7 +18,7 @@
 LL | struct TestType<T>(::std::marker::PhantomData<T>);
    | ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0367, E0751.
 For more information about an error, try `rustc --explain E0367`.
diff --git a/tests/ui/specialization/specialization-overlap-projection.rs b/tests/ui/specialization/specialization-overlap-projection.rs
index f7a2a79..504e5d1 100644
--- a/tests/ui/specialization/specialization-overlap-projection.rs
+++ b/tests/ui/specialization/specialization-overlap-projection.rs
@@ -2,7 +2,6 @@
 // projections involve specialization, so long as the associated type is
 // provided by the most specialized impl.
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
 
 trait Assoc {
     type Output;
diff --git a/tests/ui/specialization/specialization-overlap-projection.stderr b/tests/ui/specialization/specialization-overlap-projection.stderr
index 5f3cd9c..270a498 100644
--- a/tests/ui/specialization/specialization-overlap-projection.stderr
+++ b/tests/ui/specialization/specialization-overlap-projection.stderr
@@ -1,15 +1,5 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-overlap-projection.rs:4:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0119]: conflicting implementations of trait `Foo` for type `u32`
-  --> $DIR/specialization-overlap-projection.rs:20:1
+  --> $DIR/specialization-overlap-projection.rs:19:1
    |
 LL | impl Foo for u32 {}
    | ---------------- first implementation here
@@ -17,7 +7,7 @@
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
 
 error[E0119]: conflicting implementations of trait `Foo` for type `u32`
-  --> $DIR/specialization-overlap-projection.rs:22:1
+  --> $DIR/specialization-overlap-projection.rs:21:1
    |
 LL | impl Foo for u32 {}
    | ---------------- first implementation here
@@ -25,6 +15,6 @@
 LL | impl Foo for <u16 as Assoc>::Output {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/specialization/specialization-overlap.rs b/tests/ui/specialization/specialization-overlap.rs
index 6bee22c..c8ef8d6 100644
--- a/tests/ui/specialization/specialization-overlap.rs
+++ b/tests/ui/specialization/specialization-overlap.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Foo { fn foo() {} }
 impl<T: Clone> Foo for T {}
diff --git a/tests/ui/specialization/specialization-overlap.stderr b/tests/ui/specialization/specialization-overlap.stderr
index 098bf4a..ca32c17 100644
--- a/tests/ui/specialization/specialization-overlap.stderr
+++ b/tests/ui/specialization/specialization-overlap.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-overlap.rs:1:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0119]: conflicting implementations of trait `Foo` for type `Vec<_>`
   --> $DIR/specialization-overlap.rs:5:1
    |
@@ -40,6 +30,6 @@
 LL | impl<T: Eq> Qux for T {}
    | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
 
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/specialization/specialization-polarity.rs b/tests/ui/specialization/specialization-polarity.rs
index b3cd825..7427246 100644
--- a/tests/ui/specialization/specialization-polarity.rs
+++ b/tests/ui/specialization/specialization-polarity.rs
@@ -2,7 +2,7 @@
 
 #![feature(auto_traits)]
 #![feature(negative_impls)]
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 auto trait Foo {}
 
diff --git a/tests/ui/specialization/specialization-polarity.stderr b/tests/ui/specialization/specialization-polarity.stderr
index f287018..44e60ca 100644
--- a/tests/ui/specialization/specialization-polarity.stderr
+++ b/tests/ui/specialization/specialization-polarity.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-polarity.rs:5:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0751]: found both positive and negative implementation of trait `Foo` for type `u8`:
   --> $DIR/specialization-polarity.rs:10:1
    |
@@ -24,6 +14,6 @@
 LL | impl Bar for u8 {}
    | ^^^^^^^^^^^^^^^ positive implementation here
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0751`.
diff --git a/tests/ui/specialization/specialization-projection-alias.rs b/tests/ui/specialization/specialization-projection-alias.rs
index 73d6115..92368b1 100644
--- a/tests/ui/specialization/specialization-projection-alias.rs
+++ b/tests/ui/specialization/specialization-projection-alias.rs
@@ -2,7 +2,7 @@
 #![allow(dead_code)]
 #![allow(unused_variables)]
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 // Regression test for ICE when combining specialized associated types and type
 // aliases
diff --git a/tests/ui/specialization/specialization-projection-alias.stderr b/tests/ui/specialization/specialization-projection-alias.stderr
deleted file mode 100644
index c94d9ed..0000000
--- a/tests/ui/specialization/specialization-projection-alias.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-projection-alias.rs:5:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/specialization-projection.rs b/tests/ui/specialization/specialization-projection.rs
index b3efa6f..20105fb 100644
--- a/tests/ui/specialization/specialization-projection.rs
+++ b/tests/ui/specialization/specialization-projection.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 #![allow(dead_code)]
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 // Make sure we *can* project non-defaulted associated types
 // cf ui/specialization/specialization-default-projection.rs
diff --git a/tests/ui/specialization/specialization-projection.stderr b/tests/ui/specialization/specialization-projection.stderr
deleted file mode 100644
index bfc4e0a..0000000
--- a/tests/ui/specialization/specialization-projection.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-projection.rs:4:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/specialization-supertraits.rs b/tests/ui/specialization/specialization-supertraits.rs
index cb4cfef..ffb20fe 100644
--- a/tests/ui/specialization/specialization-supertraits.rs
+++ b/tests/ui/specialization/specialization-supertraits.rs
@@ -1,6 +1,6 @@
 //@ check-pass
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 // Test that you can specialize via an explicit trait hierarchy
 
diff --git a/tests/ui/specialization/specialization-supertraits.stderr b/tests/ui/specialization/specialization-supertraits.stderr
deleted file mode 100644
index e716bc2..0000000
--- a/tests/ui/specialization/specialization-supertraits.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-supertraits.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/specialization-translate-projections-with-lifetimes.rs b/tests/ui/specialization/specialization-translate-projections-with-lifetimes.rs
index 75d9a0d..06f7cdd 100644
--- a/tests/ui/specialization/specialization-translate-projections-with-lifetimes.rs
+++ b/tests/ui/specialization/specialization-translate-projections-with-lifetimes.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Iterator {
     fn next(&self);
diff --git a/tests/ui/specialization/specialization-translate-projections-with-lifetimes.stderr b/tests/ui/specialization/specialization-translate-projections-with-lifetimes.stderr
deleted file mode 100644
index c7aad3c..0000000
--- a/tests/ui/specialization/specialization-translate-projections-with-lifetimes.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-translate-projections-with-lifetimes.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/specialization-translate-projections-with-params.rs b/tests/ui/specialization/specialization-translate-projections-with-params.rs
index 330f518..3b2f2c6 100644
--- a/tests/ui/specialization/specialization-translate-projections-with-params.rs
+++ b/tests/ui/specialization/specialization-translate-projections-with-params.rs
@@ -4,7 +4,7 @@
 // type parameters *and* rely on projections, and the type parameters are input
 // types on the trait.
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Trait<T> {
     fn convert(&self) -> T;
diff --git a/tests/ui/specialization/specialization-translate-projections-with-params.stderr b/tests/ui/specialization/specialization-translate-projections-with-params.stderr
deleted file mode 100644
index 1c4fd93..0000000
--- a/tests/ui/specialization/specialization-translate-projections-with-params.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-translate-projections-with-params.rs:7:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/specialization-translate-projections.rs b/tests/ui/specialization/specialization-translate-projections.rs
index 01c7619..c718f93 100644
--- a/tests/ui/specialization/specialization-translate-projections.rs
+++ b/tests/ui/specialization/specialization-translate-projections.rs
@@ -3,8 +3,7 @@
 // Ensure that provided items are inherited properly even when impls vary in
 // type parameters *and* rely on projections.
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
-
+#![feature(specialization)]
 
 trait Trait {
     fn to_u8(&self) -> u8;
diff --git a/tests/ui/specialization/specialization-translate-projections.stderr b/tests/ui/specialization/specialization-translate-projections.stderr
deleted file mode 100644
index 22bbb12..0000000
--- a/tests/ui/specialization/specialization-translate-projections.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-translate-projections.rs:6:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/trait-specialization-default-methods-55380.rs b/tests/ui/specialization/trait-specialization-default-methods-55380.rs
index b3d79fb..eeafcc1 100644
--- a/tests/ui/specialization/trait-specialization-default-methods-55380.rs
+++ b/tests/ui/specialization/trait-specialization-default-methods-55380.rs
@@ -1,7 +1,6 @@
 // https://github.com/rust-lang/rust/issues/55380
 //@ run-pass
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
 
 pub trait Foo {
     fn abc() -> u32;
diff --git a/tests/ui/specialization/trait-specialization-default-methods-55380.stderr b/tests/ui/specialization/trait-specialization-default-methods-55380.stderr
deleted file mode 100644
index f7c1903..0000000
--- a/tests/ui/specialization/trait-specialization-default-methods-55380.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/trait-specialization-default-methods-55380.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/specialization/transmute-specialization.rs b/tests/ui/specialization/transmute-specialization.rs
index a896c14..da0f12c 100644
--- a/tests/ui/specialization/transmute-specialization.rs
+++ b/tests/ui/specialization/transmute-specialization.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 
 trait Specializable { type Output; }
 
diff --git a/tests/ui/specialization/transmute-specialization.stderr b/tests/ui/specialization/transmute-specialization.stderr
deleted file mode 100644
index b1c26d7..0000000
--- a/tests/ui/specialization/transmute-specialization.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/transmute-specialization.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/statics/mutable_memory_validation.rs b/tests/ui/statics/mutable_memory_validation.rs
index 033c2bc..bdef949 100644
--- a/tests/ui/statics/mutable_memory_validation.rs
+++ b/tests/ui/statics/mutable_memory_validation.rs
@@ -11,7 +11,7 @@ struct Meh {
 }
 
 const MUH: Meh = Meh { x: unsafe { &mut *(&READONLY as *const _ as *mut _) } };
-//~^ ERROR: invalid value at .x.<deref>: encountered `UnsafeCell` in read-only memory
+//~^ ERROR: at .x.<deref>, encountered `UnsafeCell` in read-only memory
 
 static READONLY: i32 = 0;
 
diff --git a/tests/ui/statics/mutable_memory_validation.stderr b/tests/ui/statics/mutable_memory_validation.stderr
index 1d6ba19..297a965 100644
--- a/tests/ui/statics/mutable_memory_validation.stderr
+++ b/tests/ui/statics/mutable_memory_validation.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value at .x.<deref>: encountered `UnsafeCell` in read-only memory
+error[E0080]: constructing invalid value of type Meh: at .x.<deref>, encountered `UnsafeCell` in read-only memory
   --> $DIR/mutable_memory_validation.rs:13:1
    |
 LL | const MUH: Meh = Meh { x: unsafe { &mut *(&READONLY as *const _ as *mut _) } };
diff --git a/tests/ui/issues/issue-3521-2.fixed b/tests/ui/statics/static-cannot-use-local-variable.fixed
similarity index 68%
rename from tests/ui/issues/issue-3521-2.fixed
rename to tests/ui/statics/static-cannot-use-local-variable.fixed
index 2a6e082..df9dfb7 100644
--- a/tests/ui/issues/issue-3521-2.fixed
+++ b/tests/ui/statics/static-cannot-use-local-variable.fixed
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/3521
+//!
 //@ run-rustfix
 fn main() {
     let foo = 100;
diff --git a/tests/ui/issues/issue-3521-2.rs b/tests/ui/statics/static-cannot-use-local-variable.rs
similarity index 69%
rename from tests/ui/issues/issue-3521-2.rs
rename to tests/ui/statics/static-cannot-use-local-variable.rs
index bd82202..0269f9e 100644
--- a/tests/ui/issues/issue-3521-2.rs
+++ b/tests/ui/statics/static-cannot-use-local-variable.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/3521
+//!
 //@ run-rustfix
 fn main() {
     let foo = 100;
diff --git a/tests/ui/issues/issue-3521-2.stderr b/tests/ui/statics/static-cannot-use-local-variable.stderr
similarity index 87%
rename from tests/ui/issues/issue-3521-2.stderr
rename to tests/ui/statics/static-cannot-use-local-variable.stderr
index ecf1ad0..350c384 100644
--- a/tests/ui/issues/issue-3521-2.stderr
+++ b/tests/ui/statics/static-cannot-use-local-variable.stderr
@@ -1,5 +1,5 @@
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/issue-3521-2.rs:5:23
+  --> $DIR/static-cannot-use-local-variable.rs:7:23
    |
 LL |     static y: isize = foo + 1;
    |                       ^^^ non-constant value
diff --git a/tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668-2.fixed b/tests/ui/statics/static-in-fn-cannot-use-param.fixed
similarity index 64%
rename from tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668-2.fixed
rename to tests/ui/statics/static-in-fn-cannot-use-param.fixed
index bf10075..bf6df45 100644
--- a/tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668-2.fixed
+++ b/tests/ui/statics/static-in-fn-cannot-use-param.fixed
@@ -1,6 +1,8 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/3668
+//!
 //@ run-rustfix
 #![allow(unused_variables, dead_code)]
-fn f(x:isize) {
+fn f(x: isize) {
     let child: isize = x + 1;
     //~^ ERROR attempt to use a non-constant value in a constant
 }
diff --git a/tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668-2.rs b/tests/ui/statics/static-in-fn-cannot-use-param.rs
similarity index 64%
rename from tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668-2.rs
rename to tests/ui/statics/static-in-fn-cannot-use-param.rs
index 3751781..bd121a7 100644
--- a/tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668-2.rs
+++ b/tests/ui/statics/static-in-fn-cannot-use-param.rs
@@ -1,6 +1,8 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/3668
+//!
 //@ run-rustfix
 #![allow(unused_variables, dead_code)]
-fn f(x:isize) {
+fn f(x: isize) {
     static child: isize = x + 1;
     //~^ ERROR attempt to use a non-constant value in a constant
 }
diff --git a/tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668-2.stderr b/tests/ui/statics/static-in-fn-cannot-use-param.stderr
similarity index 88%
rename from tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668-2.stderr
rename to tests/ui/statics/static-in-fn-cannot-use-param.stderr
index f87514b..67890de 100644
--- a/tests/ui/issues/issue-3668-non-constant-value-in-constant/issue-3668-2.stderr
+++ b/tests/ui/statics/static-in-fn-cannot-use-param.stderr
@@ -1,5 +1,5 @@
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/issue-3668-2.rs:4:27
+  --> $DIR/static-in-fn-cannot-use-param.rs:6:27
    |
 LL |     static child: isize = x + 1;
    |                           ^ non-constant value
diff --git a/tests/ui/statics/static-in-method-cannot-use-self.rs b/tests/ui/statics/static-in-method-cannot-use-self.rs
new file mode 100644
index 0000000..a5d6fea
--- /dev/null
+++ b/tests/ui/statics/static-in-method-cannot-use-self.rs
@@ -0,0 +1,18 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/3668
+//!
+struct P {
+    child: Option<Box<P>>,
+}
+trait PTrait {
+    fn getChildOption(&self) -> Option<Box<P>>;
+}
+
+impl PTrait for P {
+    fn getChildOption(&self) -> Option<Box<P>> {
+        static childVal: Box<P> = self.child.get();
+        //~^ ERROR attempt to use a non-constant value in a constant
+        panic!();
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/statics/static-in-method-cannot-use-self.stderr b/tests/ui/statics/static-in-method-cannot-use-self.stderr
new file mode 100644
index 0000000..d5db956
--- /dev/null
+++ b/tests/ui/statics/static-in-method-cannot-use-self.stderr
@@ -0,0 +1,15 @@
+error[E0435]: attempt to use a non-constant value in a constant
+  --> $DIR/static-in-method-cannot-use-self.rs:12:35
+   |
+LL |         static childVal: Box<P> = self.child.get();
+   |                                   ^^^^ non-constant value
+   |
+help: consider using `let` instead of `static`
+   |
+LL -         static childVal: Box<P> = self.child.get();
+LL +         let childVal: Box<P> = self.child.get();
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0435`.
diff --git a/tests/ui/statics/static-lazy-init-with-arena-set.rs b/tests/ui/statics/static-lazy-init-with-arena-set.rs
new file mode 100644
index 0000000..009d1d9
--- /dev/null
+++ b/tests/ui/statics/static-lazy-init-with-arena-set.rs
@@ -0,0 +1,46 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/39367
+//!
+//! Tests that lazy static initialization using `Once` and `transmute`
+//! works correctly with a struct that has a default type parameter.
+//@ run-pass
+
+use std::ops::Deref;
+
+struct ArenaSet<U: Deref, V = <U as Deref>::Target>(U, &'static V)
+where
+    V: 'static + ?Sized;
+
+static Z: [u8; 4] = [1, 2, 3, 4];
+
+fn arena() -> &'static ArenaSet<Vec<u8>> {
+    fn __static_ref_initialize() -> ArenaSet<Vec<u8>> {
+        ArenaSet(vec![], &Z)
+    }
+    unsafe {
+        use std::sync::Once;
+        fn require_sync<T: Sync>(_: &T) {}
+        unsafe fn __stability() -> &'static ArenaSet<Vec<u8>> {
+            use std::mem::transmute;
+            static mut DATA: *const ArenaSet<Vec<u8>> = std::ptr::null_mut();
+
+            static mut ONCE: Once = Once::new();
+            ONCE.call_once(|| {
+                //~^ WARN creating a shared reference to mutable static [static_mut_refs]
+                DATA = transmute::<Box<ArenaSet<Vec<u8>>>, *const ArenaSet<Vec<u8>>>(Box::new(
+                    __static_ref_initialize(),
+                ));
+            });
+
+            &*DATA
+        }
+        let static_ref = __stability();
+        require_sync(static_ref);
+        static_ref
+    }
+}
+
+fn main() {
+    let &ArenaSet(ref u, v) = arena();
+    assert!(u.is_empty());
+    assert_eq!(v, Z);
+}
diff --git a/tests/ui/issues/issue-39367.stderr b/tests/ui/statics/static-lazy-init-with-arena-set.stderr
similarity index 72%
rename from tests/ui/issues/issue-39367.stderr
rename to tests/ui/statics/static-lazy-init-with-arena-set.stderr
index e94c961..134129f 100644
--- a/tests/ui/issues/issue-39367.stderr
+++ b/tests/ui/statics/static-lazy-init-with-arena-set.stderr
@@ -1,11 +1,11 @@
 warning: creating a shared reference to mutable static
-  --> $DIR/issue-39367.rs:22:13
+  --> $DIR/static-lazy-init-with-arena-set.rs:27:13
    |
 LL | /             ONCE.call_once(|| {
 LL | |
-LL | |                 DATA = transmute
-LL | |                     ::<Box<ArenaSet<Vec<u8>>>, *const ArenaSet<Vec<u8>>>
-LL | |                     (Box::new(__static_ref_initialize()));
+LL | |                 DATA = transmute::<Box<ArenaSet<Vec<u8>>>, *const ArenaSet<Vec<u8>>>(Box::new(
+LL | |                     __static_ref_initialize(),
+LL | |                 ));
 LL | |             });
    | |______________^ shared reference to mutable static
    |
diff --git a/tests/ui/issues/issue-46604.rs b/tests/ui/statics/static-mut-borrow-of-temporary.rs
similarity index 74%
rename from tests/ui/issues/issue-46604.rs
rename to tests/ui/statics/static-mut-borrow-of-temporary.rs
index e15f0b5..8f679d2 100644
--- a/tests/ui/issues/issue-46604.rs
+++ b/tests/ui/statics/static-mut-borrow-of-temporary.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/46604
+//!
 static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];   //~ ERROR mutable borrows of temporaries
 fn write<T: AsRef<[u8]>>(buffer: T) { }
 
diff --git a/tests/ui/issues/issue-46604.stderr b/tests/ui/statics/static-mut-borrow-of-temporary.stderr
similarity index 90%
rename from tests/ui/issues/issue-46604.stderr
rename to tests/ui/statics/static-mut-borrow-of-temporary.stderr
index 21abc49..a3d0601 100644
--- a/tests/ui/issues/issue-46604.stderr
+++ b/tests/ui/statics/static-mut-borrow-of-temporary.stderr
@@ -1,5 +1,5 @@
 error[E0764]: mutable borrows of temporaries that have their lifetime extended until the end of the program are not allowed
-  --> $DIR/issue-46604.rs:1:25
+  --> $DIR/static-mut-borrow-of-temporary.rs:3:25
    |
 LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];
    |                         ^^^^^^^^^^^^^^^^^^^^ this mutable borrow refers to such a temporary
@@ -9,7 +9,7 @@
    = help: if you really want global mutable state, try replacing the temporary by an interior mutable `static` or a `static mut`
 
 error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item
-  --> $DIR/issue-46604.rs:6:5
+  --> $DIR/static-mut-borrow-of-temporary.rs:8:5
    |
 LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];
    | --------------------- this `static` cannot be written to
diff --git a/tests/ui/issues/issue-29821.rs b/tests/ui/statics/static-mut-with-assoc-type-field.rs
similarity index 67%
rename from tests/ui/issues/issue-29821.rs
rename to tests/ui/statics/static-mut-with-assoc-type-field.rs
index 5080093..347c50e 100644
--- a/tests/ui/issues/issue-29821.rs
+++ b/tests/ui/statics/static-mut-with-assoc-type-field.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/29821
+//!
 //@ build-pass
 
 pub trait Foo {
@@ -5,7 +7,7 @@ pub trait Foo {
 }
 
 pub struct Bar<F: Foo> {
-    id: F::FooAssoc
+    id: F::FooAssoc,
 }
 
 pub struct Baz;
diff --git a/tests/ui/statics/static-ref-deref-non-const-trait.rs b/tests/ui/statics/static-ref-deref-non-const-trait.rs
new file mode 100644
index 0000000..6d7b375
--- /dev/null
+++ b/tests/ui/statics/static-ref-deref-non-const-trait.rs
@@ -0,0 +1,19 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/25901
+//!
+struct A;
+struct B;
+
+static S: &'static B = &A;
+//~^ ERROR the trait bound `A: const Deref` is not satisfied
+
+use std::ops::Deref;
+
+impl Deref for A {
+    type Target = B;
+    fn deref(&self) -> &B {
+        static B_: B = B;
+        &B_
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/issues/issue-25901.stderr b/tests/ui/statics/static-ref-deref-non-const-trait.stderr
similarity index 86%
rename from tests/ui/issues/issue-25901.stderr
rename to tests/ui/statics/static-ref-deref-non-const-trait.stderr
index 9b65366..88ddffe 100644
--- a/tests/ui/issues/issue-25901.stderr
+++ b/tests/ui/statics/static-ref-deref-non-const-trait.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `A: const Deref` is not satisfied
-  --> $DIR/issue-25901.rs:4:24
+  --> $DIR/static-ref-deref-non-const-trait.rs:6:24
    |
 LL | static S: &'static B = &A;
    |                        ^^
diff --git a/tests/ui/statics/uninhabited-static.stderr b/tests/ui/statics/uninhabited-static.stderr
index 47627845..8087108 100644
--- a/tests/ui/statics/uninhabited-static.stderr
+++ b/tests/ui/statics/uninhabited-static.stderr
@@ -43,13 +43,13 @@
    = 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 #74840 <https://github.com/rust-lang/rust/issues/74840>
 
-error[E0080]: constructing invalid value: encountered a value of uninhabited type `Void`
+error[E0080]: constructing invalid value of type Void: encountered a value of uninhabited type `Void`
   --> $DIR/uninhabited-static.rs:12:31
    |
 LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `VOID2` failed here
 
-error[E0080]: constructing invalid value: encountered a value of uninhabited type `Void`
+error[E0080]: constructing invalid value of type Void: encountered a value of uninhabited type `Void`
   --> $DIR/uninhabited-static.rs:15:32
    |
 LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
diff --git a/tests/ui/str/str-idx.stderr b/tests/ui/str/str-idx.stderr
index 97a083b..84f698a6 100644
--- a/tests/ui/str/str-idx.stderr
+++ b/tests/ui/str/str-idx.stderr
@@ -7,13 +7,13 @@
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
    = note: required for `str` to implement `Index<{integer}>`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
@@ -27,13 +27,13 @@
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
 note: required by a bound in `core::str::<impl str>::get`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
@@ -48,13 +48,13 @@
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
 note: required by a bound in `core::str::<impl str>::get_unchecked`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr
index c9bd66d..87b7891 100644
--- a/tests/ui/str/str-mut-idx.stderr
+++ b/tests/ui/str/str-mut-idx.stderr
@@ -31,13 +31,13 @@
    |       ^^^^^^ string indices are ranges of `usize`
    |
    = help: the trait `SliceIndex<str>` is not implemented for `usize`
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
    = note: required for `str` to implement `Index<usize>`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
@@ -51,13 +51,13 @@
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
 note: required by a bound in `core::str::<impl str>::get_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
@@ -72,13 +72,13 @@
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
 note: required by a bound in `core::str::<impl str>::get_unchecked_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
 
diff --git a/tests/ui/structs-enums/auxiliary/cci_class.rs b/tests/ui/structs-enums/auxiliary/cci_class.rs
deleted file mode 100644
index de2945d..0000000
--- a/tests/ui/structs-enums/auxiliary/cci_class.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-pub mod kitties {
-    pub struct cat {
-      meows : usize,
-
-      pub how_hungry : isize,
-    }
-
-    pub fn cat(in_x : usize, in_y : isize) -> cat  {
-        cat {
-            meows: in_x,
-            how_hungry: in_y
-        }
-    }
-}
diff --git a/tests/ui/structs-enums/auxiliary/cci_class_2.rs b/tests/ui/structs-enums/auxiliary/cci_class_2.rs
deleted file mode 100644
index c3de315..0000000
--- a/tests/ui/structs-enums/auxiliary/cci_class_2.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-pub mod kitties {
-    pub struct cat {
-      meows : usize,
-
-      pub how_hungry : isize,
-
-    }
-
-    impl cat {
-        pub fn speak(&self) {}
-    }
-
-    pub fn cat(in_x : usize, in_y : isize) -> cat {
-        cat {
-            meows: in_x,
-            how_hungry: in_y
-        }
-    }
-}
diff --git a/tests/ui/structs-enums/auxiliary/cci_class_3.rs b/tests/ui/structs-enums/auxiliary/cci_class_3.rs
deleted file mode 100644
index fb7fad0..0000000
--- a/tests/ui/structs-enums/auxiliary/cci_class_3.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-pub mod kitties {
-    pub struct cat {
-        meows : usize,
-
-        pub how_hungry : isize,
-    }
-
-    impl cat {
-        pub fn speak(&mut self) { self.meows += 1; }
-        pub fn meow_count(&mut self) -> usize { self.meows }
-    }
-
-    pub fn cat(in_x : usize, in_y : isize) -> cat {
-        cat {
-            meows: in_x,
-            how_hungry: in_y
-        }
-    }
-}
diff --git a/tests/ui/structs-enums/auxiliary/cci_class_4.rs b/tests/ui/structs-enums/auxiliary/cci_class_4.rs
index 85aa3bc..fff7b78 100644
--- a/tests/ui/structs-enums/auxiliary/cci_class_4.rs
+++ b/tests/ui/structs-enums/auxiliary/cci_class_4.rs
@@ -1,41 +1,54 @@
-pub mod kitties {
-    pub struct cat {
-        meows : usize,
+use std::fmt;
 
-        pub how_hungry : isize,
-        pub name : String,
+#[derive(Clone)]
+pub struct Cat {
+    meows: usize,
+
+    pub how_hungry: isize,
+    pub name: String,
+}
+
+impl Cat {
+    pub fn speak(&mut self) {
+        self.meow();
     }
 
-    impl cat {
-        pub fn speak(&mut self) { self.meow(); }
-
-        pub fn eat(&mut self) -> bool {
-            if self.how_hungry > 0 {
-                println!("OM NOM NOM");
-                self.how_hungry -= 2;
-                return true;
-            } else {
-                println!("Not hungry!");
-                return false;
-            }
+    pub fn eat(&mut self) -> bool {
+        if self.how_hungry > 0 {
+            println!("OM NOM NOM");
+            self.how_hungry -= 2;
+            return true;
+        } else {
+            println!("Not hungry!");
+            return false;
         }
     }
 
-    impl cat {
-        pub fn meow(&mut self) {
-            println!("Meow");
-            self.meows += 1;
-            if self.meows % 5 == 0 {
-                self.how_hungry += 1;
-            }
+    pub fn noop(&self) {}
+}
+
+impl Cat {
+    pub fn meow(&mut self) {
+        println!("Meow");
+        self.meows += 1;
+        if self.meows % 5 == 0 {
+            self.how_hungry += 1;
         }
     }
+    pub fn meow_count(&self) -> usize {
+        self.meows
+    }
+}
 
-    pub fn cat(in_x : usize, in_y : isize, in_name: String) -> cat {
-        cat {
-            meows: in_x,
-            how_hungry: in_y,
-            name: in_name
-        }
+pub fn cat(in_x: usize, in_y: isize, in_name: String) -> Cat {
+    Cat { meows: in_x, how_hungry: in_y, name: in_name }
+}
+pub fn cat_unnamed(in_x: usize, in_y: isize) -> Cat {
+    Cat { meows: in_x, how_hungry: in_y, name: String::new() }
+}
+
+impl fmt::Display for Cat {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.name)
     }
 }
diff --git a/tests/ui/structs-enums/auxiliary/cci_class_cast.rs b/tests/ui/structs-enums/auxiliary/cci_class_cast.rs
deleted file mode 100644
index dfc3c56..0000000
--- a/tests/ui/structs-enums/auxiliary/cci_class_cast.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-pub mod kitty {
-    use std::fmt;
-
-    pub struct cat {
-      meows : usize,
-      pub how_hungry : isize,
-      pub name : String,
-    }
-
-    impl fmt::Display for cat {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-            write!(f, "{}", self.name)
-        }
-    }
-
-    impl cat {
-        fn meow(&mut self) {
-            println!("Meow");
-            self.meows += 1;
-            if self.meows % 5 == 0 {
-                self.how_hungry += 1;
-            }
-        }
-
-    }
-
-    impl cat {
-        pub fn speak(&mut self) { self.meow(); }
-
-        pub fn eat(&mut self) -> bool {
-            if self.how_hungry > 0 {
-                println!("OM NOM NOM");
-                self.how_hungry -= 2;
-                return true;
-            }
-            else {
-                println!("Not hungry!");
-                return false;
-            }
-        }
-    }
-
-    pub fn cat(in_x : usize, in_y : isize, in_name: String) -> cat {
-        cat {
-            meows: in_x,
-            how_hungry: in_y,
-            name: in_name
-        }
-    }
-}
diff --git a/tests/ui/structs-enums/auxiliary/cci_class_trait.rs b/tests/ui/structs-enums/auxiliary/cci_class_trait.rs
deleted file mode 100644
index 2d02b59..0000000
--- a/tests/ui/structs-enums/auxiliary/cci_class_trait.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-pub mod animals {
-    pub trait noisy {
-        fn speak(&mut self);
-    }
-}
diff --git a/tests/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs b/tests/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs
deleted file mode 100644
index d4caa19..0000000
--- a/tests/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-//@ run-pass
-//@ aux-build:cci_class_cast.rs
-
-extern crate cci_class_cast;
-
-use cci_class_cast::kitty::cat;
-
-fn print_out(thing: Box<dyn ToString>, expected: String) {
-  let actual = (*thing).to_string();
-  println!("{}", actual);
-  assert_eq!(actual.to_string(), expected);
-}
-
-pub fn main() {
-  let nyan: Box<dyn ToString> = Box::new(cat(0, 2, "nyan".to_string())) as Box<dyn ToString>;
-  print_out(nyan, "nyan".to_string());
-}
diff --git a/tests/ui/structs-enums/class-cast-to-trait-multiple-types.rs b/tests/ui/structs-enums/class-cast-to-trait-multiple-types.rs
deleted file mode 100644
index 658e9d2..0000000
--- a/tests/ui/structs-enums/class-cast-to-trait-multiple-types.rs
+++ /dev/null
@@ -1,94 +0,0 @@
-//@ run-pass
-#![allow(non_camel_case_types)]
-#![allow(dead_code)]
-
-trait noisy {
-  fn speak(&mut self) -> isize;
-}
-
-struct dog {
-  barks: usize,
-
-  volume: isize,
-}
-
-impl dog {
-    fn bark(&mut self) -> isize {
-      println!("Woof {} {}", self.barks, self.volume);
-      self.barks += 1_usize;
-      if self.barks % 3_usize == 0_usize {
-          self.volume += 1;
-      }
-      if self.barks % 10_usize == 0_usize {
-          self.volume -= 2;
-      }
-      println!("Grrr {} {}", self.barks, self.volume);
-      self.volume
-    }
-}
-
-impl noisy for dog {
-    fn speak(&mut self) -> isize {
-        self.bark()
-    }
-}
-
-fn dog() -> dog {
-    dog {
-        volume: 0,
-        barks: 0_usize
-    }
-}
-
-#[derive(Clone)]
-struct cat {
-  meows: usize,
-
-  how_hungry: isize,
-  name: String,
-}
-
-impl noisy for cat {
-    fn speak(&mut self) -> isize {
-        self.meow() as isize
-    }
-}
-
-impl cat {
-    pub fn meow_count(&self) -> usize {
-        self.meows
-    }
-}
-
-impl cat {
-    fn meow(&mut self) -> usize {
-        println!("Meow");
-        self.meows += 1_usize;
-        if self.meows % 5_usize == 0_usize {
-            self.how_hungry += 1;
-        }
-        self.meows
-    }
-}
-
-fn cat(in_x: usize, in_y: isize, in_name: String) -> cat {
-    cat {
-        meows: in_x,
-        how_hungry: in_y,
-        name: in_name
-    }
-}
-
-
-fn annoy_neighbors(critter: &mut dyn noisy) {
-    for _i in 0_usize..10 { critter.speak(); }
-}
-
-pub fn main() {
-  let mut nyan: cat = cat(0_usize, 2, "nyan".to_string());
-  let mut whitefang: dog = dog();
-  annoy_neighbors(&mut nyan);
-  annoy_neighbors(&mut whitefang);
-  assert_eq!(nyan.meow_count(), 10_usize);
-  assert_eq!(whitefang.volume, 1);
-}
diff --git a/tests/ui/structs-enums/class-cast-to-trait.rs b/tests/ui/structs-enums/class-cast-to-trait.rs
deleted file mode 100644
index bbbde34..0000000
--- a/tests/ui/structs-enums/class-cast-to-trait.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-//@ run-pass
-#![allow(dead_code)]
-#![allow(unused_mut)]
-#![allow(non_camel_case_types)]
-
-//@ ignore-freebsd FIXME fails on BSD
-
-
-trait noisy {
-  fn speak(&mut self);
-}
-
-struct cat {
-  meows: usize,
-  how_hungry: isize,
-  name: String,
-}
-
-impl noisy for cat {
-  fn speak(&mut self) { self.meow(); }
-}
-
-impl cat {
-  pub fn eat(&mut self) -> bool {
-    if self.how_hungry > 0 {
-        println!("OM NOM NOM");
-        self.how_hungry -= 2;
-        return true;
-    }
-    else {
-        println!("Not hungry!");
-        return false;
-    }
-  }
-}
-
-impl cat {
-    fn meow(&mut self) {
-      println!("Meow");
-      self.meows += 1;
-      if self.meows % 5 == 0 {
-          self.how_hungry += 1;
-      }
-    }
-}
-
-fn cat(in_x : usize, in_y : isize, in_name: String) -> cat {
-    cat {
-        meows: in_x,
-        how_hungry: in_y,
-        name: in_name
-    }
-}
-
-
-pub fn main() {
-    let mut nyan = cat(0, 2, "nyan".to_string());
-    let mut nyan: &mut dyn noisy = &mut nyan;
-    nyan.speak();
-}
diff --git a/tests/ui/structs-enums/class-dtor.rs b/tests/ui/structs-enums/class-dtor.rs
index a08f0f0..b791182 100644
--- a/tests/ui/structs-enums/class-dtor.rs
+++ b/tests/ui/structs-enums/class-dtor.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(dead_code)]
 #![allow(non_camel_case_types)]
 
diff --git a/tests/ui/structs-enums/class-exports.rs b/tests/ui/structs-enums/class-exports.rs
deleted file mode 100644
index 53d0e3d..0000000
--- a/tests/ui/structs-enums/class-exports.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-//@ run-pass
-#![allow(dead_code)]
-#![allow(non_camel_case_types)]
-
-/* Test that exporting a class also exports its
-   public fields and methods */
-
-use kitty::cat;
-
-mod kitty {
-    pub struct cat {
-        meows: usize,
-        name: String,
-    }
-
-    impl cat {
-        pub fn get_name(&self) -> String { self.name.clone() }
-    }
-
-    pub fn cat(in_name: String) -> cat {
-        cat {
-            name: in_name,
-            meows: 0
-        }
-    }
-}
-
-pub fn main() {
-  assert_eq!(cat("Spreckles".to_string()).get_name(),
-                 "Spreckles".to_string());
-}
diff --git a/tests/ui/structs-enums/class-implement-trait-cross-crate.rs b/tests/ui/structs-enums/class-implement-trait-cross-crate.rs
deleted file mode 100644
index 781ac6ad..0000000
--- a/tests/ui/structs-enums/class-implement-trait-cross-crate.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-//@ run-pass
-#![allow(dead_code)]
-#![allow(non_camel_case_types)]
-
-//@ aux-build:cci_class_trait.rs
-extern crate cci_class_trait;
-use cci_class_trait::animals::noisy;
-
-struct cat {
-  meows: usize,
-
-  how_hungry : isize,
-  name : String,
-}
-
-impl cat {
-    pub fn eat(&mut self) -> bool {
-        if self.how_hungry > 0 {
-            println!("OM NOM NOM");
-            self.how_hungry -= 2;
-            return true;
-        }
-        else {
-            println!("Not hungry!");
-            return false;
-        }
-    }
-}
-
-impl noisy for cat {
-    fn speak(&mut self) { self.meow(); }
-}
-
-impl cat {
-    fn meow(&mut self) {
-        println!("Meow");
-        self.meows += 1_usize;
-        if self.meows % 5_usize == 0_usize {
-            self.how_hungry += 1;
-        }
-    }
-}
-
-fn cat(in_x : usize, in_y : isize, in_name: String) -> cat {
-    cat {
-        meows: in_x,
-        how_hungry: in_y,
-        name: in_name
-    }
-}
-
-
-pub fn main() {
-  let mut nyan = cat(0_usize, 2, "nyan".to_string());
-  nyan.eat();
-  assert!(!nyan.eat());
-  for _ in 1_usize..10_usize { nyan.speak(); };
-  assert!(nyan.eat());
-}
diff --git a/tests/ui/structs-enums/class-implement-traits.rs b/tests/ui/structs-enums/class-implement-traits.rs
deleted file mode 100644
index 3a514ff..0000000
--- a/tests/ui/structs-enums/class-implement-traits.rs
+++ /dev/null
@@ -1,64 +0,0 @@
-//@ run-pass
-#![allow(non_camel_case_types)]
-#![allow(dead_code)]
-
-trait noisy {
-    fn speak(&mut self);
-}
-
-#[derive(Clone)]
-struct cat {
-    meows : usize,
-
-    how_hungry : isize,
-    name : String,
-}
-
-impl cat {
-    fn meow(&mut self) {
-        println!("Meow");
-        self.meows += 1_usize;
-        if self.meows % 5_usize == 0_usize {
-            self.how_hungry += 1;
-        }
-    }
-}
-
-impl cat {
-    pub fn eat(&mut self) -> bool {
-        if self.how_hungry > 0 {
-            println!("OM NOM NOM");
-            self.how_hungry -= 2;
-            return true;
-        } else {
-            println!("Not hungry!");
-            return false;
-        }
-    }
-}
-
-impl noisy for cat {
-    fn speak(&mut self) { self.meow(); }
-}
-
-fn cat(in_x : usize, in_y : isize, in_name: String) -> cat {
-    cat {
-        meows: in_x,
-        how_hungry: in_y,
-        name: in_name.clone()
-    }
-}
-
-
-fn make_speak<C:noisy>(mut c: C) {
-    c.speak();
-}
-
-pub fn main() {
-    let mut nyan = cat(0_usize, 2, "nyan".to_string());
-    nyan.eat();
-    assert!(!nyan.eat());
-    for _ in 1_usize..10_usize {
-        make_speak(nyan.clone());
-    }
-}
diff --git a/tests/ui/structs-enums/class-method-cross-crate.rs b/tests/ui/structs-enums/class-method-cross-crate.rs
deleted file mode 100644
index f73999a..0000000
--- a/tests/ui/structs-enums/class-method-cross-crate.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-//@ run-pass
-//@ aux-build:cci_class_2.rs
-
-extern crate cci_class_2;
-use cci_class_2::kitties::cat;
-
-pub fn main() {
-  let nyan : cat = cat(52, 99);
-  let kitty = cat(1000, 2);
-  assert_eq!(nyan.how_hungry, 99);
-  assert_eq!(kitty.how_hungry, 2);
-  nyan.speak();
-}
diff --git a/tests/ui/structs-enums/class-methods-cross-crate.rs b/tests/ui/structs-enums/class-methods-cross-crate.rs
deleted file mode 100644
index b2c4824..0000000
--- a/tests/ui/structs-enums/class-methods-cross-crate.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//@ run-pass
-//@ aux-build:cci_class_3.rs
-
-extern crate cci_class_3;
-use cci_class_3::kitties::cat;
-
-pub fn main() {
-    let mut nyan : cat = cat(52, 99);
-    let kitty = cat(1000, 2);
-    assert_eq!(nyan.how_hungry, 99);
-    assert_eq!(kitty.how_hungry, 2);
-    nyan.speak();
-    assert_eq!(nyan.meow_count(), 53);
-}
diff --git a/tests/ui/structs-enums/class-methods.rs b/tests/ui/structs-enums/class-methods.rs
deleted file mode 100644
index b0dbbbe..0000000
--- a/tests/ui/structs-enums/class-methods.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-//@ run-pass
-#![allow(non_camel_case_types)]
-
-
-struct cat {
-  meows : usize,
-
-  how_hungry : isize,
-}
-
-impl cat {
-    pub fn speak(&mut self) { self.meows += 1; }
-    pub fn meow_count(&mut self) -> usize { self.meows }
-}
-
-fn cat(in_x: usize, in_y: isize) -> cat {
-    cat {
-        meows: in_x,
-        how_hungry: in_y
-    }
-}
-
-pub fn main() {
-  let mut nyan: cat = cat(52, 99);
-  let kitty = cat(1000, 2);
-  assert_eq!(nyan.how_hungry, 99);
-  assert_eq!(kitty.how_hungry, 2);
-  nyan.speak();
-  assert_eq!(nyan.meow_count(), 53);
-}
diff --git a/tests/ui/structs-enums/class-separate-impl.rs b/tests/ui/structs-enums/class-separate-impl.rs
deleted file mode 100644
index 2768e28..0000000
--- a/tests/ui/structs-enums/class-separate-impl.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-//@ run-pass
-#![allow(dead_code)]
-#![allow(non_camel_case_types)]
-
-use std::fmt;
-
-struct cat {
-    meows : usize,
-
-    how_hungry : isize,
-    name : String,
-}
-
-impl cat {
-    pub fn speak(&mut self) { self.meow(); }
-
-    pub fn eat(&mut self) -> bool {
-        if self.how_hungry > 0 {
-            println!("OM NOM NOM");
-            self.how_hungry -= 2;
-            return true;
-        }
-        else {
-            println!("Not hungry!");
-            return false;
-        }
-    }
-}
-
-impl cat {
-    fn meow(&mut self) {
-        println!("Meow");
-        self.meows += 1;
-        if self.meows % 5 == 0 {
-            self.how_hungry += 1;
-        }
-    }
-}
-
-fn cat(in_x : usize, in_y : isize, in_name: String) -> cat {
-    cat {
-        meows: in_x,
-        how_hungry: in_y,
-        name: in_name
-    }
-}
-
-impl fmt::Display for cat {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self.name)
-    }
-}
-
-fn print_out(thing: Box<dyn ToString>, expected: String) {
-  let actual = (*thing).to_string();
-  println!("{}", actual);
-  assert_eq!(actual.to_string(), expected);
-}
-
-pub fn main() {
-  let nyan: Box<dyn ToString> = Box::new(cat(0, 2, "nyan".to_string())) as Box<dyn ToString>;
-  print_out(nyan, "nyan".to_string());
-}
diff --git a/tests/ui/structs-enums/class-str-field.rs b/tests/ui/structs-enums/class-str-field.rs
deleted file mode 100644
index 24f648a..0000000
--- a/tests/ui/structs-enums/class-str-field.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//@ run-pass
-#![allow(dead_code)]
-#![allow(non_camel_case_types)]
-
-
-struct cat {
-
-  name : String,
-
-}
-
-fn cat(in_name: String) -> cat {
-    cat {
-        name: in_name
-    }
-}
-
-pub fn main() {
-  let _nyan = cat("nyan".to_string());
-}
diff --git a/tests/ui/structs-enums/classes-cross-crate.rs b/tests/ui/structs-enums/classes-cross-crate.rs
index 6fb5f2e..85454bb 100644
--- a/tests/ui/structs-enums/classes-cross-crate.rs
+++ b/tests/ui/structs-enums/classes-cross-crate.rs
@@ -2,12 +2,118 @@
 //@ aux-build:cci_class_4.rs
 
 extern crate cci_class_4;
-use cci_class_4::kitties::cat;
+use cci_class_4::*;
 
-pub fn main() {
+fn simple_cross_crate() {
+    let nyan: Cat = cat_unnamed(52, 99);
+    let kitty = cat_unnamed(1000, 2);
+    assert_eq!(nyan.how_hungry, 99);
+    assert_eq!(kitty.how_hungry, 2);
+    nyan.noop();
+}
+
+fn cross_crate() {
     let mut nyan = cat(0_usize, 2, "nyan".to_string());
     nyan.eat();
     assert!(!nyan.eat());
-    for _ in 1_usize..10_usize { nyan.speak(); };
+    for _ in 1_usize..10_usize {
+        nyan.speak();
+    }
     assert!(nyan.eat());
 }
+
+fn print_out(thing: Box<dyn ToString>, expected: String) {
+    let actual = (*thing).to_string();
+    println!("{}", actual);
+    assert_eq!(actual.to_string(), expected);
+}
+
+fn separate_impl() {
+    let nyan: Box<dyn ToString> = Box::new(cat(0, 2, "nyan".to_string())) as Box<dyn ToString>;
+    print_out(nyan, "nyan".to_string());
+}
+
+trait Noisy {
+    fn speak(&mut self) -> isize;
+}
+
+impl Noisy for Cat {
+    fn speak(&mut self) -> isize {
+        self.meow();
+        0
+    }
+}
+
+fn make_speak<C: Noisy>(mut c: C) {
+    c.speak();
+}
+
+fn implement_traits() {
+    let mut nyan = cat(0_usize, 2, "nyan".to_string());
+    nyan.eat();
+    assert!(!nyan.eat());
+    for _ in 1_usize..10_usize {
+        make_speak(nyan.clone());
+    }
+}
+
+struct Dog {
+    barks: usize,
+
+    volume: isize,
+}
+
+impl Dog {
+    fn bark(&mut self) -> isize {
+        println!("Woof {} {}", self.barks, self.volume);
+        self.barks += 1_usize;
+        if self.barks % 3_usize == 0_usize {
+            self.volume += 1;
+        }
+        if self.barks % 10_usize == 0_usize {
+            self.volume -= 2;
+        }
+        println!("Grrr {} {}", self.barks, self.volume);
+        self.volume
+    }
+}
+
+impl Noisy for Dog {
+    fn speak(&mut self) -> isize {
+        self.bark()
+    }
+}
+
+fn dog() -> Dog {
+    Dog { volume: 0, barks: 0_usize }
+}
+
+fn annoy_neighbors(critter: &mut dyn Noisy) {
+    for _i in 0_usize..10 {
+        critter.speak();
+    }
+}
+
+fn multiple_types() {
+    let mut nyan: Cat = cat(0_usize, 2, "nyan".to_string());
+    let mut whitefang: Dog = dog();
+    annoy_neighbors(&mut nyan);
+    annoy_neighbors(&mut whitefang);
+    assert_eq!(nyan.meow_count(), 10_usize);
+    assert_eq!(whitefang.volume, 1);
+}
+
+fn cast_to_trait() {
+    let mut nyan = cat(0, 2, "nyan".to_string());
+    let nyan: &mut dyn Noisy = &mut nyan;
+    nyan.speak();
+}
+
+fn main() {
+    simple_cross_crate();
+    cross_crate();
+    separate_impl();
+    implement_traits();
+    multiple_types();
+    cast_to_trait();
+}
diff --git a/tests/ui/structs-enums/classes-self-referential.rs b/tests/ui/structs-enums/classes-self-referential.rs
index f819e55..40c51a1 100644
--- a/tests/ui/structs-enums/classes-self-referential.rs
+++ b/tests/ui/structs-enums/classes-self-referential.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(dead_code)]
 #![allow(non_camel_case_types)]
 
diff --git a/tests/ui/structs-enums/classes-simple-cross-crate.rs b/tests/ui/structs-enums/classes-simple-cross-crate.rs
deleted file mode 100644
index 1548f76..0000000
--- a/tests/ui/structs-enums/classes-simple-cross-crate.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//@ run-pass
-//@ aux-build:cci_class.rs
-
-extern crate cci_class;
-use cci_class::kitties::cat;
-
-pub fn main() {
-  let nyan : cat = cat(52, 99);
-  let kitty = cat(1000, 2);
-  assert_eq!(nyan.how_hungry, 99);
-  assert_eq!(kitty.how_hungry, 2);
-}
diff --git a/tests/ui/structs-enums/classes-simple-method.rs b/tests/ui/structs-enums/classes-simple-method.rs
deleted file mode 100644
index 562fd59..0000000
--- a/tests/ui/structs-enums/classes-simple-method.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-//@ run-pass
-#![allow(dead_code)]
-#![allow(non_camel_case_types)]
-
-struct cat {
-    meows : usize,
-
-    how_hungry : isize,
-}
-
-impl cat {
-    pub fn speak(&mut self) {}
-}
-
-fn cat(in_x : usize, in_y : isize) -> cat {
-    cat {
-        meows: in_x,
-        how_hungry: in_y
-    }
-}
-
-pub fn main() {
-  let mut nyan : cat = cat(52, 99);
-  let kitty = cat(1000, 2);
-  assert_eq!(nyan.how_hungry, 99);
-  assert_eq!(kitty.how_hungry, 2);
-  nyan.speak();
-}
diff --git a/tests/ui/structs-enums/classes-simple.rs b/tests/ui/structs-enums/classes-simple.rs
deleted file mode 100644
index d870a31..0000000
--- a/tests/ui/structs-enums/classes-simple.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-//@ run-pass
-#![allow(dead_code)]
-#![allow(non_camel_case_types)]
-
-struct cat {
-    meows : usize,
-
-    how_hungry : isize,
-}
-
-fn cat(in_x : usize, in_y : isize) -> cat {
-    cat {
-        meows: in_x,
-        how_hungry: in_y
-    }
-}
-
-pub fn main() {
-  let nyan : cat = cat(52, 99);
-  let kitty = cat(1000, 2);
-  assert_eq!(nyan.how_hungry, 99);
-  assert_eq!(kitty.how_hungry, 2);
-}
diff --git a/tests/ui/structs-enums/classes.rs b/tests/ui/structs-enums/classes.rs
deleted file mode 100644
index 05976f6..0000000
--- a/tests/ui/structs-enums/classes.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-//@ run-pass
-#![allow(dead_code)]
-#![allow(non_camel_case_types)]
-
-struct cat {
-    meows : usize,
-
-    how_hungry : isize,
-    name : String,
-}
-
-impl cat {
-    pub fn speak(&mut self) { self.meow(); }
-
-    pub fn eat(&mut self) -> bool {
-        if self.how_hungry > 0 {
-            println!("OM NOM NOM");
-            self.how_hungry -= 2;
-            return true;
-        } else {
-            println!("Not hungry!");
-            return false;
-        }
-    }
-}
-
-impl cat {
-    fn meow(&mut self) {
-        println!("Meow");
-        self.meows += 1_usize;
-        if self.meows % 5_usize == 0_usize {
-            self.how_hungry += 1;
-        }
-    }
-}
-
-fn cat(in_x : usize, in_y : isize, in_name: String) -> cat {
-    cat {
-        meows: in_x,
-        how_hungry: in_y,
-        name: in_name
-    }
-}
-
-pub fn main() {
-  let mut nyan = cat(0_usize, 2, "nyan".to_string());
-  nyan.eat();
-  assert!(!nyan.eat());
-  for _ in 1_usize..10_usize { nyan.speak(); };
-  assert!(nyan.eat());
-}
diff --git a/tests/ui/structs-enums/enum-discrim-range-overflow.rs b/tests/ui/structs-enums/enum-discrim-range-overflow.rs
index 91be801..641e556 100644
--- a/tests/ui/structs-enums/enum-discrim-range-overflow.rs
+++ b/tests/ui/structs-enums/enum-discrim-range-overflow.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(overflowing_literals)]
 
 
diff --git a/tests/ui/structs-enums/export-abstract-tag.rs b/tests/ui/structs-enums/export-abstract-tag.rs
deleted file mode 100644
index e6d3598..0000000
--- a/tests/ui/structs-enums/export-abstract-tag.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//@ run-pass
-#![allow(non_camel_case_types)]
-
-// We can export tags without exporting the variants to create a simple
-// sort of ADT.
-
-
-mod foo {
-    pub enum t { t1, }
-
-    pub fn f() -> t { return t::t1; }
-}
-
-pub fn main() { let _v: foo::t = foo::f(); }
diff --git a/tests/ui/structs-enums/export-tag-variant.rs b/tests/ui/structs-enums/export-tag-variant.rs
deleted file mode 100644
index c6216d1..0000000
--- a/tests/ui/structs-enums/export-tag-variant.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//@ run-pass
-#![allow(non_camel_case_types)]
-
-mod foo {
-    pub enum t { t1, }
-}
-
-pub fn main() { let _v = foo::t::t1; }
diff --git a/tests/ui/structs-enums/foreign-struct.rs b/tests/ui/structs-enums/foreign-struct.rs
index f339c19..b710d83 100644
--- a/tests/ui/structs-enums/foreign-struct.rs
+++ b/tests/ui/structs-enums/foreign-struct.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(dead_code)]
 #![allow(non_camel_case_types)]
 
diff --git a/tests/ui/structs-enums/namespaced-enum-emulate-flat.rs b/tests/ui/structs-enums/namespaced-enum-emulate-flat.rs
index 774cfa1..2bc23d9 100644
--- a/tests/ui/structs-enums/namespaced-enum-emulate-flat.rs
+++ b/tests/ui/structs-enums/namespaced-enum-emulate-flat.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(dead_code)]
 
 pub use Foo::*;
diff --git a/tests/ui/structs-enums/namespaced-enum-glob-import.rs b/tests/ui/structs-enums/namespaced-enum-glob-import.rs
index 82742a9..52bfa9d 100644
--- a/tests/ui/structs-enums/namespaced-enum-glob-import.rs
+++ b/tests/ui/structs-enums/namespaced-enum-glob-import.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(dead_code)]
 
 mod m2 {
diff --git a/tests/ui/structs-enums/namespaced-enums.rs b/tests/ui/structs-enums/namespaced-enums.rs
index 3e2e0b5..f3f1a3b 100644
--- a/tests/ui/structs-enums/namespaced-enums.rs
+++ b/tests/ui/structs-enums/namespaced-enums.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(dead_code)]
 
 enum Foo {
diff --git a/tests/ui/structs-enums/nested-enum-same-names.rs b/tests/ui/structs-enums/nested-enum-same-names.rs
index 5ff730a..1d3fab4 100644
--- a/tests/ui/structs-enums/nested-enum-same-names.rs
+++ b/tests/ui/structs-enums/nested-enum-same-names.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(dead_code)]
 
 /*
diff --git a/tests/ui/structs-enums/newtype-struct-with-dtor.rs b/tests/ui/structs-enums/newtype-struct-with-dtor.rs
index 35476c5..c0d0493 100644
--- a/tests/ui/structs-enums/newtype-struct-with-dtor.rs
+++ b/tests/ui/structs-enums/newtype-struct-with-dtor.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(unused_unsafe)]
 #![allow(unused_variables)]
 
diff --git a/tests/ui/structs-enums/rec-auto.rs b/tests/ui/structs-enums/rec-auto.rs
deleted file mode 100644
index bf2e37a..0000000
--- a/tests/ui/structs-enums/rec-auto.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//@ run-pass
-
-
-
-
-// Issue #50.
-
-struct X { foo: String, bar: String }
-
-pub fn main() {
-    let x = X {foo: "hello".to_string(), bar: "world".to_string()};
-    println!("{}", x.foo.clone());
-    println!("{}", x.bar.clone());
-}
diff --git a/tests/ui/structs-enums/simple-generic-tag.rs b/tests/ui/structs-enums/simple-generic-tag.rs
index b78505e..dbb5d70 100644
--- a/tests/ui/structs-enums/simple-generic-tag.rs
+++ b/tests/ui/structs-enums/simple-generic-tag.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(dead_code)]
 #![allow(non_camel_case_types)]
 
diff --git a/tests/ui/structs-enums/struct-variant-field-visibility.rs b/tests/ui/structs-enums/struct-variant-field-visibility.rs
index a6528f9..40acea9 100644
--- a/tests/ui/structs-enums/struct-variant-field-visibility.rs
+++ b/tests/ui/structs-enums/struct-variant-field-visibility.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(dead_code)]
 
 mod foo {
diff --git a/tests/ui/structs-enums/tag-in-block.rs b/tests/ui/structs-enums/tag-in-block.rs
index 27b48aa..75691f0 100644
--- a/tests/ui/structs-enums/tag-in-block.rs
+++ b/tests/ui/structs-enums/tag-in-block.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(dead_code)]
 #![allow(non_camel_case_types)]
 
diff --git a/tests/ui/structs-enums/tag-variant-disr-type-mismatch.rs b/tests/ui/structs-enums/tag-variant-disr-type-mismatch.rs
deleted file mode 100644
index f4c202d..0000000
--- a/tests/ui/structs-enums/tag-variant-disr-type-mismatch.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ run-pass
-#![allow(dead_code)]
-#![allow(non_camel_case_types)]
-
-
-enum color {
-    red = 1,
-    blue = 2,
-}
-
-pub fn main() {}
diff --git a/tests/ui/structs-enums/tuple-struct-construct.rs b/tests/ui/structs-enums/tuple-struct-construct.rs
deleted file mode 100644
index 4243bcc..0000000
--- a/tests/ui/structs-enums/tuple-struct-construct.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ run-pass
-#[allow(dead_code)]
-#[derive(Debug)]
-struct Foo(isize, isize);
-
-pub fn main() {
-    let x = Foo(1, 2);
-    println!("{:?}", x);
-}
diff --git a/tests/ui/structs-enums/tuple-struct-destructuring.rs b/tests/ui/structs-enums/tuple-struct-destructuring.rs
index 5213052..36a3660 100644
--- a/tests/ui/structs-enums/tuple-struct-destructuring.rs
+++ b/tests/ui/structs-enums/tuple-struct-destructuring.rs
@@ -1,4 +1,5 @@
 //@ run-pass
+#[derive(Debug)]
 struct Foo(isize, isize);
 
 pub fn main() {
@@ -7,4 +8,16 @@ pub fn main() {
     println!("{} {}", y, z);
     assert_eq!(y, 1);
     assert_eq!(z, 2);
+
+    let x = Foo(1, 2);
+    match x {
+        Foo(a, b) => {
+            assert_eq!(a, 1);
+            assert_eq!(b, 2);
+            println!("{} {}", a, b);
+        }
+    }
+
+    let x = Foo(1, 2);
+    assert_eq!(format!("{x:?}"), "Foo(1, 2)");
 }
diff --git a/tests/ui/structs-enums/tuple-struct-matching.rs b/tests/ui/structs-enums/tuple-struct-matching.rs
deleted file mode 100644
index a543662..0000000
--- a/tests/ui/structs-enums/tuple-struct-matching.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-//@ run-pass
-struct Foo(isize, isize);
-
-pub fn main() {
-    let x = Foo(1, 2);
-    match x {
-        Foo(a, b) => {
-            assert_eq!(a, 1);
-            assert_eq!(b, 2);
-            println!("{} {}", a, b);
-        }
-    }
-}
diff --git a/tests/ui/structs-enums/tuple-struct-trivial.rs b/tests/ui/structs-enums/tuple-struct-trivial.rs
deleted file mode 100644
index e239503..0000000
--- a/tests/ui/structs-enums/tuple-struct-trivial.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ run-pass
-#![allow(dead_code)]
-
-struct Foo(isize, isize, isize);
-
-pub fn main() {
-}
diff --git a/tests/ui/structs-enums/uninstantiable-struct.rs b/tests/ui/structs-enums/uninstantiable-struct.rs
index 97bc7d84..def0fa0 100644
--- a/tests/ui/structs-enums/uninstantiable-struct.rs
+++ b/tests/ui/structs-enums/uninstantiable-struct.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 pub struct Z(#[allow(dead_code)] &'static Z);
 
 pub fn main() {}
diff --git a/tests/ui/structs-enums/variant-structs-trivial.rs b/tests/ui/structs-enums/variant-structs-trivial.rs
index a7b0575..c1403b7 100644
--- a/tests/ui/structs-enums/variant-structs-trivial.rs
+++ b/tests/ui/structs-enums/variant-structs-trivial.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 #![allow(dead_code)]
 
 enum Foo {
diff --git a/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.stderr b/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.stderr
index 5eb64c4..836d31f 100644
--- a/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.stderr
+++ b/tests/ui/suggestions/dont-suggest-borrowing-existing-borrow.stderr
@@ -4,13 +4,13 @@
 LL |     let _ = &str::from("value");
    |              ^^^ the trait `From<_>` is not implemented for `str`
    |
-   = help: the following other types implement trait `From<T>`:
-             `String` implements `From<&String>`
-             `String` implements `From<&mut str>`
-             `String` implements `From<&str>`
-             `String` implements `From<Box<str>>`
-             `String` implements `From<Cow<'_, str>>`
-             `String` implements `From<char>`
+   = help: `String` implements trait `From<T>`:
+             From<&String>
+             From<&mut str>
+             From<&str>
+             From<Box<str>>
+             From<Cow<'_, str>>
+             From<char>
 help: you likely meant to call the associated function `from` for type `&str`, but the code as written calls associated function `from` on type `str`
    |
 LL |     let _ = <&str>::from("value");
diff --git a/tests/ui/suggestions/into-str.stderr b/tests/ui/suggestions/into-str.stderr
index d02d318..cfb8f33 100644
--- a/tests/ui/suggestions/into-str.stderr
+++ b/tests/ui/suggestions/into-str.stderr
@@ -7,13 +7,13 @@
    |     required by a bound introduced by this call
    |
    = note: to coerce a `String` into a `&str`, use `&*` as a prefix
-   = help: the following other types implement trait `From<T>`:
-             `String` implements `From<&String>`
-             `String` implements `From<&mut str>`
-             `String` implements `From<&str>`
-             `String` implements `From<Box<str>>`
-             `String` implements `From<Cow<'_, str>>`
-             `String` implements `From<char>`
+   = help: `String` implements trait `From<T>`:
+             From<&String>
+             From<&mut str>
+             From<&str>
+             From<Box<str>>
+             From<Cow<'_, str>>
+             From<char>
    = note: required for `String` to implement `Into<&str>`
 note: required by a bound in `foo`
   --> $DIR/into-str.rs:1:31
diff --git a/tests/ui/suggestions/let-binding-init-expr-as-ty.rs b/tests/ui/suggestions/let-binding-init-expr-as-ty.rs
index 71e5a0c..c108b56 100644
--- a/tests/ui/suggestions/let-binding-init-expr-as-ty.rs
+++ b/tests/ui/suggestions/let-binding-init-expr-as-ty.rs
@@ -1,11 +1,41 @@
-pub fn foo(num: i32) -> i32 {
+fn foo(num: i32) -> i32 {
+    // FIXME: This case doesn't really check that `from_be` is a valid function in `i32`.
     let foo: i32::from_be(num);
     //~^ ERROR expected type, found local variable `num`
-    //~| ERROR argument types not allowed with return type notation
-    //~| ERROR return type notation not allowed in this position yet
+    //~| ERROR expected type, found associated function call
     foo
 }
 
+struct S;
+
+impl S {
+    fn new(_: ()) -> S {
+        S
+    }
+}
+
+// We should still mention that it should be `S::new(..)`, even though rtn is not allowed there:
+struct K(S::new(())); //~ ERROR return type notation not allowed in this position yet
+
+fn bar() {}
+
 fn main() {
     let _ = foo(42);
+    // Associated functions (#134087)
+    let x: Vec::new(); //~ ERROR expected type, found associated function call
+    let x: Vec<()>::new(); //~ ERROR expected type, found associated function call
+    let x: S::new(..); //~ ERROR expected type, found associated function call
+    //~^ ERROR return type notation is experimental
+    let x: S::new(()); //~ ERROR expected type, found associated function call
+
+    // Literals
+    let x: 42; //~ ERROR expected type, found `42`
+    let x: ""; //~ ERROR expected type, found `""`
+
+    // Functions
+    let x: bar(); //~ ERROR expected type, found function `bar`
+    let x: bar; //~ ERROR expected type, found function `bar`
+
+    // Locals
+    let x: x; //~ ERROR expected type, found local variable `x`
 }
diff --git a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr
index 19a0e4b..354d119 100644
--- a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr
+++ b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr
@@ -1,32 +1,159 @@
-error[E0573]: expected type, found local variable `num`
-  --> $DIR/let-binding-init-expr-as-ty.rs:2:27
+error: expected type, found `42`
+  --> $DIR/let-binding-init-expr-as-ty.rs:32:12
    |
-LL |     let foo: i32::from_be(num);
-   |            --             ^^^ not a type
-   |            |
-   |            help: use `=` if you meant to assign
+LL |     let x: 42;
+   |          - ^^ expected type
+   |          |
+   |          while parsing the type for `x`
+   |
+help: use `=` if you meant to assign
+   |
+LL -     let x: 42;
+LL +     let x = 42;
+   |
 
-error: argument types not allowed with return type notation
-  --> $DIR/let-binding-init-expr-as-ty.rs:2:26
+error: expected type, found `""`
+  --> $DIR/let-binding-init-expr-as-ty.rs:33:12
+   |
+LL |     let x: "";
+   |          - ^^ expected type
+   |          |
+   |          while parsing the type for `x`
+   |
+help: use `=` if you meant to assign
+   |
+LL -     let x: "";
+LL +     let x = "";
+   |
+
+error[E0573]: expected type, found local variable `num`
+  --> $DIR/let-binding-init-expr-as-ty.rs:3:27
    |
 LL |     let foo: i32::from_be(num);
-   |                          ^^^^^
+   |                           ^^^ not a type
+   |
+help: use `=` if you meant to assign
+   |
+LL -     let foo: i32::from_be(num);
+LL +     let foo = i32::from_be(num);
+   |
+
+error[E0573]: expected type, found function `bar`
+  --> $DIR/let-binding-init-expr-as-ty.rs:36:12
+   |
+LL |     let x: bar();
+   |            ^^^^^ not a type
+   |
+help: use `=` if you meant to assign
+   |
+LL -     let x: bar();
+LL +     let x = bar();
+   |
+
+error[E0573]: expected type, found function `bar`
+  --> $DIR/let-binding-init-expr-as-ty.rs:37:12
+   |
+LL |     let x: bar;
+   |            ^^^ not a type
+
+error[E0573]: expected type, found local variable `x`
+  --> $DIR/let-binding-init-expr-as-ty.rs:40:12
+   |
+LL | struct K(S::new(()));
+   | --------------------- similarly named struct `K` defined here
+...
+LL |     let x: x;
+   |            ^
+   |
+help: a struct with a similar name exists
+   |
+LL -     let x: x;
+LL +     let x: K;
+   |
+
+error[E0658]: return type notation is experimental
+  --> $DIR/let-binding-init-expr-as-ty.rs:27:18
+   |
+LL |     let x: S::new(..);
+   |                  ^^^^
    |
    = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
    = help: add `#![feature(return_type_notation)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-help: remove the input types
-   |
-LL -     let foo: i32::from_be(num);
-LL +     let foo: i32::from_be(..);
-   |
 
 error: return type notation not allowed in this position yet
-  --> $DIR/let-binding-init-expr-as-ty.rs:2:14
+  --> $DIR/let-binding-init-expr-as-ty.rs:18:10
+   |
+LL | struct K(S::new(()));
+   |          ^^^^^^^^^^
+   |
+help: furthermore, argument types not allowed with return type notation
+   |
+LL - struct K(S::new(()));
+LL + struct K(S::new(..));
+   |
+
+error: expected type, found associated function call
+  --> $DIR/let-binding-init-expr-as-ty.rs:3:14
    |
 LL |     let foo: i32::from_be(num);
    |              ^^^^^^^^^^^^^^^^^
+   |
+help: use `=` if you meant to assign
+   |
+LL -     let foo: i32::from_be(num);
+LL +     let foo = i32::from_be(num);
+   |
 
-error: aborting due to 3 previous errors
+error: expected type, found associated function call
+  --> $DIR/let-binding-init-expr-as-ty.rs:25:12
+   |
+LL |     let x: Vec::new();
+   |            ^^^^^^^^^^
+   |
+help: use `=` if you meant to assign
+   |
+LL -     let x: Vec::new();
+LL +     let x = Vec::new();
+   |
 
-For more information about this error, try `rustc --explain E0573`.
+error: expected type, found associated function call
+  --> $DIR/let-binding-init-expr-as-ty.rs:26:12
+   |
+LL |     let x: Vec<()>::new();
+   |            ^^^^^^^^^^^^^^
+   |
+help: use `=` if you meant to assign
+   |
+LL -     let x: Vec<()>::new();
+LL +     let x = Vec<()>::new();
+   |
+
+error: expected type, found associated function call
+  --> $DIR/let-binding-init-expr-as-ty.rs:27:12
+   |
+LL |     let x: S::new(..);
+   |            ^^^^^^^^^^
+   |
+help: use `=` if you meant to assign
+   |
+LL -     let x: S::new(..);
+LL +     let x = S::new(..);
+   |
+
+error: expected type, found associated function call
+  --> $DIR/let-binding-init-expr-as-ty.rs:29:12
+   |
+LL |     let x: S::new(());
+   |            ^^^^^^^^^^
+   |
+help: use `=` if you meant to assign
+   |
+LL -     let x: S::new(());
+LL +     let x = S::new(());
+   |
+
+error: aborting due to 13 previous errors
+
+Some errors have detailed explanations: E0573, E0658.
+For more information about an error, try `rustc --explain E0573`.
diff --git a/tests/ui/suggestions/partialeq_suggest_swap_on_e0277.stderr b/tests/ui/suggestions/partialeq_suggest_swap_on_e0277.stderr
index c5984f5..29e1c6b 100644
--- a/tests/ui/suggestions/partialeq_suggest_swap_on_e0277.stderr
+++ b/tests/ui/suggestions/partialeq_suggest_swap_on_e0277.stderr
@@ -5,15 +5,15 @@
    |                                    ^^ no implementation for `String == T`
    |
    = help: the trait `PartialEq<T>` is not implemented for `String`
-   = help: the following other types implement trait `PartialEq<Rhs>`:
-             `String` implements `PartialEq<&str>`
-             `String` implements `PartialEq<ByteStr>`
-             `String` implements `PartialEq<ByteString>`
-             `String` implements `PartialEq<Cow<'_, str>>`
-             `String` implements `PartialEq<Path>`
-             `String` implements `PartialEq<PathBuf>`
-             `String` implements `PartialEq<str>`
-             `String` implements `PartialEq`
+   = help: `String` implements trait `PartialEq<Rhs>`:
+             PartialEq<&str>
+             PartialEq<ByteStr>
+             PartialEq<ByteString>
+             PartialEq<Cow<'_, str>>
+             PartialEq<Path>
+             PartialEq<PathBuf>
+             PartialEq<str>
+             PartialEq
    = note: `T` implements `PartialEq<String>`
 help: consider swapping the equality
    |
diff --git a/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.stderr b/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.stderr
index 9f34d27..6dd4b1e 100644
--- a/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.stderr
+++ b/tests/ui/suggestions/semi-suggestion-when-stmt-and-expr-span-equal.stderr
@@ -20,15 +20,15 @@
    |          required by a bound introduced by this call
    |
    = help: the trait `FromIterator<()>` is not implemented for `String`
-   = help: the following other types implement trait `FromIterator<A>`:
-             `String` implements `FromIterator<&char>`
-             `String` implements `FromIterator<&std::ascii::Char>`
-             `String` implements `FromIterator<&str>`
-             `String` implements `FromIterator<Box<str, A>>`
-             `String` implements `FromIterator<Cow<'_, str>>`
-             `String` implements `FromIterator<String>`
-             `String` implements `FromIterator<char>`
-             `String` implements `FromIterator<std::ascii::Char>`
+   = help: `String` implements trait `FromIterator<A>`:
+             FromIterator<&char>
+             FromIterator<&std::ascii::Char>
+             FromIterator<&str>
+             FromIterator<Box<str, A>>
+             FromIterator<Cow<'_, str>>
+             FromIterator<String>
+             FromIterator<char>
+             FromIterator<std::ascii::Char>
 note: the method call chain might not have had the expected associated types
   --> $DIR/semi-suggestion-when-stmt-and-expr-span-equal.rs:20:10
    |
diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr
index 541c625..cee5ffc 100644
--- a/tests/ui/suggestions/suggest-dereferencing-index.stderr
+++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr
@@ -5,13 +5,13 @@
    |                                          ^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize`
-help: the following other types implement trait `SliceIndex<T>`
+help: `usize` implements trait `SliceIndex<T>`
   --> $SRC_DIR/core/src/slice/index.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<[T]>`
+   = note: `SliceIndex<[T]>`
   --> $SRC_DIR/core/src/bstr/traits.rs:LL:COL
    |
-   = note: `usize` implements `SliceIndex<ByteStr>`
+   = note: `SliceIndex<ByteStr>`
    = note: required for `[{integer}]` to implement `Index<&usize>`
 help: dereference this index
    |
diff --git a/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.next.stderr b/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.next.stderr
new file mode 100644
index 0000000..8b5c4f5
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.next.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `Vec<u8>: const Destruct` is not satisfied
+  --> $DIR/const-closure-with-indestructible-indestructible.rs:10:16
+   |
+LL |           i_need(const || {
+   |  _________------_^
+   | |         |
+   | |         required by a bound introduced by this call
+LL | |
+LL | |             let y = v;
+LL | |         })
+   | |_________^
+   |
+note: required by a bound in `i_need`
+  --> $DIR/const-closure-with-indestructible-indestructible.rs:5:20
+   |
+LL | const fn i_need<F: [const] std::marker::Destruct>(x: F) {}
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `i_need`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.old.stderr b/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.old.stderr
new file mode 100644
index 0000000..8b5c4f5
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.old.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `Vec<u8>: const Destruct` is not satisfied
+  --> $DIR/const-closure-with-indestructible-indestructible.rs:10:16
+   |
+LL |           i_need(const || {
+   |  _________------_^
+   | |         |
+   | |         required by a bound introduced by this call
+LL | |
+LL | |             let y = v;
+LL | |         })
+   | |_________^
+   |
+note: required by a bound in `i_need`
+  --> $DIR/const-closure-with-indestructible-indestructible.rs:5:20
+   |
+LL | const fn i_need<F: [const] std::marker::Destruct>(x: F) {}
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `i_need`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.rs b/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.rs
new file mode 100644
index 0000000..d26260d
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-closure-with-indestructible-indestructible.rs
@@ -0,0 +1,15 @@
+//@revisions: next old
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+#![feature(const_trait_impl, const_closures, const_destruct)]
+const fn i_need<F: [const] std::marker::Destruct>(x: F) {}
+
+fn main() {
+    const {
+        let v = Vec::<u8>::new();
+        i_need(const || {
+            //~^ ERROR the trait bound
+            let y = v;
+        })
+    };
+}
diff --git a/tests/ui/traits/const-traits/mismatched_generic_args.rs b/tests/ui/traits/const-traits/mismatched_generic_args.rs
index 21e91c7..409a704 100644
--- a/tests/ui/traits/const-traits/mismatched_generic_args.rs
+++ b/tests/ui/traits/const-traits/mismatched_generic_args.rs
@@ -1,5 +1,4 @@
 #![feature(generic_const_exprs)]
-//~^ WARN: the feature `generic_const_exprs` is incomplete
 
 // Regression test for #125770 which would ICE under the old effects desugaring that
 // created a const generic parameter for constness on `Add`.
diff --git a/tests/ui/traits/const-traits/mismatched_generic_args.stderr b/tests/ui/traits/const-traits/mismatched_generic_args.stderr
index e810331..3094cb5 100644
--- a/tests/ui/traits/const-traits/mismatched_generic_args.stderr
+++ b/tests/ui/traits/const-traits/mismatched_generic_args.stderr
@@ -1,5 +1,5 @@
 error[E0425]: cannot find value `y` in this scope
-  --> $DIR/mismatched_generic_args.rs:20:9
+  --> $DIR/mismatched_generic_args.rs:19:9
    |
 LL | pub fn add<const U: Dimension>(x: Quantity<f32, U>) -> Quantity<f32, U> {
    |                  - similarly named const parameter `U` defined here
@@ -13,17 +13,8 @@
 LL +     x + U
    |
 
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/mismatched_generic_args.rs:1:12
-   |
-LL | #![feature(generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: `Dimension` is forbidden as the type of a const generic parameter
-  --> $DIR/mismatched_generic_args.rs:11:33
+  --> $DIR/mismatched_generic_args.rs:10:33
    |
 LL | pub struct Quantity<S, const D: Dimension>(S);
    |                                 ^^^^^^^^^
@@ -35,13 +26,13 @@
    |
 
 error[E0107]: trait takes at most 1 generic argument but 2 generic arguments were supplied
-  --> $DIR/mismatched_generic_args.rs:14:36
+  --> $DIR/mismatched_generic_args.rs:13:36
    |
 LL | impl<const D: Dimension, LHS, RHS> Add<LHS, D> for Quantity<LHS, { Dimension }> {}
    |                                    ^^^ expected at most 1 generic argument
 
 error: `Dimension` is forbidden as the type of a const generic parameter
-  --> $DIR/mismatched_generic_args.rs:14:15
+  --> $DIR/mismatched_generic_args.rs:13:15
    |
 LL | impl<const D: Dimension, LHS, RHS> Add<LHS, D> for Quantity<LHS, { Dimension }> {}
    |               ^^^^^^^^^
@@ -53,7 +44,7 @@
    |
 
 error: `Dimension` is forbidden as the type of a const generic parameter
-  --> $DIR/mismatched_generic_args.rs:18:21
+  --> $DIR/mismatched_generic_args.rs:17:21
    |
 LL | pub fn add<const U: Dimension>(x: Quantity<f32, U>) -> Quantity<f32, U> {
    |                     ^^^^^^^^^
@@ -64,7 +55,7 @@
 LL + #![feature(adt_const_params)]
    |
 
-error: aborting due to 5 previous errors; 1 warning emitted
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0107, E0425.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr b/tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr
index a6bd861..57bb556 100644
--- a/tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr
+++ b/tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Foo` for type `(_,)`
-  --> $DIR/overlap-const-with-nonconst.rs:21:1
+  --> $DIR/overlap-const-with-nonconst.rs:20:1
    |
 LL | / impl<T> const Foo for T
 LL | | where
diff --git a/tests/ui/traits/const-traits/overlap-const-with-nonconst.rs b/tests/ui/traits/const-traits/overlap-const-with-nonconst.rs
index 10dfb20..0e21d31 100644
--- a/tests/ui/traits/const-traits/overlap-const-with-nonconst.rs
+++ b/tests/ui/traits/const-traits/overlap-const-with-nonconst.rs
@@ -2,7 +2,6 @@
 
 #![feature(const_trait_impl)]
 #![cfg_attr(spec, feature(specialization))]
-//[spec]~^ WARN the feature `specialization` is incomplete
 #![cfg_attr(min_spec, feature(min_specialization))]
 
 const trait Bar {}
diff --git a/tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr b/tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr
index 91628f6..57bb556 100644
--- a/tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr
+++ b/tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr
@@ -1,15 +1,5 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/overlap-const-with-nonconst.rs:4:27
-   |
-LL | #![cfg_attr(spec, feature(specialization))]
-   |                           ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0119]: conflicting implementations of trait `Foo` for type `(_,)`
-  --> $DIR/overlap-const-with-nonconst.rs:21:1
+  --> $DIR/overlap-const-with-nonconst.rs:20:1
    |
 LL | / impl<T> const Foo for T
 LL | | where
@@ -19,6 +9,6 @@
 LL |   impl<T> Foo for (T,) {
    |   ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_,)`
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr
index 520a683..ad3c177 100644
--- a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr
+++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Value` for type `FortyTwo`
-  --> $DIR/const-default-impl-non-const-specialized-impl.rs:21:1
+  --> $DIR/const-default-impl-non-const-specialized-impl.rs:20:1
    |
 LL | impl<T> const Value for T {
    | ------------------------- first implementation here
diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs
index f7cd459..b26e655 100644
--- a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs
+++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs
@@ -3,7 +3,6 @@
 
 #![feature(const_trait_impl)]
 #![cfg_attr(spec, feature(specialization))]
-//[spec]~^ WARN the feature `specialization` is incomplete
 #![cfg_attr(min_spec, feature(min_specialization))]
 
 const trait Value {
diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr
index 397d678..ad3c177 100644
--- a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr
+++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr
@@ -1,15 +1,5 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-default-impl-non-const-specialized-impl.rs:5:27
-   |
-LL | #![cfg_attr(spec, feature(specialization))]
-   |                           ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0119]: conflicting implementations of trait `Value` for type `FortyTwo`
-  --> $DIR/const-default-impl-non-const-specialized-impl.rs:21:1
+  --> $DIR/const-default-impl-non-const-specialized-impl.rs:20:1
    |
 LL | impl<T> const Value for T {
    | ------------------------- first implementation here
@@ -17,6 +7,6 @@
 LL | impl Value for FortyTwo {
    | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `FortyTwo`
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/explicit-reference-cast.rs b/tests/ui/traits/explicit-reference-cast.rs
index efb4f10..b9ccc18 100644
--- a/tests/ui/traits/explicit-reference-cast.rs
+++ b/tests/ui/traits/explicit-reference-cast.rs
@@ -7,7 +7,7 @@
 //~^ HELP the trait `From<&PathBuf>` is not implemented for `ToolA`
 
 impl From<&Path> for ToolA {
-    //~^ HELP the following other types implement trait `From<T>`
+    //~^ HELP `ToolA` implements trait `From<T>`
     fn from(p: &Path) -> ToolA {
         ToolA(p.to_path_buf())
     }
diff --git a/tests/ui/traits/explicit-reference-cast.stderr b/tests/ui/traits/explicit-reference-cast.stderr
index 924de3d..78eb25b 100644
--- a/tests/ui/traits/explicit-reference-cast.stderr
+++ b/tests/ui/traits/explicit-reference-cast.stderr
@@ -10,14 +10,14 @@
    |
 LL | pub struct ToolA(PathBuf);
    | ^^^^^^^^^^^^^^^^
-help: the following other types implement trait `From<T>`
+help: `ToolA` implements trait `From<T>`
   --> $DIR/explicit-reference-cast.rs:9:1
    |
 LL | impl From<&Path> for ToolA {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `ToolA` implements `From<&Path>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `From<&Path>`
 ...
 LL | impl From<&str> for ToolA {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ `ToolA` implements `From<&str>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ `From<&str>`
 
 error[E0277]: the trait bound `ToolB: TryFrom<&PathBuf>` is not satisfied
   --> $DIR/explicit-reference-cast.rs:43:13
diff --git a/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr
index e58f5c3..9b27491 100644
--- a/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr
+++ b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr
@@ -6,14 +6,14 @@
    |       |
    |       required by a bound introduced by this call
    |
-help: the following other types implement trait `CompareTo<T>`
+help: `i64` implements trait `CompareTo<T>`
   --> $DIR/repeated-supertrait-ambig.rs:15:1
    |
 LL | impl CompareTo<i64> for i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `i64` implements `CompareTo<i64>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CompareTo<i64>`
 ...
 LL | impl CompareTo<u64> for i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `i64` implements `CompareTo<u64>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CompareTo<u64>`
 
 error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied
   --> $DIR/repeated-supertrait-ambig.rs:30:15
@@ -34,14 +34,14 @@
 LL |     <dyn CompareToInts>::same_as(c, 22)
    |      ^^^^^^^^^^^^^^^^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts`
    |
-help: the following other types implement trait `CompareTo<T>`
+help: `i64` implements trait `CompareTo<T>`
   --> $DIR/repeated-supertrait-ambig.rs:15:1
    |
 LL | impl CompareTo<i64> for i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `i64` implements `CompareTo<i64>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CompareTo<i64>`
 ...
 LL | impl CompareTo<u64> for i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `i64` implements `CompareTo<u64>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CompareTo<u64>`
 
 error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied
   --> $DIR/repeated-supertrait-ambig.rs:38:24
@@ -64,14 +64,14 @@
    |                       |
    |                       required by a bound introduced by this call
    |
-help: the following other types implement trait `CompareTo<T>`
+help: `i64` implements trait `CompareTo<T>`
   --> $DIR/repeated-supertrait-ambig.rs:15:1
    |
 LL | impl CompareTo<i64> for i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `i64` implements `CompareTo<i64>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CompareTo<i64>`
 ...
 LL | impl CompareTo<u64> for i64 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `i64` implements `CompareTo<u64>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CompareTo<u64>`
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/traits/negative-impls/negative-default-impls.rs b/tests/ui/traits/negative-impls/negative-default-impls.rs
index c68bca4..2d50bc8 100644
--- a/tests/ui/traits/negative-impls/negative-default-impls.rs
+++ b/tests/ui/traits/negative-impls/negative-default-impls.rs
@@ -1,6 +1,5 @@
 #![feature(negative_impls)]
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
 
 trait MyTrait {
     type Foo;
diff --git a/tests/ui/traits/negative-impls/negative-default-impls.stderr b/tests/ui/traits/negative-impls/negative-default-impls.stderr
index 328e744..b321898 100644
--- a/tests/ui/traits/negative-impls/negative-default-impls.stderr
+++ b/tests/ui/traits/negative-impls/negative-default-impls.stderr
@@ -1,19 +1,9 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/negative-default-impls.rs:2:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0750]: negative impls cannot be default impls
-  --> $DIR/negative-default-impls.rs:9:1
+  --> $DIR/negative-default-impls.rs:8:1
    |
 LL | default impl !MyTrait for u32 {}
    | ^^^^^^^      ^
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0750`.
diff --git a/tests/ui/traits/negative-impls/negative-specializes-negative.rs b/tests/ui/traits/negative-impls/negative-specializes-negative.rs
index bb2856a..fe5165a 100644
--- a/tests/ui/traits/negative-impls/negative-specializes-negative.rs
+++ b/tests/ui/traits/negative-impls/negative-specializes-negative.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 #![feature(negative_impls)]
 
 // Test a negative impl that "specializes" another negative impl.
diff --git a/tests/ui/traits/negative-impls/negative-specializes-negative.stderr b/tests/ui/traits/negative-impls/negative-specializes-negative.stderr
deleted file mode 100644
index 751e29c..0000000
--- a/tests/ui/traits/negative-impls/negative-specializes-negative.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/negative-specializes-negative.rs:1:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive-item.rs b/tests/ui/traits/negative-impls/negative-specializes-positive-item.rs
index 4281eed..da22e43 100644
--- a/tests/ui/traits/negative-impls/negative-specializes-positive-item.rs
+++ b/tests/ui/traits/negative-impls/negative-specializes-positive-item.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 #![feature(negative_impls)]
 
 // Negative impl for u32 cannot "specialize" the base impl.
diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr b/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr
index 97727da..e281969 100644
--- a/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr
+++ b/tests/ui/traits/negative-impls/negative-specializes-positive-item.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/negative-specializes-positive-item.rs:1:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
   --> $DIR/negative-specializes-positive-item.rs:11:1
    |
@@ -17,6 +7,6 @@
 LL | impl !MyTrait for u32 {}
    | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0751`.
diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive.rs b/tests/ui/traits/negative-impls/negative-specializes-positive.rs
index 0e22769..1939a09 100644
--- a/tests/ui/traits/negative-impls/negative-specializes-positive.rs
+++ b/tests/ui/traits/negative-impls/negative-specializes-positive.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 #![feature(negative_impls)]
 
 // Negative impl for u32 cannot "specialize" the base impl.
diff --git a/tests/ui/traits/negative-impls/negative-specializes-positive.stderr b/tests/ui/traits/negative-impls/negative-specializes-positive.stderr
index 100f97a..6eab4aa 100644
--- a/tests/ui/traits/negative-impls/negative-specializes-positive.stderr
+++ b/tests/ui/traits/negative-impls/negative-specializes-positive.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/negative-specializes-positive.rs:1:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
   --> $DIR/negative-specializes-positive.rs:7:1
    |
@@ -16,6 +6,6 @@
 LL | impl !MyTrait for u32 {}
    | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0751`.
diff --git a/tests/ui/traits/negative-impls/positive-specializes-negative.rs b/tests/ui/traits/negative-impls/positive-specializes-negative.rs
index a06b357..f2c5f50 100644
--- a/tests/ui/traits/negative-impls/positive-specializes-negative.rs
+++ b/tests/ui/traits/negative-impls/positive-specializes-negative.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
 #![feature(negative_impls)]
 
 trait MyTrait {}
diff --git a/tests/ui/traits/negative-impls/positive-specializes-negative.stderr b/tests/ui/traits/negative-impls/positive-specializes-negative.stderr
index 1655cb0..7c3f5f6 100644
--- a/tests/ui/traits/negative-impls/positive-specializes-negative.stderr
+++ b/tests/ui/traits/negative-impls/positive-specializes-negative.stderr
@@ -1,13 +1,3 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/positive-specializes-negative.rs:1:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
   --> $DIR/positive-specializes-negative.rs:7:1
    |
@@ -16,6 +6,6 @@
 LL | impl MyTrait for u32 {}
    | ^^^^^^^^^^^^^^^^^^^^ positive implementation here
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0751`.
diff --git a/tests/ui/traits/next-solver/coherence/negative-coherence-bounds.rs b/tests/ui/traits/next-solver/coherence/negative-coherence-bounds.rs
index d98cd11..327f731 100644
--- a/tests/ui/traits/next-solver/coherence/negative-coherence-bounds.rs
+++ b/tests/ui/traits/next-solver/coherence/negative-coherence-bounds.rs
@@ -10,7 +10,6 @@
 // which is provided by the first impl that it is specializing.
 
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
 #![feature(with_negative_coherence)]
 
 trait BoxIter {
diff --git a/tests/ui/traits/next-solver/coherence/negative-coherence-bounds.stderr b/tests/ui/traits/next-solver/coherence/negative-coherence-bounds.stderr
deleted file mode 100644
index 4127f51f..0000000
--- a/tests/ui/traits/next-solver/coherence/negative-coherence-bounds.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/negative-coherence-bounds.rs:12:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/next-solver/cycles/forced_ambiguity-use-head-maybe-cause.stderr b/tests/ui/traits/next-solver/cycles/forced_ambiguity-use-head-maybe-cause.stderr
index 42b76a8..04a4c70 100644
--- a/tests/ui/traits/next-solver/cycles/forced_ambiguity-use-head-maybe-cause.stderr
+++ b/tests/ui/traits/next-solver/cycles/forced_ambiguity-use-head-maybe-cause.stderr
@@ -5,7 +5,7 @@
    |                   ^^^^^^^ cannot infer type for struct `Head<_>`
    |
    = note: cannot satisfy `Head<_>: Trait`
-help: the following types implement trait `Trait`
+help: `Head<T>` implements trait `Trait`
   --> $DIR/forced_ambiguity-use-head-maybe-cause.rs:23:1
    |
 LL | / impl<T> Trait for Head<T>
diff --git a/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.stderr b/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.stderr
index 8b24e68..cea95eb 100644
--- a/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.stderr
+++ b/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.stderr
@@ -21,7 +21,7 @@
    |
 LL | struct MultipleCandidates;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
-help: the following other types implement trait `Trait`
+help: `MultipleCandidates` implements trait `Trait`
   --> $DIR/inductive-cycle-but-err.rs:26:1
    |
 LL | / impl Trait for MultipleCandidates
diff --git a/tests/ui/traits/next-solver/generalize/constrain-inference-during-normalize.rs b/tests/ui/traits/next-solver/generalize/constrain-inference-during-normalize.rs
new file mode 100644
index 0000000..c3942b0
--- /dev/null
+++ b/tests/ui/traits/next-solver/generalize/constrain-inference-during-normalize.rs
@@ -0,0 +1,25 @@
+// revisions: next old
+//[next] compile-flags: -Znext-solver
+//@ check-pass
+// Regression test for https://github.com/rust-lang/rust/issues/154173.
+// The ICE there was caused by a (flawed) attempt to eagerly normalize during generalization.
+// The normalize would constrain other inference variables, which we couldn't deal with.
+
+trait Trait<T> {
+    type Assoc;
+}
+
+impl Trait<u32> for () {
+    type Assoc = u32;
+}
+
+trait Eq {}
+impl<C: Trait<T>, T> Eq for (C, T, <C as Trait<T>>::Assoc) {}
+fn foo<A>()
+where
+    ((), A, A): Eq
+{}
+
+fn main() {
+    foo::<_>();
+}
diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.rs b/tests/ui/traits/next-solver/issue-118950-root-region.rs
index 84e2f4c..7a4cd2a 100644
--- a/tests/ui/traits/next-solver/issue-118950-root-region.rs
+++ b/tests/ui/traits/next-solver/issue-118950-root-region.rs
@@ -3,7 +3,6 @@
 // This is a gnarly test but I don't know how to minimize it, frankly.
 
 #![feature(lazy_type_alias)]
-//~^ WARN the feature `lazy_type_alias` is incomplete
 
 trait ToUnit<'a> {
     type Unit;
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 74cbb5b..5516f1e 100644
--- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr
+++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr
@@ -1,32 +1,23 @@
 error[E0425]: cannot find type `Missing` in this scope
-  --> $DIR/issue-118950-root-region.rs:19:55
+  --> $DIR/issue-118950-root-region.rs:18:55
    |
 LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {}
    |                                                       ^^^^^^^ not found in this scope
 
-warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-118950-root-region.rs:5: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[E0277]: the trait bound `*const T: ToUnit<'a>` is not satisfied
-  --> $DIR/issue-118950-root-region.rs:14:1
+  --> $DIR/issue-118950-root-region.rs:13:1
    |
 LL | type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit;
    | ^^^^^^^^^^^^^^^^^ the trait `ToUnit<'a>` is not implemented for `*const T`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/issue-118950-root-region.rs:8:1
+  --> $DIR/issue-118950-root-region.rs:7:1
    |
 LL | trait ToUnit<'a> {
    | ^^^^^^^^^^^^^^^^
 
  WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a)), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc), .. }
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0277, E0425.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.current.stderr b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.current.stderr
deleted file mode 100644
index ef63681..0000000
--- a/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.current.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/normalize-self-type-constrains-trait-args.rs:8: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
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.next.stderr b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.next.stderr
deleted file mode 100644
index ef63681..0000000
--- a/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.next.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/normalize-self-type-constrains-trait-args.rs:8: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
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.rs b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.rs
index c2a0167..921d753 100644
--- a/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.rs
+++ b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.rs
@@ -6,7 +6,6 @@
 // This goal is also possible w/ a GAT, but lazy_type_alias
 // makes the behavior a bit more readable.
 #![feature(lazy_type_alias)]
-//~^ WARN the feature `lazy_type_alias` is incomplete
 
 struct Wr<T>(T);
 trait Foo {}
diff --git a/tests/ui/traits/next-solver/specialization-transmute.rs b/tests/ui/traits/next-solver/specialization-transmute.rs
index f1447cd..ba8b49c9 100644
--- a/tests/ui/traits/next-solver/specialization-transmute.rs
+++ b/tests/ui/traits/next-solver/specialization-transmute.rs
@@ -1,6 +1,5 @@
 //@ compile-flags: -Znext-solver
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
 
 trait Default {
     type Id;
diff --git a/tests/ui/traits/next-solver/specialization-transmute.stderr b/tests/ui/traits/next-solver/specialization-transmute.stderr
index 8bd290e..bdc03e5 100644
--- a/tests/ui/traits/next-solver/specialization-transmute.stderr
+++ b/tests/ui/traits/next-solver/specialization-transmute.stderr
@@ -1,15 +1,5 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-transmute.rs:2:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0308]: mismatched types
-  --> $DIR/specialization-transmute.rs:14:9
+  --> $DIR/specialization-transmute.rs:13:9
    |
 LL |     fn intu(&self) -> &Self::Id {
    |                       --------- expected `&<T as Default>::Id` because of return type
@@ -20,7 +10,7 @@
               found reference `&T`
 
 error[E0271]: type mismatch resolving `<u8 as Default>::Id == Option<NonZero<u8>>`
-  --> $DIR/specialization-transmute.rs:25:50
+  --> $DIR/specialization-transmute.rs:24:50
    |
 LL |     let s = transmute::<u8, Option<NonZero<u8>>>(0);
    |             ------------------------------------ ^ types differ
@@ -28,12 +18,12 @@
    |             required by a bound introduced by this call
    |
 note: required by a bound in `transmute`
-  --> $DIR/specialization-transmute.rs:18:25
+  --> $DIR/specialization-transmute.rs:17:25
    |
 LL | fn transmute<T: Default<Id = U>, U: Copy>(t: T) -> U {
    |                         ^^^^^^ required by this bound in `transmute`
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0271, E0308.
 For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/next-solver/specialization-unconstrained.rs b/tests/ui/traits/next-solver/specialization-unconstrained.rs
index 6835c07..27f6d00 100644
--- a/tests/ui/traits/next-solver/specialization-unconstrained.rs
+++ b/tests/ui/traits/next-solver/specialization-unconstrained.rs
@@ -1,7 +1,6 @@
 //@ compile-flags: -Znext-solver
 
 #![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
 
 // Do not treat the RHS of a projection-goal as an unconstrained `Certainty::Yes` response
 // if the impl is still further specializable.
diff --git a/tests/ui/traits/next-solver/specialization-unconstrained.stderr b/tests/ui/traits/next-solver/specialization-unconstrained.stderr
index 1bcf5ed..3e36381 100644
--- a/tests/ui/traits/next-solver/specialization-unconstrained.stderr
+++ b/tests/ui/traits/next-solver/specialization-unconstrained.stderr
@@ -1,25 +1,15 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-unconstrained.rs:3:12
-   |
-LL | #![feature(specialization)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
-   = help: consider using `min_specialization` instead, which is more stable and complete
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0271]: type mismatch resolving `<u32 as Default>::Id == ()`
-  --> $DIR/specialization-unconstrained.rs:20:12
+  --> $DIR/specialization-unconstrained.rs:19:12
    |
 LL |     test::<u32, ()>();
    |            ^^^ types differ
    |
 note: required by a bound in `test`
-  --> $DIR/specialization-unconstrained.rs:17:20
+  --> $DIR/specialization-unconstrained.rs:16:20
    |
 LL | fn test<T: Default<Id = U>, U>() {}
    |                    ^^^^^^ required by this bound in `test`
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/next-solver/unevaluated-const-impl-trait-ref.fails.stderr b/tests/ui/traits/next-solver/unevaluated-const-impl-trait-ref.fails.stderr
index 8202b6e..ce68c2f 100644
--- a/tests/ui/traits/next-solver/unevaluated-const-impl-trait-ref.fails.stderr
+++ b/tests/ui/traits/next-solver/unevaluated-const-impl-trait-ref.fails.stderr
@@ -4,13 +4,13 @@
 LL |     needs::<1>();
    |             ^ the trait `Trait<1>` is not implemented for `()`
    |
-help: the following other types implement trait `Trait<N>`
+help: `()` implements trait `Trait<N>`
   --> $DIR/unevaluated-const-impl-trait-ref.rs:7:1
    |
 LL | impl Trait<{ 1 - 1 }> for () {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` implements `Trait<0>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Trait<0>`
 LL | impl Trait<{ 1 + 1 }> for () {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` implements `Trait<2>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Trait<2>`
 note: required by a bound in `needs`
   --> $DIR/unevaluated-const-impl-trait-ref.rs:10:38
    |
diff --git a/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr b/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr
deleted file mode 100644
index 5393db6..0000000
--- a/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/non-lifetime-via-dyn-builtin.rs:6:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr b/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr
deleted file mode 100644
index 5393db6..0000000
--- a/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/non-lifetime-via-dyn-builtin.rs:6:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/non-lifetime-via-dyn-builtin.rs b/tests/ui/traits/non-lifetime-via-dyn-builtin.rs
index ac61f8b..00bf237 100644
--- a/tests/ui/traits/non-lifetime-via-dyn-builtin.rs
+++ b/tests/ui/traits/non-lifetime-via-dyn-builtin.rs
@@ -4,7 +4,6 @@
 //@ check-pass
 
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete and may not be safe
 
 fn trivial<A>()
 where
diff --git a/tests/ui/traits/non_lifetime_binders/bad-copy-cond.rs b/tests/ui/traits/non_lifetime_binders/bad-copy-cond.rs
index 506cad2..9d792ad 100644
--- a/tests/ui/traits/non_lifetime_binders/bad-copy-cond.rs
+++ b/tests/ui/traits/non_lifetime_binders/bad-copy-cond.rs
@@ -1,5 +1,4 @@
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 fn foo() where for<T> T: Copy {}
 
diff --git a/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr b/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr
index 4694e7d..f77d562 100644
--- a/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr
+++ b/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr
@@ -1,24 +1,15 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/bad-copy-cond.rs:1:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/bad-copy-cond.rs:7:5
+  --> $DIR/bad-copy-cond.rs:6:5
    |
 LL |     foo();
    |     ^^^^^ the trait `Copy` is not implemented for `T`
    |
 note: required by a bound in `foo`
-  --> $DIR/bad-copy-cond.rs:4:26
+  --> $DIR/bad-copy-cond.rs:3:26
    |
 LL | fn foo() where for<T> T: Copy {}
    |                          ^^^^ required by this bound in `foo`
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.rs b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.rs
index dfc800c..244ac2f 100644
--- a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.rs
+++ b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.rs
@@ -1,5 +1,4 @@
 #![feature(non_lifetime_binders)]
-//~^ WARN is incomplete and may not be safe
 
 pub fn foo()
 where
diff --git a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr
index f4deb16..0b3aa5c 100644
--- a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr
+++ b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr
@@ -1,21 +1,12 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/bad-sized-cond.rs:1:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0277]: the size for values of type `V` cannot be known at compilation time
-  --> $DIR/bad-sized-cond.rs:17:5
+  --> $DIR/bad-sized-cond.rs:16:5
    |
 LL |     foo();
    |     ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `V`
 note: required by a bound in `foo`
-  --> $DIR/bad-sized-cond.rs:6:15
+  --> $DIR/bad-sized-cond.rs:5:15
    |
 LL | pub fn foo()
    |        --- required by a bound in this function
@@ -24,7 +15,7 @@
    |               ^^^^^ required by this bound in `foo`
 
 error[E0277]: `V` is not an iterator
-  --> $DIR/bad-sized-cond.rs:20:5
+  --> $DIR/bad-sized-cond.rs:19:5
    |
 LL |     bar();
    |     ^^^^^ `V` is not an iterator
@@ -32,7 +23,7 @@
    = help: the trait `Iterator` is not implemented for `V`
    = note: required for `V` to implement `IntoIterator`
 note: required by a bound in `bar`
-  --> $DIR/bad-sized-cond.rs:12:15
+  --> $DIR/bad-sized-cond.rs:11:15
    |
 LL | pub fn bar()
    |        --- required by a bound in this function
@@ -41,7 +32,7 @@
    |               ^^^^^^^^^^^^ required by this bound in `bar`
 
 error[E0277]: the size for values of type `V` cannot be known at compilation time
-  --> $DIR/bad-sized-cond.rs:20:5
+  --> $DIR/bad-sized-cond.rs:19:5
    |
 LL |     bar();
    |     ^^^^^ doesn't have a size known at compile-time
@@ -49,7 +40,7 @@
    = help: the trait `Sized` is not implemented for `V`
    = note: required for `V` to implement `IntoIterator`
 note: required by a bound in `bar`
-  --> $DIR/bad-sized-cond.rs:12:15
+  --> $DIR/bad-sized-cond.rs:11:15
    |
 LL | pub fn bar()
    |        --- required by a bound in this function
@@ -57,6 +48,6 @@
 LL |     for<V> V: IntoIterator,
    |               ^^^^^^^^^^^^ required by this bound in `bar`
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.rs b/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.rs
index b61a21e..8ad2ecf 100644
--- a/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.rs
+++ b/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.rs
@@ -1,7 +1,5 @@
 #![feature(generic_const_exprs)]
-//~^ WARN the feature `generic_const_exprs` is incomplete
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 // Test for <https://github.com/rust-lang/rust/issues/115497>,
 // which originally relied on associated_type_bounds, but was
diff --git a/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.stderr b/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.stderr
index e891df3..0f0d2af 100644
--- a/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.stderr
+++ b/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.stderr
@@ -1,40 +1,23 @@
 error: late-bound const parameters cannot be used currently
-  --> $DIR/bad-suggestion-on-missing-assoc.rs:20:15
+  --> $DIR/bad-suggestion-on-missing-assoc.rs:18:15
    |
 LL |     for<const N: u8 = { T::A }> T: TraitA<AsA = impl TraitB<AsB = impl TraitC>>,
    |               ^
 
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/bad-suggestion-on-missing-assoc.rs:1:12
-   |
-LL | #![feature(generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/bad-suggestion-on-missing-assoc.rs:3:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-
 error: defaults for generic parameters are not allowed in `for<...>` binders
-  --> $DIR/bad-suggestion-on-missing-assoc.rs:20:9
+  --> $DIR/bad-suggestion-on-missing-assoc.rs:18:9
    |
 LL |     for<const N: u8 = { T::A }> T: TraitA<AsA = impl TraitB<AsB = impl TraitC>>,
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0562]: `impl Trait` is not allowed in bounds
-  --> $DIR/bad-suggestion-on-missing-assoc.rs:20:49
+  --> $DIR/bad-suggestion-on-missing-assoc.rs:18:49
    |
 LL |     for<const N: u8 = { T::A }> T: TraitA<AsA = impl TraitB<AsB = impl TraitC>>,
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
-error: aborting due to 3 previous errors; 2 warnings emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0562`.
diff --git a/tests/ui/traits/non_lifetime_binders/basic.rs b/tests/ui/traits/non_lifetime_binders/basic.rs
index 09c0244..893bfd8 100644
--- a/tests/ui/traits/non_lifetime_binders/basic.rs
+++ b/tests/ui/traits/non_lifetime_binders/basic.rs
@@ -3,7 +3,6 @@
 
 #![feature(sized_hierarchy)]
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 use std::marker::PointeeSized;
 
diff --git a/tests/ui/traits/non_lifetime_binders/basic.stderr b/tests/ui/traits/non_lifetime_binders/basic.stderr
deleted file mode 100644
index 9f2df22..0000000
--- a/tests/ui/traits/non_lifetime_binders/basic.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/basic.rs:5:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs
index 13f9f19..894f11c 100644
--- a/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs
@@ -1,5 +1,4 @@
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 pub fn bar()
 where
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr
index 608e813..7383a55 100644
--- a/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr
@@ -1,5 +1,5 @@
 error[E0425]: cannot find type `V` in this scope
-  --> $DIR/binder-defaults-112547.rs:10:4
+  --> $DIR/binder-defaults-112547.rs:9:4
    |
 LL | }> V: IntoIterator
    |    ^ not found in this scope
@@ -10,22 +10,13 @@
    |           +++
 
 error: late-bound const parameters cannot be used currently
-  --> $DIR/binder-defaults-112547.rs:6:15
+  --> $DIR/binder-defaults-112547.rs:5:15
    |
 LL |     for<const N: usize = {
    |               ^
 
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/binder-defaults-112547.rs:1:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: defaults for generic parameters are not allowed in `for<...>` binders
-  --> $DIR/binder-defaults-112547.rs:6:9
+  --> $DIR/binder-defaults-112547.rs:5:9
    |
 LL |       for<const N: usize = {
    |  _________^
@@ -35,6 +26,6 @@
 LL | | }> V: IntoIterator
    | |_^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs
index bdfe41ca..509bdfc 100644
--- a/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs
@@ -1,6 +1,4 @@
 #![feature(non_lifetime_binders, generic_const_exprs)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
-//~| WARN the feature `generic_const_exprs` is incomplete
 
 fn fun()
 where
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr
index 947dd3a..4fb7c26 100644
--- a/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr
@@ -1,37 +1,20 @@
 error: late-bound const parameters cannot be used currently
-  --> $DIR/binder-defaults-119489.rs:7:23
+  --> $DIR/binder-defaults-119489.rs:5:23
    |
 LL |     for<T = (), const N: usize = 1> ():,
    |                       ^
 
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/binder-defaults-119489.rs:1:12
-   |
-LL | #![feature(non_lifetime_binders, generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/binder-defaults-119489.rs:1:34
-   |
-LL | #![feature(non_lifetime_binders, generic_const_exprs)]
-   |                                  ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-
 error: defaults for generic parameters are not allowed in `for<...>` binders
-  --> $DIR/binder-defaults-119489.rs:7:9
+  --> $DIR/binder-defaults-119489.rs:5:9
    |
 LL |     for<T = (), const N: usize = 1> ():,
    |         ^^^^^^
 
 error: defaults for generic parameters are not allowed in `for<...>` binders
-  --> $DIR/binder-defaults-119489.rs:7:17
+  --> $DIR/binder-defaults-119489.rs:5:17
    |
 LL |     for<T = (), const N: usize = 1> ():,
    |                 ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors; 2 warnings emitted
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.rs b/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.rs
index 22044c2..a2a926e 100644
--- a/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.rs
+++ b/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.rs
@@ -3,7 +3,6 @@
 
 #![feature(sized_hierarchy)]
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 use std::marker::PointeeSized;
 
diff --git a/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.stderr b/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.stderr
index 8270fbe..0277abf 100644
--- a/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.stderr
+++ b/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.stderr
@@ -1,31 +1,22 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/diagnostic-hir-wf-check.rs:5:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0277]: the trait bound `(): B` is not satisfied
-  --> $DIR/diagnostic-hir-wf-check.rs:16:12
+  --> $DIR/diagnostic-hir-wf-check.rs:15:12
    |
 LL | fn b() -> (W<()>, impl for<C> A<C>) { (W(()), ()) }
    |            ^^^^^ the trait `B` is not implemented for `()`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/diagnostic-hir-wf-check.rs:13:1
+  --> $DIR/diagnostic-hir-wf-check.rs:12:1
    |
 LL | trait B {}
    | ^^^^^^^
 note: required by a bound in `W`
-  --> $DIR/diagnostic-hir-wf-check.rs:14:13
+  --> $DIR/diagnostic-hir-wf-check.rs:13:13
    |
 LL | struct W<T: B>(T);
    |             ^ required by this bound in `W`
 
 error[E0277]: the trait bound `(): B` is not satisfied
-  --> $DIR/diagnostic-hir-wf-check.rs:16:42
+  --> $DIR/diagnostic-hir-wf-check.rs:15:42
    |
 LL | fn b() -> (W<()>, impl for<C> A<C>) { (W(()), ()) }
    |                                        - ^^ the trait `B` is not implemented for `()`
@@ -33,33 +24,33 @@
    |                                        required by a bound introduced by this call
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/diagnostic-hir-wf-check.rs:13:1
+  --> $DIR/diagnostic-hir-wf-check.rs:12:1
    |
 LL | trait B {}
    | ^^^^^^^
 note: required by a bound in `W`
-  --> $DIR/diagnostic-hir-wf-check.rs:14:13
+  --> $DIR/diagnostic-hir-wf-check.rs:13:13
    |
 LL | struct W<T: B>(T);
    |             ^ required by this bound in `W`
 
 error[E0277]: the trait bound `(): B` is not satisfied
-  --> $DIR/diagnostic-hir-wf-check.rs:16:40
+  --> $DIR/diagnostic-hir-wf-check.rs:15:40
    |
 LL | fn b() -> (W<()>, impl for<C> A<C>) { (W(()), ()) }
    |                                        ^^^^^ the trait `B` is not implemented for `()`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/diagnostic-hir-wf-check.rs:13:1
+  --> $DIR/diagnostic-hir-wf-check.rs:12:1
    |
 LL | trait B {}
    | ^^^^^^^
 note: required by a bound in `W`
-  --> $DIR/diagnostic-hir-wf-check.rs:14:13
+  --> $DIR/diagnostic-hir-wf-check.rs:13:13
    |
 LL | struct W<T: B>(T);
    |             ^ required by this bound in `W`
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.no.stderr b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.no.stderr
index 1f13207..9a4d36a 100644
--- a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.no.stderr
+++ b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.no.stderr
@@ -1,24 +1,15 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/drop-impl-pred.rs:6:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0367]: `Drop` impl requires `H: Foo` but the struct it is implemented for does not
-  --> $DIR/drop-impl-pred.rs:19:15
+  --> $DIR/drop-impl-pred.rs:18:15
    |
 LL |     for<H> H: Foo,
    |               ^^^
    |
 note: the implementor must specify the same requirement
-  --> $DIR/drop-impl-pred.rs:12:1
+  --> $DIR/drop-impl-pred.rs:11:1
    |
 LL | struct Bar<T>(T) where T: Foo;
    | ^^^^^^^^^^^^^
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0367`.
diff --git a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.rs b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.rs
index db8f3de..3444f10 100644
--- a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.rs
+++ b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.rs
@@ -4,7 +4,6 @@
 // Issue 110557
 
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 pub trait Foo {}
 
diff --git a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.yes.stderr b/tests/ui/traits/non_lifetime_binders/drop-impl-pred.yes.stderr
deleted file mode 100644
index 165cf2e..0000000
--- a/tests/ui/traits/non_lifetime_binders/drop-impl-pred.yes.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/drop-impl-pred.rs:6:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/non_lifetime_binders/fail.rs b/tests/ui/traits/non_lifetime_binders/fail.rs
index 460f689..7d916c4 100644
--- a/tests/ui/traits/non_lifetime_binders/fail.rs
+++ b/tests/ui/traits/non_lifetime_binders/fail.rs
@@ -1,7 +1,6 @@
 // Error reporting for where `for<T> T: Trait` doesn't hold
 
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 trait Trait {}
 
diff --git a/tests/ui/traits/non_lifetime_binders/fail.stderr b/tests/ui/traits/non_lifetime_binders/fail.stderr
index 9a324c9..38a0eab 100644
--- a/tests/ui/traits/non_lifetime_binders/fail.stderr
+++ b/tests/ui/traits/non_lifetime_binders/fail.stderr
@@ -1,25 +1,16 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/fail.rs:3:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0277]: the trait bound `T: Trait` is not satisfied
-  --> $DIR/fail.rs:19:5
+  --> $DIR/fail.rs:18:5
    |
 LL |     fail();
    |     ^^^^^^ the trait `Trait` is not implemented for `T`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/fail.rs:6:1
+  --> $DIR/fail.rs:5:1
    |
 LL | trait Trait {}
    | ^^^^^^^^^^^
 note: required by a bound in `fail`
-  --> $DIR/fail.rs:10:15
+  --> $DIR/fail.rs:9:15
    |
 LL | fn fail()
    |    ---- required by a bound in this function
@@ -28,14 +19,14 @@
    |               ^^^^^ required by this bound in `fail`
 
 error[E0277]: `T` cannot be sent between threads safely
-  --> $DIR/fail.rs:21:5
+  --> $DIR/fail.rs:20:5
    |
 LL |     auto_trait();
    |     ^^^^^^^^^^^^ `T` cannot be sent between threads safely
    |
    = help: the trait `Send` is not implemented for `T`
 note: required by a bound in `auto_trait`
-  --> $DIR/fail.rs:15:15
+  --> $DIR/fail.rs:14:15
    |
 LL | fn auto_trait()
    |    ---------- required by a bound in this function
@@ -43,6 +34,6 @@
 LL |     for<T> T: Send,
    |               ^^^^ required by this bound in `auto_trait`
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.rs b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.rs
index 96a7424..0c4347b 100644
--- a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.rs
+++ b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.rs
@@ -1,5 +1,4 @@
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 fn auto_trait()
 where
diff --git a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr
index abbdecf..b621f5c 100644
--- a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr
+++ b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr
@@ -1,21 +1,12 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/foreach-partial-eq.rs:1:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0277]: can't compare `T` with `T`
-  --> $DIR/foreach-partial-eq.rs:10:5
+  --> $DIR/foreach-partial-eq.rs:9:5
    |
 LL |     auto_trait();
    |     ^^^^^^^^^^^^ no implementation for `T < T` and `T > T`
    |
    = help: the trait `PartialOrd` is not implemented for `T`
 note: required by a bound in `auto_trait`
-  --> $DIR/foreach-partial-eq.rs:6:27
+  --> $DIR/foreach-partial-eq.rs:5:27
    |
 LL | fn auto_trait()
    |    ---------- required by a bound in this function
@@ -23,6 +14,6 @@
 LL |     for<T> T: PartialEq + PartialOrd,
    |                           ^^^^^^^^^^ required by this bound in `auto_trait`
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.rs b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.rs
index 94733f8..e8b7139 100644
--- a/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.rs
+++ b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.rs
@@ -1,6 +1,4 @@
 #![feature(non_lifetime_binders, generic_const_exprs)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
-//~| WARN the feature `generic_const_exprs` is incomplete
 
 fn foo() -> usize
 where
diff --git a/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr
index cc48288..cd8bc33 100644
--- a/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr
+++ b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr
@@ -1,27 +1,10 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/late-bound-in-anon-ct.rs:1:12
-   |
-LL | #![feature(non_lifetime_binders, generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/late-bound-in-anon-ct.rs:1:34
-   |
-LL | #![feature(non_lifetime_binders, generic_const_exprs)]
-   |                                  ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-
 error: cannot capture late-bound type parameter in constant
-  --> $DIR/late-bound-in-anon-ct.rs:7:27
+  --> $DIR/late-bound-in-anon-ct.rs:5:27
    |
 LL |     for<T> [i32; { let _: T = todo!(); 0 }]:,
    |         -                 ^
    |         |
    |         parameter defined here
 
-error: aborting due to 1 previous error; 2 warnings emitted
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/non_lifetime_binders/late-const-param-wf.rs b/tests/ui/traits/non_lifetime_binders/late-const-param-wf.rs
index 2d44388..75117e1 100644
--- a/tests/ui/traits/non_lifetime_binders/late-const-param-wf.rs
+++ b/tests/ui/traits/non_lifetime_binders/late-const-param-wf.rs
@@ -1,5 +1,4 @@
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 fn b()
 where
diff --git a/tests/ui/traits/non_lifetime_binders/late-const-param-wf.stderr b/tests/ui/traits/non_lifetime_binders/late-const-param-wf.stderr
index 136d533..98558dc 100644
--- a/tests/ui/traits/non_lifetime_binders/late-const-param-wf.stderr
+++ b/tests/ui/traits/non_lifetime_binders/late-const-param-wf.stderr
@@ -1,17 +1,8 @@
 error: late-bound const parameters cannot be used currently
-  --> $DIR/late-const-param-wf.rs:6:15
+  --> $DIR/late-const-param-wf.rs:5:15
    |
 LL |     for<const C: usize> [(); C]: Copy,
    |               ^
 
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/late-const-param-wf.rs:1:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/non_lifetime_binders/method-probe.rs b/tests/ui/traits/non_lifetime_binders/method-probe.rs
index 5f8e314..3d16252 100644
--- a/tests/ui/traits/non_lifetime_binders/method-probe.rs
+++ b/tests/ui/traits/non_lifetime_binders/method-probe.rs
@@ -1,7 +1,6 @@
 //@ check-pass
 
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 trait Foo: for<T> Bar<T> {}
 
diff --git a/tests/ui/traits/non_lifetime_binders/method-probe.stderr b/tests/ui/traits/non_lifetime_binders/method-probe.stderr
deleted file mode 100644
index 8f61792..0000000
--- a/tests/ui/traits/non_lifetime_binders/method-probe.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/method-probe.rs:3:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs
index 50f0152e..1e645f3 100644
--- a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs
+++ b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.rs
@@ -1,5 +1,4 @@
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 fn f()
 where
diff --git a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr
index 0229530..4de30e7 100644
--- a/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr
+++ b/tests/ui/traits/non_lifetime_binders/missing-assoc-item.stderr
@@ -1,14 +1,5 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/missing-assoc-item.rs:1:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0223]: ambiguous associated type
-  --> $DIR/missing-assoc-item.rs:6:12
+  --> $DIR/missing-assoc-item.rs:5:12
    |
 LL |     for<B> B::Item: Send,
    |            ^^^^^^^
@@ -19,6 +10,6 @@
 LL +     for<B> <B as Example>::Item: Send,
    |
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0223`.
diff --git a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs
index e9ae00d..e5ab8d6 100644
--- a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs
+++ b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs
@@ -1,5 +1,4 @@
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 trait Trait<Input> {
     type Assoc;
diff --git a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr
index 8304469..12eb6c3 100644
--- a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr
+++ b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr
@@ -1,17 +1,8 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/nested-apit-mentioning-outer-bound-var.rs:1:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: `impl Trait` can only mention type parameters from an fn or impl
-  --> $DIR/nested-apit-mentioning-outer-bound-var.rs:8:52
+  --> $DIR/nested-apit-mentioning-outer-bound-var.rs:7:52
    |
 LL | fn uwu(_: impl for<T> Trait<(), Assoc = impl Trait<T>>) {}
    |                    - type parameter declared here  ^
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.rs b/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.rs
index e776d5f..4ccf4db 100644
--- a/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.rs
+++ b/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.rs
@@ -2,6 +2,5 @@
 //@ compile-flags: --crate-type=lib
 
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 pub fn f<T>() where for<U> (T, U): Copy {}
diff --git a/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.stderr b/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.stderr
deleted file mode 100644
index 667575b..0000000
--- a/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/object-lifetime-default-for-late.rs:4:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.rs b/tests/ui/traits/non_lifetime_binders/on-dyn.rs
index 8fb7dd2..a081974 100644
--- a/tests/ui/traits/non_lifetime_binders/on-dyn.rs
+++ b/tests/ui/traits/non_lifetime_binders/on-dyn.rs
@@ -1,7 +1,6 @@
 // Tests to make sure that we reject polymorphic dyn trait.
 
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 trait Test<T> {}
 
diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.stderr b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr
index 2d330f6..8d7cb51 100644
--- a/tests/ui/traits/non_lifetime_binders/on-dyn.stderr
+++ b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr
@@ -1,17 +1,8 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/on-dyn.rs:3:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: late-bound type parameter not allowed on trait object types
-  --> $DIR/on-dyn.rs:8:30
+  --> $DIR/on-dyn.rs:7:30
    |
 LL | fn foo() -> &'static dyn for<T> Test<T> {
    |                              ^
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.rs b/tests/ui/traits/non_lifetime_binders/on-ptr.rs
index 0aaff52..96c155a 100644
--- a/tests/ui/traits/non_lifetime_binders/on-ptr.rs
+++ b/tests/ui/traits/non_lifetime_binders/on-ptr.rs
@@ -1,7 +1,6 @@
 // Tests to make sure that we reject polymorphic fn ptrs.
 
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 fn foo() -> for<T> fn(T) {
     //~^ ERROR late-bound type parameter not allowed on function pointer types
diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.stderr b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr
index fbd723a..680df6d 100644
--- a/tests/ui/traits/non_lifetime_binders/on-ptr.stderr
+++ b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr
@@ -1,17 +1,8 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/on-ptr.rs:3:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: late-bound type parameter not allowed on function pointer types
-  --> $DIR/on-ptr.rs:6:17
+  --> $DIR/on-ptr.rs:5:17
    |
 LL | fn foo() -> for<T> fn(T) {
    |                 ^
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/non_lifetime_binders/on-rpit.rs b/tests/ui/traits/non_lifetime_binders/on-rpit.rs
index 1364f63..092f838 100644
--- a/tests/ui/traits/non_lifetime_binders/on-rpit.rs
+++ b/tests/ui/traits/non_lifetime_binders/on-rpit.rs
@@ -2,7 +2,6 @@
 
 #![feature(sized_hierarchy)]
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 use std::marker::PointeeSized;
 
diff --git a/tests/ui/traits/non_lifetime_binders/on-rpit.stderr b/tests/ui/traits/non_lifetime_binders/on-rpit.stderr
deleted file mode 100644
index c8396c3..0000000
--- a/tests/ui/traits/non_lifetime_binders/on-rpit.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/on-rpit.rs:4:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.bad.stderr b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.bad.stderr
index d51927a..f8de7c7 100644
--- a/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.bad.stderr
+++ b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.bad.stderr
@@ -1,14 +1,5 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/placeholders-dont-outlive-static.rs:6:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0310]: the placeholder type `T` may not live long enough
-  --> $DIR/placeholders-dont-outlive-static.rs:13:5
+  --> $DIR/placeholders-dont-outlive-static.rs:12:5
    |
 LL |     foo();
    |     ^^^^^
@@ -21,6 +12,6 @@
 LL | fn bad() where T: 'static {
    |          ++++++++++++++++
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0310`.
diff --git a/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.good.stderr b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.good.stderr
index bc1a199..cc76a8e 100644
--- a/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.good.stderr
+++ b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.good.stderr
@@ -1,14 +1,5 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/placeholders-dont-outlive-static.rs:6:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0310]: the placeholder type `T` may not live long enough
-  --> $DIR/placeholders-dont-outlive-static.rs:19:5
+  --> $DIR/placeholders-dont-outlive-static.rs:18:5
    |
 LL |     foo();
    |     ^^^^^
@@ -21,6 +12,6 @@
 LL | fn good() where for<T> T: 'static, T: 'static {
    |                                  ++++++++++++
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0310`.
diff --git a/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.rs b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.rs
index 3133d6a..ca39eb6 100644
--- a/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.rs
+++ b/tests/ui/traits/non_lifetime_binders/placeholders-dont-outlive-static.rs
@@ -4,7 +4,6 @@
 // `for<T> T: 'static` doesn't imply itself when processing outlives obligations
 
 #![feature(non_lifetime_binders)]
-//[bad]~^ WARN the feature `non_lifetime_binders` is incomplete
 
 fn foo() where for<T> T: 'static {}
 
diff --git a/tests/ui/traits/non_lifetime_binders/shadowed.rs b/tests/ui/traits/non_lifetime_binders/shadowed.rs
index 1c480e3..ff8d3f7 100644
--- a/tests/ui/traits/non_lifetime_binders/shadowed.rs
+++ b/tests/ui/traits/non_lifetime_binders/shadowed.rs
@@ -1,5 +1,4 @@
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 fn function<T>() where for<T> (): Sized {}
 //~^ ERROR the name `T` is already used for a generic parameter
diff --git a/tests/ui/traits/non_lifetime_binders/shadowed.stderr b/tests/ui/traits/non_lifetime_binders/shadowed.stderr
index 59a073a..982bd93 100644
--- a/tests/ui/traits/non_lifetime_binders/shadowed.stderr
+++ b/tests/ui/traits/non_lifetime_binders/shadowed.stderr
@@ -1,5 +1,5 @@
 error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
-  --> $DIR/shadowed.rs:4:28
+  --> $DIR/shadowed.rs:3:28
    |
 LL | fn function<T>() where for<T> (): Sized {}
    |             -              ^ already used
@@ -7,7 +7,7 @@
    |             first use of `T`
 
 error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
-  --> $DIR/shadowed.rs:7:31
+  --> $DIR/shadowed.rs:6:31
    |
 LL | struct Struct<T>(T) where for<T> (): Sized;
    |               -               ^ already used
@@ -15,7 +15,7 @@
    |               first use of `T`
 
 error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
-  --> $DIR/shadowed.rs:11:27
+  --> $DIR/shadowed.rs:10:27
    |
 LL | impl<T> Struct<T> {
    |      - first use of `T`
@@ -23,22 +23,13 @@
    |                           ^ already used
 
 error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
-  --> $DIR/shadowed.rs:15:28
+  --> $DIR/shadowed.rs:14:28
    |
 LL | fn repeated() where for<T, T> (): Sized {}
    |                         -  ^ already used
    |                         |
    |                         first use of `T`
 
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/shadowed.rs:1:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0403`.
diff --git a/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.rs b/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.rs
index e4c3b4d..981edc7 100644
--- a/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.rs
+++ b/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.rs
@@ -1,7 +1,6 @@
 //@ check-pass
 
 #![feature(non_lifetime_binders)]
-//~^ WARN is incomplete and may not be safe
 
 pub fn foo()
 where
diff --git a/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.stderr b/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.stderr
deleted file mode 100644
index e75d812..0000000
--- a/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/sized-late-bound-issue-114872.rs:3:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs
index aab5479..3ef1201 100644
--- a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs
+++ b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs
@@ -1,6 +1,5 @@
 #![feature(sized_hierarchy)]
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 use std::marker::PointeeSized;
 
diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr
index b32915f..f118278 100644
--- a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr
+++ b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr
@@ -1,21 +1,12 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/supertrait-dyn-compatibility.rs:2:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0038]: the trait `Foo` is not dyn compatible
-  --> $DIR/supertrait-dyn-compatibility.rs:22:17
+  --> $DIR/supertrait-dyn-compatibility.rs:21:17
    |
 LL |     let x: &dyn Foo = &();
    |                 ^^^ `Foo` is not dyn compatible
    |
 note: for a trait to be dyn compatible it needs to allow building a vtable
       for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/supertrait-dyn-compatibility.rs:7:12
+  --> $DIR/supertrait-dyn-compatibility.rs:6:12
    |
 LL | trait Foo: for<T> Bar<T> {}
    |       ---  ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables
@@ -23,6 +14,6 @@
    |       this trait is not dyn compatible...
    = help: only type `()` implements `Foo`; consider using it directly instead.
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
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 c325718..e70ff4a 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
@@ -1,12 +1,3 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/type-match-with-late-bound.rs:6:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0309]: the placeholder type `F` may not live long enough
   --> $DIR/type-match-with-late-bound.rs:8:32
    |
@@ -54,6 +45,6 @@
 LL |     for<F> F: 'a, F: 'a
    |                   +++++
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0309`.
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr
deleted file mode 100644
index 6551253..0000000
--- a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unifying-placeholders-in-query-response-2.rs:7:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr
deleted file mode 100644
index 6551253..0000000
--- a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unifying-placeholders-in-query-response-2.rs:7:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs
index d900bd4..2962a5b 100644
--- a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs
+++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs
@@ -5,7 +5,6 @@
 
 #![feature(sized_hierarchy)]
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 use std::marker::PointeeSized;
 
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr
deleted file mode 100644
index fecdc86..0000000
--- a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unifying-placeholders-in-query-response.rs:7:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr
deleted file mode 100644
index fecdc86..0000000
--- a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unifying-placeholders-in-query-response.rs:7:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs
index 04e3453..caad8bf 100644
--- a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs
+++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs
@@ -5,7 +5,6 @@
 
 #![feature(sized_hierarchy)]
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 use std::marker::PointeeSized;
 
diff --git a/tests/ui/traits/non_lifetime_binders/universe-error1.rs b/tests/ui/traits/non_lifetime_binders/universe-error1.rs
index b4e8e3a..1c99794 100644
--- a/tests/ui/traits/non_lifetime_binders/universe-error1.rs
+++ b/tests/ui/traits/non_lifetime_binders/universe-error1.rs
@@ -1,6 +1,5 @@
 #![feature(sized_hierarchy)]
 #![feature(non_lifetime_binders)]
-//~^ WARN the feature `non_lifetime_binders` is incomplete
 
 use std::marker::PointeeSized;
 
diff --git a/tests/ui/traits/non_lifetime_binders/universe-error1.stderr b/tests/ui/traits/non_lifetime_binders/universe-error1.stderr
index b997e73..899378b 100644
--- a/tests/ui/traits/non_lifetime_binders/universe-error1.stderr
+++ b/tests/ui/traits/non_lifetime_binders/universe-error1.stderr
@@ -1,20 +1,11 @@
-warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/universe-error1.rs:2:12
-   |
-LL | #![feature(non_lifetime_binders)]
-   |            ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0277]: the trait bound `T: Other<_>` is not satisfied
-  --> $DIR/universe-error1.rs:17:11
+  --> $DIR/universe-error1.rs:16:11
    |
 LL |     foo::<_>();
    |           ^ the trait `Other<_>` is not implemented for `T`
    |
 note: required by a bound in `foo`
-  --> $DIR/universe-error1.rs:14:15
+  --> $DIR/universe-error1.rs:13:15
    |
 LL | fn foo<U: PointeeSized>()
    |    --- required by a bound in this function
@@ -22,6 +13,6 @@
 LL |     for<T> T: Other<U> {}
    |               ^^^^^^^^ required by this bound in `foo`
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/question-mark-result-err-mismatch.rs b/tests/ui/traits/question-mark-result-err-mismatch.rs
index dfea4b9..f9ca6e0 100644
--- a/tests/ui/traits/question-mark-result-err-mismatch.rs
+++ b/tests/ui/traits/question-mark-result-err-mismatch.rs
@@ -35,7 +35,7 @@ fn bar() -> Result<(), String> { //~ NOTE expected `String` because of this
     //~| NOTE the trait `From<()>` is not implemented for `String`
     //~| NOTE the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
     //~| NOTE required for `Result<(), String>` to implement `FromResidual<Result<Infallible, ()>>`
-    //~| HELP the following other types implement trait `From<T>`:
+    //~| HELP `String` implements trait `From<T>`:
     Ok(one)
 }
 
diff --git a/tests/ui/traits/question-mark-result-err-mismatch.stderr b/tests/ui/traits/question-mark-result-err-mismatch.stderr
index be3f17c..3739b50 100644
--- a/tests/ui/traits/question-mark-result-err-mismatch.stderr
+++ b/tests/ui/traits/question-mark-result-err-mismatch.stderr
@@ -30,13 +30,13 @@
    |          this can't be annotated with `?` because it has type `Result<_, ()>`
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
-   = help: the following other types implement trait `From<T>`:
-             `String` implements `From<&String>`
-             `String` implements `From<&mut str>`
-             `String` implements `From<&str>`
-             `String` implements `From<Box<str>>`
-             `String` implements `From<Cow<'_, str>>`
-             `String` implements `From<char>`
+   = help: `String` implements trait `From<T>`:
+             From<&String>
+             From<&mut str>
+             From<&str>
+             From<Box<str>>
+             From<Cow<'_, str>>
+             From<char>
    = note: required for `Result<(), String>` to implement `FromResidual<Result<Infallible, ()>>`
 
 error[E0277]: `?` couldn't convert the error to `String`
diff --git a/tests/ui/traits/question-mark-span-144304.stderr b/tests/ui/traits/question-mark-span-144304.stderr
index a412da0..37452cd 100644
--- a/tests/ui/traits/question-mark-span-144304.stderr
+++ b/tests/ui/traits/question-mark-span-144304.stderr
@@ -9,12 +9,12 @@
    |     this has type `Result<_, &str>`
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
-   = help: the following other types implement trait `From<T>`:
-             `i32` implements `From<bool>`
-             `i32` implements `From<i16>`
-             `i32` implements `From<i8>`
-             `i32` implements `From<u16>`
-             `i32` implements `From<u8>`
+   = help: `i32` implements trait `From<T>`:
+             From<bool>
+             From<i16>
+             From<i8>
+             From<u16>
+             From<u8>
 
 error[E0277]: `?` couldn't convert the error to `i32`
   --> $DIR/question-mark-span-144304.rs:4:42
@@ -29,12 +29,12 @@
    |     this has type `Result<_, &str>`
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
-   = help: the following other types implement trait `From<T>`:
-             `i32` implements `From<bool>`
-             `i32` implements `From<i16>`
-             `i32` implements `From<i8>`
-             `i32` implements `From<u16>`
-             `i32` implements `From<u8>`
+   = help: `i32` implements trait `From<T>`:
+             From<bool>
+             From<i16>
+             From<i8>
+             From<u16>
+             From<u8>
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/transmutability/dont-assume-err-is-yes-issue-126377.rs b/tests/ui/transmutability/dont-assume-err-is-yes-issue-126377.rs
index eeb0777..67e5760 100644
--- a/tests/ui/transmutability/dont-assume-err-is-yes-issue-126377.rs
+++ b/tests/ui/transmutability/dont-assume-err-is-yes-issue-126377.rs
@@ -1,6 +1,5 @@
 #![feature(transmutability)]
 #![feature(generic_const_exprs)]
-//~^ WARN the feature `generic_const_exprs` is incomplete
 
 use std::mem::{Assume, TransmuteFrom};
 
diff --git a/tests/ui/transmutability/dont-assume-err-is-yes-issue-126377.stderr b/tests/ui/transmutability/dont-assume-err-is-yes-issue-126377.stderr
index 6f7e9e1..5c59fb9 100644
--- a/tests/ui/transmutability/dont-assume-err-is-yes-issue-126377.stderr
+++ b/tests/ui/transmutability/dont-assume-err-is-yes-issue-126377.stderr
@@ -1,26 +1,17 @@
-warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/dont-assume-err-is-yes-issue-126377.rs:2:12
-   |
-LL | #![feature(generic_const_exprs)]
-   |            ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0308]: mismatched types
-  --> $DIR/dont-assume-err-is-yes-issue-126377.rs:14:23
+  --> $DIR/dont-assume-err-is-yes-issue-126377.rs:13:23
    |
 LL |     is_transmutable::<{}>();
    |                       ^^ expected `bool`, found `()`
 
 error[E0277]: the trait bound `(): TransmuteFrom<(), { Assume::SAFETY }>` is not satisfied
-  --> $DIR/dont-assume-err-is-yes-issue-126377.rs:14:23
+  --> $DIR/dont-assume-err-is-yes-issue-126377.rs:13:23
    |
 LL |     is_transmutable::<{}>();
    |                       ^^ the nightly-only, unstable trait `TransmuteFrom<(), { Assume::SAFETY }>` is not implemented for `()`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/dont-assume-err-is-yes-issue-126377.rs:9:9
+  --> $DIR/dont-assume-err-is-yes-issue-126377.rs:8:9
    |
 LL | pub fn is_transmutable<const ASSUME_ALIGNMENT: bool>()
    |        --------------- required by a bound in this function
@@ -28,7 +19,7 @@
 LL |     (): TransmuteFrom<(), { Assume::SAFETY }>,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/transmutability/non_scalar_alignment_value.rs b/tests/ui/transmutability/non_scalar_alignment_value.rs
index 45c9e61..3b21cdd 100644
--- a/tests/ui/transmutability/non_scalar_alignment_value.rs
+++ b/tests/ui/transmutability/non_scalar_alignment_value.rs
@@ -1,5 +1,4 @@
 #![feature(min_generic_const_args)]
-//~^ WARN the feature `min_generic_const_args` is incomplete
 
 #![feature(transmutability)]
 
diff --git a/tests/ui/transmutability/non_scalar_alignment_value.stderr b/tests/ui/transmutability/non_scalar_alignment_value.stderr
index d22c6d0..99d1852 100644
--- a/tests/ui/transmutability/non_scalar_alignment_value.stderr
+++ b/tests/ui/transmutability/non_scalar_alignment_value.stderr
@@ -1,35 +1,26 @@
-warning: the feature `min_generic_const_args` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/non_scalar_alignment_value.rs:1:12
-   |
-LL | #![feature(min_generic_const_args)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error: struct expression with missing field initialiser for `alignment`
-  --> $DIR/non_scalar_alignment_value.rs:15:32
+  --> $DIR/non_scalar_alignment_value.rs:14:32
    |
 LL |                     alignment: Assume {},
    |                                ^^^^^^^^^
 
 error: struct expression with missing field initialiser for `lifetimes`
-  --> $DIR/non_scalar_alignment_value.rs:15:32
+  --> $DIR/non_scalar_alignment_value.rs:14:32
    |
 LL |                     alignment: Assume {},
    |                                ^^^^^^^^^
 
 error: struct expression with missing field initialiser for `safety`
-  --> $DIR/non_scalar_alignment_value.rs:15:32
+  --> $DIR/non_scalar_alignment_value.rs:14:32
    |
 LL |                     alignment: Assume {},
    |                                ^^^^^^^^^
 
 error: struct expression with missing field initialiser for `validity`
-  --> $DIR/non_scalar_alignment_value.rs:15:32
+  --> $DIR/non_scalar_alignment_value.rs:14:32
    |
 LL |                     alignment: Assume {},
    |                                ^^^^^^^^^
 
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr
index a566800..e1cc7a4 100644
--- a/tests/ui/try-trait/bad-interconversion.stderr
+++ b/tests/ui/try-trait/bad-interconversion.stderr
@@ -9,16 +9,16 @@
    |        this can't be annotated with `?` because it has type `Result<_, i32>`
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
-help: the following other types implement trait `From<T>`
+help: `u8` implements trait `From<T>`
   --> $SRC_DIR/core/src/convert/num.rs:LL:COL
    |
-   = note: `u8` implements `From<bool>`
+   = note: `From<bool>`
   ::: $SRC_DIR/core/src/convert/num.rs:LL:COL
    |
    = note: in this macro invocation
   --> $SRC_DIR/core/src/ascii/ascii_char.rs:LL:COL
    |
-   = note: `u8` implements `From<std::ascii::Char>`
+   = note: `From<std::ascii::Char>`
   ::: $SRC_DIR/core/src/ascii/ascii_char.rs:LL:COL
    |
    = note: in this macro invocation
diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr
index d17a821..fc6bf3f 100644
--- a/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr
+++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr
@@ -9,14 +9,14 @@
    |
 LL | struct Foo;
    | ^^^^^^^^^^
-help: the following other types implement trait `Trait<T>`
+help: `Foo` implements trait `Trait<T>`
   --> $DIR/constrain_in_projection2.rs:18:1
    |
 LL | impl Trait<()> for Foo {
-   | ^^^^^^^^^^^^^^^^^^^^^^ `Foo` implements `Trait<()>`
+   | ^^^^^^^^^^^^^^^^^^^^^^ `Trait<()>`
 ...
 LL | impl Trait<u32> for Foo {
-   | ^^^^^^^^^^^^^^^^^^^^^^^ `Foo` implements `Trait<u32>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^ `Trait<u32>`
 
 error[E0277]: the trait bound `Foo: Trait<Bar>` is not satisfied
   --> $DIR/constrain_in_projection2.rs:28:13
@@ -29,14 +29,14 @@
    |
 LL | struct Foo;
    | ^^^^^^^^^^
-help: the following other types implement trait `Trait<T>`
+help: `Foo` implements trait `Trait<T>`
   --> $DIR/constrain_in_projection2.rs:18:1
    |
 LL | impl Trait<()> for Foo {
-   | ^^^^^^^^^^^^^^^^^^^^^^ `Foo` implements `Trait<()>`
+   | ^^^^^^^^^^^^^^^^^^^^^^ `Trait<()>`
 ...
 LL | impl Trait<u32> for Foo {
-   | ^^^^^^^^^^^^^^^^^^^^^^^ `Foo` implements `Trait<u32>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^ `Trait<u32>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr
index 4cc69da..6744427 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr
@@ -7,13 +7,13 @@
 LL |     ()
    |     -- return type was inferred to be `()` here
    |
-help: the following other types implement trait `Foo<A>`
+help: `()` implements trait `Foo<A>`
   --> $DIR/nested-tait-inference2.rs:14:1
    |
 LL | impl Foo<()> for () {}
-   | ^^^^^^^^^^^^^^^^^^^ `()` implements `Foo<()>`
+   | ^^^^^^^^^^^^^^^^^^^ `Foo<()>`
 LL | impl Foo<u32> for () {}
-   | ^^^^^^^^^^^^^^^^^^^^ `()` implements `Foo<u32>`
+   | ^^^^^^^^^^^^^^^^^^^^ `Foo<u32>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type/pattern_types/validity.rs b/tests/ui/type/pattern_types/validity.rs
index 8323049..6c630fc 100644
--- a/tests/ui/type/pattern_types/validity.rs
+++ b/tests/ui/type/pattern_types/validity.rs
@@ -8,7 +8,7 @@
 use std::pat::pattern_type;
 
 const BAD: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(0) };
-//~^ ERROR: constructing invalid value: encountered 0
+//~^ ERROR: encountered 0
 
 const BAD_UNINIT: pattern_type!(u32 is 1..) =
     //~^ ERROR: this operation requires initialized memory
@@ -18,22 +18,22 @@
 //~^ ERROR: unable to turn pointer into integer
 
 const BAD_AGGREGATE: (pattern_type!(u32 is 1..), u32) = (unsafe { std::mem::transmute(0) }, 0);
-//~^ ERROR: constructing invalid value at .0: encountered 0
+//~^ ERROR: at .0, encountered 0
 
 struct Foo(Bar);
 struct Bar(pattern_type!(u32 is 1..));
 
 const BAD_FOO: Foo = Foo(Bar(unsafe { std::mem::transmute(0) }));
-//~^ ERROR: constructing invalid value at .0.0: encountered 0
+//~^ ERROR: at .0.0, encountered 0
 
 const CHAR_UNINIT: pattern_type!(char is 'A'..'Z') =
     //~^ ERROR: this operation requires initialized memory
     unsafe { std::mem::transmute(std::mem::MaybeUninit::<u32>::uninit()) };
 
 const CHAR_OOB_PAT: pattern_type!(char is 'A'..'Z') = unsafe { std::mem::transmute('a') };
-//~^ ERROR: constructing invalid value: encountered 97, but expected something in the range 65..=89
+//~^ ERROR: encountered 97, but expected something in the range 65..=89
 
 const CHAR_OOB: pattern_type!(char is 'A'..'Z') = unsafe { std::mem::transmute(u32::MAX) };
-//~^ ERROR: constructing invalid value: encountered 0xffffffff
+//~^ ERROR: encountered 0xffffffff
 
 fn main() {}
diff --git a/tests/ui/type/pattern_types/validity.stderr b/tests/ui/type/pattern_types/validity.stderr
index e19915a..a4fb46c 100644
--- a/tests/ui/type/pattern_types/validity.stderr
+++ b/tests/ui/type/pattern_types/validity.stderr
@@ -1,4 +1,4 @@
-error[E0080]: constructing invalid value: encountered 0, but expected something greater or equal to 1
+error[E0080]: constructing invalid value of type (u32) is 1..: encountered 0, but expected something greater or equal to 1
   --> $DIR/validity.rs:10:1
    |
 LL | const BAD: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(0) };
@@ -28,7 +28,7 @@
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
-error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
+error[E0080]: constructing invalid value of type ((u32) is 1.., u32): at .0, encountered 0, but expected something greater or equal to 1
   --> $DIR/validity.rs:20:1
    |
 LL | const BAD_AGGREGATE: (pattern_type!(u32 is 1..), u32) = (unsafe { std::mem::transmute(0) }, 0);
@@ -39,7 +39,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
+error[E0080]: constructing invalid value of type Foo: at .0.0, encountered 0, but expected something greater or equal to 1
   --> $DIR/validity.rs:26:1
    |
 LL | const BAD_FOO: Foo = Foo(Bar(unsafe { std::mem::transmute(0) }));
@@ -60,7 +60,7 @@
                __ __ __ __                                     │ ░░░░
            }
 
-error[E0080]: constructing invalid value: encountered 97, but expected something in the range 65..=89
+error[E0080]: constructing invalid value of type (char) is 'A'..='Y': encountered 97, but expected something in the range 65..=89
   --> $DIR/validity.rs:33:1
    |
 LL | const CHAR_OOB_PAT: pattern_type!(char is 'A'..'Z') = unsafe { std::mem::transmute('a') };
@@ -71,7 +71,7 @@
                HEX_DUMP
            }
 
-error[E0080]: constructing invalid value: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
+error[E0080]: constructing invalid value of type (char) is 'A'..='Y': encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
   --> $DIR/validity.rs:36:1
    |
 LL | const CHAR_OOB: pattern_type!(char is 'A'..'Z') = unsafe { std::mem::transmute(u32::MAX) };
diff --git a/tests/ui/type/type-ascription-instead-of-initializer.stderr b/tests/ui/type/type-ascription-instead-of-initializer.stderr
index 630e82d..edc38b0 100644
--- a/tests/ui/type/type-ascription-instead-of-initializer.stderr
+++ b/tests/ui/type/type-ascription-instead-of-initializer.stderr
@@ -5,7 +5,12 @@
    |          -                    ^^ expected type
    |          |
    |          while parsing the type for `x`
-   |          help: use `=` if you meant to assign
+   |
+help: use `=` if you meant to assign
+   |
+LL -     let x: Vec::with_capacity(10, 20);
+LL +     let x = Vec::with_capacity(10, 20);
+   |
 
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/type-ascription-instead-of-initializer.rs:2:12
diff --git a/tests/ui/typeck/issue-90101.stderr b/tests/ui/typeck/issue-90101.stderr
index 2e14046..fe9af5a 100644
--- a/tests/ui/typeck/issue-90101.stderr
+++ b/tests/ui/typeck/issue-90101.stderr
@@ -6,12 +6,12 @@
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the following other types implement trait `From<T>`:
-             `PathBuf` implements `From<&T>`
-             `PathBuf` implements `From<Box<Path>>`
-             `PathBuf` implements `From<Cow<'_, Path>>`
-             `PathBuf` implements `From<OsString>`
-             `PathBuf` implements `From<String>`
+   = help: `PathBuf` implements trait `From<T>`:
+             From<&T>
+             From<Box<Path>>
+             From<Cow<'_, Path>>
+             From<OsString>
+             From<String>
    = note: required for `Cow<'_, str>` to implement `Into<PathBuf>`
 note: required by a bound in `func`
   --> $DIR/issue-90101.rs:3:20
diff --git a/tests/ui/union/union-no-derive-suggestion.rs b/tests/ui/union/union-no-derive-suggestion.rs
new file mode 100644
index 0000000..0ccbac3
--- /dev/null
+++ b/tests/ui/union/union-no-derive-suggestion.rs
@@ -0,0 +1,37 @@
+//! Check that we do not suggest using `#[derive(...)]` for unions,
+//! as some traits cannot be autoderived for them.
+//@ dont-require-annotations: NOTE
+
+union U { //~ HELP consider annotating `U` with `#[derive(Clone)]`
+         //~| HELP consider annotating `U` with `#[derive(Copy)]`
+         //~| HELP the trait `Debug` is not implemented for `U`
+         //~| HELP the trait `Default` is not implemented for `U`
+         //~| HELP the trait `Hash` is not implemented for `U`
+    a: u8,
+}
+
+fn x<T: Clone>() {}
+fn y<T: Copy>() {}
+
+fn main() {
+    let u = U { a: 0 };
+    // Debug
+    println!("{u:?}"); //~ ERROR `U` doesn't implement `Debug`
+                       //~| NOTE manually `impl Debug for U`
+    // PartialEq
+    let _ = u == U { a: 0 }; //~ ERROR binary operation `==` cannot be applied to type `U`
+                              //~| NOTE the trait `PartialEq` must be implemented
+    // PartialOrd
+    let _ = u < U { a: 1 }; //~ ERROR binary operation `<` cannot be applied to type `U`
+                             //~| NOTE the trait `PartialOrd` must be implemented
+    // Default
+    let _: U = Default::default(); //~ ERROR the trait bound `U: Default` is not satisfied
+    // Hash
+    let mut h = std::collections::hash_map::DefaultHasher::new();
+    std::hash::Hash::hash(&u, &mut h); //~ ERROR the trait bound `U: Hash` is not satisfied
+
+    // Clone
+    x::<U>(); //~ ERROR the trait bound `U: Clone` is not satisfied
+    // Copy
+    y::<U>(); //~ ERROR the trait bound `U: Copy` is not satisfied
+}
diff --git a/tests/ui/union/union-no-derive-suggestion.stderr b/tests/ui/union/union-no-derive-suggestion.stderr
new file mode 100644
index 0000000..7a42b87
--- /dev/null
+++ b/tests/ui/union/union-no-derive-suggestion.stderr
@@ -0,0 +1,109 @@
+error[E0277]: `U` doesn't implement `Debug`
+  --> $DIR/union-no-derive-suggestion.rs:19:15
+   |
+LL |     println!("{u:?}");
+   |               ^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+help: the trait `Debug` is not implemented for `U`
+  --> $DIR/union-no-derive-suggestion.rs:5:1
+   |
+LL | union U {
+   | ^^^^^^^
+   = note: manually `impl Debug for U`
+
+error[E0369]: binary operation `==` cannot be applied to type `U`
+  --> $DIR/union-no-derive-suggestion.rs:22:15
+   |
+LL |     let _ = u == U { a: 0 };
+   |             - ^^ ---------- U
+   |             |
+   |             U
+   |
+note: an implementation of `PartialEq` might be missing for `U`
+  --> $DIR/union-no-derive-suggestion.rs:5:1
+   |
+LL | union U {
+   | ^^^^^^^ must implement `PartialEq`
+note: the trait `PartialEq` must be implemented
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+
+error[E0369]: binary operation `<` cannot be applied to type `U`
+  --> $DIR/union-no-derive-suggestion.rs:25:15
+   |
+LL |     let _ = u < U { a: 1 };
+   |             - ^ ---------- U
+   |             |
+   |             U
+   |
+note: an implementation of `PartialOrd` might be missing for `U`
+  --> $DIR/union-no-derive-suggestion.rs:5:1
+   |
+LL | union U {
+   | ^^^^^^^ must implement `PartialOrd`
+note: the trait `PartialOrd` must be implemented
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+
+error[E0277]: the trait bound `U: Default` is not satisfied
+  --> $DIR/union-no-derive-suggestion.rs:28:16
+   |
+LL |     let _: U = Default::default();
+   |                ^^^^^^^^^^^^^^^^^^ unsatisfied trait bound
+   |
+help: the trait `Default` is not implemented for `U`
+  --> $DIR/union-no-derive-suggestion.rs:5:1
+   |
+LL | union U {
+   | ^^^^^^^
+
+error[E0277]: the trait bound `U: Hash` is not satisfied
+  --> $DIR/union-no-derive-suggestion.rs:31:27
+   |
+LL |     std::hash::Hash::hash(&u, &mut h);
+   |     --------------------- ^^ unsatisfied trait bound
+   |     |
+   |     required by a bound introduced by this call
+   |
+help: the trait `Hash` is not implemented for `U`
+  --> $DIR/union-no-derive-suggestion.rs:5:1
+   |
+LL | union U {
+   | ^^^^^^^
+
+error[E0277]: the trait bound `U: Clone` is not satisfied
+  --> $DIR/union-no-derive-suggestion.rs:34:9
+   |
+LL |     x::<U>();
+   |         ^ the trait `Clone` is not implemented for `U`
+   |
+note: required by a bound in `x`
+  --> $DIR/union-no-derive-suggestion.rs:13:9
+   |
+LL | fn x<T: Clone>() {}
+   |         ^^^^^ required by this bound in `x`
+help: consider annotating `U` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | union U {
+   |
+
+error[E0277]: the trait bound `U: Copy` is not satisfied
+  --> $DIR/union-no-derive-suggestion.rs:36:9
+   |
+LL |     y::<U>();
+   |         ^ the trait `Copy` is not implemented for `U`
+   |
+note: required by a bound in `y`
+  --> $DIR/union-no-derive-suggestion.rs:14:9
+   |
+LL | fn y<T: Copy>() {}
+   |         ^^^^ required by this bound in `y`
+help: consider annotating `U` with `#[derive(Copy)]`
+   |
+LL + #[derive(Copy)]
+LL | union U {
+   |
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0277, E0369.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/unsafe-binders/binder-sized-crit.rs b/tests/ui/unsafe-binders/binder-sized-crit.rs
index 37677c0..cda8071 100644
--- a/tests/ui/unsafe-binders/binder-sized-crit.rs
+++ b/tests/ui/unsafe-binders/binder-sized-crit.rs
@@ -1,7 +1,6 @@
 //@ check-pass
 
 #![feature(unsafe_binders)]
-//~^ WARN the feature `unsafe_binders` is incomplete
 
 use std::unsafe_binder::wrap_binder;
 
diff --git a/tests/ui/unsafe-binders/binder-sized-crit.stderr b/tests/ui/unsafe-binders/binder-sized-crit.stderr
deleted file mode 100644
index 3ba6cf2..0000000
--- a/tests/ui/unsafe-binders/binder-sized-crit.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/binder-sized-crit.rs:3:12
-   |
-LL | #![feature(unsafe_binders)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/unsafe-binders/expr.rs b/tests/ui/unsafe-binders/expr.rs
index d437d8f..9feb294 100644
--- a/tests/ui/unsafe-binders/expr.rs
+++ b/tests/ui/unsafe-binders/expr.rs
@@ -1,7 +1,6 @@
 //@ check-pass
 
 #![feature(unsafe_binders)]
-//~^ WARN the feature `unsafe_binders` is incomplete
 
 use std::unsafe_binder::{wrap_binder, unwrap_binder};
 
diff --git a/tests/ui/unsafe-binders/expr.stderr b/tests/ui/unsafe-binders/expr.stderr
deleted file mode 100644
index 07026e1..0000000
--- a/tests/ui/unsafe-binders/expr.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/expr.rs:3:12
-   |
-LL | #![feature(unsafe_binders)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/unsafe-binders/lifetime-resolution.rs b/tests/ui/unsafe-binders/lifetime-resolution.rs
index d243154..9935edf 100644
--- a/tests/ui/unsafe-binders/lifetime-resolution.rs
+++ b/tests/ui/unsafe-binders/lifetime-resolution.rs
@@ -1,5 +1,4 @@
 #![feature(unsafe_binders)]
-//~^ WARN the feature `unsafe_binders` is incomplete
 
 fn foo<'a>() {
     let good: unsafe<'b> &'a &'b ();
diff --git a/tests/ui/unsafe-binders/lifetime-resolution.stderr b/tests/ui/unsafe-binders/lifetime-resolution.stderr
index 69660c2..2f445e9 100644
--- a/tests/ui/unsafe-binders/lifetime-resolution.stderr
+++ b/tests/ui/unsafe-binders/lifetime-resolution.stderr
@@ -1,5 +1,5 @@
 error[E0261]: use of undeclared lifetime name `'missing`
-  --> $DIR/lifetime-resolution.rs:7:28
+  --> $DIR/lifetime-resolution.rs:6:28
    |
 LL |     let missing: unsafe<> &'missing ();
    |                            ^^^^^^^^ undeclared lifetime
@@ -15,7 +15,7 @@
    |        +++++++++
 
 error[E0401]: can't use generic parameters from outer item
-  --> $DIR/lifetime-resolution.rs:11:30
+  --> $DIR/lifetime-resolution.rs:10:30
    |
 LL | fn foo<'a>() {
    |        -- lifetime parameter from outer item
@@ -32,16 +32,7 @@
 LL |     fn inner<'a, 'b>() {
    |              +++
 
-warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/lifetime-resolution.rs:1:12
-   |
-LL | #![feature(unsafe_binders)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0261, E0401.
 For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/unsafe-binders/mismatch.rs b/tests/ui/unsafe-binders/mismatch.rs
index 840d938..8da94cc 100644
--- a/tests/ui/unsafe-binders/mismatch.rs
+++ b/tests/ui/unsafe-binders/mismatch.rs
@@ -1,5 +1,4 @@
 #![feature(unsafe_binders)]
-//~^ WARN the feature `unsafe_binders` is incomplete
 
 use std::unsafe_binder::{wrap_binder, unwrap_binder};
 
diff --git a/tests/ui/unsafe-binders/mismatch.stderr b/tests/ui/unsafe-binders/mismatch.stderr
index f64db92..5e0720f 100644
--- a/tests/ui/unsafe-binders/mismatch.stderr
+++ b/tests/ui/unsafe-binders/mismatch.stderr
@@ -1,14 +1,5 @@
-warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/mismatch.rs:1:12
-   |
-LL | #![feature(unsafe_binders)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:7:46
+  --> $DIR/mismatch.rs:6:46
    |
 LL |     let _: unsafe<'a> &'a i32 = wrap_binder!(&());
    |                                              ^^^ expected `&i32`, found `&()`
@@ -17,7 +8,7 @@
               found reference `&()`
 
 error: `wrap_binder!()` can only wrap into unsafe binder, not `i32`
-  --> $DIR/mismatch.rs:12:18
+  --> $DIR/mismatch.rs:11:18
    |
 LL |     let _: i32 = wrap_binder!(&());
    |                  ^^^^^^^^^^^^^^^^^
@@ -26,7 +17,7 @@
    = note: this error originates in the macro `wrap_binder` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: expected unsafe binder, found integer as input of `unwrap_binder!()`
-  --> $DIR/mismatch.rs:18:20
+  --> $DIR/mismatch.rs:17:20
    |
 LL |     unwrap_binder!(y);
    |                    ^
@@ -34,7 +25,7 @@
    = note: only an unsafe binder type can be unwrapped
 
 error[E0282]: type annotations needed
-  --> $DIR/mismatch.rs:23:9
+  --> $DIR/mismatch.rs:22:9
    |
 LL |     let unknown = Default::default();
    |         ^^^^^^^
@@ -48,12 +39,12 @@
    |                ++++++++++++
 
 error[E0282]: type annotations needed
-  --> $DIR/mismatch.rs:29:26
+  --> $DIR/mismatch.rs:28:26
    |
 LL |     let x = wrap_binder!(&42);
    |                          ^^^ cannot infer type
 
-error: aborting due to 5 previous errors; 1 warning emitted
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0282, E0308.
 For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/unsafe-binders/moves.rs b/tests/ui/unsafe-binders/moves.rs
index 9397c2b..df2cb22 100644
--- a/tests/ui/unsafe-binders/moves.rs
+++ b/tests/ui/unsafe-binders/moves.rs
@@ -1,5 +1,4 @@
 #![feature(unsafe_binders)]
-//~^ WARN the feature `unsafe_binders` is incomplete
 
 use std::mem::{ManuallyDrop, drop};
 use std::unsafe_binder::{unwrap_binder, wrap_binder};
diff --git a/tests/ui/unsafe-binders/moves.stderr b/tests/ui/unsafe-binders/moves.stderr
index bd48015..a6d6380 100644
--- a/tests/ui/unsafe-binders/moves.stderr
+++ b/tests/ui/unsafe-binders/moves.stderr
@@ -1,14 +1,5 @@
-warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/moves.rs:1:12
-   |
-LL | #![feature(unsafe_binders)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0382]: use of moved value: `base`
-  --> $DIR/moves.rs:15:14
+  --> $DIR/moves.rs:14:14
    |
 LL |         let base = NotCopy::default();
    |             ---- move occurs because `base` has type `ManuallyDrop<NotCopyInner>`, which does not implement the `Copy` trait
@@ -18,7 +9,7 @@
    |              ^^^^ value used here after move
    |
 note: if `NotCopyInner` implemented `Clone`, you could clone the value
-  --> $DIR/moves.rs:8:1
+  --> $DIR/moves.rs:7:1
    |
 LL | struct NotCopyInner;
    | ^^^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
@@ -27,7 +18,7 @@
    |                                                     ---- you could clone this value
 
 error[E0382]: use of moved value: `binder`
-  --> $DIR/moves.rs:24:14
+  --> $DIR/moves.rs:23:14
    |
 LL |         drop(unwrap_binder!(binder));
    |              ---------------------- value moved here
@@ -38,7 +29,7 @@
    = note: this error originates in the macro `unwrap_binder` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0382]: use of moved value: `binder.0`
-  --> $DIR/moves.rs:36:14
+  --> $DIR/moves.rs:35:14
    |
 LL |         drop(unwrap_binder!(binder).0);
    |              ------------------------ value moved here
@@ -48,6 +39,6 @@
    |
    = note: move occurs because `binder.0` has type `ManuallyDrop<NotCopyInner>`, which does not implement the `Copy` trait
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/unsafe-binders/simple.rs b/tests/ui/unsafe-binders/simple.rs
index 6172a9e..99f20d6 100644
--- a/tests/ui/unsafe-binders/simple.rs
+++ b/tests/ui/unsafe-binders/simple.rs
@@ -1,7 +1,6 @@
 //@ check-pass
 
 #![feature(unsafe_binders)]
-//~^ WARN the feature `unsafe_binders` is incomplete
 
 fn main() {
     let x: unsafe<'a> &'a ();
diff --git a/tests/ui/unsafe-binders/simple.stderr b/tests/ui/unsafe-binders/simple.stderr
deleted file mode 100644
index e4b82c1..0000000
--- a/tests/ui/unsafe-binders/simple.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/simple.rs:3:12
-   |
-LL | #![feature(unsafe_binders)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/unsafe-binders/type-mismatch.rs b/tests/ui/unsafe-binders/type-mismatch.rs
index 9ac4e81..22937bb 100644
--- a/tests/ui/unsafe-binders/type-mismatch.rs
+++ b/tests/ui/unsafe-binders/type-mismatch.rs
@@ -1,5 +1,4 @@
 #![feature(unsafe_binders)]
-//~^ WARN the feature `unsafe_binders` is incomplete
 
 fn main() {
     let x: unsafe<> i32 = 0;
diff --git a/tests/ui/unsafe-binders/type-mismatch.stderr b/tests/ui/unsafe-binders/type-mismatch.stderr
index e694b5d..6262620 100644
--- a/tests/ui/unsafe-binders/type-mismatch.stderr
+++ b/tests/ui/unsafe-binders/type-mismatch.stderr
@@ -1,14 +1,5 @@
-warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/type-mismatch.rs:1:12
-   |
-LL | #![feature(unsafe_binders)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0308]: mismatched types
-  --> $DIR/type-mismatch.rs:5:27
+  --> $DIR/type-mismatch.rs:4:27
    |
 LL |     let x: unsafe<> i32 = 0;
    |            ------------   ^ expected `unsafe<> i32`, found integer
@@ -19,7 +10,7 @@
                        found type `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/type-mismatch.rs:7:33
+  --> $DIR/type-mismatch.rs:6:33
    |
 LL |     let x: unsafe<'a> &'a i32 = &0;
    |            ------------------   ^^ expected `unsafe<'a> &i32`, found `&{integer}`
@@ -29,6 +20,6 @@
    = note: expected unsafe binder `unsafe<'a> &'a i32`
                   found reference `&{integer}`
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/unsafe-binders/unsafe-binders-debuginfo.rs b/tests/ui/unsafe-binders/unsafe-binders-debuginfo.rs
index 15245d9..21f8fe7 100644
--- a/tests/ui/unsafe-binders/unsafe-binders-debuginfo.rs
+++ b/tests/ui/unsafe-binders/unsafe-binders-debuginfo.rs
@@ -3,7 +3,6 @@
 //@ compile-flags: -Cdebuginfo=2
 //@ ignore-backends: gcc
 #![feature(unsafe_binders)]
-//~^ WARN the feature `unsafe_binders` is incomplete
 
 use std::unsafe_binder::wrap_binder;
 fn main() {
diff --git a/tests/ui/unsafe-binders/unsafe-binders-debuginfo.stderr b/tests/ui/unsafe-binders/unsafe-binders-debuginfo.stderr
deleted file mode 100644
index 283b8b9c..0000000
--- a/tests/ui/unsafe-binders/unsafe-binders-debuginfo.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unsafe-binders-debuginfo.rs:5:12
-   |
-LL | #![feature(unsafe_binders)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/use/pub-use-self-super-crate.rs b/tests/ui/use/pub-use-self-super-crate.rs
new file mode 100644
index 0000000..1a799ac
--- /dev/null
+++ b/tests/ui/use/pub-use-self-super-crate.rs
@@ -0,0 +1,24 @@
+mod foo {
+    pub use self as this;
+    //~^ ERROR `self` is only public within the crate, and cannot be re-exported outside
+
+    pub mod bar {
+        pub use super as parent;
+        //~^ ERROR `super` is only public within the crate, and cannot be re-exported outside
+        pub use self::super as parent2;
+        //~^ ERROR `super` is only public within the crate, and cannot be re-exported outside
+        pub use super::{self as parent3};
+        //~^ ERROR `super` is only public within the crate, and cannot be re-exported outside
+        pub use self::{super as parent4};
+        //~^ ERROR `super` is only public within the crate, and cannot be re-exported outside
+
+        pub use crate as root;
+        pub use crate::{self as root2};
+        pub use super::super as root3;
+    }
+}
+
+pub use foo::*;
+pub use foo::bar::*;
+
+pub fn main() {}
diff --git a/tests/ui/use/pub-use-self-super-crate.stderr b/tests/ui/use/pub-use-self-super-crate.stderr
new file mode 100644
index 0000000..3b33680
--- /dev/null
+++ b/tests/ui/use/pub-use-self-super-crate.stderr
@@ -0,0 +1,43 @@
+error[E0365]: `self` is only public within the crate, and cannot be re-exported outside
+  --> $DIR/pub-use-self-super-crate.rs:2:13
+   |
+LL |     pub use self as this;
+   |             ^^^^^^^^^^^^ re-export of crate public `self`
+   |
+   = note: consider declaring type or module `self` with `pub`
+
+error[E0365]: `super` is only public within the crate, and cannot be re-exported outside
+  --> $DIR/pub-use-self-super-crate.rs:6:17
+   |
+LL |         pub use super as parent;
+   |                 ^^^^^^^^^^^^^^^ re-export of crate public `super`
+   |
+   = note: consider declaring type or module `super` with `pub`
+
+error[E0365]: `super` is only public within the crate, and cannot be re-exported outside
+  --> $DIR/pub-use-self-super-crate.rs:8:17
+   |
+LL |         pub use self::super as parent2;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^ re-export of crate public `super`
+   |
+   = note: consider declaring type or module `super` with `pub`
+
+error[E0365]: `super` is only public within the crate, and cannot be re-exported outside
+  --> $DIR/pub-use-self-super-crate.rs:10:25
+   |
+LL |         pub use super::{self as parent3};
+   |                         ^^^^^^^^^^^^^^^ re-export of crate public `super`
+   |
+   = note: consider declaring type or module `super` with `pub`
+
+error[E0365]: `super` is only public within the crate, and cannot be re-exported outside
+  --> $DIR/pub-use-self-super-crate.rs:12:24
+   |
+LL |         pub use self::{super as parent4};
+   |                        ^^^^^^^^^^^^^^^^ re-export of crate public `super`
+   |
+   = note: consider declaring type or module `super` with `pub`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0365`.
diff --git a/tests/ui/use/use-path-segment-kw.rs b/tests/ui/use/use-path-segment-kw.rs
index be64f23..164f645 100644
--- a/tests/ui/use/use-path-segment-kw.rs
+++ b/tests/ui/use/use-path-segment-kw.rs
@@ -70,7 +70,7 @@ macro_rules! macro_dollar_crate {
 
 fn outer() {}
 
-mod foo {
+pub mod foo {
     pub mod bar {
         pub mod foobar {
             pub mod qux {
diff --git a/tests/ui/where-clauses/cfg_attribute.a.stderr b/tests/ui/where-clauses/cfg_attribute.a.stderr
index ee81072..5bfa65d 100644
--- a/tests/ui/where-clauses/cfg_attribute.a.stderr
+++ b/tests/ui/where-clauses/cfg_attribute.a.stderr
@@ -93,6 +93,38 @@
    = help: only `#[cfg]` and `#[cfg_attr]` are supported
 
 error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:42:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:45:9
+   |
+LL |         #[rustfmt::skip] ():;
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:53:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:56:9
+   |
+LL |         #[rustfmt::skip] ():;
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
   --> $DIR/cfg_attribute.rs:65:5
    |
 LL |     #[derive(Clone)] ():,
@@ -109,6 +141,38 @@
    = help: only `#[cfg]` and `#[cfg_attr]` are supported
 
 error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:75:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:78:9
+   |
+LL |         #[rustfmt::skip] ():;
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:86:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:89:9
+   |
+LL |         #[rustfmt::skip] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
   --> $DIR/cfg_attribute.rs:99:5
    |
 LL |     #[derive(Clone)] ():,
@@ -189,86 +253,6 @@
    = help: only `#[cfg]` and `#[cfg_attr]` are supported
 
 error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:177:5
-   |
-LL |     #[derive(Clone)] ():,
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:180:5
-   |
-LL |     #[rustfmt::skip] ():,
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:42:9
-   |
-LL |         #[derive(Clone)] ():,
-   |         ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:45:9
-   |
-LL |         #[rustfmt::skip] ():;
-   |         ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:53:9
-   |
-LL |         #[derive(Clone)] ():,
-   |         ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:56:9
-   |
-LL |         #[rustfmt::skip] ():;
-   |         ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:75:9
-   |
-LL |         #[derive(Clone)] ():,
-   |         ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:78:9
-   |
-LL |         #[rustfmt::skip] ():;
-   |         ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:86:9
-   |
-LL |         #[derive(Clone)] ():,
-   |         ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:89:9
-   |
-LL |         #[rustfmt::skip] ():,
-   |         ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
   --> $DIR/cfg_attribute.rs:164:9
    |
 LL |         #[derive(Clone)] ():,
@@ -284,5 +268,21 @@
    |
    = help: only `#[cfg]` and `#[cfg_attr]` are supported
 
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:177:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:180:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
 error: aborting due to 39 previous errors
 
diff --git a/tests/ui/where-clauses/cfg_attribute.b.stderr b/tests/ui/where-clauses/cfg_attribute.b.stderr
index ee81072..5bfa65d 100644
--- a/tests/ui/where-clauses/cfg_attribute.b.stderr
+++ b/tests/ui/where-clauses/cfg_attribute.b.stderr
@@ -93,6 +93,38 @@
    = help: only `#[cfg]` and `#[cfg_attr]` are supported
 
 error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:42:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:45:9
+   |
+LL |         #[rustfmt::skip] ():;
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:53:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:56:9
+   |
+LL |         #[rustfmt::skip] ():;
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
   --> $DIR/cfg_attribute.rs:65:5
    |
 LL |     #[derive(Clone)] ():,
@@ -109,6 +141,38 @@
    = help: only `#[cfg]` and `#[cfg_attr]` are supported
 
 error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:75:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:78:9
+   |
+LL |         #[rustfmt::skip] ():;
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:86:9
+   |
+LL |         #[derive(Clone)] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:89:9
+   |
+LL |         #[rustfmt::skip] ():,
+   |         ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
   --> $DIR/cfg_attribute.rs:99:5
    |
 LL |     #[derive(Clone)] ():,
@@ -189,86 +253,6 @@
    = help: only `#[cfg]` and `#[cfg_attr]` are supported
 
 error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:177:5
-   |
-LL |     #[derive(Clone)] ():,
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:180:5
-   |
-LL |     #[rustfmt::skip] ():,
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:42:9
-   |
-LL |         #[derive(Clone)] ():,
-   |         ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:45:9
-   |
-LL |         #[rustfmt::skip] ():;
-   |         ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:53:9
-   |
-LL |         #[derive(Clone)] ():,
-   |         ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:56:9
-   |
-LL |         #[rustfmt::skip] ():;
-   |         ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:75:9
-   |
-LL |         #[derive(Clone)] ():,
-   |         ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:78:9
-   |
-LL |         #[rustfmt::skip] ():;
-   |         ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:86:9
-   |
-LL |         #[derive(Clone)] ():,
-   |         ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/cfg_attribute.rs:89:9
-   |
-LL |         #[rustfmt::skip] ():,
-   |         ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
   --> $DIR/cfg_attribute.rs:164:9
    |
 LL |         #[derive(Clone)] ():,
@@ -284,5 +268,21 @@
    |
    = help: only `#[cfg]` and `#[cfg_attr]` are supported
 
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:177:5
+   |
+LL |     #[derive(Clone)] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/cfg_attribute.rs:180:5
+   |
+LL |     #[rustfmt::skip] ():,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
 error: aborting due to 39 previous errors
 
diff --git a/tests/ui/where-clauses/unsupported_attribute.stderr b/tests/ui/where-clauses/unsupported_attribute.stderr
index e55a7c3..11f13ff 100644
--- a/tests/ui/where-clauses/unsupported_attribute.stderr
+++ b/tests/ui/where-clauses/unsupported_attribute.stderr
@@ -10,6 +10,22 @@
 LL |     #[derive(Clone)] 'a: 'static,
    |       ^^^^^^ not a non-macro attribute
 
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:13:5
+   |
+LL |     #[doc = "doc"] T: Trait,
+   |     ^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:14:5
+   |
+LL |     #[doc = "doc"] 'a: 'static,
+   |     ^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
 error: `#[ignore]` attribute cannot be used on where predicates
   --> $DIR/unsupported_attribute.rs:15:5
    |
@@ -58,6 +74,22 @@
    |
    = help: `#[macro_use]` can be applied to crates, extern crates, and modules
 
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:21:5
+   |
+LL |     #[allow(unused)] T: Trait,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
+error: most attributes are not supported in `where` clauses
+  --> $DIR/unsupported_attribute.rs:22:5
+   |
+LL |     #[allow(unused)] 'a: 'static,
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: only `#[cfg]` and `#[cfg_attr]` are supported
+
 error: `#[deprecated]` attribute cannot be used on where predicates
   --> $DIR/unsupported_attribute.rs:23:5
    |
@@ -91,38 +123,6 @@
    = help: `#[automatically_derived]` can only be applied to trait impl blocks
 
 error: most attributes are not supported in `where` clauses
-  --> $DIR/unsupported_attribute.rs:13:5
-   |
-LL |     #[doc = "doc"] T: Trait,
-   |     ^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/unsupported_attribute.rs:14:5
-   |
-LL |     #[doc = "doc"] 'a: 'static,
-   |     ^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/unsupported_attribute.rs:21:5
-   |
-LL |     #[allow(unused)] T: Trait,
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
-  --> $DIR/unsupported_attribute.rs:22:5
-   |
-LL |     #[allow(unused)] 'a: 'static,
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = help: only `#[cfg]` and `#[cfg_attr]` are supported
-
-error: most attributes are not supported in `where` clauses
   --> $DIR/unsupported_attribute.rs:27:5
    |
 LL |     #[derive(Clone)] T: Trait,
diff --git a/typos.toml b/typos.toml
index 82e2b98..8e14ce5 100644
--- a/typos.toml
+++ b/typos.toml
@@ -48,6 +48,7 @@
 # the non-empty form can be automatically fixed by `--bless`.
 #
 # tidy-alphabetical-start
+atomicaly = "atomically"
 definitinon = "definition"
 dependy = ""
 similarlty = "similarity"