about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-02-20 02:39:28 +0000
committerbors <bors@rust-lang.org>2025-02-20 02:39:28 +0000
commit6d3c050de81c8858e28b0e59cc9398d840edfbff (patch)
treebbd53de4a8b2c9322a95b5cea7fd1fe635608c47
parent4e1356b95972c1a52acb9f0dd078687132ec02be (diff)
parented45c1187fc94990cd633db47a34696db7ffd580 (diff)
Auto merge of #137295 - matthiaskrgr:rollup-tdu3t39, r=matthiaskrgr
Rollup of 9 pull requests

Successful merges:

 - #135296 (interpret: adjust vtable validity check for higher-ranked types)
 - #137106 (Add customized compare for Link in rustdoc)
 - #137253 (Restrict `bevy_ecs` `ParamSet` hack)
 - #137262 (Make fewer crates depend on `rustc_ast_ir`)
 - #137263 (Register `USAGE_OF_TYPE_IR_INHERENT`, remove inherent usages)
 - #137266 (MIR visitor tweaks)
 - #137269 (Pattern Migration 2024: properly label `&` patterns whose subpatterns are from macro expansions)
 - #137277 (stabilize `inherent_str_constructors`)
 - #137281 (Tweak "expected ident" parse error to avoid talking about doc comments)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--Cargo.lock7
-rw-r--r--compiler/rustc_ast_ir/src/lib.rs7
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/find_use.rs34
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs10
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs40
-rw-r--r--compiler/rustc_const_eval/src/interpret/traits.rs20
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs54
-rw-r--r--compiler/rustc_hir_typeck/Cargo.toml1
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs35
-rw-r--r--compiler/rustc_infer/Cargo.toml1
-rw-r--r--compiler/rustc_infer/src/traits/structural_impls.rs3
-rw-r--r--compiler/rustc_lint/src/lib.rs1
-rw-r--r--compiler/rustc_macros/src/type_visitable.rs6
-rw-r--r--compiler/rustc_middle/Cargo.toml1
-rw-r--r--compiler/rustc_middle/src/macros.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs3
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs5
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs310
-rw-r--r--compiler/rustc_middle/src/traits/solve.rs2
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs4
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs3
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs3
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs2
-rw-r--r--compiler/rustc_monomorphize/src/mono_checks/abi_check.rs5
-rw-r--r--compiler/rustc_next_trait_solver/Cargo.toml2
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs3
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/trait_goals.rs5
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs16
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_trait_selection/Cargo.toml1
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs3
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs3
-rw-r--r--compiler/rustc_transmute/Cargo.toml2
-rw-r--r--compiler/rustc_ty_utils/Cargo.toml1
-rw-r--r--compiler/rustc_ty_utils/src/sig_types.rs3
-rw-r--r--compiler/rustc_type_ir/src/lib.rs1
-rw-r--r--compiler/rustc_type_ir/src/visit.rs11
-rw-r--r--compiler/rustc_type_ir_macros/src/lib.rs6
-rw-r--r--library/core/src/str/mod.rs25
-rw-r--r--src/librustdoc/html/render/sidebar.rs18
-rw-r--r--src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.rs30
-rw-r--r--src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.stderr15
-rw-r--r--src/tools/miri/tests/pass/dyn-upcast.rs30
-rw-r--r--tests/rustdoc-gui/sidebar-foreign-impl-sort.goml15
-rw-r--r--tests/rustdoc-gui/src/test_docs/lib.rs18
-rw-r--r--tests/ui/implied-bounds/bevy_world_query.rs2
-rw-r--r--tests/ui/lint/invalid_from_utf8.rs1
-rw-r--r--tests/ui/lint/invalid_from_utf8.stderr80
-rw-r--r--tests/ui/parser/doc-before-bad-variant.rs6
-rw-r--r--tests/ui/parser/doc-before-bad-variant.stderr13
-rw-r--r--tests/ui/parser/doc-before-syntax-error.rs2
-rw-r--r--tests/ui/parser/doc-before-syntax-error.stderr8
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed6
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs6
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr20
55 files changed, 507 insertions, 406 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 22a349b2d32..c31fed86bc8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3748,7 +3748,6 @@ dependencies = [
  "itertools",
  "rustc_abi",
  "rustc_ast",
- "rustc_ast_ir",
  "rustc_attr_parsing",
  "rustc_data_structures",
  "rustc_errors",
@@ -3813,7 +3812,6 @@ dependencies = [
 name = "rustc_infer"
 version = "0.0.0"
 dependencies = [
- "rustc_ast_ir",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_fluent_macro",
@@ -4004,7 +4002,6 @@ dependencies = [
  "rustc_apfloat",
  "rustc_arena",
  "rustc_ast",
- "rustc_ast_ir",
  "rustc_attr_parsing",
  "rustc_data_structures",
  "rustc_error_messages",
@@ -4134,7 +4131,6 @@ name = "rustc_next_trait_solver"
 version = "0.0.0"
 dependencies = [
  "derive-where",
- "rustc_ast_ir",
  "rustc_data_structures",
  "rustc_index",
  "rustc_macros",
@@ -4454,7 +4450,6 @@ dependencies = [
  "itertools",
  "rustc_abi",
  "rustc_ast",
- "rustc_ast_ir",
  "rustc_attr_parsing",
  "rustc_data_structures",
  "rustc_errors",
@@ -4493,7 +4488,6 @@ version = "0.0.0"
 dependencies = [
  "itertools",
  "rustc_abi",
- "rustc_ast_ir",
  "rustc_data_structures",
  "rustc_hir",
  "rustc_infer",
@@ -4509,7 +4503,6 @@ version = "0.0.0"
 dependencies = [
  "itertools",
  "rustc_abi",
- "rustc_ast_ir",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_fluent_macro",
diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs
index ff9d940ce9f..9884e191ea7 100644
--- a/compiler/rustc_ast_ir/src/lib.rs
+++ b/compiler/rustc_ast_ir/src/lib.rs
@@ -1,3 +1,10 @@
+//! Common utilities shared by both `rustc_ast` and `rustc_type_ir`.
+//!
+//! Don't depend on this crate directly; both of those crates should re-export
+//! the functionality. Additionally, if you're in scope of `rustc_middle`, then
+//! prefer imports via that too, to avoid needing to directly depend on (e.g.)
+//! `rustc_type_ir` for a single import.
+
 // tidy-alphabetical-start
 #![cfg_attr(feature = "nightly", allow(internal_features))]
 #![cfg_attr(feature = "nightly", feature(never_type))]
diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
index 26a090f5579..96f48840468 100644
--- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
@@ -1,7 +1,7 @@
 use std::collections::VecDeque;
 
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_middle::mir::visit::{MirVisitable, PlaceContext, Visitor};
+use rustc_middle::mir::visit::{PlaceContext, Visitor};
 use rustc_middle::mir::{self, Body, Local, Location};
 use rustc_middle::ty::{RegionVid, TyCtxt};
 
@@ -45,7 +45,22 @@ impl<'a, 'tcx> UseFinder<'a, 'tcx> {
 
             let block_data = &self.body[p.block];
 
-            match self.def_use(p, block_data.visitable(p.statement_index)) {
+            let mut visitor = DefUseVisitor {
+                body: self.body,
+                tcx: self.tcx,
+                region_vid: self.region_vid,
+                def_use_result: None,
+            };
+
+            let is_statement = p.statement_index < block_data.statements.len();
+
+            if is_statement {
+                visitor.visit_statement(&block_data.statements[p.statement_index], p);
+            } else {
+                visitor.visit_terminator(block_data.terminator.as_ref().unwrap(), p);
+            }
+
+            match visitor.def_use_result {
                 Some(DefUseResult::Def) => {}
 
                 Some(DefUseResult::UseLive { local }) => {
@@ -57,7 +72,7 @@ impl<'a, 'tcx> UseFinder<'a, 'tcx> {
                 }
 
                 None => {
-                    if p.statement_index < block_data.statements.len() {
+                    if is_statement {
                         queue.push_back(p.successor_within_block());
                     } else {
                         queue.extend(
@@ -77,19 +92,6 @@ impl<'a, 'tcx> UseFinder<'a, 'tcx> {
 
         None
     }
-
-    fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> Option<DefUseResult> {
-        let mut visitor = DefUseVisitor {
-            body: self.body,
-            tcx: self.tcx,
-            region_vid: self.region_vid,
-            def_use_result: None,
-        };
-
-        thing.apply(location, &mut visitor);
-
-        visitor.def_use_result
-    }
 }
 
 struct DefUseVisitor<'a, 'tcx> {
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index b53c1505f6b..7b706334ed8 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -430,10 +430,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                     };
                     let erased_trait_ref =
                         ty::ExistentialTraitRef::erase_self_ty(*self.tcx, upcast_trait_ref);
-                    assert!(data_b.principal().is_some_and(|b| self.eq_in_param_env(
-                        erased_trait_ref,
-                        self.tcx.instantiate_bound_regions_with_erased(b)
-                    )));
+                    assert_eq!(
+                        data_b.principal().map(|b| {
+                            self.tcx.normalize_erasing_late_bound_regions(self.typing_env, b)
+                        }),
+                        Some(erased_trait_ref),
+                    );
                 } else {
                     // In this case codegen would keep using the old vtable. We don't want to do
                     // that as it has the wrong trait. The reason codegen can do this is that
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 66a75113652..c1948e9f31f 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -4,9 +4,6 @@ use either::{Left, Right};
 use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout};
 use rustc_errors::DiagCtxtHandle;
 use rustc_hir::def_id::DefId;
-use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::infer::at::ToTrace;
-use rustc_infer::traits::ObligationCause;
 use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo};
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::layout::{
@@ -17,8 +14,7 @@ use rustc_middle::{mir, span_bug};
 use rustc_session::Limit;
 use rustc_span::Span;
 use rustc_target::callconv::FnAbi;
-use rustc_trait_selection::traits::ObligationCtxt;
-use tracing::{debug, instrument, trace};
+use tracing::{debug, trace};
 
 use super::{
     Frame, FrameInfo, GlobalId, InterpErrorInfo, InterpErrorKind, InterpResult, MPlaceTy, Machine,
@@ -320,40 +316,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         }
     }
 
-    /// Check if the two things are equal in the current param_env, using an infcx to get proper
-    /// equality checks.
-    #[instrument(level = "trace", skip(self), ret)]
-    pub(super) fn eq_in_param_env<T>(&self, a: T, b: T) -> bool
-    where
-        T: PartialEq + TypeFoldable<TyCtxt<'tcx>> + ToTrace<'tcx>,
-    {
-        // Fast path: compare directly.
-        if a == b {
-            return true;
-        }
-        // Slow path: spin up an inference context to check if these traits are sufficiently equal.
-        let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env);
-        let ocx = ObligationCtxt::new(&infcx);
-        let cause = ObligationCause::dummy_with_span(self.cur_span());
-        // equate the two trait refs after normalization
-        let a = ocx.normalize(&cause, param_env, a);
-        let b = ocx.normalize(&cause, param_env, b);
-
-        if let Err(terr) = ocx.eq(&cause, param_env, a, b) {
-            trace!(?terr);
-            return false;
-        }
-
-        let errors = ocx.select_all_or_error();
-        if !errors.is_empty() {
-            trace!(?errors);
-            return false;
-        }
-
-        // All good.
-        true
-    }
-
     /// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
     /// frame which is not `#[track_caller]`. This matches the `caller_location` intrinsic,
     /// and is primarily intended for the panic machinery.
diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs
index 4cfaacebfcd..a5029eea5a7 100644
--- a/compiler/rustc_const_eval/src/interpret/traits.rs
+++ b/compiler/rustc_const_eval/src/interpret/traits.rs
@@ -86,21 +86,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             throw_ub!(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type });
         }
 
+        // This checks whether there is a subtyping relation between the predicates in either direction.
+        // For example:
+        // - casting between `dyn for<'a> Trait<fn(&'a u8)>` and `dyn Trait<fn(&'static u8)>` is OK
+        // - casting between `dyn Trait<for<'a> fn(&'a u8)>` and either of the above is UB
         for (a_pred, b_pred) in std::iter::zip(sorted_vtable, sorted_expected) {
-            let is_eq = match (a_pred.skip_binder(), b_pred.skip_binder()) {
-                (
-                    ty::ExistentialPredicate::Trait(a_data),
-                    ty::ExistentialPredicate::Trait(b_data),
-                ) => self.eq_in_param_env(a_pred.rebind(a_data), b_pred.rebind(b_data)),
+            let a_pred = self.tcx.normalize_erasing_late_bound_regions(self.typing_env, a_pred);
+            let b_pred = self.tcx.normalize_erasing_late_bound_regions(self.typing_env, b_pred);
 
-                (
-                    ty::ExistentialPredicate::Projection(a_data),
-                    ty::ExistentialPredicate::Projection(b_data),
-                ) => self.eq_in_param_env(a_pred.rebind(a_data), b_pred.rebind(b_data)),
-
-                _ => false,
-            };
-            if !is_eq {
+            if a_pred != b_pred {
                 throw_ub!(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type });
             }
         }
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index edfa897860b..f98504e19de 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -16,7 +16,6 @@ use rustc_lint_defs::builtin::SUPERTRAIT_ITEM_SHADOWING_DEFINITION;
 use rustc_macros::LintDiagnostic;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{
     self, AdtKind, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable,
@@ -143,33 +142,7 @@ where
         return Ok(());
     }
 
-    let is_bevy = 'is_bevy: {
-        // We don't want to emit this for dependents of Bevy, for now.
-        // See #119956
-        let is_bevy_paramset = |def: ty::AdtDef<'_>| {
-            let adt_did = with_no_trimmed_paths!(infcx.tcx.def_path_str(def.0.did));
-            adt_did.contains("ParamSet")
-        };
-        for ty in assumed_wf_types.iter() {
-            match ty.kind() {
-                ty::Adt(def, _) => {
-                    if is_bevy_paramset(*def) {
-                        break 'is_bevy true;
-                    }
-                }
-                ty::Ref(_, ty, _) => match ty.kind() {
-                    ty::Adt(def, _) => {
-                        if is_bevy_paramset(*def) {
-                            break 'is_bevy true;
-                        }
-                    }
-                    _ => {}
-                },
-                _ => {}
-            }
-        }
-        false
-    };
+    let is_bevy = assumed_wf_types.visit_with(&mut ContainsBevyParamSet { tcx }).is_break();
 
     // If we have set `no_implied_bounds_compat`, then do not attempt compatibility.
     // We could also just always enter if `is_bevy`, and call `implied_bounds_tys`,
@@ -194,6 +167,31 @@ where
     }
 }
 
+struct ContainsBevyParamSet<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsBevyParamSet<'tcx> {
+    type Result = ControlFlow<()>;
+
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
+        // We only care to match `ParamSet<T>` or `&ParamSet<T>`.
+        match t.kind() {
+            ty::Adt(def, _) => {
+                if self.tcx.item_name(def.did()) == sym::ParamSet
+                    && self.tcx.crate_name(def.did().krate) == sym::bevy_ecs
+                {
+                    return ControlFlow::Break(());
+                }
+            }
+            ty::Ref(_, ty, _) => ty.visit_with(self)?,
+            _ => {}
+        }
+
+        ControlFlow::Continue(())
+    }
+}
+
 fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
     let node = tcx.hir_node_by_def_id(def_id);
     let mut res = match node {
diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml
index 1f5acaa58a9..0331a20f95b 100644
--- a/compiler/rustc_hir_typeck/Cargo.toml
+++ b/compiler/rustc_hir_typeck/Cargo.toml
@@ -8,7 +8,6 @@ edition = "2021"
 itertools = "0.12"
 rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
-rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_attr_parsing = { path = "../rustc_attr_parsing" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 73a1432b06c..e63cc090993 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -847,20 +847,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.add_rust_2024_migration_desugared_pat(
                         pat_info.top_info.hir_id,
                         pat,
-                        ident.span,
+                        't', // last char of `mut`
                         def_br_mutbl,
                     );
                     BindingMode(ByRef::No, Mutability::Mut)
                 }
             }
             BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl),
-            BindingMode(ByRef::Yes(_), _) => {
+            BindingMode(ByRef::Yes(user_br_mutbl), _) => {
                 if let ByRef::Yes(def_br_mutbl) = def_br {
                     // `ref`/`ref mut` overrides the binding mode on edition <= 2021
                     self.add_rust_2024_migration_desugared_pat(
                         pat_info.top_info.hir_id,
                         pat,
-                        ident.span,
+                        match user_br_mutbl {
+                            Mutability::Not => 'f', // last char of `ref`
+                            Mutability::Mut => 't', // last char of `ref mut`
+                        },
                         def_br_mutbl,
                     );
                 }
@@ -2440,7 +2443,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.add_rust_2024_migration_desugared_pat(
                         pat_info.top_info.hir_id,
                         pat,
-                        inner.span,
+                        match pat_mutbl {
+                            Mutability::Not => '&', // last char of `&`
+                            Mutability::Mut => 't', // last char of `&mut`
+                        },
                         inh_mut,
                     )
                 }
@@ -2832,18 +2838,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         pat_id: HirId,
         subpat: &'tcx Pat<'tcx>,
-        cutoff_span: Span,
+        final_char: char,
         def_br_mutbl: Mutability,
     ) {
         // Try to trim the span we're labeling to just the `&` or binding mode that's an issue.
-        // If the subpattern's span is is from an expansion, the emitted label will not be trimmed.
-        let source_map = self.tcx.sess.source_map();
-        let cutoff_span = source_map
-            .span_extend_prev_while(cutoff_span, |c| c.is_whitespace() || c == '(')
-            .unwrap_or(cutoff_span);
-        // Ensure we use the syntax context and thus edition of `subpat.span`; this will be a hard
-        // error if the subpattern is of edition >= 2024.
-        let trimmed_span = subpat.span.until(cutoff_span).with_ctxt(subpat.span.ctxt());
+        let from_expansion = subpat.span.from_expansion();
+        let trimmed_span = if from_expansion {
+            // If the subpattern is from an expansion, highlight the whole macro call instead.
+            subpat.span
+        } else {
+            let trimmed = self.tcx.sess.source_map().span_through_char(subpat.span, final_char);
+            // The edition of the trimmed span should be the same as `subpat.span`; this will be a
+            // a hard error if the subpattern is of edition >= 2024. We set it manually to be sure:
+            trimmed.with_ctxt(subpat.span.ctxt())
+        };
 
         let mut typeck_results = self.typeck_results.borrow_mut();
         let mut table = typeck_results.rust_2024_migration_desugared_pats_mut();
@@ -2877,7 +2885,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
         // Only provide a detailed label if the problematic subpattern isn't from an expansion.
         // In the case that it's from a macro, we'll add a more detailed note in the emitter.
-        let from_expansion = subpat.span.from_expansion();
         let primary_label = if from_expansion {
             // We can't suggest eliding modifiers within expansions.
             info.suggest_eliding_modes = false;
diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml
index 6d1a2d3de9e..baf5dbbfd42 100644
--- a/compiler/rustc_infer/Cargo.toml
+++ b/compiler/rustc_infer/Cargo.toml
@@ -8,7 +8,6 @@ doctest = false
 
 [dependencies]
 # tidy-alphabetical-start
-rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs
index 31f585c0c9e..b346e193d0b 100644
--- a/compiler/rustc_infer/src/traits/structural_impls.rs
+++ b/compiler/rustc_infer/src/traits/structural_impls.rs
@@ -1,8 +1,7 @@
 use std::fmt;
 
-use rustc_ast_ir::try_visit;
 use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable};
-use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor};
+use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor, try_visit};
 use rustc_middle::ty::{self, TyCtxt};
 
 use crate::traits;
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index c8de5e87753..044a613dad6 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -641,6 +641,7 @@ fn register_internals(store: &mut LintStore) {
             LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
             LintId::of(USAGE_OF_QUALIFIED_TY),
             LintId::of(NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT),
+            LintId::of(USAGE_OF_TYPE_IR_INHERENT),
             LintId::of(BAD_OPT_ACCESS),
             LintId::of(SPAN_USE_EQ_CTXT),
         ],
diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs
index 527ca26c0eb..a7906d50d0f 100644
--- a/compiler/rustc_macros/src/type_visitable.rs
+++ b/compiler/rustc_macros/src/type_visitable.rs
@@ -36,12 +36,12 @@ pub(super) fn type_visitable_derive(
     s.add_bounds(synstructure::AddBounds::Generics);
     let body_visit = s.each(|bind| {
         quote! {
-            match ::rustc_ast_ir::visit::VisitorResult::branch(
+            match ::rustc_middle::ty::visit::VisitorResult::branch(
                 ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor)
             ) {
                 ::core::ops::ControlFlow::Continue(()) => {},
                 ::core::ops::ControlFlow::Break(r) => {
-                    return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
+                    return ::rustc_middle::ty::visit::VisitorResult::from_residual(r);
                 },
             }
         }
@@ -56,7 +56,7 @@ pub(super) fn type_visitable_derive(
                 __visitor: &mut __V
             ) -> __V::Result {
                 match *self { #body_visit }
-                <__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
+                <__V::Result as ::rustc_middle::ty::visit::VisitorResult>::output()
             }
         },
     )
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index 1b6a174c093..389c861c3b5 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -14,7 +14,6 @@ rustc_abi = { path = "../rustc_abi" }
 rustc_apfloat = "0.2.0"
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
-rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_attr_parsing = { path = "../rustc_attr_parsing" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_error_messages = { path = "../rustc_error_messages" } # Used for intra-doc links
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index b3064d8fe25..b5f3a0e1482 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -83,7 +83,7 @@ macro_rules! TrivialTypeTraversalImpls {
                     _: &mut F)
                     -> F::Result
                 {
-                    <F::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
+                    <F::Result as ::rustc_middle::ty::visit::VisitorResult>::output()
                 }
             }
         )+
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 8861e31b099..743812e3a20 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -5,7 +5,6 @@ use std::{convert, fmt, mem, ops};
 
 use either::Either;
 use rustc_abi::{Align, Size, VariantIdx, WrappingRange};
-use rustc_ast_ir::Mutability;
 use rustc_data_structures::sync::Lock;
 use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
@@ -16,7 +15,7 @@ use rustc_span::{DUMMY_SP, Span, Symbol};
 use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar};
 use crate::error;
 use crate::mir::{ConstAlloc, ConstValue};
-use crate::ty::{self, Ty, TyCtxt, ValTree, layout, tls};
+use crate::ty::{self, Mutability, Ty, TyCtxt, ValTree, layout, tls};
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
 pub enum ErrorHandled {
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 528da4ca057..ff493fa65a6 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -32,7 +32,6 @@ use tracing::{debug, trace};
 pub use self::query::*;
 use self::visit::TyContext;
 use crate::mir::interpret::{AllocRange, Scalar};
-use crate::mir::visit::MirVisitable;
 use crate::ty::codec::{TyDecoder, TyEncoder};
 use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths};
 use crate::ty::visit::TypeVisitableExt;
@@ -1364,10 +1363,6 @@ impl<'tcx> BasicBlockData<'tcx> {
         self.terminator.as_mut().expect("invalid terminator state")
     }
 
-    pub fn visitable(&self, index: usize) -> &dyn MirVisitable<'tcx> {
-        if index < self.statements.len() { &self.statements[index] } else { &self.terminator }
-    }
-
     /// Does the block have no statements and an unreachable terminator?
     #[inline]
     pub fn is_empty_unreachable(&self) -> bool {
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 8ad88fbda7c..193806f238b 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -270,10 +270,12 @@ macro_rules! make_mir_visitor {
 
             fn visit_local(
                 &mut self,
-                _local: $(& $mutability)? Local,
-                _context: PlaceContext,
-                _location: Location,
-            ) {}
+                local: $(& $mutability)? Local,
+                context: PlaceContext,
+                location: Location,
+            ) {
+                self.super_local(local, context, location)
+            }
 
             fn visit_source_scope(
                 &mut self,
@@ -292,9 +294,11 @@ macro_rules! make_mir_visitor {
                 super_body!(self, body, $($mutability, true)?);
             }
 
-            fn super_basic_block_data(&mut self,
-                                      block: BasicBlock,
-                                      data: & $($mutability)? BasicBlockData<'tcx>) {
+            fn super_basic_block_data(
+                &mut self,
+                block: BasicBlock,
+                data: & $($mutability)? BasicBlockData<'tcx>)
+            {
                 let BasicBlockData {
                     statements,
                     terminator,
@@ -339,24 +343,24 @@ macro_rules! make_mir_visitor {
                     match callee_def {
                         ty::InstanceKind::Item(_def_id) => {}
 
-                        ty::InstanceKind::Intrinsic(_def_id) |
-                        ty::InstanceKind::VTableShim(_def_id) |
-                        ty::InstanceKind::ReifyShim(_def_id, _) |
-                        ty::InstanceKind::Virtual(_def_id, _) |
-                        ty::InstanceKind::ThreadLocalShim(_def_id) |
-                        ty::InstanceKind::ClosureOnceShim { call_once: _def_id, track_caller: _ } |
-                        ty::InstanceKind::ConstructCoroutineInClosureShim {
+                        ty::InstanceKind::Intrinsic(_def_id)
+                        | ty::InstanceKind::VTableShim(_def_id)
+                        | ty::InstanceKind::ReifyShim(_def_id, _)
+                        | ty::InstanceKind::Virtual(_def_id, _)
+                        | ty::InstanceKind::ThreadLocalShim(_def_id)
+                        | ty::InstanceKind::ClosureOnceShim { call_once: _def_id, track_caller: _ }
+                        | ty::InstanceKind::ConstructCoroutineInClosureShim {
                             coroutine_closure_def_id: _def_id,
                             receiver_by_ref: _,
-                        } |
-                        ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, None) |
-                        ty::InstanceKind::DropGlue(_def_id, None) => {}
-
-                        ty::InstanceKind::FnPtrShim(_def_id, ty) |
-                        ty::InstanceKind::DropGlue(_def_id, Some(ty)) |
-                        ty::InstanceKind::CloneShim(_def_id, ty) |
-                        ty::InstanceKind::FnPtrAddrShim(_def_id, ty) |
-                        ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, Some(ty)) => {
+                        }
+                        | ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, None)
+                        | ty::InstanceKind::DropGlue(_def_id, None) => {}
+
+                        ty::InstanceKind::FnPtrShim(_def_id, ty)
+                        | ty::InstanceKind::DropGlue(_def_id, Some(ty))
+                        | ty::InstanceKind::CloneShim(_def_id, ty)
+                        | ty::InstanceKind::FnPtrAddrShim(_def_id, ty)
+                        | ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, Some(ty)) => {
                             // FIXME(eddyb) use a better `TyContext` here.
                             self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
                         }
@@ -368,19 +372,16 @@ macro_rules! make_mir_visitor {
                 }
             }
 
-            fn super_statement(&mut self,
-                               statement: & $($mutability)? Statement<'tcx>,
-                               location: Location) {
-                let Statement {
-                    source_info,
-                    kind,
-                } = statement;
+            fn super_statement(
+                &mut self,
+                statement: & $($mutability)? Statement<'tcx>,
+                location: Location
+            ) {
+                let Statement { source_info, kind } = statement;
 
                 self.visit_source_info(source_info);
                 match kind {
-                    StatementKind::Assign(
-                        box (place, rvalue)
-                    ) => {
+                    StatementKind::Assign(box (place, rvalue)) => {
                         self.visit_assign(place, rvalue, location);
                     }
                     StatementKind::FakeRead(box (_, place)) => {
@@ -428,11 +429,13 @@ macro_rules! make_mir_visitor {
                             location
                         );
                     }
-                    StatementKind::AscribeUserType(
-                        box (place, user_ty),
-                        variance
-                    ) => {
-                        self.visit_ascribe_user_ty(place, $(& $mutability)? *variance, user_ty, location);
+                    StatementKind::AscribeUserType(box (place, user_ty), variance) => {
+                        self.visit_ascribe_user_ty(
+                            place,
+                            $(& $mutability)? *variance,
+                            user_ty,
+                            location
+                        );
                     }
                     StatementKind::Coverage(coverage) => {
                         self.visit_coverage(
@@ -443,7 +446,11 @@ macro_rules! make_mir_visitor {
                     StatementKind::Intrinsic(box ref $($mutability)? intrinsic) => {
                         match intrinsic {
                             NonDivergingIntrinsic::Assume(op) => self.visit_operand(op, location),
-                            NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { src, dst, count }) => {
+                            NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
+                                src,
+                                dst,
+                                count
+                            }) => {
                                 self.visit_operand(src, location);
                                 self.visit_operand(dst, location);
                                 self.visit_operand(count, location);
@@ -456,10 +463,12 @@ macro_rules! make_mir_visitor {
                 }
             }
 
-            fn super_assign(&mut self,
-                            place: &$($mutability)? Place<'tcx>,
-                            rvalue: &$($mutability)? Rvalue<'tcx>,
-                            location: Location) {
+            fn super_assign(
+                &mut self,
+                place: &$($mutability)? Place<'tcx>,
+                rvalue: &$($mutability)? Rvalue<'tcx>,
+                location: Location
+            ) {
                 self.visit_place(
                     place,
                     PlaceContext::MutatingUse(MutatingUseContext::Store),
@@ -468,20 +477,22 @@ macro_rules! make_mir_visitor {
                 self.visit_rvalue(rvalue, location);
             }
 
-            fn super_terminator(&mut self,
-                                terminator: &$($mutability)? Terminator<'tcx>,
-                                location: Location) {
+            fn super_terminator(
+                &mut self,
+                terminator: &$($mutability)? Terminator<'tcx>,
+                location: Location
+            ) {
                 let Terminator { source_info, kind } = terminator;
 
                 self.visit_source_info(source_info);
                 match kind {
-                    TerminatorKind::Goto { .. } |
-                    TerminatorKind::UnwindResume |
-                    TerminatorKind::UnwindTerminate(_) |
-                    TerminatorKind::CoroutineDrop |
-                    TerminatorKind::Unreachable |
-                    TerminatorKind::FalseEdge { .. } |
-                    TerminatorKind::FalseUnwind { .. } => {}
+                    TerminatorKind::Goto { .. }
+                    | TerminatorKind::UnwindResume
+                    | TerminatorKind::UnwindTerminate(_)
+                    | TerminatorKind::CoroutineDrop
+                    | TerminatorKind::Unreachable
+                    | TerminatorKind::FalseEdge { .. }
+                    | TerminatorKind::FalseUnwind { .. } => {}
 
                     TerminatorKind::Return => {
                         // `return` logically moves from the return place `_0`. Note that the place
@@ -500,19 +511,11 @@ macro_rules! make_mir_visitor {
                         );
                     }
 
-                    TerminatorKind::SwitchInt {
-                        discr,
-                        targets: _
-                    } => {
+                    TerminatorKind::SwitchInt { discr, targets: _ } => {
                         self.visit_operand(discr, location);
                     }
 
-                    TerminatorKind::Drop {
-                        place,
-                        target: _,
-                        unwind: _,
-                        replace: _,
-                    } => {
+                    TerminatorKind::Drop { place, target: _, unwind: _, replace: _ } => {
                         self.visit_place(
                             place,
                             PlaceContext::MutatingUse(MutatingUseContext::Drop),
@@ -541,11 +544,7 @@ macro_rules! make_mir_visitor {
                         );
                     }
 
-                    TerminatorKind::TailCall {
-                        func,
-                        args,
-                        fn_span,
-                    } => {
+                    TerminatorKind::TailCall { func, args, fn_span } => {
                         self.visit_span($(& $mutability)? *fn_span);
                         self.visit_operand(func, location);
                         for arg in args {
@@ -553,23 +552,12 @@ macro_rules! make_mir_visitor {
                         }
                     },
 
-                    TerminatorKind::Assert {
-                        cond,
-                        expected: _,
-                        msg,
-                        target: _,
-                        unwind: _,
-                    } => {
+                    TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
                         self.visit_operand(cond, location);
                         self.visit_assert_message(msg, location);
                     }
 
-                    TerminatorKind::Yield {
-                        value,
-                        resume: _,
-                        resume_arg,
-                        drop: _,
-                    } => {
+                    TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => {
                         self.visit_operand(value, location);
                         self.visit_place(
                             resume_arg,
@@ -622,9 +610,11 @@ macro_rules! make_mir_visitor {
                 }
             }
 
-            fn super_assert_message(&mut self,
-                                    msg: & $($mutability)? AssertMessage<'tcx>,
-                                    location: Location) {
+            fn super_assert_message(
+                &mut self,
+                msg: & $($mutability)? AssertMessage<'tcx>,
+                location: Location
+            ) {
                 use crate::mir::AssertKind::*;
                 match msg {
                     BoundsCheck { len, index } => {
@@ -648,9 +638,11 @@ macro_rules! make_mir_visitor {
                 }
             }
 
-            fn super_rvalue(&mut self,
-                            rvalue: & $($mutability)? Rvalue<'tcx>,
-                            location: Location) {
+            fn super_rvalue(
+                &mut self,
+                rvalue: & $($mutability)? Rvalue<'tcx>,
+                location: Location
+            ) {
                 match rvalue {
                     Rvalue::Use(operand) => {
                         self.visit_operand(operand, location);
@@ -677,6 +669,7 @@ macro_rules! make_mir_visitor {
                         };
                         self.visit_place(path, ctx, location);
                     }
+
                     Rvalue::CopyForDeref(place) => {
                         self.visit_place(
                             place,
@@ -740,8 +733,7 @@ macro_rules! make_mir_visitor {
                             AggregateKind::Array(ty) => {
                                 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
                             }
-                            AggregateKind::Tuple => {
-                            }
+                            AggregateKind::Tuple => {}
                             AggregateKind::Adt(
                                 _adt_def,
                                 _variant_index,
@@ -751,22 +743,13 @@ macro_rules! make_mir_visitor {
                             ) => {
                                 self.visit_args(args, location);
                             }
-                            AggregateKind::Closure(
-                                _,
-                                closure_args
-                            ) => {
+                            AggregateKind::Closure(_, closure_args) => {
                                 self.visit_args(closure_args, location);
                             }
-                            AggregateKind::Coroutine(
-                                _,
-                                coroutine_args,
-                            ) => {
+                            AggregateKind::Coroutine(_, coroutine_args) => {
                                 self.visit_args(coroutine_args, location);
                             }
-                            AggregateKind::CoroutineClosure(
-                                _,
-                                coroutine_closure_args,
-                            ) => {
+                            AggregateKind::CoroutineClosure(_, coroutine_closure_args) => {
                                 self.visit_args(coroutine_closure_args, location);
                             }
                             AggregateKind::RawPtr(ty, _) => {
@@ -791,9 +774,11 @@ macro_rules! make_mir_visitor {
                 }
             }
 
-            fn super_operand(&mut self,
-                             operand: & $($mutability)? Operand<'tcx>,
-                             location: Location) {
+            fn super_operand(
+                &mut self,
+                operand: & $($mutability)? Operand<'tcx>,
+                location: Location
+            ) {
                 match operand {
                     Operand::Copy(place) => {
                         self.visit_place(
@@ -815,28 +800,36 @@ macro_rules! make_mir_visitor {
                 }
             }
 
-            fn super_ascribe_user_ty(&mut self,
-                                     place: & $($mutability)? Place<'tcx>,
-                                     variance: $(& $mutability)? ty::Variance,
-                                     user_ty: & $($mutability)? UserTypeProjection,
-                                     location: Location) {
+            fn super_ascribe_user_ty(
+                &mut self,
+                place: & $($mutability)? Place<'tcx>,
+                variance: $(& $mutability)? ty::Variance,
+                user_ty: & $($mutability)? UserTypeProjection,
+                location: Location)
+            {
                 self.visit_place(
                     place,
-                    PlaceContext::NonUse(NonUseContext::AscribeUserTy($(* &$mutability *)? variance)),
+                    PlaceContext::NonUse(
+                        NonUseContext::AscribeUserTy($(* &$mutability *)? variance)
+                    ),
                     location
                 );
                 self.visit_user_type_projection(user_ty);
             }
 
-            fn super_coverage(&mut self,
-                              _kind: & $($mutability)? coverage::CoverageKind,
-                              _location: Location) {
+            fn super_coverage(
+                &mut self,
+                _kind: & $($mutability)? coverage::CoverageKind,
+                _location: Location
+            ) {
             }
 
-            fn super_retag(&mut self,
-                           _kind: $(& $mutability)? RetagKind,
-                           place: & $($mutability)? Place<'tcx>,
-                           location: Location) {
+            fn super_retag(
+                &mut self,
+                _kind: $(& $mutability)? RetagKind,
+                place: & $($mutability)? Place<'tcx>,
+                location: Location
+            ) {
                 self.visit_place(
                     place,
                     PlaceContext::MutatingUse(MutatingUseContext::Retag),
@@ -844,9 +837,11 @@ macro_rules! make_mir_visitor {
                 );
             }
 
-            fn super_local_decl(&mut self,
-                                local: Local,
-                                local_decl: & $($mutability)? LocalDecl<'tcx>) {
+            fn super_local_decl(
+                &mut self,
+                local: Local,
+                local_decl: & $($mutability)? LocalDecl<'tcx>
+            ) {
                 let LocalDecl {
                     mutability: _,
                     ty,
@@ -868,6 +863,14 @@ macro_rules! make_mir_visitor {
                 }
             }
 
+            fn super_local(
+                &mut self,
+                _local: $(& $mutability)? Local,
+                _context: PlaceContext,
+                _location: Location,
+            ) {
+            }
+
             fn super_var_debug_info(
                 &mut self,
                 var_debug_info: & $($mutability)? VarDebugInfo<'tcx>
@@ -882,7 +885,10 @@ macro_rules! make_mir_visitor {
 
                 self.visit_source_info(source_info);
                 let location = Location::START;
-                if let Some(box VarDebugInfoFragment { ref $($mutability)? ty, ref $($mutability)? projection }) = composite {
+                if let Some(box VarDebugInfoFragment {
+                    ref $($mutability)? ty,
+                    ref $($mutability)? projection
+                }) = composite {
                     self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
                     for elem in projection {
                         let ProjectionElem::Field(_, ty) = elem else { bug!() };
@@ -900,10 +906,7 @@ macro_rules! make_mir_visitor {
                 }
             }
 
-            fn super_source_scope(
-                &mut self,
-                _scope: $(& $mutability)? SourceScope
-            ) {}
+            fn super_source_scope(&mut self, _scope: $(& $mutability)? SourceScope) {}
 
             fn super_const_operand(
                 &mut self,
@@ -919,8 +922,12 @@ macro_rules! make_mir_visitor {
                 self.visit_span($(& $mutability)? *span);
                 match const_ {
                     Const::Ty(_, ct) => self.visit_ty_const($(&$mutability)? *ct, location),
-                    Const::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
-                    Const::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
+                    Const::Val(_, ty) => {
+                        self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
+                    }
+                    Const::Unevaluated(_, ty) => {
+                        self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
+                    }
                 }
             }
 
@@ -929,27 +936,18 @@ macro_rules! make_mir_visitor {
                 _ct: $(& $mutability)? ty::Const<'tcx>,
                 _location: Location,
             ) {
-
             }
 
-            fn super_span(&mut self, _span: $(& $mutability)? Span) {
-            }
+            fn super_span(&mut self, _span: $(& $mutability)? Span) {}
 
             fn super_source_info(&mut self, source_info: & $($mutability)? SourceInfo) {
-                let SourceInfo {
-                    span,
-                    scope,
-                } = source_info;
+                let SourceInfo { span, scope } = source_info;
 
                 self.visit_span($(& $mutability)? *span);
                 self.visit_source_scope($(& $mutability)? *scope);
             }
 
-            fn super_user_type_projection(
-                &mut self,
-                _ty: & $($mutability)? UserTypeProjection,
-            ) {
-            }
+            fn super_user_type_projection(&mut self, _ty: & $($mutability)? UserTypeProjection) {}
 
             fn super_user_type_annotation(
                 &mut self,
@@ -960,14 +958,11 @@ macro_rules! make_mir_visitor {
                 self.visit_ty($(& $mutability)? ty.inferred_ty, TyContext::UserTy(ty.span));
             }
 
-            fn super_ty(&mut self, _ty: $(& $mutability)? Ty<'tcx>) {
-            }
+            fn super_ty(&mut self, _ty: $(& $mutability)? Ty<'tcx>) {}
 
-            fn super_region(&mut self, _region: $(& $mutability)? ty::Region<'tcx>) {
-            }
+            fn super_region(&mut self, _region: $(& $mutability)? ty::Region<'tcx>) {}
 
-            fn super_args(&mut self, _args: & $($mutability)? GenericArgsRef<'tcx>) {
-            }
+            fn super_args(&mut self, _args: & $($mutability)? GenericArgsRef<'tcx>) {}
 
             // Convenience methods
 
@@ -976,7 +971,8 @@ macro_rules! make_mir_visitor {
                 body: &$($mutability)? Body<'tcx>,
                 location: Location
             ) {
-                let basic_block = & $($mutability)? basic_blocks!(body, $($mutability, true)?)[location.block];
+                let basic_block =
+                    & $($mutability)? basic_blocks!(body, $($mutability, true)?)[location.block];
                 if basic_block.statements.len() == location.statement_index {
                     if let Some(ref $($mutability)? terminator) = basic_block.terminator {
                         self.visit_terminator(terminator, location)
@@ -1255,28 +1251,6 @@ macro_rules! visit_place_fns {
 make_mir_visitor!(Visitor,);
 make_mir_visitor!(MutVisitor, mut);
 
-pub trait MirVisitable<'tcx> {
-    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>);
-}
-
-impl<'tcx> MirVisitable<'tcx> for Statement<'tcx> {
-    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
-        visitor.visit_statement(self, location)
-    }
-}
-
-impl<'tcx> MirVisitable<'tcx> for Terminator<'tcx> {
-    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
-        visitor.visit_terminator(self, location)
-    }
-}
-
-impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
-    fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
-        visitor.visit_terminator(self.as_ref().unwrap(), location)
-    }
-}
-
 /// Extra information passed to `visit_ty` and friends to give context
 /// about where the type etc appears.
 #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
index f659bf8125a..9c74f6263b3 100644
--- a/compiler/rustc_middle/src/traits/solve.rs
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -1,9 +1,9 @@
-use rustc_ast_ir::try_visit;
 use rustc_data_structures::intern::Interned;
 use rustc_macros::HashStable;
 use rustc_type_ir as ir;
 pub use rustc_type_ir::solve::*;
 
+use crate::ty::visit::try_visit;
 use crate::ty::{
     self, FallibleTypeFolder, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor,
 };
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index 56a38a84c9f..b74ddb81710 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -6,8 +6,6 @@ use std::mem;
 use std::num::NonZero;
 use std::ptr::NonNull;
 
-use rustc_ast_ir::visit::VisitorResult;
-use rustc_ast_ir::walk_visitable_list;
 use rustc_data_structures::intern::Interned;
 use rustc_errors::{DiagArgValue, IntoDiagArg};
 use rustc_hir::def_id::DefId;
@@ -18,7 +16,7 @@ use smallvec::SmallVec;
 
 use crate::ty::codec::{TyDecoder, TyEncoder};
 use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
-use crate::ty::visit::{TypeVisitable, TypeVisitor};
+use crate::ty::visit::{TypeVisitable, TypeVisitor, VisitorResult, walk_visitable_list};
 use crate::ty::{
     self, ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineConstArgs, Lift, List, Ty, TyCtxt,
 };
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index c52e774c8b7..a1d44882e63 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -27,7 +27,6 @@ pub use intrinsic::IntrinsicDef;
 use rustc_abi::{Align, FieldIdx, Integer, IntegerType, ReprFlags, ReprOptions, VariantIdx};
 use rustc_ast::expand::StrippedCfgItem;
 use rustc_ast::node_id::NodeMap;
-pub use rustc_ast_ir::{Movability, Mutability, try_visit};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -48,7 +47,7 @@ pub use rustc_session::lint::RegisteredTools;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::{ExpnId, ExpnKind, Ident, Span, Symbol, kw, sym};
 pub use rustc_type_ir::relate::VarianceDiagInfo;
-pub use rustc_type_ir::*;
+pub use rustc_type_ir::{Movability, Mutability, *};
 use tracing::{debug, instrument};
 pub use vtable::*;
 use {rustc_ast as ast, rustc_attr_parsing as attr, rustc_hir as hir};
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 6c15e033bb0..b2286c74402 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -7,13 +7,12 @@ use std::fmt::{self, Debug};
 
 use rustc_abi::TyAndLayout;
 use rustc_ast::InlineAsmTemplatePiece;
-use rustc_ast_ir::try_visit;
-use rustc_ast_ir::visit::VisitorResult;
 use rustc_hir::def::Namespace;
 use rustc_hir::def_id::LocalDefId;
 use rustc_span::Span;
 use rustc_span::source_map::Spanned;
 use rustc_type_ir::ConstKind;
+use rustc_type_ir::visit::{VisitorResult, try_visit};
 
 use super::print::PrettyPrinter;
 use super::{GenericArg, GenericArgKind, Pattern, Region};
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 4efaccefcf7..95256b55bb4 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -2,7 +2,7 @@ use std::ops::ControlFlow;
 
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_type_ir::fold::TypeFoldable;
-pub use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
+pub use rustc_type_ir::visit::*;
 
 use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags};
 
diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
index 36cd3e00b76..8e93bdc61d0 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
@@ -1,9 +1,8 @@
 //! This module ensures that if a function's ABI requires a particular target feature,
 //! that target feature is enabled both on the callee and all callers.
-use rustc_abi::{BackendRepr, RegKind};
+use rustc_abi::{BackendRepr, ExternAbi, RegKind};
 use rustc_hir::CRATE_HIR_ID;
 use rustc_middle::mir::{self, traversal};
-use rustc_middle::ty::inherent::*;
 use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt};
 use rustc_session::lint::builtin::ABI_UNSUPPORTED_VECTOR_TYPES;
 use rustc_span::def_id::DefId;
@@ -97,7 +96,7 @@ fn check_call_site_abi<'tcx>(
     span: Span,
     caller: InstanceKind<'tcx>,
 ) {
-    if callee.fn_sig(tcx).abi().is_rust() {
+    if callee.fn_sig(tcx).abi() == ExternAbi::Rust {
         // "Rust" ABI never passes arguments in vector registers.
         return;
     }
diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml
index 451c215566b..eacb6002f5a 100644
--- a/compiler/rustc_next_trait_solver/Cargo.toml
+++ b/compiler/rustc_next_trait_solver/Cargo.toml
@@ -6,7 +6,6 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 derive-where = "1.2.7"
-rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false }
 rustc_data_structures = { path = "../rustc_data_structures", optional = true }
 rustc_index = { path = "../rustc_index", default-features = false }
 rustc_macros = { path = "../rustc_macros", optional = true }
@@ -22,7 +21,6 @@ nightly = [
     "dep:rustc_data_structures",
     "dep:rustc_macros",
     "dep:rustc_serialize",
-    "rustc_ast_ir/nightly",
     "rustc_index/nightly",
     "rustc_type_ir/nightly",
 ]
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
index 082c356cc5f..dc0f4c4483e 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
@@ -2,12 +2,11 @@
 //! traits, `Copy`/`Clone`.
 
 use derive_where::derive_where;
-use rustc_ast_ir::{Movability, Mutability};
 use rustc_type_ir::data_structures::HashMap;
 use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::lang_items::TraitSolverLangItem;
-use rustc_type_ir::{self as ty, Interner, Upcast as _, elaborate};
+use rustc_type_ir::{self as ty, Interner, Movability, Mutability, Upcast as _, elaborate};
 use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
 use tracing::instrument;
 
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index dabfa5cc04c..1665dbb3018 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -1,13 +1,14 @@
 //! Dealing with trait goals, i.e. `T: Trait<'a, U>`.
 
-use rustc_ast_ir::Movability;
 use rustc_type_ir::data_structures::IndexSet;
 use rustc_type_ir::fast_reject::DeepRejectCtxt;
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::lang_items::TraitSolverLangItem;
 use rustc_type_ir::solve::CanonicalResponse;
 use rustc_type_ir::visit::TypeVisitableExt as _;
-use rustc_type_ir::{self as ty, Interner, TraitPredicate, TypingMode, Upcast as _, elaborate};
+use rustc_type_ir::{
+    self as ty, Interner, Movability, TraitPredicate, TypingMode, Upcast as _, elaborate,
+};
 use tracing::{instrument, trace};
 
 use crate::delegate::SolverDelegate;
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 72aebb5d121..67abc2d5394 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -301,13 +301,6 @@ impl<'a> Parser<'a> {
         &mut self,
         recover: bool,
     ) -> PResult<'a, (Ident, IdentIsRaw)> {
-        if let TokenKind::DocComment(..) = self.prev_token.kind {
-            return Err(self.dcx().create_err(DocCommentDoesNotDocumentAnything {
-                span: self.prev_token.span,
-                missing_comma: None,
-            }));
-        }
-
         let valid_follow = &[
             TokenKind::Eq,
             TokenKind::Colon,
@@ -319,6 +312,15 @@ impl<'a> Parser<'a> {
             TokenKind::CloseDelim(Delimiter::Brace),
             TokenKind::CloseDelim(Delimiter::Parenthesis),
         ];
+        if let TokenKind::DocComment(..) = self.prev_token.kind
+            && valid_follow.contains(&self.token.kind)
+        {
+            let err = self.dcx().create_err(DocCommentDoesNotDocumentAnything {
+                span: self.prev_token.span,
+                missing_comma: None,
+            });
+            return Err(err);
+        }
 
         let mut recovered_ident = None;
         // we take this here so that the correct original token is retained in
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index d155e95078b..d4d435d9b74 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -289,6 +289,7 @@ symbols! {
         OsString,
         Output,
         Param,
+        ParamSet,
         PartialEq,
         PartialOrd,
         Path,
@@ -520,6 +521,7 @@ symbols! {
         bang,
         begin_panic,
         bench,
+        bevy_ecs,
         bikeshed_guaranteed_no_drop,
         bin,
         binaryheap_iter,
diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml
index b13a753c4ed..2f2361609a2 100644
--- a/compiler/rustc_trait_selection/Cargo.toml
+++ b/compiler/rustc_trait_selection/Cargo.toml
@@ -8,7 +8,6 @@ edition = "2021"
 itertools = "0.12"
 rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
-rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_attr_parsing = { path = "../rustc_attr_parsing" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index 2bb38f3ed14..42b8199cb26 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -18,7 +18,6 @@ use rustc_middle::ty::{
     TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults,
 };
 use rustc_span::{BytePos, DUMMY_SP, FileName, Ident, Span, sym};
-use rustc_type_ir::inherent::*;
 use rustc_type_ir::visit::TypeVisitableExt;
 use tracing::{debug, instrument, warn};
 
@@ -217,7 +216,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'a, 'tcx> {
                                 // `_` because then we'd end up with `Vec<_, _>`, instead of
                                 // `Vec<_>`.
                                 arg
-                            } else if let GenericArgKind::Type(_) = arg.kind() {
+                            } else if let GenericArgKind::Type(_) = arg.unpack() {
                                 // We don't replace lifetime or const params, only type params.
                                 self.new_infer().into()
                             } else {
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index 9fbc1d64d74..4b1bc316d5f 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -11,12 +11,11 @@
 
 use std::assert_matches::assert_matches;
 
-use rustc_ast_ir::try_visit;
-use rustc_ast_ir::visit::VisitorResult;
 use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
 use rustc_macros::extension;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, NoSolution, QueryResult};
+use rustc_middle::ty::visit::{VisitorResult, try_visit};
 use rustc_middle::ty::{TyCtxt, TypeFoldable};
 use rustc_middle::{bug, ty};
 use rustc_next_trait_solver::resolve::EagerResolver;
diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml
index 6a98be18503..94c7695117c 100644
--- a/compiler/rustc_transmute/Cargo.toml
+++ b/compiler/rustc_transmute/Cargo.toml
@@ -6,7 +6,6 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 rustc_abi = { path = "../rustc_abi", optional = true }
-rustc_ast_ir = { path = "../rustc_ast_ir", optional = true }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_hir = { path = "../rustc_hir", optional = true }
 rustc_infer = { path = "../rustc_infer", optional = true }
@@ -19,7 +18,6 @@ tracing = "0.1"
 [features]
 rustc = [
     "dep:rustc_abi",
-    "dep:rustc_ast_ir",
     "dep:rustc_hir",
     "dep:rustc_infer",
     "dep:rustc_macros",
diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml
index f88f8c38d50..ab903c6ed73 100644
--- a/compiler/rustc_ty_utils/Cargo.toml
+++ b/compiler/rustc_ty_utils/Cargo.toml
@@ -7,7 +7,6 @@ edition = "2021"
 # tidy-alphabetical-start
 itertools = "0.12"
 rustc_abi = { path = "../rustc_abi" }
-rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs
index 64e5a609b2f..d6f9277813d 100644
--- a/compiler/rustc_ty_utils/src/sig_types.rs
+++ b/compiler/rustc_ty_utils/src/sig_types.rs
@@ -1,11 +1,10 @@
 //! This module contains helpers for walking all types of
 //! a signature, while preserving spans as much as possible
 
-use rustc_ast_ir::try_visit;
-use rustc_ast_ir::visit::VisitorResult;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::span_bug;
+use rustc_middle::ty::visit::{VisitorResult, try_visit};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::Span;
 use rustc_type_ir::visit::TypeVisitable;
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index e7ca24178cb..15ef4e7d6c1 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -74,6 +74,7 @@ pub use opaque_ty::*;
 pub use predicate::*;
 pub use predicate_kind::*;
 pub use region_kind::*;
+pub use rustc_ast_ir::{Movability, Mutability, Pinnedness};
 pub use ty_info::*;
 pub use ty_kind::*;
 pub use upcast::*;
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index a12e9856304..119b658a2bf 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -45,8 +45,8 @@ use std::fmt;
 use std::ops::ControlFlow;
 use std::sync::Arc;
 
-use rustc_ast_ir::visit::VisitorResult;
-use rustc_ast_ir::{try_visit, walk_visitable_list};
+pub use rustc_ast_ir::visit::VisitorResult;
+pub use rustc_ast_ir::{try_visit, walk_visitable_list};
 use rustc_index::{Idx, IndexVec};
 use smallvec::SmallVec;
 use thin_vec::ThinVec;
@@ -224,6 +224,13 @@ impl<I: Interner, T: TypeVisitable<I>, Ix: Idx> TypeVisitable<I> for IndexVec<Ix
     }
 }
 
+impl<I: Interner, T: TypeVisitable<I>, S> TypeVisitable<I> for indexmap::IndexSet<T, S> {
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
+        walk_visitable_list!(visitor, self.iter());
+        V::Result::output()
+    }
+}
+
 pub trait Flags {
     fn flags(&self) -> TypeFlags;
     fn outer_exclusive_binder(&self) -> ty::DebruijnIndex;
diff --git a/compiler/rustc_type_ir_macros/src/lib.rs b/compiler/rustc_type_ir_macros/src/lib.rs
index ede6dcd469c..640299c2167 100644
--- a/compiler/rustc_type_ir_macros/src/lib.rs
+++ b/compiler/rustc_type_ir_macros/src/lib.rs
@@ -45,12 +45,12 @@ fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Tok
     s.add_bounds(synstructure::AddBounds::Fields);
     let body_visit = s.each(|bind| {
         quote! {
-            match ::rustc_ast_ir::visit::VisitorResult::branch(
+            match ::rustc_type_ir::visit::VisitorResult::branch(
                 ::rustc_type_ir::visit::TypeVisitable::visit_with(#bind, __visitor)
             ) {
                 ::core::ops::ControlFlow::Continue(()) => {},
                 ::core::ops::ControlFlow::Break(r) => {
-                    return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
+                    return ::rustc_type_ir::visit::VisitorResult::from_residual(r);
                 },
             }
         }
@@ -65,7 +65,7 @@ fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Tok
                 __visitor: &mut __V
             ) -> __V::Result {
                 match *self { #body_visit }
-                <__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
+                <__V::Result as ::rustc_type_ir::visit::VisitorResult>::output()
             }
         },
     )
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index c0ee49fbb30..4754d18b06e 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -198,8 +198,6 @@ impl str {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(inherent_str_constructors)]
-    ///
     /// // some bytes, in a vector
     /// let sparkle_heart = vec![240, 159, 146, 150];
     ///
@@ -213,8 +211,6 @@ impl str {
     /// Incorrect bytes:
     ///
     /// ```
-    /// #![feature(inherent_str_constructors)]
-    ///
     /// // some invalid bytes, in a vector
     /// let sparkle_heart = vec![0, 159, 146, 150];
     ///
@@ -227,8 +223,6 @@ impl str {
     /// A "stack allocated string":
     ///
     /// ```
-    /// #![feature(inherent_str_constructors)]
-    ///
     /// // some bytes, in a stack-allocated array
     /// let sparkle_heart = [240, 159, 146, 150];
     ///
@@ -237,7 +231,8 @@ impl str {
     ///
     /// assert_eq!("💖", sparkle_heart);
     /// ```
-    #[unstable(feature = "inherent_str_constructors", issue = "131114")]
+    #[stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")]
     #[rustc_diagnostic_item = "str_inherent_from_utf8"]
     pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
         converts::from_utf8(v)
@@ -250,8 +245,6 @@ impl str {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(inherent_str_constructors)]
-    ///
     /// // "Hello, Rust!" as a mutable vector
     /// let mut hellorust = vec![72, 101, 108, 108, 111, 44, 32, 82, 117, 115, 116, 33];
     ///
@@ -264,8 +257,6 @@ impl str {
     /// Incorrect bytes:
     ///
     /// ```
-    /// #![feature(inherent_str_constructors)]
-    ///
     /// // Some invalid bytes in a mutable vector
     /// let mut invalid = vec![128, 223];
     ///
@@ -273,7 +264,7 @@ impl str {
     /// ```
     /// See the docs for [`Utf8Error`] for more details on the kinds of
     /// errors that can be returned.
-    #[unstable(feature = "inherent_str_constructors", issue = "131114")]
+    #[stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")]
     #[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")]
     #[rustc_diagnostic_item = "str_inherent_from_utf8_mut"]
     pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
@@ -294,8 +285,6 @@ impl str {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(inherent_str_constructors)]
-    ///
     /// // some bytes, in a vector
     /// let sparkle_heart = vec![240, 159, 146, 150];
     ///
@@ -307,7 +296,8 @@ impl str {
     /// ```
     #[inline]
     #[must_use]
-    #[unstable(feature = "inherent_str_constructors", issue = "131114")]
+    #[stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")]
     #[rustc_diagnostic_item = "str_inherent_from_utf8_unchecked"]
     pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
         // SAFETY: converts::from_utf8_unchecked has the same safety requirements as this function.
@@ -324,8 +314,6 @@ impl str {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(inherent_str_constructors)]
-    ///
     /// let mut heart = vec![240, 159, 146, 150];
     /// let heart = unsafe { str::from_utf8_unchecked_mut(&mut heart) };
     ///
@@ -333,7 +321,8 @@ impl str {
     /// ```
     #[inline]
     #[must_use]
-    #[unstable(feature = "inherent_str_constructors", issue = "131114")]
+    #[stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")]
     #[rustc_diagnostic_item = "str_inherent_from_utf8_unchecked_mut"]
     pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str {
         // SAFETY: converts::from_utf8_unchecked_mut has the same safety requirements as this function.
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index 50c09b98db4..64dbaf9083e 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -1,4 +1,5 @@
 use std::borrow::Cow;
+use std::cmp::Ordering;
 
 use rinja::Template;
 use rustc_data_structures::fx::FxHashSet;
@@ -12,6 +13,7 @@ use crate::clean;
 use crate::formats::Impl;
 use crate::formats::item_type::ItemType;
 use crate::html::markdown::{IdMap, MarkdownWithToc};
+use crate::html::render::print_item::compare_names;
 
 #[derive(Clone, Copy)]
 pub(crate) enum ModuleLike {
@@ -77,7 +79,7 @@ impl<'a> LinkBlock<'a> {
 }
 
 /// A link to an item. Content should not be escaped.
-#[derive(PartialOrd, Ord, PartialEq, Eq, Hash, Clone)]
+#[derive(Ord, PartialEq, Eq, Hash, Clone)]
 pub(crate) struct Link<'a> {
     /// The content for the anchor tag and title attr
     name: Cow<'a, str>,
@@ -89,6 +91,20 @@ pub(crate) struct Link<'a> {
     children: Vec<Link<'a>>,
 }
 
+impl PartialOrd for Link<'_> {
+    fn partial_cmp(&self, other: &Link<'_>) -> Option<Ordering> {
+        match compare_names(&self.name, &other.name) {
+            Ordering::Equal => (),
+            result => return Some(result),
+        }
+        (&self.name_html, &self.href, &self.children).partial_cmp(&(
+            &other.name_html,
+            &other.href,
+            &other.children,
+        ))
+    }
+}
+
 impl<'a> Link<'a> {
     pub fn new(href: impl Into<Cow<'a, str>>, name: impl Into<Cow<'a, str>>) -> Self {
         Self { href: href.into(), name: name.into(), children: vec![], name_html: None }
diff --git a/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.rs b/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.rs
new file mode 100644
index 00000000000..7de4aef422a
--- /dev/null
+++ b/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.rs
@@ -0,0 +1,30 @@
+// Test that transmuting from `&dyn Trait<fn(&'static ())>` to `&dyn Trait<for<'a> fn(&'a ())>` is UB.
+//
+// The vtable of `() as Trait<fn(&'static ())>` and `() as Trait<for<'a> fn(&'a ())>` can have
+// different entries and, because in the former the entry for `foo` is vacant, this test will
+// segfault at runtime.
+
+trait Trait<U> {
+    fn foo(&self)
+    where
+        U: HigherRanked,
+    {
+    }
+}
+impl<T, U> Trait<U> for T {}
+
+trait HigherRanked {}
+impl HigherRanked for for<'a> fn(&'a ()) {}
+
+// 2nd candidate is required so that selecting `(): Trait<fn(&'static ())>` will
+// evaluate the candidates and fail the leak check instead of returning the
+// only applicable candidate.
+trait Unsatisfied {}
+impl<T: Unsatisfied> HigherRanked for T {}
+
+fn main() {
+    let x: &dyn Trait<fn(&'static ())> = &();
+    let y: &dyn Trait<for<'a> fn(&'a ())> = unsafe { std::mem::transmute(x) };
+    //~^ ERROR: wrong trait in wide pointer vtable
+    y.foo();
+}
diff --git a/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.stderr b/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.stderr
new file mode 100644
index 00000000000..cfdf279a605
--- /dev/null
+++ b/src/tools/miri/tests/fail/validity/dyn-transmute-inner-binder.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value: wrong trait in wide pointer vtable: expected `Trait<for<'a> fn(&'a ())>`, but encountered `Trait<fn(&())>`
+  --> tests/fail/validity/dyn-transmute-inner-binder.rs:LL:CC
+   |
+LL |     let y: &dyn Trait<for<'a> fn(&'a ())> = unsafe { std::mem::transmute(x) };
+   |                                                      ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: wrong trait in wide pointer vtable: expected `Trait<for<'a> fn(&'a ())>`, but encountered `Trait<fn(&())>`
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at tests/fail/validity/dyn-transmute-inner-binder.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/pass/dyn-upcast.rs b/src/tools/miri/tests/pass/dyn-upcast.rs
index 6f8adc09640..875891df233 100644
--- a/src/tools/miri/tests/pass/dyn-upcast.rs
+++ b/src/tools/miri/tests/pass/dyn-upcast.rs
@@ -9,6 +9,7 @@ fn main() {
     drop_principal();
     modulo_binder();
     modulo_assoc();
+    bidirectional_subtyping();
 }
 
 fn vtable_nop_cast() {
@@ -531,3 +532,32 @@ fn modulo_assoc() {
 
     (&() as &dyn Trait as &dyn Middle<()>).say_hello(&0);
 }
+
+fn bidirectional_subtyping() {
+    // Test that transmuting between subtypes of dyn traits is fine, even in the
+    // "wrong direction", i.e. going from a lower-ranked to a higher-ranked dyn trait.
+    // Note that compared to the `dyn-transmute-inner-binder` test, the `for` is on the
+    // *outside* here!
+
+    trait Trait<U: ?Sized> {}
+    impl<T, U: ?Sized> Trait<U> for T {}
+
+    struct Wrapper<T: ?Sized>(T);
+
+    let x: &dyn Trait<fn(&'static ())> = &();
+    let _y: &dyn for<'a> Trait<fn(&'a ())> = unsafe { std::mem::transmute(x) };
+
+    let x: &dyn for<'a> Trait<fn(&'a ())> = &();
+    let _y: &dyn Trait<fn(&'static ())> = unsafe { std::mem::transmute(x) };
+
+    let x: &dyn Trait<dyn Trait<fn(&'static ())>> = &();
+    let _y: &dyn for<'a> Trait<dyn Trait<fn(&'a ())>> = unsafe { std::mem::transmute(x) };
+
+    let x: &dyn for<'a> Trait<dyn Trait<fn(&'a ())>> = &();
+    let _y: &dyn Trait<dyn Trait<fn(&'static ())>> = unsafe { std::mem::transmute(x) };
+
+    // This lowers to a ptr-to-ptr cast (which behaves like a transmute)
+    // and not an unsizing coercion:
+    let x: *const dyn for<'a> Trait<&'a ()> = &();
+    let _y: *const Wrapper<dyn Trait<&'static ()>> = x as _;
+}
diff --git a/tests/rustdoc-gui/sidebar-foreign-impl-sort.goml b/tests/rustdoc-gui/sidebar-foreign-impl-sort.goml
new file mode 100644
index 00000000000..f09f0971351
--- /dev/null
+++ b/tests/rustdoc-gui/sidebar-foreign-impl-sort.goml
@@ -0,0 +1,15 @@
+// Checks sidebar resizing close the Settings popover
+go-to: "file://" + |DOC_PATH| + "/test_docs/SidebarSort/trait.Sort.html#foreign-impls"
+
+// Check that the sidebar contains the expected foreign implementations
+assert-text: (".sidebar-elems section ul > li:nth-child(1)", "&'a str")
+assert-text: (".sidebar-elems section ul > li:nth-child(2)", "AtomicBool")
+assert-text: (".sidebar-elems section ul > li:nth-child(3)", "AtomicU8")
+assert-text: (".sidebar-elems section ul > li:nth-child(4)", "AtomicU16")
+assert-text: (".sidebar-elems section ul > li:nth-child(5)", "AtomicU32")
+assert-text: (".sidebar-elems section ul > li:nth-child(6)", "Cell<u8>")
+assert-text: (".sidebar-elems section ul > li:nth-child(7)", "Cell<u16>")
+assert-text: (".sidebar-elems section ul > li:nth-child(8)", "u8")
+assert-text: (".sidebar-elems section ul > li:nth-child(9)", "u16")
+assert-text: (".sidebar-elems section ul > li:nth-child(10)", "u32")
+assert-text: (".sidebar-elems section ul > li:nth-child(11)", "usize")
diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs
index 1a9ffbe8898..f9c20ab22b8 100644
--- a/tests/rustdoc-gui/src/test_docs/lib.rs
+++ b/tests/rustdoc-gui/src/test_docs/lib.rs
@@ -713,3 +713,21 @@ pub trait ItemsTrait {
     /// blablala
     fn bar();
 }
+
+pub mod SidebarSort {
+    use std::cell::Cell;
+    use std::sync::atomic::*;
+    pub trait Sort {}
+
+    impl Sort for u32 {}
+    impl Sort for u8 {}
+    impl Sort for u16 {}
+    impl Sort for usize {}
+    impl Sort for AtomicU32 {}
+    impl Sort for AtomicU16 {}
+    impl Sort for AtomicU8 {}
+    impl Sort for AtomicBool {}
+    impl Sort for Cell<u16> {}
+    impl Sort for Cell<u8> {}
+    impl<'a> Sort for &'a str {}
+}
diff --git a/tests/ui/implied-bounds/bevy_world_query.rs b/tests/ui/implied-bounds/bevy_world_query.rs
index e36be26d003..6548c03d1b0 100644
--- a/tests/ui/implied-bounds/bevy_world_query.rs
+++ b/tests/ui/implied-bounds/bevy_world_query.rs
@@ -1,3 +1,5 @@
+#![crate_name = "bevy_ecs"]
+
 //@ check-pass
 
 // We currently special case bevy from erroring on incorrect implied bounds
diff --git a/tests/ui/lint/invalid_from_utf8.rs b/tests/ui/lint/invalid_from_utf8.rs
index 8f8000fe34d..87a906761c0 100644
--- a/tests/ui/lint/invalid_from_utf8.rs
+++ b/tests/ui/lint/invalid_from_utf8.rs
@@ -1,7 +1,6 @@
 //@ check-pass
 
 #![feature(concat_bytes)]
-#![feature(inherent_str_constructors)]
 #![warn(invalid_from_utf8_unchecked)]
 #![warn(invalid_from_utf8)]
 
diff --git a/tests/ui/lint/invalid_from_utf8.stderr b/tests/ui/lint/invalid_from_utf8.stderr
index 715ecf56f21..3cd4d227fc2 100644
--- a/tests/ui/lint/invalid_from_utf8.stderr
+++ b/tests/ui/lint/invalid_from_utf8.stderr
@@ -1,5 +1,5 @@
 warning: calls to `std::str::from_utf8_unchecked_mut` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:22:9
+  --> $DIR/invalid_from_utf8.rs:21:9
    |
 LL |         std::str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -7,13 +7,13 @@ LL |         std::str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112
    |                                                the literal was valid UTF-8 up to the 2 bytes
    |
 note: the lint level is defined here
-  --> $DIR/invalid_from_utf8.rs:5:9
+  --> $DIR/invalid_from_utf8.rs:4:9
    |
 LL | #![warn(invalid_from_utf8_unchecked)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8_unchecked_mut` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:24:9
+  --> $DIR/invalid_from_utf8.rs:23:9
    |
 LL |         str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -21,7 +21,7 @@ LL |         str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112, 121
    |                                           the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_unchecked_mut` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:26:9
+  --> $DIR/invalid_from_utf8.rs:25:9
    |
 LL |         std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -29,7 +29,7 @@ LL |         std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i',
    |                                                the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8_unchecked_mut` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:28:9
+  --> $DIR/invalid_from_utf8.rs:27:9
    |
 LL |         str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -37,7 +37,7 @@ LL |         str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', b'p',
    |                                           the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_unchecked` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:50:9
+  --> $DIR/invalid_from_utf8.rs:49:9
    |
 LL |         std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -45,7 +45,7 @@ LL |         std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
    |                                        the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8_unchecked` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:52:9
+  --> $DIR/invalid_from_utf8.rs:51:9
    |
 LL |         str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -53,7 +53,7 @@ LL |         str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]);
    |                                   the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_unchecked` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:54:9
+  --> $DIR/invalid_from_utf8.rs:53:9
    |
 LL |         std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -61,7 +61,7 @@ LL |         std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'
    |                                        the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8_unchecked` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:56:9
+  --> $DIR/invalid_from_utf8.rs:55:9
    |
 LL |         str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -69,7 +69,7 @@ LL |         str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b
    |                                   the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_unchecked` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:58:9
+  --> $DIR/invalid_from_utf8.rs:57:9
    |
 LL |         std::str::from_utf8_unchecked(b"cl\x82ippy");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^
@@ -77,7 +77,7 @@ LL |         std::str::from_utf8_unchecked(b"cl\x82ippy");
    |                                       the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8_unchecked` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:60:9
+  --> $DIR/invalid_from_utf8.rs:59:9
    |
 LL |         str::from_utf8_unchecked(b"cl\x82ippy");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^-------------^
@@ -85,7 +85,7 @@ LL |         str::from_utf8_unchecked(b"cl\x82ippy");
    |                                  the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_unchecked` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:62:9
+  --> $DIR/invalid_from_utf8.rs:61:9
    |
 LL |         std::str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy"));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------^
@@ -93,7 +93,7 @@ LL |         std::str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy"));
    |                                       the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8_unchecked` with an invalid literal are undefined behavior
-  --> $DIR/invalid_from_utf8.rs:64:9
+  --> $DIR/invalid_from_utf8.rs:63:9
    |
 LL |         str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy"));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------^
@@ -101,7 +101,7 @@ LL |         str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy"));
    |                                  the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:84:9
+  --> $DIR/invalid_from_utf8.rs:83:9
    |
 LL |         std::str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -109,13 +109,13 @@ LL |         std::str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
    |                                      the literal was valid UTF-8 up to the 2 bytes
    |
 note: the lint level is defined here
-  --> $DIR/invalid_from_utf8.rs:6:9
+  --> $DIR/invalid_from_utf8.rs:5:9
    |
 LL | #![warn(invalid_from_utf8)]
    |         ^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:86:9
+  --> $DIR/invalid_from_utf8.rs:85:9
    |
 LL |         str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -123,7 +123,7 @@ LL |         str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]);
    |                                 the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:88:9
+  --> $DIR/invalid_from_utf8.rs:87:9
    |
 LL |         std::str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -131,7 +131,7 @@ LL |         std::str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p'
    |                                      the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:90:9
+  --> $DIR/invalid_from_utf8.rs:89:9
    |
 LL |         str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -139,7 +139,7 @@ LL |         str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y
    |                                 the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:112:9
+  --> $DIR/invalid_from_utf8.rs:111:9
    |
 LL |         std::str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^^^^^^----------------------------------^
@@ -147,7 +147,7 @@ LL |         std::str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]);
    |                              the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:114:9
+  --> $DIR/invalid_from_utf8.rs:113:9
    |
 LL |         str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]);
    |         ^^^^^^^^^^^^^^^^----------------------------------^
@@ -155,7 +155,7 @@ LL |         str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]);
    |                         the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:116:9
+  --> $DIR/invalid_from_utf8.rs:115:9
    |
 LL |         std::str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -163,7 +163,7 @@ LL |         std::str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y'])
    |                              the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:118:9
+  --> $DIR/invalid_from_utf8.rs:117:9
    |
 LL |         str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |         ^^^^^^^^^^^^^^^^---------------------------------------------^
@@ -171,7 +171,7 @@ LL |         str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']);
    |                         the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:120:9
+  --> $DIR/invalid_from_utf8.rs:119:9
    |
 LL |         std::str::from_utf8(b"cl\x82ippy");
    |         ^^^^^^^^^^^^^^^^^^^^-------------^
@@ -179,7 +179,7 @@ LL |         std::str::from_utf8(b"cl\x82ippy");
    |                             the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:122:9
+  --> $DIR/invalid_from_utf8.rs:121:9
    |
 LL |         str::from_utf8(b"cl\x82ippy");
    |         ^^^^^^^^^^^^^^^-------------^
@@ -187,7 +187,7 @@ LL |         str::from_utf8(b"cl\x82ippy");
    |                        the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:124:9
+  --> $DIR/invalid_from_utf8.rs:123:9
    |
 LL |         std::str::from_utf8(concat_bytes!(b"cl", b"\x82ippy"));
    |         ^^^^^^^^^^^^^^^^^^^^---------------------------------^
@@ -195,7 +195,7 @@ LL |         std::str::from_utf8(concat_bytes!(b"cl", b"\x82ippy"));
    |                             the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:126:9
+  --> $DIR/invalid_from_utf8.rs:125:9
    |
 LL |         str::from_utf8(concat_bytes!(b"cl", b"\x82ippy"));
    |         ^^^^^^^^^^^^^^^---------------------------------^
@@ -203,7 +203,7 @@ LL |         str::from_utf8(concat_bytes!(b"cl", b"\x82ippy"));
    |                        the literal was valid UTF-8 up to the 2 bytes
 
 warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:133:5
+  --> $DIR/invalid_from_utf8.rs:132:5
    |
 LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
    |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -211,7 +211,7 @@ LL |     std::str::from_utf8_mut(&mut a);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:135:5
+  --> $DIR/invalid_from_utf8.rs:134:5
    |
 LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
    |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -220,7 +220,7 @@ LL |     str::from_utf8_mut(&mut a);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:139:5
+  --> $DIR/invalid_from_utf8.rs:138:5
    |
 LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
    |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -229,7 +229,7 @@ LL |     std::str::from_utf8_mut(c);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:141:5
+  --> $DIR/invalid_from_utf8.rs:140:5
    |
 LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
    |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -238,7 +238,7 @@ LL |     str::from_utf8_mut(c);
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:144:5
+  --> $DIR/invalid_from_utf8.rs:143:5
    |
 LL |     let mut c = &[99, 108, 130, 105, 112, 112, 121];
    |                  ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -246,7 +246,7 @@ LL |     std::str::from_utf8(c);
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:146:5
+  --> $DIR/invalid_from_utf8.rs:145:5
    |
 LL |     let mut c = &[99, 108, 130, 105, 112, 112, 121];
    |                  ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -255,7 +255,7 @@ LL |     str::from_utf8(c);
    |     ^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:149:5
+  --> $DIR/invalid_from_utf8.rs:148:5
    |
 LL |     const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -263,7 +263,7 @@ LL |     std::str::from_utf8(&INVALID_1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:151:5
+  --> $DIR/invalid_from_utf8.rs:150:5
    |
 LL |     const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -272,7 +272,7 @@ LL |     str::from_utf8(&INVALID_1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:154:5
+  --> $DIR/invalid_from_utf8.rs:153:5
    |
 LL |     static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -280,7 +280,7 @@ LL |     std::str::from_utf8(&INVALID_2);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:156:5
+  --> $DIR/invalid_from_utf8.rs:155:5
    |
 LL |     static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -289,7 +289,7 @@ LL |     str::from_utf8(&INVALID_2);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:159:5
+  --> $DIR/invalid_from_utf8.rs:158:5
    |
 LL |     const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121];
    |                                          ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -297,7 +297,7 @@ LL |     std::str::from_utf8(INVALID_3);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:161:5
+  --> $DIR/invalid_from_utf8.rs:160:5
    |
 LL |     const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121];
    |                                          ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -306,7 +306,7 @@ LL |     str::from_utf8(INVALID_3);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:164:5
+  --> $DIR/invalid_from_utf8.rs:163:5
    |
 LL |     const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] };
    |                                            ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -314,7 +314,7 @@ LL |     std::str::from_utf8(INVALID_4);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:166:5
+  --> $DIR/invalid_from_utf8.rs:165:5
    |
 LL |     const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] };
    |                                            ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
diff --git a/tests/ui/parser/doc-before-bad-variant.rs b/tests/ui/parser/doc-before-bad-variant.rs
new file mode 100644
index 00000000000..bfede28c108
--- /dev/null
+++ b/tests/ui/parser/doc-before-bad-variant.rs
@@ -0,0 +1,6 @@
+enum TestEnum {
+    Works,
+    /// Some documentation
+    Self, //~ ERROR expected identifier, found keyword `Self`
+    //~^ HELP enum variants can be
+}
diff --git a/tests/ui/parser/doc-before-bad-variant.stderr b/tests/ui/parser/doc-before-bad-variant.stderr
new file mode 100644
index 00000000000..5e4d4116f25
--- /dev/null
+++ b/tests/ui/parser/doc-before-bad-variant.stderr
@@ -0,0 +1,13 @@
+error: expected identifier, found keyword `Self`
+  --> $DIR/doc-before-bad-variant.rs:4:5
+   |
+LL | enum TestEnum {
+   |      -------- while parsing this enum
+...
+LL |     Self,
+   |     ^^^^ expected identifier, found keyword
+   |
+   = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/doc-before-syntax-error.rs b/tests/ui/parser/doc-before-syntax-error.rs
new file mode 100644
index 00000000000..435f497d186
--- /dev/null
+++ b/tests/ui/parser/doc-before-syntax-error.rs
@@ -0,0 +1,2 @@
+/// Some documentation
+<> //~ ERROR expected identifier
diff --git a/tests/ui/parser/doc-before-syntax-error.stderr b/tests/ui/parser/doc-before-syntax-error.stderr
new file mode 100644
index 00000000000..93e39d63000
--- /dev/null
+++ b/tests/ui/parser/doc-before-syntax-error.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `<`
+  --> $DIR/doc-before-syntax-error.rs:2:1
+   |
+LL | <>
+   | ^ expected identifier
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed
index e35896f32ad..bb4ecc09063 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed
@@ -244,4 +244,10 @@ fn main() {
     let &[migration_lint_macros::bind_ref!(a)] = &[0];
     //~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
     assert_type_eq(a, &0u32);
+
+    // Test that we use the correct span when labeling a `&` whose subpattern is from an expansion.
+    let &[&migration_lint_macros::bind_ref!(a)] = &[&0];
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs
index 10a23e6f2fa..2837c8d81db 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs
@@ -244,4 +244,10 @@ fn main() {
     let [migration_lint_macros::bind_ref!(a)] = &[0];
     //~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
     assert_type_eq(a, &0u32);
+
+    // Test that we use the correct span when labeling a `&` whose subpattern is from an expansion.
+    let [&migration_lint_macros::bind_ref!(a)] = &[&0];
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr
index 3dd91c86a3b..6efda4f757f 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr
@@ -580,5 +580,23 @@ help: make the implied reference pattern explicit
 LL |     let &[migration_lint_macros::bind_ref!(a)] = &[0];
    |         +
 
-error: aborting due to 30 previous errors
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+  --> $DIR/migration_lint.rs:249:10
+   |
+LL |     let [&migration_lint_macros::bind_ref!(a)] = &[&0];
+   |          ^ reference pattern not allowed under `ref` default binding mode
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
+note: matching on a reference type with a non-reference pattern changes the default binding mode
+  --> $DIR/migration_lint.rs:249:9
+   |
+LL |     let [&migration_lint_macros::bind_ref!(a)] = &[&0];
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_`
+help: make the implied reference pattern explicit
+   |
+LL |     let &[&migration_lint_macros::bind_ref!(a)] = &[&0];
+   |         +
+
+error: aborting due to 31 previous errors