about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_lowering/messages.ftl2
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs15
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs3
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs28
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs28
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs2
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs4
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs85
-rw-r--r--compiler/rustc_middle/src/thir.rs4
-rw-r--r--compiler/rustc_mir_build/src/builder/block.rs46
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/mod.rs117
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/user_ty.rs140
-rw-r--r--compiler/rustc_privacy/src/lib.rs18
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs2
-rw-r--r--compiler/rustc_type_ir/src/binder.rs6
-rw-r--r--library/core/src/ops/control_flow.rs1
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs2
-rw-r--r--src/doc/unstable-book/src/language-features/asm-goto-with-outputs.md27
-rw-r--r--src/doc/unstable-book/src/language-features/asm-goto.md32
-rw-r--r--src/librustdoc/clean/types.rs23
-rw-r--r--src/librustdoc/html/length_limit/tests.rs46
-rw-r--r--src/librustdoc/html/markdown.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unconditional_recursion.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/attrs.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs4
-rw-r--r--tests/codegen/asm/goto.rs2
-rw-r--r--tests/codegen/sanitizer/cfi/external_weak_symbols.rs24
-rw-r--r--tests/mir-opt/building/user_type_annotations.let_else.built.after.mir80
-rw-r--r--tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir62
-rw-r--r--tests/mir-opt/building/user_type_annotations.let_init.built.after.mir54
-rw-r--r--tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir39
-rw-r--r--tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir27
-rw-r--r--tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir15
-rw-r--r--tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir46
-rw-r--r--tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir74
-rw-r--r--tests/mir-opt/building/user_type_annotations.rs66
-rw-r--r--tests/rustdoc-json/attrs/deprecated.rs38
-rw-r--r--tests/ui/asm/x86_64/bad-options.rs2
-rw-r--r--tests/ui/asm/x86_64/goto-block-safe.rs1
-rw-r--r--tests/ui/asm/x86_64/goto-block-safe.stderr2
-rw-r--r--tests/ui/asm/x86_64/goto.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-asm_goto.rs10
-rw-r--r--tests/ui/feature-gates/feature-gate-asm_goto.stderr13
-rw-r--r--tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.stderr2
60 files changed, 911 insertions, 335 deletions
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index 906fb213ee7..65e5b530bbe 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -185,8 +185,6 @@ ast_lowering_underscore_expr_lhs_assign =
 ast_lowering_unstable_inline_assembly = inline assembly is not stable yet on this architecture
 ast_lowering_unstable_inline_assembly_label_operand_with_outputs =
     using both label and output operands for inline assembly is unstable
-ast_lowering_unstable_inline_assembly_label_operands =
-    label operands for inline assembly are unstable
 ast_lowering_unstable_may_unwind = the `may_unwind` option is unstable
 
 ast_lowering_use_angle_brackets = use angle brackets instead
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 65784af92c7..af279e07acc 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -470,22 +470,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             }
         }
 
-        // Feature gate checking for asm goto.
+        // Feature gate checking for `asm_goto_with_outputs`.
         if let Some((_, op_sp)) =
             operands.iter().find(|(op, _)| matches!(op, hir::InlineAsmOperand::Label { .. }))
         {
-            if !self.tcx.features().asm_goto() {
-                feature_err(
-                    sess,
-                    sym::asm_goto,
-                    *op_sp,
-                    fluent::ast_lowering_unstable_inline_assembly_label_operands,
-                )
-                .emit();
-            }
-
-            // In addition, check if an output operand is used.
-            // This is gated behind an additional feature.
+            // Check if an output operand is used.
             let output_operand_used = operands.iter().any(|(op, _)| {
                 matches!(
                     op,
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 9adc8bdd361..3b2e8581c00 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1720,7 +1720,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         let bounds = self.lower_param_bounds(bounds, itctx);
 
-        let ident = self.lower_ident(ident);
         let param_span = ident.span;
 
         // Reconstruct the span of the entire predicate from the individual generic bounds.
@@ -1739,6 +1738,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 let def_id = self.local_def_id(id).to_def_id();
                 let hir_id = self.next_id();
                 let res = Res::Def(DefKind::TyParam, def_id);
+                let ident = self.lower_ident(ident);
                 let ty_path = self.arena.alloc(hir::Path {
                     span: param_span,
                     res,
@@ -1757,7 +1757,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 })
             }
             GenericParamKind::Lifetime => {
-                let ident = self.lower_ident(ident);
                 let lt_id = self.next_node_id();
                 let lifetime = self.new_named_lifetime(id, lt_id, ident);
                 hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index df671cf4b86..e24b45c5b19 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1769,17 +1769,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 
     fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime {
-        let ident = self.lower_ident(l.ident);
-        self.new_named_lifetime(l.id, l.id, ident)
+        self.new_named_lifetime(l.id, l.id, l.ident)
     }
 
     #[instrument(level = "debug", skip(self))]
-    fn new_named_lifetime_with_res(
+    fn new_named_lifetime(
         &mut self,
         id: NodeId,
+        new_id: NodeId,
         ident: Ident,
-        res: LifetimeRes,
     ) -> &'hir hir::Lifetime {
+        let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error);
         let res = match res {
             LifetimeRes::Param { param, .. } => hir::LifetimeName::Param(param),
             LifetimeRes::Fresh { param, .. } => {
@@ -1789,31 +1789,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             LifetimeRes::Infer => hir::LifetimeName::Infer,
             LifetimeRes::Static { .. } => hir::LifetimeName::Static,
             LifetimeRes::Error => hir::LifetimeName::Error,
-            res => panic!(
-                "Unexpected lifetime resolution {:?} for {:?} at {:?}",
-                res, ident, ident.span
-            ),
+            LifetimeRes::ElidedAnchor { .. } => {
+                panic!("Unexpected `ElidedAnchar` {:?} at {:?}", ident, ident.span);
+            }
         };
 
         debug!(?res);
         self.arena.alloc(hir::Lifetime {
-            hir_id: self.lower_node_id(id),
+            hir_id: self.lower_node_id(new_id),
             ident: self.lower_ident(ident),
             res,
         })
     }
 
-    #[instrument(level = "debug", skip(self))]
-    fn new_named_lifetime(
-        &mut self,
-        id: NodeId,
-        new_id: NodeId,
-        ident: Ident,
-    ) -> &'hir hir::Lifetime {
-        let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error);
-        self.new_named_lifetime_with_res(new_id, ident, res)
-    }
-
     fn lower_generic_params_mut(
         &mut self,
         params: &[GenericParam],
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index a4e5749b3ac..62fa2884e0f 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -5,6 +5,7 @@ use rustc_abi::{
 };
 use rustc_codegen_ssa::common;
 use rustc_codegen_ssa::traits::*;
+use rustc_hir::LangItem;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
@@ -12,9 +13,9 @@ use rustc_middle::mir::interpret::{
     Allocation, ConstAllocation, ErrorHandled, InitChunk, Pointer, Scalar as InterpScalar,
     read_target_uint,
 };
-use rustc_middle::mir::mono::MonoItem;
-use rustc_middle::ty::Instance;
+use rustc_middle::mir::mono::{Linkage, MonoItem};
 use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
+use rustc_middle::ty::{self, Instance};
 use rustc_middle::{bug, span_bug};
 use tracing::{debug, instrument, trace};
 
@@ -171,8 +172,27 @@ fn check_and_apply_linkage<'ll, 'tcx>(
     if let Some(linkage) = attrs.import_linkage {
         debug!("get_static: sym={} linkage={:?}", sym, linkage);
 
-        // Declare a symbol `foo` with the desired linkage.
-        let g1 = cx.declare_global(sym, cx.type_i8());
+        // Declare a symbol `foo`. If `foo` is an extern_weak symbol, we declare
+        // an extern_weak function, otherwise a global with the desired linkage.
+        let g1 = if matches!(attrs.import_linkage, Some(Linkage::ExternalWeak)) {
+            // An `extern_weak` function is represented as an `Option<unsafe extern ...>`,
+            // we extract the function signature and declare it as an extern_weak function
+            // instead of an extern_weak i8.
+            let instance = Instance::mono(cx.tcx, def_id);
+            if let ty::Adt(struct_def, args) = instance.ty(cx.tcx, cx.typing_env()).kind()
+                && cx.tcx.is_lang_item(struct_def.did(), LangItem::Option)
+                && let ty::FnPtr(sig, header) = args.type_at(0).kind()
+            {
+                let fn_sig = sig.with(*header);
+
+                let fn_abi = cx.fn_abi_of_fn_ptr(fn_sig, ty::List::empty());
+                cx.declare_fn(sym, &fn_abi, None)
+            } else {
+                cx.declare_global(sym, cx.type_i8())
+            }
+        } else {
+            cx.declare_global(sym, cx.type_i8())
+        };
         llvm::set_linkage(g1, base::linkage_to_llvm(linkage));
 
         // Declare an internal global `extern_with_linkage_foo` which
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 535f94f6e69..5f85c10636e 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -2136,7 +2136,7 @@ fn add_library_search_dirs(
     }
 
     let fallback = Some(NativeLibSearchFallback { self_contained_components, apple_sdk_root });
-    walk_native_lib_search_dirs(sess, fallback, |dir, is_framework| {
+    let _ = walk_native_lib_search_dirs(sess, fallback, |dir, is_framework| {
         if is_framework {
             cmd.framework_path(dir);
         } else {
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index d50fe8c6a3e..980f3946035 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -62,6 +62,8 @@ declare_features! (
     (accepted, arbitrary_enum_discriminant, "1.66.0", Some(60553)),
     /// Allows using `const` operands in inline assembly.
     (accepted, asm_const, "1.82.0", Some(93332)),
+    /// Allows using `label` operands in inline assembly.
+    (accepted, asm_goto, "CURRENT_RUSTC_VERSION", Some(119364)),
     /// Allows using `sym` operands in inline assembly.
     (accepted, asm_sym, "1.66.0", Some(93333)),
     /// Allows the definition of associated constants in `trait` or `impl` blocks.
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 3c61bfd1c93..3b75c69132c 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -372,8 +372,6 @@ declare_features! (
     (unstable, asm_experimental_arch, "1.58.0", Some(93335)),
     /// Enables experimental register support in inline assembly.
     (unstable, asm_experimental_reg, "1.85.0", Some(133416)),
-    /// Allows using `label` operands in inline assembly.
-    (unstable, asm_goto, "1.78.0", Some(119364)),
     /// Allows using `label` operands in inline assembly together with output operands.
     (unstable, asm_goto_with_outputs, "1.85.0", Some(119364)),
     /// Allows the `may_unwind` option in inline assembly.
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 1a1540f505d..943661fbd56 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -533,7 +533,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                     _ => {
-                        intravisit::walk_pat(self, p);
+                        let _ = intravisit::walk_pat(self, p);
                     }
                 }
                 ControlFlow::Continue(())
@@ -556,7 +556,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     method_name,
                     sugg_let: None,
                 };
-                let_visitor.visit_body(&body);
+                let _ = let_visitor.visit_body(&body);
                 if let Some(sugg_let) = let_visitor.sugg_let
                     && let Some(self_ty) = self.node_ty_opt(sugg_let.init_hir_id)
                 {
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 7090e93549e..4dfb362f3a2 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -33,8 +33,8 @@ use crate::mir::interpret::{AllocRange, Scalar};
 use crate::ty::codec::{TyDecoder, TyEncoder};
 use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths};
 use crate::ty::{
-    self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt,
-    TypeVisitableExt, TypingEnv, UserTypeAnnotationIndex,
+    self, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypeVisitableExt,
+    TypingEnv, UserTypeAnnotationIndex,
 };
 
 mod basic_blocks;
@@ -1482,53 +1482,10 @@ pub struct UserTypeProjections {
     pub contents: Vec<UserTypeProjection>,
 }
 
-impl<'tcx> UserTypeProjections {
-    pub fn none() -> Self {
-        UserTypeProjections { contents: vec![] }
-    }
-
-    pub fn is_empty(&self) -> bool {
-        self.contents.is_empty()
-    }
-
+impl UserTypeProjections {
     pub fn projections(&self) -> impl Iterator<Item = &UserTypeProjection> + ExactSizeIterator {
         self.contents.iter()
     }
-
-    pub fn push_user_type(mut self, base_user_type: UserTypeAnnotationIndex) -> Self {
-        self.contents.push(UserTypeProjection { base: base_user_type, projs: vec![] });
-        self
-    }
-
-    fn map_projections(mut self, f: impl FnMut(UserTypeProjection) -> UserTypeProjection) -> Self {
-        self.contents = self.contents.into_iter().map(f).collect();
-        self
-    }
-
-    pub fn index(self) -> Self {
-        self.map_projections(|pat_ty_proj| pat_ty_proj.index())
-    }
-
-    pub fn subslice(self, from: u64, to: u64) -> Self {
-        self.map_projections(|pat_ty_proj| pat_ty_proj.subslice(from, to))
-    }
-
-    pub fn deref(self) -> Self {
-        self.map_projections(|pat_ty_proj| pat_ty_proj.deref())
-    }
-
-    pub fn leaf(self, field: FieldIdx) -> Self {
-        self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field))
-    }
-
-    pub fn variant(
-        self,
-        adt_def: AdtDef<'tcx>,
-        variant_index: VariantIdx,
-        field_index: FieldIdx,
-    ) -> Self {
-        self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field_index))
-    }
 }
 
 /// Encodes the effect of a user-supplied type annotation on the
@@ -1553,42 +1510,6 @@ pub struct UserTypeProjection {
     pub projs: Vec<ProjectionKind>,
 }
 
-impl UserTypeProjection {
-    pub(crate) fn index(mut self) -> Self {
-        self.projs.push(ProjectionElem::Index(()));
-        self
-    }
-
-    pub(crate) fn subslice(mut self, from: u64, to: u64) -> Self {
-        self.projs.push(ProjectionElem::Subslice { from, to, from_end: true });
-        self
-    }
-
-    pub(crate) fn deref(mut self) -> Self {
-        self.projs.push(ProjectionElem::Deref);
-        self
-    }
-
-    pub(crate) fn leaf(mut self, field: FieldIdx) -> Self {
-        self.projs.push(ProjectionElem::Field(field, ()));
-        self
-    }
-
-    pub(crate) fn variant(
-        mut self,
-        adt_def: AdtDef<'_>,
-        variant_index: VariantIdx,
-        field_index: FieldIdx,
-    ) -> Self {
-        self.projs.push(ProjectionElem::Downcast(
-            Some(adt_def.variant(variant_index).name),
-            variant_index,
-        ));
-        self.projs.push(ProjectionElem::Field(field_index, ()));
-        self
-    }
-}
-
 rustc_index::newtype_index! {
     #[derive(HashStable)]
     #[encodable]
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index f7b98d935d4..1056644b813 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -783,8 +783,12 @@ pub enum PatKind<'tcx> {
         var: LocalVarId,
         ty: Ty<'tcx>,
         subpattern: Option<Box<Pat<'tcx>>>,
+
         /// Is this the leftmost occurrence of the binding, i.e., is `var` the
         /// `HirId` of this pattern?
+        ///
+        /// (The same binding can occur multiple times in different branches of
+        /// an or-pattern, but only one of them will be primary.)
         is_primary: bool,
     },
 
diff --git a/compiler/rustc_mir_build/src/builder/block.rs b/compiler/rustc_mir_build/src/builder/block.rs
index 7c76e02fcef..a71196f79d7 100644
--- a/compiler/rustc_mir_build/src/builder/block.rs
+++ b/compiler/rustc_mir_build/src/builder/block.rs
@@ -199,19 +199,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             None,
                             Some((Some(&destination), initializer_span)),
                         );
-                        this.visit_primary_bindings(
-                            pattern,
-                            UserTypeProjections::none(),
-                            &mut |this, _, _, node, span, _, _| {
-                                this.storage_live_binding(
-                                    block,
-                                    node,
-                                    span,
-                                    OutsideGuard,
-                                    ScheduleDrops::Yes,
-                                );
-                            },
-                        );
+                        this.visit_primary_bindings(pattern, &mut |this, node, span| {
+                            this.storage_live_binding(
+                                block,
+                                node,
+                                span,
+                                OutsideGuard,
+                                ScheduleDrops::Yes,
+                            );
+                        });
                         let else_block_span = this.thir[*else_block].span;
                         let (matching, failure) =
                             this.in_if_then_scope(last_remainder_scope, else_block_span, |this| {
@@ -295,20 +291,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         });
 
                         debug!("ast_block_stmts: pattern={:?}", pattern);
-                        this.visit_primary_bindings(
-                            pattern,
-                            UserTypeProjections::none(),
-                            &mut |this, _, _, node, span, _, _| {
-                                this.storage_live_binding(
-                                    block,
-                                    node,
-                                    span,
-                                    OutsideGuard,
-                                    ScheduleDrops::Yes,
-                                );
-                                this.schedule_drop_for_binding(node, span, OutsideGuard);
-                            },
-                        )
+                        this.visit_primary_bindings(pattern, &mut |this, node, span| {
+                            this.storage_live_binding(
+                                block,
+                                node,
+                                span,
+                                OutsideGuard,
+                                ScheduleDrops::Yes,
+                            );
+                            this.schedule_drop_for_binding(node, span, OutsideGuard);
+                        })
                     }
 
                     // Enter the visibility scope, after evaluating the initializer.
diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs
index b05052a3455..ea341b604e0 100644
--- a/compiler/rustc_mir_build/src/builder/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs
@@ -5,6 +5,11 @@
 //! This also includes code for pattern bindings in `let` statements and
 //! function parameters.
 
+use std::assert_matches::assert_matches;
+use std::borrow::Borrow;
+use std::mem;
+use std::sync::Arc;
+
 use rustc_abi::VariantIdx;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -19,6 +24,7 @@ use tracing::{debug, instrument};
 
 use crate::builder::ForGuard::{self, OutsideGuard, RefWithinGuard};
 use crate::builder::expr::as_place::PlaceBuilder;
+use crate::builder::matches::user_ty::ProjectedUserTypesNode;
 use crate::builder::scope::DropKind;
 use crate::builder::{
     BlockAnd, BlockAndExtension, Builder, GuardFrame, GuardFrameLocal, LocalsForNode,
@@ -27,13 +33,9 @@ use crate::builder::{
 // helper functions, broken out by category:
 mod match_pair;
 mod test;
+mod user_ty;
 mod util;
 
-use std::assert_matches::assert_matches;
-use std::borrow::Borrow;
-use std::mem;
-use std::sync::Arc;
-
 /// Arguments to [`Builder::then_else_break_inner`] that are usually forwarded
 /// to recursive invocations.
 #[derive(Clone, Copy)]
@@ -755,24 +757,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         guard: Option<ExprId>,
         opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
     ) -> Option<SourceScope> {
-        self.visit_primary_bindings(
+        self.visit_primary_bindings_special(
             pattern,
-            UserTypeProjections::none(),
-            &mut |this, name, mode, var, span, ty, user_ty| {
-                if visibility_scope.is_none() {
-                    visibility_scope =
-                        Some(this.new_source_scope(scope_span, LintLevel::Inherited));
-                }
+            &ProjectedUserTypesNode::None,
+            &mut |this, name, mode, var, span, ty, user_tys| {
+                let vis_scope = *visibility_scope
+                    .get_or_insert_with(|| this.new_source_scope(scope_span, LintLevel::Inherited));
                 let source_info = SourceInfo { span, scope: this.source_scope };
-                let visibility_scope = visibility_scope.unwrap();
+                let user_tys = user_tys.build_user_type_projections();
+
                 this.declare_binding(
                     source_info,
-                    visibility_scope,
+                    vis_scope,
                     name,
                     mode,
                     var,
                     ty,
-                    user_ty,
+                    user_tys,
                     ArmHasGuard(guard.is_some()),
                     opt_match_place.map(|(x, y)| (x.cloned(), y)),
                     pattern.span,
@@ -848,13 +849,35 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    /// Visit all of the primary bindings in a patterns, that is, visit the
-    /// leftmost occurrence of each variable bound in a pattern. A variable
-    /// will occur more than once in an or-pattern.
+    /// Visits all of the "primary" bindings in a pattern, i.e. the leftmost
+    /// occurrence of each variable bound by the pattern.
+    /// See [`PatKind::Binding::is_primary`] for more context.
+    ///
+    /// This variant provides only the limited subset of binding data needed
+    /// by its callers, and should be a "pure" visit without side-effects.
     pub(super) fn visit_primary_bindings(
         &mut self,
         pattern: &Pat<'tcx>,
-        pattern_user_ty: UserTypeProjections,
+        f: &mut impl FnMut(&mut Self, LocalVarId, Span),
+    ) {
+        pattern.walk_always(|pat| {
+            if let PatKind::Binding { var, is_primary: true, .. } = pat.kind {
+                f(self, var, pat.span);
+            }
+        })
+    }
+
+    /// Visits all of the "primary" bindings in a pattern, while preparing
+    /// additional user-type-annotation data needed by `declare_bindings`.
+    ///
+    /// This also has the side-effect of pushing all user type annotations
+    /// onto `canonical_user_type_annotations`, so that they end up in MIR
+    /// even if they aren't associated with any bindings.
+    #[instrument(level = "debug", skip(self, f))]
+    fn visit_primary_bindings_special(
+        &mut self,
+        pattern: &Pat<'tcx>,
+        user_tys: &ProjectedUserTypesNode<'_>,
         f: &mut impl FnMut(
             &mut Self,
             Symbol,
@@ -862,20 +885,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             LocalVarId,
             Span,
             Ty<'tcx>,
-            UserTypeProjections,
+            &ProjectedUserTypesNode<'_>,
         ),
     ) {
-        debug!(
-            "visit_primary_bindings: pattern={:?} pattern_user_ty={:?}",
-            pattern, pattern_user_ty
-        );
+        // Avoid having to write the full method name at each recursive call.
+        let visit_subpat = |this: &mut Self, subpat, user_tys: &_, f: &mut _| {
+            this.visit_primary_bindings_special(subpat, user_tys, f)
+        };
+
         match pattern.kind {
             PatKind::Binding { name, mode, var, ty, ref subpattern, is_primary, .. } => {
                 if is_primary {
-                    f(self, name, mode, var, pattern.span, ty, pattern_user_ty.clone());
+                    f(self, name, mode, var, pattern.span, ty, user_tys);
                 }
                 if let Some(subpattern) = subpattern.as_ref() {
-                    self.visit_primary_bindings(subpattern, pattern_user_ty, f);
+                    visit_subpat(self, subpattern, user_tys, f);
                 }
             }
 
@@ -884,17 +908,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let from = u64::try_from(prefix.len()).unwrap();
                 let to = u64::try_from(suffix.len()).unwrap();
                 for subpattern in prefix.iter() {
-                    self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f);
+                    visit_subpat(self, subpattern, &user_tys.index(), f);
                 }
                 if let Some(subpattern) = slice {
-                    self.visit_primary_bindings(
-                        subpattern,
-                        pattern_user_ty.clone().subslice(from, to),
-                        f,
-                    );
+                    visit_subpat(self, subpattern, &user_tys.subslice(from, to), f);
                 }
                 for subpattern in suffix.iter() {
-                    self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f);
+                    visit_subpat(self, subpattern, &user_tys.index(), f);
                 }
             }
 
@@ -905,11 +925,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             | PatKind::Error(_) => {}
 
             PatKind::Deref { ref subpattern } => {
-                self.visit_primary_bindings(subpattern, pattern_user_ty.deref(), f);
+                visit_subpat(self, subpattern, &user_tys.deref(), f);
             }
 
             PatKind::DerefPattern { ref subpattern, .. } => {
-                self.visit_primary_bindings(subpattern, UserTypeProjections::none(), f);
+                visit_subpat(self, subpattern, &ProjectedUserTypesNode::None, f);
             }
 
             PatKind::AscribeUserType {
@@ -925,28 +945,31 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // Note that the variance doesn't apply here, as we are tracking the effect
                 // of `user_ty` on any bindings contained with subpattern.
 
+                // Caution: Pushing this user type here is load-bearing even for
+                // patterns containing no bindings, to ensure that the type ends
+                // up represented in MIR _somewhere_.
                 let base_user_ty = self.canonical_user_type_annotations.push(annotation.clone());
-                let subpattern_user_ty = pattern_user_ty.push_user_type(base_user_ty);
-                self.visit_primary_bindings(subpattern, subpattern_user_ty, f)
+                let subpattern_user_tys = user_tys.push_user_type(base_user_ty);
+                visit_subpat(self, subpattern, &subpattern_user_tys, f)
             }
 
             PatKind::ExpandedConstant { ref subpattern, .. } => {
-                self.visit_primary_bindings(subpattern, pattern_user_ty, f)
+                visit_subpat(self, subpattern, user_tys, f)
             }
 
             PatKind::Leaf { ref subpatterns } => {
                 for subpattern in subpatterns {
-                    let subpattern_user_ty = pattern_user_ty.clone().leaf(subpattern.field);
-                    debug!("visit_primary_bindings: subpattern_user_ty={:?}", subpattern_user_ty);
-                    self.visit_primary_bindings(&subpattern.pattern, subpattern_user_ty, f);
+                    let subpattern_user_tys = user_tys.leaf(subpattern.field);
+                    debug!("visit_primary_bindings: subpattern_user_tys={subpattern_user_tys:?}");
+                    visit_subpat(self, &subpattern.pattern, &subpattern_user_tys, f);
                 }
             }
 
             PatKind::Variant { adt_def, args: _, variant_index, ref subpatterns } => {
                 for subpattern in subpatterns {
-                    let subpattern_user_ty =
-                        pattern_user_ty.clone().variant(adt_def, variant_index, subpattern.field);
-                    self.visit_primary_bindings(&subpattern.pattern, subpattern_user_ty, f);
+                    let subpattern_user_tys =
+                        user_tys.variant(adt_def, variant_index, subpattern.field);
+                    visit_subpat(self, &subpattern.pattern, &subpattern_user_tys, f);
                 }
             }
             PatKind::Or { ref pats } => {
@@ -955,7 +978,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // `let (x | y) = ...`, the primary binding of `y` occurs in
                 // the right subpattern
                 for subpattern in pats.iter() {
-                    self.visit_primary_bindings(subpattern, pattern_user_ty.clone(), f);
+                    visit_subpat(self, subpattern, user_tys, f);
                 }
             }
         }
@@ -2747,7 +2770,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         mode: BindingMode,
         var_id: LocalVarId,
         var_ty: Ty<'tcx>,
-        user_ty: UserTypeProjections,
+        user_ty: Option<Box<UserTypeProjections>>,
         has_guard: ArmHasGuard,
         opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
         pat_span: Span,
@@ -2757,7 +2780,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let local = LocalDecl {
             mutability: mode.1,
             ty: var_ty,
-            user_ty: if user_ty.is_empty() { None } else { Some(Box::new(user_ty)) },
+            user_ty,
             source_info,
             local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(BindingForm::Var(
                 VarBindingForm {
diff --git a/compiler/rustc_mir_build/src/builder/matches/user_ty.rs b/compiler/rustc_mir_build/src/builder/matches/user_ty.rs
new file mode 100644
index 00000000000..df9f93ac328
--- /dev/null
+++ b/compiler/rustc_mir_build/src/builder/matches/user_ty.rs
@@ -0,0 +1,140 @@
+//! Helper code for building a linked list of user-type projections on the
+//! stack while visiting a THIR pattern.
+//!
+//! This avoids having to repeatedly clone a partly-built [`UserTypeProjections`]
+//! at every step of the traversal, which is what the previous code was doing.
+
+use std::assert_matches::assert_matches;
+use std::iter;
+
+use rustc_abi::{FieldIdx, VariantIdx};
+use rustc_middle::mir::{ProjectionElem, UserTypeProjection, UserTypeProjections};
+use rustc_middle::ty::{AdtDef, UserTypeAnnotationIndex};
+use rustc_span::Symbol;
+
+/// One of a list of "operations" that can be used to lazily build projections
+/// of user-specified types.
+#[derive(Clone, Debug)]
+pub(crate) enum ProjectedUserTypesOp {
+    PushUserType { base: UserTypeAnnotationIndex },
+
+    Index,
+    Subslice { from: u64, to: u64 },
+    Deref,
+    Leaf { field: FieldIdx },
+    Variant { name: Symbol, variant: VariantIdx, field: FieldIdx },
+}
+
+#[derive(Debug)]
+pub(crate) enum ProjectedUserTypesNode<'a> {
+    None,
+    Chain { parent: &'a Self, op: ProjectedUserTypesOp },
+}
+
+impl<'a> ProjectedUserTypesNode<'a> {
+    pub(crate) fn push_user_type(&'a self, base: UserTypeAnnotationIndex) -> Self {
+        // Pushing a base user type always causes the chain to become non-empty.
+        Self::Chain { parent: self, op: ProjectedUserTypesOp::PushUserType { base } }
+    }
+
+    /// Push another projection op onto the chain, but only if it is already non-empty.
+    fn maybe_push(&'a self, op_fn: impl FnOnce() -> ProjectedUserTypesOp) -> Self {
+        match self {
+            Self::None => Self::None,
+            Self::Chain { .. } => Self::Chain { parent: self, op: op_fn() },
+        }
+    }
+
+    pub(crate) fn index(&'a self) -> Self {
+        self.maybe_push(|| ProjectedUserTypesOp::Index)
+    }
+
+    pub(crate) fn subslice(&'a self, from: u64, to: u64) -> Self {
+        self.maybe_push(|| ProjectedUserTypesOp::Subslice { from, to })
+    }
+
+    pub(crate) fn deref(&'a self) -> Self {
+        self.maybe_push(|| ProjectedUserTypesOp::Deref)
+    }
+
+    pub(crate) fn leaf(&'a self, field: FieldIdx) -> Self {
+        self.maybe_push(|| ProjectedUserTypesOp::Leaf { field })
+    }
+
+    pub(crate) fn variant(
+        &'a self,
+        adt_def: AdtDef<'_>,
+        variant: VariantIdx,
+        field: FieldIdx,
+    ) -> Self {
+        self.maybe_push(|| {
+            let name = adt_def.variant(variant).name;
+            ProjectedUserTypesOp::Variant { name, variant, field }
+        })
+    }
+
+    /// Traverses the chain of nodes to yield each op in the chain.
+    /// Because this walks from child node to parent node, the ops are
+    /// naturally yielded in "reverse" order.
+    fn iter_ops_reversed(&'a self) -> impl Iterator<Item = &'a ProjectedUserTypesOp> {
+        let mut next = self;
+        iter::from_fn(move || match next {
+            Self::None => None,
+            Self::Chain { parent, op } => {
+                next = parent;
+                Some(op)
+            }
+        })
+    }
+
+    /// Assembles this chain of user-type projections into a proper data structure.
+    pub(crate) fn build_user_type_projections(&self) -> Option<Box<UserTypeProjections>> {
+        // If we know there's nothing to do, just return None immediately.
+        if matches!(self, Self::None) {
+            return None;
+        }
+
+        let ops_reversed = self.iter_ops_reversed().cloned().collect::<Vec<_>>();
+        // The "first" op should always be `PushUserType`.
+        // Other projections are only added if there is at least one user type.
+        assert_matches!(ops_reversed.last(), Some(ProjectedUserTypesOp::PushUserType { .. }));
+
+        let mut projections = vec![];
+        for op in ops_reversed.into_iter().rev() {
+            match op {
+                ProjectedUserTypesOp::PushUserType { base } => {
+                    projections.push(UserTypeProjection { base, projs: vec![] })
+                }
+
+                ProjectedUserTypesOp::Index => {
+                    for p in &mut projections {
+                        p.projs.push(ProjectionElem::Index(()))
+                    }
+                }
+                ProjectedUserTypesOp::Subslice { from, to } => {
+                    for p in &mut projections {
+                        p.projs.push(ProjectionElem::Subslice { from, to, from_end: true })
+                    }
+                }
+                ProjectedUserTypesOp::Deref => {
+                    for p in &mut projections {
+                        p.projs.push(ProjectionElem::Deref)
+                    }
+                }
+                ProjectedUserTypesOp::Leaf { field } => {
+                    for p in &mut projections {
+                        p.projs.push(ProjectionElem::Field(field, ()))
+                    }
+                }
+                ProjectedUserTypesOp::Variant { name, variant, field } => {
+                    for p in &mut projections {
+                        p.projs.push(ProjectionElem::Downcast(Some(name), variant));
+                        p.projs.push(ProjectionElem::Field(field, ()));
+                    }
+                }
+            }
+        }
+
+        Some(Box::new(UserTypeProjections { contents: projections }))
+    }
+}
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index cf32f237b86..6ed7aabcb29 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1361,12 +1361,12 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
                 GenericParamDefKind::Lifetime => {}
                 GenericParamDefKind::Type { has_default, .. } => {
                     if has_default {
-                        self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
+                        let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
                     }
                 }
                 // FIXME(generic_const_exprs): May want to look inside const here
                 GenericParamDefKind::Const { .. } => {
-                    self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
+                    let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
                 }
             }
         }
@@ -1381,19 +1381,19 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
         // consider the ones that the user wrote. This is important
         // for the inferred outlives rules; see
         // `tests/ui/rfc-2093-infer-outlives/privacy.rs`.
-        self.visit_predicates(self.tcx.explicit_predicates_of(self.item_def_id));
+        let _ = self.visit_predicates(self.tcx.explicit_predicates_of(self.item_def_id));
         self
     }
 
     fn bounds(&mut self) -> &mut Self {
         self.in_primary_interface = false;
-        self.visit_clauses(self.tcx.explicit_item_bounds(self.item_def_id).skip_binder());
+        let _ = self.visit_clauses(self.tcx.explicit_item_bounds(self.item_def_id).skip_binder());
         self
     }
 
     fn ty(&mut self) -> &mut Self {
         self.in_primary_interface = true;
-        self.visit(self.tcx.type_of(self.item_def_id).instantiate_identity());
+        let _ = self.visit(self.tcx.type_of(self.item_def_id).instantiate_identity());
         self
     }
 
@@ -1785,7 +1785,7 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
 
     let module = tcx.hir_module_items(module_def_id);
     for def_id in module.definitions() {
-        rustc_ty_utils::sig_types::walk_types(tcx, def_id, &mut visitor);
+        let _ = rustc_ty_utils::sig_types::walk_types(tcx, def_id, &mut visitor);
 
         if let Some(body_id) = tcx.hir_maybe_body_owned_by(def_id) {
             visitor.visit_nested_body(body_id.id());
@@ -1798,7 +1798,11 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
                 let trait_ref = tcx.impl_trait_ref(id.owner_id.def_id).unwrap();
                 let trait_ref = trait_ref.instantiate_identity();
                 visitor.span = item.path.span;
-                visitor.visit_def_id(trait_ref.def_id, "trait", &trait_ref.print_only_trait_path());
+                let _ = visitor.visit_def_id(
+                    trait_ref.def_id,
+                    "trait",
+                    &trait_ref.print_only_trait_path(),
+                );
             }
         }
     }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs
index 5a303c3cd03..139b2997136 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs
@@ -77,7 +77,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
         match arg.kind {
             hir::TyKind::BareFn(_) => {
                 self.current_index.shift_in(1);
-                intravisit::walk_ty(self, arg);
+                let _ = intravisit::walk_ty(self, arg);
                 self.current_index.shift_out(1);
                 return ControlFlow::Continue(());
             }
@@ -85,7 +85,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
             hir::TyKind::TraitObject(bounds, ..) => {
                 for bound in bounds {
                     self.current_index.shift_in(1);
-                    self.visit_poly_trait_ref(bound);
+                    let _ = self.visit_poly_trait_ref(bound);
                     self.current_index.shift_out(1);
                 }
             }
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index be5d6286e26..2c60be63bd5 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -743,7 +743,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
 ) {
     debug!("assemble_candidates_from_trait_def(..)");
     let mut ambiguous = false;
-    selcx.for_each_item_bound(
+    let _ = selcx.for_each_item_bound(
         obligation.predicate.self_ty(),
         |selcx, clause, _| {
             let Some(clause) = clause.as_projection_clause() else {
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index a8d8003ead6..fc352499146 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -176,7 +176,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             // normalization, so try to deduplicate when possible to avoid
             // unnecessary ambiguity.
             let mut distinct_normalized_bounds = FxHashSet::default();
-            self.for_each_item_bound::<!>(
+            let _ = self.for_each_item_bound::<!>(
                 placeholder_trait_predicate.self_ty(),
                 |selcx, bound, idx| {
                     let Some(bound) = bound.as_trait_clause() else {
diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs
index c8b71074de7..e9055940310 100644
--- a/compiler/rustc_type_ir/src/binder.rs
+++ b/compiler/rustc_type_ir/src/binder.rs
@@ -112,7 +112,7 @@ where
     pub fn bind_with_vars(value: T, bound_vars: I::BoundVarKinds) -> Binder<I, T> {
         if cfg!(debug_assertions) {
             let mut validator = ValidateBoundVars::new(bound_vars);
-            value.visit_with(&mut validator);
+            let _ = value.visit_with(&mut validator);
         }
         Binder { value, bound_vars }
     }
@@ -196,7 +196,7 @@ impl<I: Interner, T> Binder<I, T> {
         let value = f(value);
         if cfg!(debug_assertions) {
             let mut validator = ValidateBoundVars::new(bound_vars);
-            value.visit_with(&mut validator);
+            let _ = value.visit_with(&mut validator);
         }
         Binder { value, bound_vars }
     }
@@ -209,7 +209,7 @@ impl<I: Interner, T> Binder<I, T> {
         let value = f(value)?;
         if cfg!(debug_assertions) {
             let mut validator = ValidateBoundVars::new(bound_vars);
-            value.visit_with(&mut validator);
+            let _ = value.visit_with(&mut validator);
         }
         Ok(Binder { value, bound_vars })
     }
diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs
index 0d910685927..ef7e6f9c2f4 100644
--- a/library/core/src/ops/control_flow.rs
+++ b/library/core/src/ops/control_flow.rs
@@ -80,6 +80,7 @@ use crate::{convert, ops};
 /// [`Continue`]: ControlFlow::Continue
 #[stable(feature = "control_flow_enum_type", since = "1.55.0")]
 #[rustc_diagnostic_item = "ControlFlow"]
+#[must_use]
 // ControlFlow should not implement PartialOrd or Ord, per RFC 3058:
 // https://rust-lang.github.io/rfcs/3058-try-trait-v2.html#traits-for-controlflow
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 0515a4cc00e..39f9680cb2f 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -519,7 +519,7 @@ impl Step for Rustc {
 
             // The REUSE-managed license files
             let license = |path: &Path| {
-                builder.install(path, &image.join("share/doc/rust/licences"), 0o644);
+                builder.install(path, &image.join("share/doc/rust/licenses"), 0o644);
             };
             for entry in t!(std::fs::read_dir(builder.src.join("LICENSES"))).flatten() {
                 license(&entry.path());
diff --git a/src/doc/unstable-book/src/language-features/asm-goto-with-outputs.md b/src/doc/unstable-book/src/language-features/asm-goto-with-outputs.md
new file mode 100644
index 00000000000..3cce5d1d74c
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/asm-goto-with-outputs.md
@@ -0,0 +1,27 @@
+# `asm_goto_with_outputs`
+
+The tracking issue for this feature is: [#119364]
+
+[#119364]: https://github.com/rust-lang/rust/issues/119364
+
+------------------------
+
+This feature allows label operands to be used together with output operands.
+
+Example:
+```rust,ignore (partial-example, x86-only)
+
+unsafe {
+    let a: usize;
+    asm!(
+        "mov {}, 1"
+        "jmp {}",
+        out(reg) a,
+        label {
+            println!("Jumped from asm {}!", a);
+        }
+    );
+}
+```
+
+The output operands are assigned before the label blocks are executed.
diff --git a/src/doc/unstable-book/src/language-features/asm-goto.md b/src/doc/unstable-book/src/language-features/asm-goto.md
deleted file mode 100644
index 823118bcae1..00000000000
--- a/src/doc/unstable-book/src/language-features/asm-goto.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# `asm_goto`
-
-The tracking issue for this feature is: [#119364]
-
-[#119364]: https://github.com/rust-lang/rust/issues/119364
-
-------------------------
-
-This feature adds a `label <block>` operand type to `asm!`.
-
-Example:
-```rust,ignore (partial-example, x86-only)
-
-unsafe {
-    asm!(
-        "jmp {}",
-        label {
-            println!("Jumped from asm!");
-        }
-    );
-}
-```
-
-The block must have unit type or diverge. The block starts a new safety context,
-so despite outer `unsafe`, you need extra unsafe to perform unsafe operations
-within `label <block>`.
-
-When `label <block>` is used together with `noreturn` option, it means that the
-assembly will not fallthrough. It's allowed to jump to a label within the
-assembly. In this case, the entire `asm!` expression will have an unit type as
-opposed to diverging, if not all label blocks diverge. The `asm!` expression
-still diverges if `noreturn` option is used and all label blocks diverge.
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 3f9023659db..e6f88128a70 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -5,7 +5,7 @@ use std::{fmt, iter};
 
 use arrayvec::ArrayVec;
 use rustc_abi::{ExternAbi, VariantIdx};
-use rustc_attr_parsing::{ConstStability, Deprecation, Stability, StableSince};
+use rustc_attr_parsing::{AttributeKind, ConstStability, Deprecation, Stability, StableSince};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
@@ -756,12 +756,7 @@ impl Item {
         Some(tcx.visibility(def_id))
     }
 
-    pub(crate) fn attributes(
-        &self,
-        tcx: TyCtxt<'_>,
-        cache: &Cache,
-        keep_as_is: bool,
-    ) -> Vec<String> {
+    pub(crate) fn attributes(&self, tcx: TyCtxt<'_>, cache: &Cache, is_json: bool) -> Vec<String> {
         const ALLOWED_ATTRIBUTES: &[Symbol] =
             &[sym::export_name, sym::link_section, sym::no_mangle, sym::non_exhaustive];
 
@@ -772,8 +767,14 @@ impl Item {
             .other_attrs
             .iter()
             .filter_map(|attr| {
-                if keep_as_is {
-                    Some(rustc_hir_pretty::attribute_to_string(&tcx, attr))
+                if is_json {
+                    if matches!(attr, hir::Attribute::Parsed(AttributeKind::Deprecation { .. })) {
+                        // rustdoc-json stores this in `Item::deprecation`, so we
+                        // don't want it it `Item::attrs`.
+                        None
+                    } else {
+                        Some(rustc_hir_pretty::attribute_to_string(&tcx, attr))
+                    }
                 } else if ALLOWED_ATTRIBUTES.contains(&attr.name_or_empty()) {
                     Some(
                         rustc_hir_pretty::attribute_to_string(&tcx, attr)
@@ -786,7 +787,9 @@ impl Item {
                 }
             })
             .collect();
-        if !keep_as_is
+
+        // Add #[repr(...)]
+        if !is_json
             && let Some(def_id) = self.def_id()
             && let ItemType::Struct | ItemType::Enum | ItemType::Union = self.type_()
         {
diff --git a/src/librustdoc/html/length_limit/tests.rs b/src/librustdoc/html/length_limit/tests.rs
index 2185c034890..4ebecfd5f24 100644
--- a/src/librustdoc/html/length_limit/tests.rs
+++ b/src/librustdoc/html/length_limit/tests.rs
@@ -9,41 +9,41 @@ fn empty() {
 #[test]
 fn basic() {
     let mut buf = HtmlWithLimit::new(60);
-    buf.push("Hello ");
+    let _ = buf.push("Hello ");
     buf.open_tag("em");
-    buf.push("world");
+    let _ = buf.push("world");
     buf.close_tag();
-    buf.push("!");
+    let _ = buf.push("!");
     assert_eq!(buf.finish(), "Hello <em>world</em>!");
 }
 
 #[test]
 fn no_tags() {
     let mut buf = HtmlWithLimit::new(60);
-    buf.push("Hello");
-    buf.push(" world!");
+    let _ = buf.push("Hello");
+    let _ = buf.push(" world!");
     assert_eq!(buf.finish(), "Hello world!");
 }
 
 #[test]
 fn limit_0() {
     let mut buf = HtmlWithLimit::new(0);
-    buf.push("Hello ");
+    let _ = buf.push("Hello ");
     buf.open_tag("em");
-    buf.push("world");
+    let _ = buf.push("world");
     buf.close_tag();
-    buf.push("!");
+    let _ = buf.push("!");
     assert_eq!(buf.finish(), "");
 }
 
 #[test]
 fn exactly_limit() {
     let mut buf = HtmlWithLimit::new(12);
-    buf.push("Hello ");
+    let _ = buf.push("Hello ");
     buf.open_tag("em");
-    buf.push("world");
+    let _ = buf.push("world");
     buf.close_tag();
-    buf.push("!");
+    let _ = buf.push("!");
     assert_eq!(buf.finish(), "Hello <em>world</em>!");
 }
 
@@ -51,11 +51,11 @@ fn exactly_limit() {
 fn multiple_nested_tags() {
     let mut buf = HtmlWithLimit::new(60);
     buf.open_tag("p");
-    buf.push("This is a ");
+    let _ = buf.push("This is a ");
     buf.open_tag("em");
-    buf.push("paragraph");
+    let _ = buf.push("paragraph");
     buf.open_tag("strong");
-    buf.push("!");
+    let _ = buf.push("!");
     buf.close_tag();
     buf.close_tag();
     buf.close_tag();
@@ -66,11 +66,11 @@ fn multiple_nested_tags() {
 fn forgot_to_close_tags() {
     let mut buf = HtmlWithLimit::new(60);
     buf.open_tag("p");
-    buf.push("This is a ");
+    let _ = buf.push("This is a ");
     buf.open_tag("em");
-    buf.push("paragraph");
+    let _ = buf.push("paragraph");
     buf.open_tag("strong");
-    buf.push("!");
+    let _ = buf.push("!");
     assert_eq!(buf.finish(), "<p>This is a <em>paragraph<strong>!</strong></em></p>");
 }
 
@@ -78,10 +78,10 @@ fn forgot_to_close_tags() {
 fn past_the_limit() {
     let mut buf = HtmlWithLimit::new(20);
     buf.open_tag("p");
-    (0..10).try_for_each(|n| {
+    let _ = (0..10).try_for_each(|n| {
         buf.open_tag("strong");
-        buf.push("word#")?;
-        buf.push(&n.to_string())?;
+        let _ = buf.push("word#")?;
+        let _ = buf.push(&n.to_string())?;
         buf.close_tag();
         ControlFlow::Continue(())
     });
@@ -100,8 +100,8 @@ fn past_the_limit() {
 fn quickly_past_the_limit() {
     let mut buf = HtmlWithLimit::new(6);
     buf.open_tag("p");
-    buf.push("Hello");
-    buf.push(" World");
+    let _ = buf.push("Hello");
+    let _ = buf.push(" World");
     // intentionally not closing <p> before finishing
     assert_eq!(buf.finish(), "<p>Hello</p>");
 }
@@ -110,7 +110,7 @@ fn quickly_past_the_limit() {
 fn close_too_many() {
     let mut buf = HtmlWithLimit::new(60);
     buf.open_tag("p");
-    buf.push("Hello");
+    let _ = buf.push("Hello");
     buf.close_tag();
     // This call does not panic because there are valid cases
     // where `close_tag()` is called with no tags left to close.
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 079651e8603..b067dbf750e 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -1568,7 +1568,7 @@ fn markdown_summary_with_limit(
 
     let mut buf = HtmlWithLimit::new(length_limit);
     let mut stopped_early = false;
-    p.try_for_each(|event| {
+    let _ = p.try_for_each(|event| {
         match &event {
             Event::Text(text) => {
                 let r =
diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
index fb5d49a1004..5afcf51167d 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
@@ -129,7 +129,7 @@ impl BreakAfterExprVisitor {
         };
 
         get_enclosing_block(cx, hir_id).is_some_and(|block| {
-            visitor.visit_block(block);
+            let _ = visitor.visit_block(block);
             visitor.break_after_expr
         })
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs b/src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs
index c9251c1b849..fe999a3b5f8 100644
--- a/src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs
@@ -40,7 +40,7 @@ pub fn check(cx: &LateContext<'_>, call: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<
         // We've checked that `call` is a call to `Stdin::read_line()` with the right receiver,
         // now let's check if the first use of the string passed to `::read_line()`
         // is used for operations that will always fail (e.g. parsing "6\n" into a number)
-        for_each_local_use_after_expr(cx, local_id, call.hir_id, |expr| {
+        let _ = for_each_local_use_after_expr(cx, local_id, call.hir_id, |expr| {
             if let Some(parent) = get_parent_expr(cx, expr) {
                 let data = if let ExprKind::MethodCall(segment, recv, args, span) = parent.kind {
                     if args.is_empty()
diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
index 320c0286bb7..0a8e2885648 100644
--- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
@@ -141,7 +141,7 @@ impl PassByRefOrValue {
         // Gather all the lifetimes found in the output type which may affect whether
         // `TRIVIALLY_COPY_PASS_BY_REF` should be linted.
         let mut output_regions = FxHashSet::default();
-        for_each_top_level_late_bound_region(fn_sig.skip_binder().output(), |region| -> ControlFlow<!> {
+        let _ = for_each_top_level_late_bound_region(fn_sig.skip_binder().output(), |region| -> ControlFlow<!> {
             output_regions.insert(region);
             ControlFlow::Continue(())
         });
diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
index a443043bef9..51c7d6fce31 100644
--- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
@@ -381,7 +381,7 @@ impl UnconditionalRecursion {
                 implemented_ty_id,
                 method_span,
             };
-            walk_body(&mut c, body);
+            let _ = walk_body(&mut c, body);
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
index 67fb73696f7..65fb342f752 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
@@ -145,19 +145,19 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
         let mut result = vec![];
         if fps.is_empty() {
             debug!("Unrestricted search for {:?} impls...", trait_);
-            self.for_trait_impls(trait_, self_ty_fp, |impls| {
+            let _ = self.for_trait_impls(trait_, self_ty_fp, |impls| {
                 result.extend(impls.for_trait(trait_).map(id_to_chalk));
                 ControlFlow::Continue(())
-            })
+            });
         } else {
-            self.for_trait_impls(trait_, self_ty_fp, |impls| {
+            let _ = self.for_trait_impls(trait_, self_ty_fp, |impls| {
                 result.extend(
                     fps.iter().flat_map(move |fp| {
                         impls.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk)
                     }),
                 );
                 ControlFlow::Continue(())
-            })
+            });
         };
 
         debug!("impls_for_trait returned {} impls", result.len());
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
index 6a01579bccc..e042c35d0c6 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
@@ -116,7 +116,7 @@ pub fn dyn_compatibility_of_trait_query(
     trait_: TraitId,
 ) -> Option<DynCompatibilityViolation> {
     let mut res = None;
-    dyn_compatibility_of_trait_with_callback(db, trait_, &mut |osv| {
+    let _ = dyn_compatibility_of_trait_with_callback(db, trait_, &mut |osv| {
         res = Some(osv);
         ControlFlow::Break(())
     });
@@ -597,7 +597,7 @@ fn contains_illegal_impl_trait_in_trait(
 
     let ret = sig.skip_binders().ret();
     let mut visitor = OpaqueTypeCollector(FxHashSet::default());
-    ret.visit_with(visitor.as_dyn(), DebruijnIndex::INNERMOST);
+    let _ = ret.visit_with(visitor.as_dyn(), DebruijnIndex::INNERMOST);
 
     // Since we haven't implemented RPITIT in proper way like rustc yet,
     // just check whether `ret` contains RPIT for now
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs
index 3060b610bb6..50851325bd5 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs
@@ -53,7 +53,7 @@ fn check_dyn_compatibility<'a>(
             continue;
         };
         let mut osvs = FxHashSet::default();
-        dyn_compatibility_with_callback(&db, trait_id, &mut |osv| {
+        let _ = dyn_compatibility_with_callback(&db, trait_id, &mut |osv| {
             osvs.insert(match osv {
                 DynCompatibilityViolation::SizedSelf => SizedSelf,
                 DynCompatibilityViolation::SelfReferential => SelfReferential,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
index 556091c4046..3e0ce7f1933 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -1143,7 +1143,7 @@ impl<'a> InferenceContext<'a> {
             non_assocs: FxHashMap::default(),
         };
         for ty in tait_candidates {
-            ty.visit_with(collector.as_dyn(), DebruijnIndex::INNERMOST);
+            let _ = ty.visit_with(collector.as_dyn(), DebruijnIndex::INNERMOST);
         }
 
         // Non-assoc TAITs can be define-used everywhere as long as they are
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index 624767cedf8..cc02b71f05c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -1033,7 +1033,7 @@ where
     T: ?Sized + TypeVisitable<Interner>,
 {
     let mut collector = PlaceholderCollector { db, placeholders: FxHashSet::default() };
-    value.visit_with(&mut collector, DebruijnIndex::INNERMOST);
+    let _ = value.visit_with(&mut collector, DebruijnIndex::INNERMOST);
     collector.placeholders.into_iter().collect()
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
index db94351dcc9..c7228005271 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
@@ -596,7 +596,7 @@ pub(crate) fn iterate_method_candidates<T>(
     mut callback: impl FnMut(ReceiverAdjustments, AssocItemId, bool) -> Option<T>,
 ) -> Option<T> {
     let mut slot = None;
-    iterate_method_candidates_dyn(
+    let _ = iterate_method_candidates_dyn(
         ty,
         db,
         env,
diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs
index 4351a34e822..4e45b5a250e 100644
--- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs
@@ -260,7 +260,7 @@ fn resolve_impl_trait_item(
     // attributes here. Use path resolution directly instead.
     //
     // FIXME: resolve type aliases (which are not yielded by iterate_path_candidates)
-    method_resolution::iterate_path_candidates(
+    let _ = method_resolution::iterate_path_candidates(
         &canonical,
         db,
         environment,
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index a8075509474..29f45846650 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -2911,7 +2911,7 @@ impl Trait {
         db: &dyn HirDatabase,
     ) -> Option<Vec<DynCompatibilityViolation>> {
         let mut violations = vec![];
-        hir_ty::dyn_compatibility::dyn_compatibility_with_callback(db, self.id, &mut |violation| {
+        let _ = hir_ty::dyn_compatibility::dyn_compatibility_with_callback(db, self.id, &mut |violation| {
             violations.push(violation);
             ControlFlow::Continue(())
         });
@@ -5497,7 +5497,7 @@ impl Type {
             .generic_def()
             .map_or_else(|| TraitEnvironment::empty(krate.id), |d| db.trait_environment(d));
 
-        method_resolution::iterate_method_candidates_dyn(
+        let _ = method_resolution::iterate_method_candidates_dyn(
             &canonical,
             db,
             environment,
@@ -5584,7 +5584,7 @@ impl Type {
             .generic_def()
             .map_or_else(|| TraitEnvironment::empty(krate.id), |d| db.trait_environment(d));
 
-        method_resolution::iterate_path_candidates(
+        let _ = method_resolution::iterate_path_candidates(
             &canonical,
             db,
             environment,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
index 330587e0dbf..6f4b886a28d 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
@@ -750,7 +750,7 @@ impl FunctionBody {
                         ast::Stmt::Item(_) => (),
                         ast::Stmt::LetStmt(stmt) => {
                             if let Some(pat) = stmt.pat() {
-                                walk_pat(&pat, &mut |pat| {
+                                let _ = walk_pat(&pat, &mut |pat| {
                                     cb(pat);
                                     std::ops::ControlFlow::<(), ()>::Continue(())
                                 });
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs
index 0b2e8aa6836..56a66070ef7 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs
@@ -121,7 +121,7 @@ pub fn walk_patterns_in_expr(start: &ast::Expr, cb: &mut dyn FnMut(ast::Pat)) {
         match ast::Stmt::cast(node.clone()) {
             Some(ast::Stmt::LetStmt(l)) => {
                 if let Some(pat) = l.pat() {
-                    walk_pat(&pat, &mut |pat| {
+                    let _ = walk_pat(&pat, &mut |pat| {
                         cb(pat);
                         ControlFlow::<(), ()>::Continue(())
                     });
@@ -159,7 +159,7 @@ pub fn walk_patterns_in_expr(start: &ast::Expr, cb: &mut dyn FnMut(ast::Pat)) {
                     }
                 } else if let Some(pat) = ast::Pat::cast(node) {
                     preorder.skip_subtree();
-                    walk_pat(&pat, &mut |pat| {
+                    let _ = walk_pat(&pat, &mut |pat| {
                         cb(pat);
                         ControlFlow::<(), ()>::Continue(())
                     });
diff --git a/tests/codegen/asm/goto.rs b/tests/codegen/asm/goto.rs
index 7a87bb7983b..f68c399c920 100644
--- a/tests/codegen/asm/goto.rs
+++ b/tests/codegen/asm/goto.rs
@@ -2,7 +2,7 @@
 //@ only-x86_64
 
 #![crate_type = "rlib"]
-#![feature(asm_goto, asm_goto_with_outputs)]
+#![feature(asm_goto_with_outputs)]
 
 use std::arch::asm;
 
diff --git a/tests/codegen/sanitizer/cfi/external_weak_symbols.rs b/tests/codegen/sanitizer/cfi/external_weak_symbols.rs
new file mode 100644
index 00000000000..00e9b5029af
--- /dev/null
+++ b/tests/codegen/sanitizer/cfi/external_weak_symbols.rs
@@ -0,0 +1,24 @@
+// Verifies that type metadata identifiers for for weakly-linked symbols are
+// emitted correctly.
+//
+//@ needs-sanitizer-cfi
+//@ compile-flags: -Clinker-plugin-lto -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static
+#![crate_type = "bin"]
+#![feature(linkage)]
+
+unsafe extern "C" {
+    #[linkage = "extern_weak"]
+    static FOO: Option<unsafe extern "C" fn(f64) -> ()>;
+}
+// CHECK: @_rust_extern_with_linkage_FOO = internal global ptr @FOO
+
+fn main() {
+    unsafe {
+        if let Some(method) = FOO {
+            method(4.2);
+            // CHECK: call i1 @llvm.type.test(ptr {{%method|%0}}, metadata !"_ZTSFvdE")
+        }
+    }
+}
+
+// CHECK: declare !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} extern_weak void @FOO(double) unnamed_addr #{{[0-9]+}}
diff --git a/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir
new file mode 100644
index 00000000000..3a515787c10
--- /dev/null
+++ b/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir
@@ -0,0 +1,80 @@
+// MIR for `let_else` after built
+
+| User Type Annotations
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:35:20: 35:45, inferred_ty: (u32, u64, &char)
+| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:35:20: 35:45, inferred_ty: (u32, u64, &char)
+|
+fn let_else() -> () {
+    let mut _0: ();
+    let mut _1: !;
+    let _2: u32 as UserTypeProjection { base: UserType(0), projs: [Field(0, ())] };
+    let _3: u64 as UserTypeProjection { base: UserType(0), projs: [Field(1, ())] };
+    let _4: &char as UserTypeProjection { base: UserType(0), projs: [Field(2, ())] };
+    let mut _5: (u32, u64, &char);
+    let mut _6: &char;
+    let _7: &char;
+    let _8: char;
+    scope 1 {
+        debug x => _2;
+        debug y => _3;
+        debug z => _4;
+    }
+
+    bb0: {
+        StorageLive(_2);
+        StorageLive(_3);
+        StorageLive(_4);
+        StorageLive(_5);
+        StorageLive(_6);
+        StorageLive(_7);
+        StorageLive(_8);
+        _8 = const 'u';
+        _7 = &_8;
+        _6 = &(*_7);
+        _5 = (const 7_u32, const 12_u64, move _6);
+        StorageDead(_6);
+        PlaceMention(_5);
+        falseEdge -> [real: bb4, imaginary: bb3];
+    }
+
+    bb1: {
+        _1 = core::panicking::panic(const "internal error: entered unreachable code") -> bb6;
+    }
+
+    bb2: {
+        unreachable;
+    }
+
+    bb3: {
+        goto -> bb5;
+    }
+
+    bb4: {
+        AscribeUserType(_5, +, UserTypeProjection { base: UserType(1), projs: [] });
+        _2 = copy (_5.0: u32);
+        _3 = copy (_5.1: u64);
+        _4 = copy (_5.2: &char);
+        StorageDead(_7);
+        StorageDead(_5);
+        _0 = const ();
+        StorageDead(_8);
+        StorageDead(_4);
+        StorageDead(_3);
+        StorageDead(_2);
+        return;
+    }
+
+    bb5: {
+        StorageDead(_7);
+        StorageDead(_5);
+        StorageDead(_8);
+        StorageDead(_4);
+        StorageDead(_3);
+        StorageDead(_2);
+        goto -> bb1;
+    }
+
+    bb6 (cleanup): {
+        resume;
+    }
+}
diff --git a/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir
new file mode 100644
index 00000000000..52a6d904d45
--- /dev/null
+++ b/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir
@@ -0,0 +1,62 @@
+// MIR for `let_else_bindless` after built
+
+| User Type Annotations
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:40:20: 40:45, inferred_ty: (u32, u64, &char)
+| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:40:20: 40:45, inferred_ty: (u32, u64, &char)
+|
+fn let_else_bindless() -> () {
+    let mut _0: ();
+    let mut _1: !;
+    let mut _2: (u32, u64, &char);
+    let mut _3: &char;
+    let _4: &char;
+    let _5: char;
+    scope 1 {
+    }
+
+    bb0: {
+        StorageLive(_2);
+        StorageLive(_3);
+        StorageLive(_4);
+        StorageLive(_5);
+        _5 = const 'u';
+        _4 = &_5;
+        _3 = &(*_4);
+        _2 = (const 7_u32, const 12_u64, move _3);
+        StorageDead(_3);
+        PlaceMention(_2);
+        falseEdge -> [real: bb4, imaginary: bb3];
+    }
+
+    bb1: {
+        _1 = core::panicking::panic(const "internal error: entered unreachable code") -> bb6;
+    }
+
+    bb2: {
+        unreachable;
+    }
+
+    bb3: {
+        goto -> bb5;
+    }
+
+    bb4: {
+        AscribeUserType(_2, +, UserTypeProjection { base: UserType(1), projs: [] });
+        StorageDead(_4);
+        StorageDead(_2);
+        _0 = const ();
+        StorageDead(_5);
+        return;
+    }
+
+    bb5: {
+        StorageDead(_4);
+        StorageDead(_2);
+        StorageDead(_5);
+        goto -> bb1;
+    }
+
+    bb6 (cleanup): {
+        resume;
+    }
+}
diff --git a/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir
new file mode 100644
index 00000000000..d1b8f823e9b
--- /dev/null
+++ b/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir
@@ -0,0 +1,54 @@
+// MIR for `let_init` after built
+
+| User Type Annotations
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:25:20: 25:45, inferred_ty: (u32, u64, &char)
+| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:25:20: 25:45, inferred_ty: (u32, u64, &char)
+|
+fn let_init() -> () {
+    let mut _0: ();
+    let _1: u32 as UserTypeProjection { base: UserType(0), projs: [Field(0, ())] };
+    let _2: u64 as UserTypeProjection { base: UserType(0), projs: [Field(1, ())] };
+    let _3: &char as UserTypeProjection { base: UserType(0), projs: [Field(2, ())] };
+    let mut _4: (u32, u64, &char);
+    let mut _5: &char;
+    let _6: &char;
+    let _7: char;
+    scope 1 {
+        debug x => _1;
+        debug y => _2;
+        debug z => _3;
+    }
+
+    bb0: {
+        StorageLive(_4);
+        StorageLive(_5);
+        StorageLive(_6);
+        StorageLive(_7);
+        _7 = const 'u';
+        _6 = &_7;
+        _5 = &(*_6);
+        _4 = (const 7_u32, const 12_u64, move _5);
+        StorageDead(_5);
+        PlaceMention(_4);
+        AscribeUserType(_4, +, UserTypeProjection { base: UserType(1), projs: [] });
+        StorageLive(_1);
+        _1 = copy (_4.0: u32);
+        StorageLive(_2);
+        _2 = copy (_4.1: u64);
+        StorageLive(_3);
+        _3 = copy (_4.2: &char);
+        StorageDead(_6);
+        StorageDead(_4);
+        _0 = const ();
+        StorageDead(_3);
+        StorageDead(_2);
+        StorageDead(_1);
+        StorageDead(_7);
+        return;
+    }
+
+    bb1: {
+        FakeRead(ForMatchedPlace(None), _4);
+        unreachable;
+    }
+}
diff --git a/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir
new file mode 100644
index 00000000000..6702f930060
--- /dev/null
+++ b/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir
@@ -0,0 +1,39 @@
+// MIR for `let_init_bindless` after built
+
+| User Type Annotations
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:30:20: 30:45, inferred_ty: (u32, u64, &char)
+| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:30:20: 30:45, inferred_ty: (u32, u64, &char)
+|
+fn let_init_bindless() -> () {
+    let mut _0: ();
+    let mut _1: (u32, u64, &char);
+    let mut _2: &char;
+    let _3: &char;
+    let _4: char;
+    scope 1 {
+    }
+
+    bb0: {
+        StorageLive(_1);
+        StorageLive(_2);
+        StorageLive(_3);
+        StorageLive(_4);
+        _4 = const 'u';
+        _3 = &_4;
+        _2 = &(*_3);
+        _1 = (const 7_u32, const 12_u64, move _2);
+        StorageDead(_2);
+        PlaceMention(_1);
+        AscribeUserType(_1, +, UserTypeProjection { base: UserType(1), projs: [] });
+        StorageDead(_3);
+        StorageDead(_1);
+        _0 = const ();
+        StorageDead(_4);
+        return;
+    }
+
+    bb1: {
+        FakeRead(ForMatchedPlace(None), _1);
+        unreachable;
+    }
+}
diff --git a/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir
new file mode 100644
index 00000000000..76b5938b87d
--- /dev/null
+++ b/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir
@@ -0,0 +1,27 @@
+// MIR for `let_uninit` after built
+
+| User Type Annotations
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:15:20: 15:45, inferred_ty: (u32, u64, &char)
+|
+fn let_uninit() -> () {
+    let mut _0: ();
+    let _1: u32 as UserTypeProjection { base: UserType(0), projs: [Field(0, ())] };
+    let _2: u64 as UserTypeProjection { base: UserType(0), projs: [Field(1, ())] };
+    let _3: &char as UserTypeProjection { base: UserType(0), projs: [Field(2, ())] };
+    scope 1 {
+        debug x => _1;
+        debug y => _2;
+        debug z => _3;
+    }
+
+    bb0: {
+        StorageLive(_1);
+        StorageLive(_2);
+        StorageLive(_3);
+        _0 = const ();
+        StorageDead(_3);
+        StorageDead(_2);
+        StorageDead(_1);
+        return;
+    }
+}
diff --git a/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir
new file mode 100644
index 00000000000..0cd12558771
--- /dev/null
+++ b/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir
@@ -0,0 +1,15 @@
+// MIR for `let_uninit_bindless` after built
+
+| User Type Annotations
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:20:20: 20:45, inferred_ty: (u32, u64, &char)
+|
+fn let_uninit_bindless() -> () {
+    let mut _0: ();
+    scope 1 {
+    }
+
+    bb0: {
+        _0 = const ();
+        return;
+    }
+}
diff --git a/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir b/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir
new file mode 100644
index 00000000000..c0ce6f1d06b
--- /dev/null
+++ b/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir
@@ -0,0 +1,46 @@
+// MIR for `match_assoc_const` after built
+
+| User Type Annotations
+| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:54:9: 54:44, inferred_ty: u32
+| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:54:9: 54:44, inferred_ty: u32
+|
+fn match_assoc_const() -> () {
+    let mut _0: ();
+    let mut _1: u32;
+
+    bb0: {
+        StorageLive(_1);
+        _1 = const 8_u32;
+        PlaceMention(_1);
+        switchInt(copy _1) -> [99: bb2, otherwise: bb1];
+    }
+
+    bb1: {
+        _0 = const ();
+        goto -> bb6;
+    }
+
+    bb2: {
+        falseEdge -> [real: bb5, imaginary: bb1];
+    }
+
+    bb3: {
+        goto -> bb1;
+    }
+
+    bb4: {
+        FakeRead(ForMatchedPlace(None), _1);
+        unreachable;
+    }
+
+    bb5: {
+        AscribeUserType(_1, -, UserTypeProjection { base: UserType(1), projs: [] });
+        _0 = const ();
+        goto -> bb6;
+    }
+
+    bb6: {
+        StorageDead(_1);
+        return;
+    }
+}
diff --git a/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir b/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir
new file mode 100644
index 00000000000..3a6aa5b7c2c
--- /dev/null
+++ b/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir
@@ -0,0 +1,74 @@
+// MIR for `match_assoc_const_range` after built
+
+| User Type Annotations
+| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:62:11: 62:46, inferred_ty: u32
+| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:62:11: 62:46, inferred_ty: u32
+| 2: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:63:9: 63:44, inferred_ty: u32
+| 3: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:63:9: 63:44, inferred_ty: u32
+|
+fn match_assoc_const_range() -> () {
+    let mut _0: ();
+    let mut _1: u32;
+    let mut _2: bool;
+    let mut _3: bool;
+
+    bb0: {
+        StorageLive(_1);
+        _1 = const 8_u32;
+        PlaceMention(_1);
+        _3 = Lt(copy _1, const 99_u32);
+        switchInt(move _3) -> [0: bb4, otherwise: bb2];
+    }
+
+    bb1: {
+        _0 = const ();
+        goto -> bb11;
+    }
+
+    bb2: {
+        falseEdge -> [real: bb10, imaginary: bb4];
+    }
+
+    bb3: {
+        goto -> bb1;
+    }
+
+    bb4: {
+        _2 = Le(const 99_u32, copy _1);
+        switchInt(move _2) -> [0: bb5, otherwise: bb6];
+    }
+
+    bb5: {
+        goto -> bb1;
+    }
+
+    bb6: {
+        falseEdge -> [real: bb9, imaginary: bb1];
+    }
+
+    bb7: {
+        goto -> bb5;
+    }
+
+    bb8: {
+        FakeRead(ForMatchedPlace(None), _1);
+        unreachable;
+    }
+
+    bb9: {
+        AscribeUserType(_1, -, UserTypeProjection { base: UserType(3), projs: [] });
+        _0 = const ();
+        goto -> bb11;
+    }
+
+    bb10: {
+        AscribeUserType(_1, -, UserTypeProjection { base: UserType(1), projs: [] });
+        _0 = const ();
+        goto -> bb11;
+    }
+
+    bb11: {
+        StorageDead(_1);
+        return;
+    }
+}
diff --git a/tests/mir-opt/building/user_type_annotations.rs b/tests/mir-opt/building/user_type_annotations.rs
new file mode 100644
index 00000000000..d55c678d5ae
--- /dev/null
+++ b/tests/mir-opt/building/user_type_annotations.rs
@@ -0,0 +1,66 @@
+//@ edition: 2024
+// skip-filecheck
+
+// This test demonstrates how many user type annotations are recorded in MIR
+// for various binding constructs. In particular, this makes it possible to see
+// the number of duplicate user-type-annotation entries, and whether that
+// number has changed.
+//
+// Duplicates are mostly harmless, other than being inefficient.
+// "Unused" entries that are _not_ duplicates may nevertheless be necessary so
+// that they are seen by MIR lifetime checks.
+
+// EMIT_MIR user_type_annotations.let_uninit.built.after.mir
+fn let_uninit() {
+    let (x, y, z): (u32, u64, &'static char);
+}
+
+// EMIT_MIR user_type_annotations.let_uninit_bindless.built.after.mir
+fn let_uninit_bindless() {
+    let (_, _, _): (u32, u64, &'static char);
+}
+
+// EMIT_MIR user_type_annotations.let_init.built.after.mir
+fn let_init() {
+    let (x, y, z): (u32, u64, &'static char) = (7, 12, &'u');
+}
+
+// EMIT_MIR user_type_annotations.let_init_bindless.built.after.mir
+fn let_init_bindless() {
+    let (_, _, _): (u32, u64, &'static char) = (7, 12, &'u');
+}
+
+// EMIT_MIR user_type_annotations.let_else.built.after.mir
+fn let_else() {
+    let (x, y, z): (u32, u64, &'static char) = (7, 12, &'u') else { unreachable!() };
+}
+
+// EMIT_MIR user_type_annotations.let_else_bindless.built.after.mir
+fn let_else_bindless() {
+    let (_, _, _): (u32, u64, &'static char) = (7, 12, &'u') else { unreachable!() };
+}
+
+trait MyTrait<'a> {
+    const FOO: u32;
+}
+struct MyStruct {}
+impl MyTrait<'static> for MyStruct {
+    const FOO: u32 = 99;
+}
+
+// EMIT_MIR user_type_annotations.match_assoc_const.built.after.mir
+fn match_assoc_const() {
+    match 8 {
+        <MyStruct as MyTrait<'static>>::FOO => {}
+        _ => {}
+    }
+}
+
+// EMIT_MIR user_type_annotations.match_assoc_const_range.built.after.mir
+fn match_assoc_const_range() {
+    match 8 {
+        ..<MyStruct as MyTrait<'static>>::FOO => {}
+        <MyStruct as MyTrait<'static>>::FOO.. => {}
+        _ => {}
+    }
+}
diff --git a/tests/rustdoc-json/attrs/deprecated.rs b/tests/rustdoc-json/attrs/deprecated.rs
new file mode 100644
index 00000000000..5cde7af841f
--- /dev/null
+++ b/tests/rustdoc-json/attrs/deprecated.rs
@@ -0,0 +1,38 @@
+//@ is "$.index[*][?(@.name=='not')].attrs" []
+//@ is "$.index[*][?(@.name=='not')].deprecation" null
+pub fn not() {}
+
+//@ is "$.index[*][?(@.name=='raw')].attrs" []
+//@ is "$.index[*][?(@.name=='raw')].deprecation" '{"since": null, "note": null}'
+#[deprecated]
+pub fn raw() {}
+
+//@ is "$.index[*][?(@.name=='equals_string')].attrs" []
+//@ is "$.index[*][?(@.name=='equals_string')].deprecation" '{"since": null, "note": "here is a reason"}'
+#[deprecated = "here is a reason"]
+pub fn equals_string() {}
+
+//@ is "$.index[*][?(@.name=='since')].attrs" []
+//@ is "$.index[*][?(@.name=='since')].deprecation" '{"since": "yoinks ago", "note": null}'
+#[deprecated(since = "yoinks ago")]
+pub fn since() {}
+
+//@ is "$.index[*][?(@.name=='note')].attrs" []
+//@ is "$.index[*][?(@.name=='note')].deprecation" '{"since": null, "note": "7"}'
+#[deprecated(note = "7")]
+pub fn note() {}
+
+//@ is "$.index[*][?(@.name=='since_and_note')].attrs" []
+//@ is "$.index[*][?(@.name=='since_and_note')].deprecation" '{"since": "tomorrow", "note": "sorry"}'
+#[deprecated(since = "tomorrow", note = "sorry")]
+pub fn since_and_note() {}
+
+//@ is "$.index[*][?(@.name=='note_and_since')].attrs" []
+//@ is "$.index[*][?(@.name=='note_and_since')].deprecation" '{"since": "a year from tomorrow", "note": "your welcome"}'
+#[deprecated(note = "your welcome", since = "a year from tomorrow")]
+pub fn note_and_since() {}
+
+//@ is "$.index[*][?(@.name=='neither_but_parens')].attrs" []
+//@ is "$.index[*][?(@.name=='neither_but_parens')].deprecation" '{"since": null, "note": null}'
+#[deprecated()]
+pub fn neither_but_parens() {}
diff --git a/tests/ui/asm/x86_64/bad-options.rs b/tests/ui/asm/x86_64/bad-options.rs
index 6424a1b1d42..123febc06fc 100644
--- a/tests/ui/asm/x86_64/bad-options.rs
+++ b/tests/ui/asm/x86_64/bad-options.rs
@@ -1,6 +1,6 @@
 //@ only-x86_64
 
-#![feature(asm_unwind, asm_goto)]
+#![feature(asm_unwind)]
 
 use std::arch::{asm, global_asm};
 
diff --git a/tests/ui/asm/x86_64/goto-block-safe.rs b/tests/ui/asm/x86_64/goto-block-safe.rs
index ee833a48a4b..b739e9f9ced 100644
--- a/tests/ui/asm/x86_64/goto-block-safe.rs
+++ b/tests/ui/asm/x86_64/goto-block-safe.rs
@@ -2,7 +2,6 @@
 //@ needs-asm-support
 
 #![deny(unreachable_code)]
-#![feature(asm_goto)]
 
 use std::arch::asm;
 
diff --git a/tests/ui/asm/x86_64/goto-block-safe.stderr b/tests/ui/asm/x86_64/goto-block-safe.stderr
index 49818db7484..ee7313bc8be 100644
--- a/tests/ui/asm/x86_64/goto-block-safe.stderr
+++ b/tests/ui/asm/x86_64/goto-block-safe.stderr
@@ -1,5 +1,5 @@
 error[E0133]: call to unsafe function `unreachable_unchecked` is unsafe and requires unsafe function or block
-  --> $DIR/goto-block-safe.rs:14:17
+  --> $DIR/goto-block-safe.rs:13:17
    |
 LL |     unsafe {
    |     ------ items do not inherit unsafety from separate enclosing items
diff --git a/tests/ui/asm/x86_64/goto.rs b/tests/ui/asm/x86_64/goto.rs
index 50e7441509a..00a8e588f96 100644
--- a/tests/ui/asm/x86_64/goto.rs
+++ b/tests/ui/asm/x86_64/goto.rs
@@ -3,7 +3,7 @@
 //@ needs-asm-support
 
 #![deny(unreachable_code)]
-#![feature(asm_goto, asm_goto_with_outputs)]
+#![feature(asm_goto_with_outputs)]
 
 use std::arch::asm;
 
diff --git a/tests/ui/feature-gates/feature-gate-asm_goto.rs b/tests/ui/feature-gates/feature-gate-asm_goto.rs
deleted file mode 100644
index beac4590349..00000000000
--- a/tests/ui/feature-gates/feature-gate-asm_goto.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//@ only-x86_64
-
-use std::arch::asm;
-
-fn main() {
-    unsafe {
-        asm!("jmp {}", label {});
-        //~^ ERROR label operands for inline assembly are unstable
-    }
-}
diff --git a/tests/ui/feature-gates/feature-gate-asm_goto.stderr b/tests/ui/feature-gates/feature-gate-asm_goto.stderr
deleted file mode 100644
index 62fd1a320d3..00000000000
--- a/tests/ui/feature-gates/feature-gate-asm_goto.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0658]: label operands for inline assembly are unstable
-  --> $DIR/feature-gate-asm_goto.rs:7:24
-   |
-LL |         asm!("jmp {}", label {});
-   |                        ^^^^^^^^
-   |
-   = note: see issue #119364 <https://github.com/rust-lang/rust/issues/119364> for more information
-   = help: add `#![feature(asm_goto)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.rs b/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.rs
index 294827f78d2..26b7d5d2fbf 100644
--- a/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.rs
+++ b/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.rs
@@ -1,7 +1,5 @@
 //@ only-x86_64
 
-#![feature(asm_goto)]
-
 use std::arch::asm;
 
 fn main() {
diff --git a/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.stderr b/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.stderr
index ff7a7d5760a..06e11301565 100644
--- a/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.stderr
+++ b/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.stderr
@@ -1,5 +1,5 @@
 error[E0658]: using both label and output operands for inline assembly is unstable
-  --> $DIR/feature-gate-asm_goto_with_outputs.rs:10:52
+  --> $DIR/feature-gate-asm_goto_with_outputs.rs:8:52
    |
 LL |         asm!("mov {}, 1", "jmp {}", out(reg) _out, label {});
    |                                                    ^^^^^^^^