about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_lowering/src/delegation.rs1
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/var_name.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs1487
-rw-r--r--compiler/rustc_codegen_ssa/src/assert_module_sources.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs4
-rw-r--r--compiler/rustc_const_eval/src/check_consts/mod.rs2
-rw-r--r--compiler/rustc_driver_impl/src/pretty.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs26
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check_unused.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs20
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/collect/dump.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/delegation.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs14
-rw-r--r--compiler/rustc_incremental/src/assert_dep_graph.rs2
-rw-r--r--compiler/rustc_interface/src/proc_macro_decls.rs2
-rw-r--r--compiler/rustc_lint/src/builtin.rs6
-rw-r--r--compiler/rustc_lint/src/expect.rs2
-rw-r--r--compiler/rustc_lint/src/late.rs2
-rw-r--r--compiler/rustc_lint/src/levels.rs2
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs9
-rw-r--r--compiler/rustc_lint/src/types.rs2
-rw-r--r--compiler/rustc_metadata/src/dependency_format.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs9
-rw-r--r--compiler/rustc_middle/src/hir/map.rs310
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs4
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs9
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs7
-rw-r--r--compiler/rustc_middle/src/traits/specialization_graph.rs2
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs12
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs6
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs2
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs4
-rw-r--r--compiler/rustc_mir_build/src/builder/mod.rs4
-rw-r--r--compiler/rustc_mir_build/src/builder/scope.rs3
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs5
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs2
-rw-r--r--compiler/rustc_passes/src/check_attr.rs19
-rw-r--r--compiler/rustc_passes/src/dead.rs6
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs2
-rw-r--r--compiler/rustc_passes/src/entry.rs6
-rw-r--r--compiler/rustc_passes/src/hir_id_validator.rs7
-rw-r--r--compiler/rustc_passes/src/liveness.rs2
-rw-r--r--compiler/rustc_passes/src/loops.rs2
-rw-r--r--compiler/rustc_passes/src/reachable.rs2
-rw-r--r--compiler/rustc_passes/src/stability.rs6
-rw-r--r--compiler/rustc_privacy/src/lib.rs6
-rw-r--r--compiler/rustc_resolve/messages.ftl12
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs30
-rw-r--r--compiler/rustc_resolve/src/errors.rs18
-rw-r--r--compiler/rustc_resolve/src/ident.rs61
-rw-r--r--compiler/rustc_resolve/src/late.rs42
-rw-r--r--compiler/rustc_resolve/src/lib.rs9
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/region.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs18
-rw-r--r--compiler/rustc_traits/src/codegen.rs2
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs6
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs2
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs8
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs2
-rw-r--r--library/std/src/io/error.rs4
-rw-r--r--src/doc/rustc-dev-guide/src/hir.md4
-rw-r--r--src/librustdoc/clean/inline.rs4
-rw-r--r--src/librustdoc/clean/mod.rs16
-rw-r--r--src/librustdoc/doctest.rs2
-rw-r--r--src/librustdoc/doctest/rust.rs2
-rw-r--r--src/librustdoc/html/static/js/main.js64
-rw-r--r--src/librustdoc/html/static/js/rustdoc.d.ts25
-rw-r--r--src/librustdoc/visit_ast.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/mod.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/default_union_representation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/derivable_impls.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/missing_headers.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/exhaustive_items.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/format_impl.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/four_forward_slashes.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/must_use.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_use.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/is_empty.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_doc.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_if.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_late_init.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/op_ref.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/self_named_constructors.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_self.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/dump_hir.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs22
-rw-r--r--src/tools/clippy/clippy_utils/src/msrvs.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs4
-rw-r--r--tests/mir-opt/global_asm.rs9
-rw-r--r--tests/mir-opt/global_asm.{global_asm#0}.SimplifyLocals-final.after.mir9
-rw-r--r--tests/ui/const-generics/const-param-type-depends-on-const-param.rs8
-rw-r--r--tests/ui/const-generics/const-param-type-depends-on-parent-param.rs8
-rw-r--r--tests/ui/const-generics/const-param-type-depends-on-parent-param.stderr9
-rw-r--r--tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr6
-rw-r--r--tests/ui/const-generics/defaults/forward-declared.rs8
-rw-r--r--tests/ui/const-generics/defaults/forward-declared.stderr16
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.rs4
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.stderr9
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr2
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr15
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs5
-rw-r--r--tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr4
-rw-r--r--tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr4
-rw-r--r--tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs2
-rw-r--r--tests/ui/consts/const-unsized.stderr12
-rw-r--r--tests/ui/delegation/fn-header-variadic.rs25
-rw-r--r--tests/ui/delegation/fn-header-variadic.stderr22
-rw-r--r--tests/ui/delegation/fn-header.rs11
-rw-r--r--tests/ui/delegation/ice-issue-138362.rs15
-rw-r--r--tests/ui/delegation/ice-issue-138362.stderr19
-rw-r--r--tests/ui/error-codes/E0128.stderr4
-rw-r--r--tests/ui/generics/generic-non-trailing-defaults.rs2
-rw-r--r--tests/ui/generics/generic-non-trailing-defaults.stderr4
-rw-r--r--tests/ui/generics/generic-type-params-forward-mention.rs2
-rw-r--r--tests/ui/generics/generic-type-params-forward-mention.stderr4
-rw-r--r--tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr12
-rw-r--r--tests/ui/issues/issue-18183.stderr4
-rw-r--r--tests/ui/issues/issue-26812.rs2
-rw-r--r--tests/ui/issues/issue-26812.stderr4
-rw-r--r--tests/ui/rmeta/rmeta_bin-pass.rs14
-rw-r--r--tests/ui/rmeta/rmeta_bin.rs14
-rw-r--r--tests/ui/rmeta/rmeta_bin.stderr4
-rw-r--r--tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs9
-rw-r--r--tests/ui/runtime/on-broken-pipe/auxiliary/sigpipe-utils.rs9
-rw-r--r--tests/ui/runtime/signal-alternate-stack-cleanup.rs9
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-4.stderr4
177 files changed, 1488 insertions, 1448 deletions
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index 571172be4ed..946f2cafa15 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -330,6 +330,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             .unwrap_or_default()
             && delegation.qself.is_none()
             && !has_generic_args
+            && !args.is_empty()
         {
             let ast_segment = delegation.path.segments.last().unwrap();
             let segment = self.lower_path_segment(
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index d1f238331d5..208d510db2e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -505,7 +505,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                     let var_id =
                         self.infcx.tcx.closure_captures(def_id)[field.index()].get_root_variable();
 
-                    Some(self.infcx.tcx.hir().name(var_id).to_string())
+                    Some(self.infcx.tcx.hir_name(var_id).to_string())
                 }
                 _ => {
                     // Might need a revision when the fields in trait RFC is implemented
@@ -1124,7 +1124,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             def_id, target_place, places
         );
         let hir_id = self.infcx.tcx.local_def_id_to_hir_id(def_id);
-        let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
+        let expr = &self.infcx.tcx.hir_expect_expr(hir_id).kind;
         debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
         if let &hir::ExprKind::Closure(&hir::Closure { kind, fn_decl_span, .. }) = expr {
             for (captured_place, place) in
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 145137f9236..3951b467961 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -698,7 +698,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                         if !matches!(k, hir::AssocItemKind::Fn { .. }) {
                             continue;
                         }
-                        if self.infcx.tcx.hir().name(hi) != self.infcx.tcx.hir().name(my_hir) {
+                        if self.infcx.tcx.hir_name(hi) != self.infcx.tcx.hir_name(my_hir) {
                             continue;
                         }
                         f_in_trait_opt = Some(hi);
diff --git a/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs b/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs
index 876b8f214b0..7192a889adc 100644
--- a/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs
@@ -105,7 +105,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
                     if let Some(opaque_def_id) = opaque_def_id.as_local()
                         && let hir::OpaqueTyOrigin::FnReturn { parent, .. } =
-                            tcx.hir().expect_opaque_ty(opaque_def_id).origin
+                            tcx.hir_expect_opaque_ty(opaque_def_id).origin
                     {
                         if let Some(sugg) = impl_trait_overcapture_suggestion(
                             tcx,
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index a15f9744bf3..412aaf70c3f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -343,7 +343,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
                         }
                     };
                     let hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }) =
-                        tcx.hir().expect_expr(self.mir_hir_id()).kind
+                        tcx.hir_expect_expr(self.mir_hir_id()).kind
                     else {
                         bug!("Closure is not defined by a closure expr");
                     };
diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
index 191c0444c74..693d22abbe6 100644
--- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
@@ -69,7 +69,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let upvar_hir_id = upvars[upvar_index].get_root_variable();
         debug!("get_upvar_name_and_span_for_region: upvar_hir_id={upvar_hir_id:?}");
 
-        let upvar_name = tcx.hir().name(upvar_hir_id);
+        let upvar_name = tcx.hir_name(upvar_hir_id);
         let upvar_span = tcx.hir().span(upvar_hir_id);
         debug!(
             "get_upvar_name_and_span_for_region: upvar_name={upvar_name:?} upvar_span={upvar_span:?}",
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 9d5022f2bef..d2eb7a52f78 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -156,6 +156,7 @@ pub(crate) fn type_check<'a, 'tcx>(
         infcx,
         last_span: body.span,
         body,
+        promoted,
         user_type_annotations: &body.user_type_annotations,
         region_bound_pairs,
         known_type_outlives_obligations,
@@ -170,11 +171,7 @@ pub(crate) fn type_check<'a, 'tcx>(
     };
 
     typeck.check_user_type_annotations();
-
-    let mut verifier = TypeVerifier { typeck: &mut typeck, promoted, last_span: body.span };
-    verifier.visit_body(body);
-
-    typeck.typeck_mir();
+    typeck.visit_body(body);
     typeck.equate_inputs_and_outputs(&normalized_inputs_and_output);
     typeck.check_signature_annotation();
 
@@ -212,370 +209,6 @@ enum FieldAccessError {
     OutOfRange { field_count: usize },
 }
 
-/// Verifies that MIR types are sane.
-///
-/// FIXME: This should be merged with the actual `TypeChecker`.
-struct TypeVerifier<'a, 'b, 'tcx> {
-    typeck: &'a mut TypeChecker<'b, 'tcx>,
-    promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
-    last_span: Span,
-}
-
-impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
-    fn visit_span(&mut self, span: Span) {
-        if !span.is_dummy() {
-            self.last_span = span;
-        }
-    }
-
-    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
-        self.super_place(place, context, location);
-        let tcx = self.tcx();
-        let place_ty = place.ty(self.body(), tcx);
-        if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
-            let trait_ref = ty::TraitRef::new(
-                tcx,
-                tcx.require_lang_item(LangItem::Copy, Some(self.last_span)),
-                [place_ty.ty],
-            );
-
-            // To have a `Copy` operand, the type `T` of the
-            // value must be `Copy`. Note that we prove that `T: Copy`,
-            // rather than using the `is_copy_modulo_regions`
-            // test. This is important because
-            // `is_copy_modulo_regions` ignores the resulting region
-            // obligations and assumes they pass. This can result in
-            // bounds from `Copy` impls being unsoundly ignored (e.g.,
-            // #29149). Note that we decide to use `Copy` before knowing
-            // whether the bounds fully apply: in effect, the rule is
-            // that if a value of some type could implement `Copy`, then
-            // it must.
-            self.typeck.prove_trait_ref(
-                trait_ref,
-                location.to_locations(),
-                ConstraintCategory::CopyBound,
-            );
-        }
-    }
-
-    fn visit_projection_elem(
-        &mut self,
-        place: PlaceRef<'tcx>,
-        elem: PlaceElem<'tcx>,
-        context: PlaceContext,
-        location: Location,
-    ) {
-        let tcx = self.tcx();
-        let base_ty = place.ty(self.body(), tcx);
-        match elem {
-            // All these projections don't add any constraints, so there's nothing to
-            // do here. We check their invariants in the MIR validator after all.
-            ProjectionElem::Deref
-            | ProjectionElem::Index(_)
-            | ProjectionElem::ConstantIndex { .. }
-            | ProjectionElem::Subslice { .. }
-            | ProjectionElem::Downcast(..) => {}
-            ProjectionElem::Field(field, fty) => {
-                let fty = self.typeck.normalize(fty, location);
-                let ty = base_ty.field_ty(tcx, field);
-                let ty = self.typeck.normalize(ty, location);
-                debug!(?fty, ?ty);
-
-                if let Err(terr) = self.typeck.relate_types(
-                    ty,
-                    context.ambient_variance(),
-                    fty,
-                    location.to_locations(),
-                    ConstraintCategory::Boring,
-                ) {
-                    span_mirbug!(self, place, "bad field access ({:?}: {:?}): {:?}", ty, fty, terr);
-                }
-            }
-            ProjectionElem::OpaqueCast(ty) => {
-                let ty = self.typeck.normalize(ty, location);
-                self.typeck
-                    .relate_types(
-                        ty,
-                        context.ambient_variance(),
-                        base_ty.ty,
-                        location.to_locations(),
-                        ConstraintCategory::TypeAnnotation(AnnotationSource::OpaqueCast),
-                    )
-                    .unwrap();
-            }
-            ProjectionElem::UnwrapUnsafeBinder(ty) => {
-                let ty::UnsafeBinder(binder_ty) = *base_ty.ty.kind() else {
-                    unreachable!();
-                };
-                let found_ty = self.typeck.infcx.instantiate_binder_with_fresh_vars(
-                    self.body().source_info(location).span,
-                    BoundRegionConversionTime::HigherRankedType,
-                    binder_ty.into(),
-                );
-                self.typeck
-                    .relate_types(
-                        ty,
-                        context.ambient_variance(),
-                        found_ty,
-                        location.to_locations(),
-                        ConstraintCategory::Boring,
-                    )
-                    .unwrap();
-            }
-            ProjectionElem::Subtype(_) => {
-                bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
-            }
-        }
-    }
-
-    #[instrument(level = "debug", skip(self))]
-    fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
-        self.super_const_operand(constant, location);
-        let ty = constant.const_.ty();
-
-        self.typeck.infcx.tcx.for_each_free_region(&ty, |live_region| {
-            let live_region_vid = self.typeck.universal_regions.to_region_vid(live_region);
-            self.typeck.constraints.liveness_constraints.add_location(live_region_vid, location);
-        });
-
-        let locations = location.to_locations();
-        if let Some(annotation_index) = constant.user_ty {
-            if let Err(terr) = self.typeck.relate_type_and_user_type(
-                constant.const_.ty(),
-                ty::Invariant,
-                &UserTypeProjection { base: annotation_index, projs: vec![] },
-                locations,
-                ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg),
-            ) {
-                let annotation = &self.typeck.user_type_annotations[annotation_index];
-                span_mirbug!(
-                    self,
-                    constant,
-                    "bad constant user type {:?} vs {:?}: {:?}",
-                    annotation,
-                    constant.const_.ty(),
-                    terr,
-                );
-            }
-        } else {
-            let tcx = self.tcx();
-            let maybe_uneval = match constant.const_ {
-                Const::Ty(_, ct) => match ct.kind() {
-                    ty::ConstKind::Unevaluated(uv) => {
-                        Some(UnevaluatedConst { def: uv.def, args: uv.args, promoted: None })
-                    }
-                    _ => None,
-                },
-                Const::Unevaluated(uv, _) => Some(uv),
-                _ => None,
-            };
-
-            if let Some(uv) = maybe_uneval {
-                if let Some(promoted) = uv.promoted {
-                    let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
-                                     promoted: &Body<'tcx>,
-                                     ty,
-                                     san_ty| {
-                        if let Err(terr) = verifier.typeck.eq_types(
-                            ty,
-                            san_ty,
-                            locations,
-                            ConstraintCategory::Boring,
-                        ) {
-                            span_mirbug!(
-                                verifier,
-                                promoted,
-                                "bad promoted type ({:?}: {:?}): {:?}",
-                                ty,
-                                san_ty,
-                                terr
-                            );
-                        };
-                    };
-
-                    let promoted_body = &self.promoted[promoted];
-                    self.verify_promoted(promoted_body, location);
-
-                    let promoted_ty = promoted_body.return_ty();
-                    check_err(self, promoted_body, ty, promoted_ty);
-                } else {
-                    self.typeck.ascribe_user_type(
-                        constant.const_.ty(),
-                        ty::UserType::new(ty::UserTypeKind::TypeOf(
-                            uv.def,
-                            UserArgs { args: uv.args, user_self_ty: None },
-                        )),
-                        locations.span(self.typeck.body),
-                    );
-                }
-            } else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
-                let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
-                let normalized_ty = self.typeck.normalize(unnormalized_ty, locations);
-                let literal_ty = constant.const_.ty().builtin_deref(true).unwrap();
-
-                if let Err(terr) = self.typeck.eq_types(
-                    literal_ty,
-                    normalized_ty,
-                    locations,
-                    ConstraintCategory::Boring,
-                ) {
-                    span_mirbug!(self, constant, "bad static type {:?} ({:?})", constant, terr);
-                }
-            }
-
-            if let ty::FnDef(def_id, args) = *constant.const_.ty().kind() {
-                let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
-                self.typeck.normalize_and_prove_instantiated_predicates(
-                    def_id,
-                    instantiated_predicates,
-                    locations,
-                );
-
-                assert!(!matches!(
-                    tcx.impl_of_method(def_id).map(|imp| tcx.def_kind(imp)),
-                    Some(DefKind::Impl { of_trait: true })
-                ));
-                self.typeck.prove_predicates(
-                    args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
-                    locations,
-                    ConstraintCategory::Boring,
-                );
-            }
-        }
-    }
-
-    fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
-        self.super_local_decl(local, local_decl);
-
-        for user_ty in
-            local_decl.user_ty.as_deref().into_iter().flat_map(UserTypeProjections::projections)
-        {
-            let span = self.typeck.user_type_annotations[user_ty.base].span;
-
-            let ty = if local_decl.is_nonref_binding() {
-                local_decl.ty
-            } else if let &ty::Ref(_, rty, _) = local_decl.ty.kind() {
-                // If we have a binding of the form `let ref x: T = ..`
-                // then remove the outermost reference so we can check the
-                // type annotation for the remaining type.
-                rty
-            } else {
-                bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty);
-            };
-
-            if let Err(terr) = self.typeck.relate_type_and_user_type(
-                ty,
-                ty::Invariant,
-                user_ty,
-                Locations::All(span),
-                ConstraintCategory::TypeAnnotation(AnnotationSource::Declaration),
-            ) {
-                span_mirbug!(
-                    self,
-                    local,
-                    "bad user type on variable {:?}: {:?} != {:?} ({:?})",
-                    local,
-                    local_decl.ty,
-                    local_decl.user_ty,
-                    terr,
-                );
-            }
-        }
-    }
-
-    #[instrument(level = "debug", skip(self))]
-    fn visit_body(&mut self, body: &Body<'tcx>) {
-        debug_assert!(std::ptr::eq(self.typeck.body, body));
-        // We intentionally do not recurse into `body.required_consts` or
-        // `body.mentioned_items` here as the MIR at this phase should still
-        // refer to all items and we don't want to check them multiple times.
-
-        for (local, local_decl) in body.local_decls.iter_enumerated() {
-            self.visit_local_decl(local, local_decl);
-        }
-
-        for (block, block_data) in body.basic_blocks.iter_enumerated() {
-            let mut location = Location { block, statement_index: 0 };
-            for stmt in &block_data.statements {
-                if !stmt.source_info.span.is_dummy() {
-                    self.last_span = stmt.source_info.span;
-                }
-                self.visit_statement(stmt, location);
-                location.statement_index += 1;
-            }
-
-            self.visit_terminator(block_data.terminator(), location);
-        }
-    }
-}
-
-impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
-    fn body(&self) -> &Body<'tcx> {
-        self.typeck.body
-    }
-
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.typeck.infcx.tcx
-    }
-
-    fn verify_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Location) {
-        // Determine the constraints from the promoted MIR by running the type
-        // checker on the promoted MIR, then transfer the constraints back to
-        // the main MIR, changing the locations to the provided location.
-
-        let parent_body = mem::replace(&mut self.typeck.body, promoted_body);
-
-        // Use new sets of constraints and closure bounds so that we can
-        // modify their locations.
-        let polonius_facts = &mut None;
-        let mut constraints = Default::default();
-        let mut liveness_constraints =
-            LivenessValues::without_specific_points(Rc::new(DenseLocationMap::new(promoted_body)));
-        // Don't try to add borrow_region facts for the promoted MIR
-
-        let mut swap_constraints = |this: &mut Self| {
-            mem::swap(this.typeck.polonius_facts, polonius_facts);
-            mem::swap(&mut this.typeck.constraints.outlives_constraints, &mut constraints);
-            mem::swap(&mut this.typeck.constraints.liveness_constraints, &mut liveness_constraints);
-        };
-
-        swap_constraints(self);
-
-        self.visit_body(promoted_body);
-
-        self.typeck.typeck_mir();
-
-        self.typeck.body = parent_body;
-        // Merge the outlives constraints back in, at the given location.
-        swap_constraints(self);
-
-        let locations = location.to_locations();
-        for constraint in constraints.outlives().iter() {
-            let mut constraint = *constraint;
-            constraint.locations = locations;
-            if let ConstraintCategory::Return(_)
-            | ConstraintCategory::UseAsConst
-            | ConstraintCategory::UseAsStatic = constraint.category
-            {
-                // "Returning" from a promoted is an assignment to a
-                // temporary from the user's point of view.
-                constraint.category = ConstraintCategory::Boring;
-            }
-            self.typeck.constraints.outlives_constraints.push(constraint)
-        }
-        // If the region is live at least one location in the promoted MIR,
-        // then add a liveness constraint to the main MIR for this region
-        // at the location provided as an argument to this method
-        //
-        // add_location doesn't care about ordering so not a problem for the live regions to be
-        // unordered.
-        #[allow(rustc::potential_query_instability)]
-        for region in liveness_constraints.live_regions_unordered() {
-            self.typeck.constraints.liveness_constraints.add_location(region, location);
-        }
-    }
-}
-
 /// The MIR type checker. Visits the MIR and enforces all the
 /// constraints needed for it to be valid and well-typed. Along the
 /// way, it accrues region constraints -- these can later be used by
@@ -584,6 +217,9 @@ struct TypeChecker<'a, 'tcx> {
     infcx: &'a BorrowckInferCtxt<'tcx>,
     last_span: Span,
     body: &'a Body<'tcx>,
+    /// The bodies of all promoteds. As promoteds have a completely separate CFG
+    /// recursing into them may corrupt your data structures if you're not careful.
+    promoted: &'a IndexSlice<Promoted, Body<'tcx>>,
     /// User type annotations are shared between the main MIR and the MIR of
     /// all of the promoted items.
     user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
@@ -732,6 +368,10 @@ impl Locations {
 }
 
 impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
+    }
+
     fn body(&self) -> &Body<'tcx> {
         self.body
     }
@@ -859,6 +499,62 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         Ok(())
     }
 
+    fn check_promoted(&mut self, promoted_body: &'a Body<'tcx>, location: Location) {
+        // Determine the constraints from the promoted MIR by running the type
+        // checker on the promoted MIR, then transfer the constraints back to
+        // the main MIR, changing the locations to the provided location.
+
+        let parent_body = mem::replace(&mut self.body, promoted_body);
+
+        // Use new sets of constraints and closure bounds so that we can
+        // modify their locations.
+        let polonius_facts = &mut None;
+        let mut constraints = Default::default();
+        let mut liveness_constraints =
+            LivenessValues::without_specific_points(Rc::new(DenseLocationMap::new(promoted_body)));
+
+        // Don't try to add borrow_region facts for the promoted MIR as they refer
+        // to the wrong locations.
+        let mut swap_constraints = |this: &mut Self| {
+            mem::swap(this.polonius_facts, polonius_facts);
+            mem::swap(&mut this.constraints.outlives_constraints, &mut constraints);
+            mem::swap(&mut this.constraints.liveness_constraints, &mut liveness_constraints);
+        };
+
+        swap_constraints(self);
+
+        self.visit_body(promoted_body);
+
+        self.body = parent_body;
+
+        // Merge the outlives constraints back in, at the given location.
+        swap_constraints(self);
+        let locations = location.to_locations();
+        for constraint in constraints.outlives().iter() {
+            let mut constraint = *constraint;
+            constraint.locations = locations;
+            if let ConstraintCategory::Return(_)
+            | ConstraintCategory::UseAsConst
+            | ConstraintCategory::UseAsStatic = constraint.category
+            {
+                // "Returning" from a promoted is an assignment to a
+                // temporary from the user's point of view.
+                constraint.category = ConstraintCategory::Boring;
+            }
+            self.constraints.outlives_constraints.push(constraint)
+        }
+        // If the region is live at least one location in the promoted MIR,
+        // then add a liveness constraint to the main MIR for this region
+        // at the location provided as an argument to this method
+        //
+        // add_location doesn't care about ordering so not a problem for the live regions to be
+        // unordered.
+        #[allow(rustc::potential_query_instability)]
+        for region in liveness_constraints.live_regions_unordered() {
+            self.constraints.liveness_constraints.add_location(region, location);
+        }
+    }
+
     fn check_inline_const(
         &mut self,
         inferred_ty: Ty<'tcx>,
@@ -888,15 +584,40 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             Locations::All(span),
         );
     }
+}
 
-    fn tcx(&self) -> TyCtxt<'tcx> {
-        self.infcx.tcx
+impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
+    fn visit_span(&mut self, span: Span) {
+        if !span.is_dummy() {
+            debug!(?span);
+            self.last_span = span;
+        }
+    }
+
+    #[instrument(skip(self, body), level = "debug")]
+    fn visit_body(&mut self, body: &Body<'tcx>) {
+        debug_assert!(std::ptr::eq(self.body, body));
+
+        for (local, local_decl) in body.local_decls.iter_enumerated() {
+            self.visit_local_decl(local, local_decl);
+        }
+
+        for (block, block_data) in body.basic_blocks.iter_enumerated() {
+            let mut location = Location { block, statement_index: 0 };
+            for stmt in &block_data.statements {
+                self.visit_statement(stmt, location);
+                location.statement_index += 1;
+            }
+
+            self.visit_terminator(block_data.terminator(), location);
+            self.check_iscleanup(block_data);
+        }
     }
 
     #[instrument(skip(self), level = "debug")]
-    fn check_stmt(&mut self, stmt: &Statement<'tcx>, location: Location) {
+    fn visit_statement(&mut self, stmt: &Statement<'tcx>, location: Location) {
+        self.super_statement(stmt, location);
         let tcx = self.tcx();
-        debug!("stmt kind: {:?}", stmt.kind);
         match &stmt.kind {
             StatementKind::Assign(box (place, rv)) => {
                 // Assignments to temporaries are not "interesting";
@@ -976,7 +697,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     }
                 }
 
-                self.check_rvalue(rv, location);
                 if !self.unsized_feature_enabled() {
                     let trait_ref = ty::TraitRef::new(
                         tcx,
@@ -1011,14 +731,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     );
                 }
             }
-            StatementKind::Intrinsic(box kind) => match kind {
-                NonDivergingIntrinsic::Assume(op) => self.check_operand(op, location),
-                NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
-                    stmt.source_info.span,
-                    "Unexpected NonDivergingIntrinsic::CopyNonOverlapping, should only appear after lowering_intrinsics",
-                ),
-            },
-            StatementKind::FakeRead(..)
+            StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(..))
+            | StatementKind::FakeRead(..)
             | StatementKind::StorageLive(..)
             | StatementKind::StorageDead(..)
             | StatementKind::Retag { .. }
@@ -1027,14 +741,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             | StatementKind::PlaceMention(..)
             | StatementKind::BackwardIncompatibleDropHint { .. }
             | StatementKind::Nop => {}
-            StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => {
+            StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(..))
+            | StatementKind::Deinit(..)
+            | StatementKind::SetDiscriminant { .. } => {
                 bug!("Statement not allowed in this MIR phase")
             }
         }
     }
 
-    #[instrument(skip(self, term_location), level = "debug")]
-    fn check_terminator(&mut self, term: &Terminator<'tcx>, term_location: Location) {
+    #[instrument(skip(self), level = "debug")]
+    fn visit_terminator(&mut self, term: &Terminator<'tcx>, term_location: Location) {
+        self.super_terminator(term, term_location);
         let tcx = self.tcx();
         debug!("terminator kind: {:?}", term.kind);
         match &term.kind {
@@ -1052,8 +769,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
 
             TerminatorKind::SwitchInt { discr, .. } => {
-                self.check_operand(discr, term_location);
-
                 let switch_ty = discr.ty(self.body, tcx);
                 if !switch_ty.is_integral() && !switch_ty.is_char() && !switch_ty.is_bool() {
                     span_mirbug!(self, term, "bad SwitchInt discr ty {:?}", switch_ty);
@@ -1068,11 +783,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     _ => unreachable!(),
                 };
 
-                self.check_operand(func, term_location);
-                for arg in args {
-                    self.check_operand(&arg.node, term_location);
-                }
-
                 let func_ty = func.ty(self.body, tcx);
                 debug!("func_ty.kind: {:?}", func_ty.kind());
 
@@ -1159,8 +869,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 self.check_call_inputs(term, func, &sig, args, term_location, call_source);
             }
             TerminatorKind::Assert { cond, msg, .. } => {
-                self.check_operand(cond, term_location);
-
                 let cond_ty = cond.ty(self.body, tcx);
                 if cond_ty != tcx.types.bool {
                     span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
@@ -1176,8 +884,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }
             }
             TerminatorKind::Yield { value, resume_arg, .. } => {
-                self.check_operand(value, term_location);
-
                 match self.body.yield_ty() {
                     None => span_mirbug!(self, term, "yield in non-coroutine"),
                     Some(ty) => {
@@ -1225,385 +931,75 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
     }
 
-    fn check_call_dest(
-        &mut self,
-        term: &Terminator<'tcx>,
-        sig: &ty::FnSig<'tcx>,
-        destination: Place<'tcx>,
-        target: Option<BasicBlock>,
-        term_location: Location,
-    ) {
-        let tcx = self.tcx();
-        match target {
-            Some(_) => {
-                let dest_ty = destination.ty(self.body, tcx).ty;
-                let dest_ty = self.normalize(dest_ty, term_location);
-                let category = match destination.as_local() {
-                    Some(RETURN_PLACE) => {
-                        if let DefiningTy::Const(def_id, _) | DefiningTy::InlineConst(def_id, _) =
-                            self.universal_regions.defining_ty
-                        {
-                            if tcx.is_static(def_id) {
-                                ConstraintCategory::UseAsStatic
-                            } else {
-                                ConstraintCategory::UseAsConst
-                            }
-                        } else {
-                            ConstraintCategory::Return(ReturnConstraint::Normal)
-                        }
-                    }
-                    Some(l) if !self.body.local_decls[l].is_user_variable() => {
-                        ConstraintCategory::Boring
-                    }
-                    // The return type of a call is interesting for diagnostics.
-                    _ => ConstraintCategory::Assignment,
-                };
-
-                let locations = term_location.to_locations();
-
-                if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations, category) {
-                    span_mirbug!(
-                        self,
-                        term,
-                        "call dest mismatch ({:?} <- {:?}): {:?}",
-                        dest_ty,
-                        sig.output(),
-                        terr
-                    );
-                }
-
-                // When `unsized_fn_params` and `unsized_locals` are both not enabled,
-                // this check is done at `check_local`.
-                if self.unsized_feature_enabled() {
-                    let span = term.source_info.span;
-                    self.ensure_place_sized(dest_ty, span);
-                }
-            }
-            None => {
-                // The signature in this call can reference region variables,
-                // so erase them before calling a query.
-                let output_ty = self.tcx().erase_regions(sig.output());
-                if !output_ty.is_privately_uninhabited(
-                    self.tcx(),
-                    self.infcx.typing_env(self.infcx.param_env),
-                ) {
-                    span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
-                }
-            }
-        }
-    }
-
-    #[instrument(level = "debug", skip(self, term, func, term_location, call_source))]
-    fn check_call_inputs(
-        &mut self,
-        term: &Terminator<'tcx>,
-        func: &Operand<'tcx>,
-        sig: &ty::FnSig<'tcx>,
-        args: &[Spanned<Operand<'tcx>>],
-        term_location: Location,
-        call_source: CallSource,
-    ) {
-        if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) {
-            span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
-        }
-
-        let func_ty = func.ty(self.body, self.infcx.tcx);
-        if let ty::FnDef(def_id, _) = *func_ty.kind() {
-            // Some of the SIMD intrinsics are special: they need a particular argument to be a
-            // constant. (Eventually this should use const-generics, but those are not up for the
-            // task yet: https://github.com/rust-lang/rust/issues/85229.)
-            if let Some(name @ (sym::simd_shuffle | sym::simd_insert | sym::simd_extract)) =
-                self.tcx().intrinsic(def_id).map(|i| i.name)
-            {
-                let idx = match name {
-                    sym::simd_shuffle => 2,
-                    _ => 1,
-                };
-                if !matches!(args[idx], Spanned { node: Operand::Constant(_), .. }) {
-                    self.tcx().dcx().emit_err(SimdIntrinsicArgConst {
-                        span: term.source_info.span,
-                        arg: idx + 1,
-                        intrinsic: name.to_string(),
-                    });
-                }
-            }
-        }
-        debug!(?func_ty);
+    fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
+        self.super_local_decl(local, local_decl);
 
-        for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
-            let op_arg_ty = op_arg.node.ty(self.body, self.tcx());
+        for user_ty in
+            local_decl.user_ty.as_deref().into_iter().flat_map(UserTypeProjections::projections)
+        {
+            let span = self.user_type_annotations[user_ty.base].span;
 
-            let op_arg_ty = self.normalize(op_arg_ty, term_location);
-            let category = if call_source.from_hir_call() {
-                ConstraintCategory::CallArgument(Some(self.infcx.tcx.erase_regions(func_ty)))
+            let ty = if local_decl.is_nonref_binding() {
+                local_decl.ty
+            } else if let &ty::Ref(_, rty, _) = local_decl.ty.kind() {
+                // If we have a binding of the form `let ref x: T = ..`
+                // then remove the outermost reference so we can check the
+                // type annotation for the remaining type.
+                rty
             } else {
-                ConstraintCategory::Boring
+                bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty);
             };
-            if let Err(terr) =
-                self.sub_types(op_arg_ty, *fn_arg, term_location.to_locations(), category)
-            {
+
+            if let Err(terr) = self.relate_type_and_user_type(
+                ty,
+                ty::Invariant,
+                user_ty,
+                Locations::All(span),
+                ConstraintCategory::TypeAnnotation(AnnotationSource::Declaration),
+            ) {
                 span_mirbug!(
                     self,
-                    term,
-                    "bad arg #{:?} ({:?} <- {:?}): {:?}",
-                    n,
-                    fn_arg,
-                    op_arg_ty,
-                    terr
+                    local,
+                    "bad user type on variable {:?}: {:?} != {:?} ({:?})",
+                    local,
+                    local_decl.ty,
+                    local_decl.user_ty,
+                    terr,
                 );
             }
         }
-    }
-
-    fn check_iscleanup(&mut self, block_data: &BasicBlockData<'tcx>) {
-        let is_cleanup = block_data.is_cleanup;
-        self.last_span = block_data.terminator().source_info.span;
-        match block_data.terminator().kind {
-            TerminatorKind::Goto { target } => {
-                self.assert_iscleanup(block_data, target, is_cleanup)
-            }
-            TerminatorKind::SwitchInt { ref targets, .. } => {
-                for target in targets.all_targets() {
-                    self.assert_iscleanup(block_data, *target, is_cleanup);
-                }
-            }
-            TerminatorKind::UnwindResume => {
-                if !is_cleanup {
-                    span_mirbug!(self, block_data, "resume on non-cleanup block!")
-                }
-            }
-            TerminatorKind::UnwindTerminate(_) => {
-                if !is_cleanup {
-                    span_mirbug!(self, block_data, "terminate on non-cleanup block!")
-                }
-            }
-            TerminatorKind::Return => {
-                if is_cleanup {
-                    span_mirbug!(self, block_data, "return on cleanup block")
-                }
-            }
-            TerminatorKind::TailCall { .. } => {
-                if is_cleanup {
-                    span_mirbug!(self, block_data, "tailcall on cleanup block")
-                }
-            }
-            TerminatorKind::CoroutineDrop { .. } => {
-                if is_cleanup {
-                    span_mirbug!(self, block_data, "coroutine_drop in cleanup block")
-                }
-            }
-            TerminatorKind::Yield { resume, drop, .. } => {
-                if is_cleanup {
-                    span_mirbug!(self, block_data, "yield in cleanup block")
-                }
-                self.assert_iscleanup(block_data, resume, is_cleanup);
-                if let Some(drop) = drop {
-                    self.assert_iscleanup(block_data, drop, is_cleanup);
-                }
-            }
-            TerminatorKind::Unreachable => {}
-            TerminatorKind::Drop { target, unwind, .. }
-            | TerminatorKind::Assert { target, unwind, .. } => {
-                self.assert_iscleanup(block_data, target, is_cleanup);
-                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
-            }
-            TerminatorKind::Call { ref target, unwind, .. } => {
-                if let &Some(target) = target {
-                    self.assert_iscleanup(block_data, target, is_cleanup);
-                }
-                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
-            }
-            TerminatorKind::FalseEdge { real_target, imaginary_target } => {
-                self.assert_iscleanup(block_data, real_target, is_cleanup);
-                self.assert_iscleanup(block_data, imaginary_target, is_cleanup);
-            }
-            TerminatorKind::FalseUnwind { real_target, unwind } => {
-                self.assert_iscleanup(block_data, real_target, is_cleanup);
-                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
-            }
-            TerminatorKind::InlineAsm { ref targets, unwind, .. } => {
-                for &target in targets {
-                    self.assert_iscleanup(block_data, target, is_cleanup);
-                }
-                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
-            }
-        }
-    }
-
-    fn assert_iscleanup(&mut self, ctxt: &dyn fmt::Debug, bb: BasicBlock, iscleanuppad: bool) {
-        if self.body[bb].is_cleanup != iscleanuppad {
-            span_mirbug!(self, ctxt, "cleanuppad mismatch: {:?} should be {:?}", bb, iscleanuppad);
-        }
-    }
-
-    fn assert_iscleanup_unwind(
-        &mut self,
-        ctxt: &dyn fmt::Debug,
-        unwind: UnwindAction,
-        is_cleanup: bool,
-    ) {
-        match unwind {
-            UnwindAction::Cleanup(unwind) => {
-                if is_cleanup {
-                    span_mirbug!(self, ctxt, "unwind on cleanup block")
-                }
-                self.assert_iscleanup(ctxt, unwind, true);
-            }
-            UnwindAction::Continue => {
-                if is_cleanup {
-                    span_mirbug!(self, ctxt, "unwind on cleanup block")
-                }
-            }
-            UnwindAction::Unreachable | UnwindAction::Terminate(_) => (),
-        }
-    }
-
-    fn check_local(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
-        match self.body.local_kind(local) {
-            LocalKind::ReturnPointer | LocalKind::Arg => {
-                // return values of normal functions are required to be
-                // sized by typeck, but return values of ADT constructors are
-                // not because we don't include a `Self: Sized` bounds on them.
-                //
-                // Unbound parts of arguments were never required to be Sized
-                // - maybe we should make that a warning.
-                return;
-            }
-            LocalKind::Temp => {}
-        }
 
         // When `unsized_fn_params` or `unsized_locals` is enabled, only function calls
         // and nullary ops are checked in `check_call_dest`.
         if !self.unsized_feature_enabled() {
-            let span = local_decl.source_info.span;
-            let ty = local_decl.ty;
-            self.ensure_place_sized(ty, span);
-        }
-    }
-
-    fn ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span) {
-        let tcx = self.tcx();
-
-        // Erase the regions from `ty` to get a global type. The
-        // `Sized` bound in no way depends on precise regions, so this
-        // shouldn't affect `is_sized`.
-        let erased_ty = tcx.erase_regions(ty);
-        // FIXME(#132279): Using `Ty::is_sized` causes us to incorrectly handle opaques here.
-        if !erased_ty.is_sized(tcx, self.infcx.typing_env(self.infcx.param_env)) {
-            // in current MIR construction, all non-control-flow rvalue
-            // expressions evaluate through `as_temp` or `into` a return
-            // slot or local, so to find all unsized rvalues it is enough
-            // to check all temps, return slots and locals.
-            if self.reported_errors.replace((ty, span)).is_none() {
-                // While this is located in `nll::typeck` this error is not
-                // an NLL error, it's a required check to prevent creation
-                // of unsized rvalues in a call expression.
-                self.tcx().dcx().emit_err(MoveUnsized { ty, span });
-            }
-        }
-    }
-
-    fn aggregate_field_ty(
-        &mut self,
-        ak: &AggregateKind<'tcx>,
-        field_index: FieldIdx,
-        location: Location,
-    ) -> Result<Ty<'tcx>, FieldAccessError> {
-        let tcx = self.tcx();
-
-        match *ak {
-            AggregateKind::Adt(adt_did, variant_index, args, _, active_field_index) => {
-                let def = tcx.adt_def(adt_did);
-                let variant = &def.variant(variant_index);
-                let adj_field_index = active_field_index.unwrap_or(field_index);
-                if let Some(field) = variant.fields.get(adj_field_index) {
-                    Ok(self.normalize(field.ty(tcx, args), location))
-                } else {
-                    Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
+            match self.body.local_kind(local) {
+                LocalKind::ReturnPointer | LocalKind::Arg => {
+                    // return values of normal functions are required to be
+                    // sized by typeck, but return values of ADT constructors are
+                    // not because we don't include a `Self: Sized` bounds on them.
+                    //
+                    // Unbound parts of arguments were never required to be Sized
+                    // - maybe we should make that a warning.
+                    return;
                 }
-            }
-            AggregateKind::Closure(_, args) => {
-                match args.as_closure().upvar_tys().get(field_index.as_usize()) {
-                    Some(ty) => Ok(*ty),
-                    None => Err(FieldAccessError::OutOfRange {
-                        field_count: args.as_closure().upvar_tys().len(),
-                    }),
-                }
-            }
-            AggregateKind::Coroutine(_, args) => {
-                // It doesn't make sense to look at a field beyond the prefix;
-                // these require a variant index, and are not initialized in
-                // aggregate rvalues.
-                match args.as_coroutine().prefix_tys().get(field_index.as_usize()) {
-                    Some(ty) => Ok(*ty),
-                    None => Err(FieldAccessError::OutOfRange {
-                        field_count: args.as_coroutine().prefix_tys().len(),
-                    }),
-                }
-            }
-            AggregateKind::CoroutineClosure(_, args) => {
-                match args.as_coroutine_closure().upvar_tys().get(field_index.as_usize()) {
-                    Some(ty) => Ok(*ty),
-                    None => Err(FieldAccessError::OutOfRange {
-                        field_count: args.as_coroutine_closure().upvar_tys().len(),
-                    }),
-                }
-            }
-            AggregateKind::Array(ty) => Ok(ty),
-            AggregateKind::Tuple | AggregateKind::RawPtr(..) => {
-                unreachable!("This should have been covered in check_rvalues");
-            }
-        }
-    }
-
-    fn check_operand(&mut self, op: &Operand<'tcx>, location: Location) {
-        debug!(?op, ?location, "check_operand");
-
-        if let Operand::Constant(constant) = op {
-            let maybe_uneval = match constant.const_ {
-                Const::Val(..) | Const::Ty(_, _) => None,
-                Const::Unevaluated(uv, _) => Some(uv),
-            };
-
-            if let Some(uv) = maybe_uneval {
-                if uv.promoted.is_none() {
-                    let tcx = self.tcx();
-                    let def_id = uv.def;
-                    if tcx.def_kind(def_id) == DefKind::InlineConst {
-                        let def_id = def_id.expect_local();
-                        let predicates = self.prove_closure_bounds(
-                            tcx,
-                            def_id,
-                            uv.args,
-                            location.to_locations(),
-                        );
-                        self.normalize_and_prove_instantiated_predicates(
-                            def_id.to_def_id(),
-                            predicates,
-                            location.to_locations(),
-                        );
-                    }
+                LocalKind::Temp => {
+                    let span = local_decl.source_info.span;
+                    let ty = local_decl.ty;
+                    self.ensure_place_sized(ty, span);
                 }
             }
         }
     }
 
     #[instrument(skip(self), level = "debug")]
-    fn check_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
+    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
+        self.super_rvalue(rvalue, location);
         let tcx = self.tcx();
         let span = self.body.source_info(location).span;
-
         match rvalue {
-            Rvalue::Aggregate(ak, ops) => {
-                for op in ops {
-                    self.check_operand(op, location);
-                }
-                self.check_aggregate_rvalue(rvalue, ak, ops, location)
-            }
+            Rvalue::Aggregate(ak, ops) => self.check_aggregate_rvalue(rvalue, ak, ops, location),
 
             Rvalue::Repeat(operand, len) => {
-                self.check_operand(operand, location);
-
                 let array_ty = rvalue.ty(self.body.local_decls(), tcx);
                 self.prove_predicate(
                     ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(array_ty.into())),
@@ -1656,9 +1052,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             &Rvalue::NullaryOp(NullOp::ContractChecks, _) => {}
             &Rvalue::NullaryOp(NullOp::UbChecks, _) => {}
 
-            Rvalue::ShallowInitBox(operand, ty) => {
-                self.check_operand(operand, location);
-
+            Rvalue::ShallowInitBox(_operand, ty) => {
                 let trait_ref = ty::TraitRef::new(
                     tcx,
                     tcx.require_lang_item(LangItem::Sized, Some(span)),
@@ -1673,8 +1067,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
 
             Rvalue::Cast(cast_kind, op, ty) => {
-                self.check_operand(op, location);
-
                 match *cast_kind {
                     CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, coercion_source) => {
                         let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
@@ -2191,9 +1583,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge,
                 box (left, right),
             ) => {
-                self.check_operand(left, location);
-                self.check_operand(right, location);
-
                 let ty_left = left.ty(self.body, tcx);
                 match ty_left.kind() {
                     // Types with regions are comparable if they have a common super-type.
@@ -2242,23 +1631,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }
             }
 
-            Rvalue::Use(operand) | Rvalue::UnaryOp(_, operand) => {
-                self.check_operand(operand, location);
-            }
-            Rvalue::CopyForDeref(place) => {
-                let op = &Operand::Copy(*place);
-                self.check_operand(op, location);
-            }
-
-            Rvalue::BinaryOp(_, box (left, right)) => {
-                self.check_operand(left, location);
-                self.check_operand(right, location);
-            }
-
             Rvalue::WrapUnsafeBinder(op, ty) => {
-                self.check_operand(op, location);
                 let operand_ty = op.ty(self.body, self.tcx());
-
                 let ty::UnsafeBinder(binder_ty) = *ty.kind() else {
                     unreachable!();
                 };
@@ -2276,7 +1650,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 .unwrap();
             }
 
-            Rvalue::RawPtr(..)
+            Rvalue::Use(_)
+            | Rvalue::UnaryOp(_, _)
+            | Rvalue::CopyForDeref(_)
+            | Rvalue::BinaryOp(..)
+            | Rvalue::RawPtr(..)
             | Rvalue::ThreadLocalRef(..)
             | Rvalue::Len(..)
             | Rvalue::Discriminant(..)
@@ -2284,6 +1662,543 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
+    fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
+        self.super_operand(op, location);
+        if let Operand::Constant(constant) = op {
+            let maybe_uneval = match constant.const_ {
+                Const::Val(..) | Const::Ty(_, _) => None,
+                Const::Unevaluated(uv, _) => Some(uv),
+            };
+
+            if let Some(uv) = maybe_uneval {
+                if uv.promoted.is_none() {
+                    let tcx = self.tcx();
+                    let def_id = uv.def;
+                    if tcx.def_kind(def_id) == DefKind::InlineConst {
+                        let def_id = def_id.expect_local();
+                        let predicates = self.prove_closure_bounds(
+                            tcx,
+                            def_id,
+                            uv.args,
+                            location.to_locations(),
+                        );
+                        self.normalize_and_prove_instantiated_predicates(
+                            def_id.to_def_id(),
+                            predicates,
+                            location.to_locations(),
+                        );
+                    }
+                }
+            }
+        }
+    }
+
+    #[instrument(level = "debug", skip(self))]
+    fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
+        self.super_const_operand(constant, location);
+        let ty = constant.const_.ty();
+
+        self.infcx.tcx.for_each_free_region(&ty, |live_region| {
+            let live_region_vid = self.universal_regions.to_region_vid(live_region);
+            self.constraints.liveness_constraints.add_location(live_region_vid, location);
+        });
+
+        let locations = location.to_locations();
+        if let Some(annotation_index) = constant.user_ty {
+            if let Err(terr) = self.relate_type_and_user_type(
+                constant.const_.ty(),
+                ty::Invariant,
+                &UserTypeProjection { base: annotation_index, projs: vec![] },
+                locations,
+                ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg),
+            ) {
+                let annotation = &self.user_type_annotations[annotation_index];
+                span_mirbug!(
+                    self,
+                    constant,
+                    "bad constant user type {:?} vs {:?}: {:?}",
+                    annotation,
+                    constant.const_.ty(),
+                    terr,
+                );
+            }
+        } else {
+            let tcx = self.tcx();
+            let maybe_uneval = match constant.const_ {
+                Const::Ty(_, ct) => match ct.kind() {
+                    ty::ConstKind::Unevaluated(uv) => {
+                        Some(UnevaluatedConst { def: uv.def, args: uv.args, promoted: None })
+                    }
+                    _ => None,
+                },
+                Const::Unevaluated(uv, _) => Some(uv),
+                _ => None,
+            };
+
+            if let Some(uv) = maybe_uneval {
+                if let Some(promoted) = uv.promoted {
+                    let promoted_body = &self.promoted[promoted];
+                    self.check_promoted(promoted_body, location);
+                    let promoted_ty = promoted_body.return_ty();
+                    if let Err(terr) =
+                        self.eq_types(ty, promoted_ty, locations, ConstraintCategory::Boring)
+                    {
+                        span_mirbug!(
+                            self,
+                            promoted,
+                            "bad promoted type ({:?}: {:?}): {:?}",
+                            ty,
+                            promoted_ty,
+                            terr
+                        );
+                    };
+                } else {
+                    self.ascribe_user_type(
+                        constant.const_.ty(),
+                        ty::UserType::new(ty::UserTypeKind::TypeOf(
+                            uv.def,
+                            UserArgs { args: uv.args, user_self_ty: None },
+                        )),
+                        locations.span(self.body),
+                    );
+                }
+            } else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
+                let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
+                let normalized_ty = self.normalize(unnormalized_ty, locations);
+                let literal_ty = constant.const_.ty().builtin_deref(true).unwrap();
+
+                if let Err(terr) =
+                    self.eq_types(literal_ty, normalized_ty, locations, ConstraintCategory::Boring)
+                {
+                    span_mirbug!(self, constant, "bad static type {:?} ({:?})", constant, terr);
+                }
+            }
+
+            if let ty::FnDef(def_id, args) = *constant.const_.ty().kind() {
+                let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
+                self.normalize_and_prove_instantiated_predicates(
+                    def_id,
+                    instantiated_predicates,
+                    locations,
+                );
+
+                assert!(!matches!(
+                    tcx.impl_of_method(def_id).map(|imp| tcx.def_kind(imp)),
+                    Some(DefKind::Impl { of_trait: true })
+                ));
+                self.prove_predicates(
+                    args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
+                    locations,
+                    ConstraintCategory::Boring,
+                );
+            }
+        }
+    }
+
+    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
+        self.super_place(place, context, location);
+        let tcx = self.tcx();
+        let place_ty = place.ty(self.body, tcx);
+        if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
+            let trait_ref = ty::TraitRef::new(
+                tcx,
+                tcx.require_lang_item(LangItem::Copy, Some(self.last_span)),
+                [place_ty.ty],
+            );
+
+            // To have a `Copy` operand, the type `T` of the
+            // value must be `Copy`. Note that we prove that `T: Copy`,
+            // rather than using the `is_copy_modulo_regions`
+            // test. This is important because
+            // `is_copy_modulo_regions` ignores the resulting region
+            // obligations and assumes they pass. This can result in
+            // bounds from `Copy` impls being unsoundly ignored (e.g.,
+            // #29149). Note that we decide to use `Copy` before knowing
+            // whether the bounds fully apply: in effect, the rule is
+            // that if a value of some type could implement `Copy`, then
+            // it must.
+            self.prove_trait_ref(trait_ref, location.to_locations(), ConstraintCategory::CopyBound);
+        }
+    }
+
+    fn visit_projection_elem(
+        &mut self,
+        place: PlaceRef<'tcx>,
+        elem: PlaceElem<'tcx>,
+        context: PlaceContext,
+        location: Location,
+    ) {
+        let tcx = self.tcx();
+        let base_ty = place.ty(self.body(), tcx);
+        match elem {
+            // All these projections don't add any constraints, so there's nothing to
+            // do here. We check their invariants in the MIR validator after all.
+            ProjectionElem::Deref
+            | ProjectionElem::Index(_)
+            | ProjectionElem::ConstantIndex { .. }
+            | ProjectionElem::Subslice { .. }
+            | ProjectionElem::Downcast(..) => {}
+            ProjectionElem::Field(field, fty) => {
+                let fty = self.normalize(fty, location);
+                let ty = base_ty.field_ty(tcx, field);
+                let ty = self.normalize(ty, location);
+                debug!(?fty, ?ty);
+
+                if let Err(terr) = self.relate_types(
+                    ty,
+                    context.ambient_variance(),
+                    fty,
+                    location.to_locations(),
+                    ConstraintCategory::Boring,
+                ) {
+                    span_mirbug!(self, place, "bad field access ({:?}: {:?}): {:?}", ty, fty, terr);
+                }
+            }
+            ProjectionElem::OpaqueCast(ty) => {
+                let ty = self.normalize(ty, location);
+                self.relate_types(
+                    ty,
+                    context.ambient_variance(),
+                    base_ty.ty,
+                    location.to_locations(),
+                    ConstraintCategory::TypeAnnotation(AnnotationSource::OpaqueCast),
+                )
+                .unwrap();
+            }
+            ProjectionElem::UnwrapUnsafeBinder(ty) => {
+                let ty::UnsafeBinder(binder_ty) = *base_ty.ty.kind() else {
+                    unreachable!();
+                };
+                let found_ty = self.infcx.instantiate_binder_with_fresh_vars(
+                    self.body.source_info(location).span,
+                    BoundRegionConversionTime::HigherRankedType,
+                    binder_ty.into(),
+                );
+                self.relate_types(
+                    ty,
+                    context.ambient_variance(),
+                    found_ty,
+                    location.to_locations(),
+                    ConstraintCategory::Boring,
+                )
+                .unwrap();
+            }
+            ProjectionElem::Subtype(_) => {
+                bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
+            }
+        }
+    }
+}
+
+impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
+    fn check_call_dest(
+        &mut self,
+        term: &Terminator<'tcx>,
+        sig: &ty::FnSig<'tcx>,
+        destination: Place<'tcx>,
+        target: Option<BasicBlock>,
+        term_location: Location,
+    ) {
+        let tcx = self.tcx();
+        match target {
+            Some(_) => {
+                let dest_ty = destination.ty(self.body, tcx).ty;
+                let dest_ty = self.normalize(dest_ty, term_location);
+                let category = match destination.as_local() {
+                    Some(RETURN_PLACE) => {
+                        if let DefiningTy::Const(def_id, _) | DefiningTy::InlineConst(def_id, _) =
+                            self.universal_regions.defining_ty
+                        {
+                            if tcx.is_static(def_id) {
+                                ConstraintCategory::UseAsStatic
+                            } else {
+                                ConstraintCategory::UseAsConst
+                            }
+                        } else {
+                            ConstraintCategory::Return(ReturnConstraint::Normal)
+                        }
+                    }
+                    Some(l) if !self.body.local_decls[l].is_user_variable() => {
+                        ConstraintCategory::Boring
+                    }
+                    // The return type of a call is interesting for diagnostics.
+                    _ => ConstraintCategory::Assignment,
+                };
+
+                let locations = term_location.to_locations();
+
+                if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations, category) {
+                    span_mirbug!(
+                        self,
+                        term,
+                        "call dest mismatch ({:?} <- {:?}): {:?}",
+                        dest_ty,
+                        sig.output(),
+                        terr
+                    );
+                }
+
+                // When `unsized_fn_params` and `unsized_locals` are both not enabled,
+                // this check is done at `check_local`.
+                if self.unsized_feature_enabled() {
+                    let span = term.source_info.span;
+                    self.ensure_place_sized(dest_ty, span);
+                }
+            }
+            None => {
+                // The signature in this call can reference region variables,
+                // so erase them before calling a query.
+                let output_ty = self.tcx().erase_regions(sig.output());
+                if !output_ty.is_privately_uninhabited(
+                    self.tcx(),
+                    self.infcx.typing_env(self.infcx.param_env),
+                ) {
+                    span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
+                }
+            }
+        }
+    }
+
+    #[instrument(level = "debug", skip(self, term, func, term_location, call_source))]
+    fn check_call_inputs(
+        &mut self,
+        term: &Terminator<'tcx>,
+        func: &Operand<'tcx>,
+        sig: &ty::FnSig<'tcx>,
+        args: &[Spanned<Operand<'tcx>>],
+        term_location: Location,
+        call_source: CallSource,
+    ) {
+        if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) {
+            span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
+        }
+
+        let func_ty = func.ty(self.body, self.infcx.tcx);
+        if let ty::FnDef(def_id, _) = *func_ty.kind() {
+            // Some of the SIMD intrinsics are special: they need a particular argument to be a
+            // constant. (Eventually this should use const-generics, but those are not up for the
+            // task yet: https://github.com/rust-lang/rust/issues/85229.)
+            if let Some(name @ (sym::simd_shuffle | sym::simd_insert | sym::simd_extract)) =
+                self.tcx().intrinsic(def_id).map(|i| i.name)
+            {
+                let idx = match name {
+                    sym::simd_shuffle => 2,
+                    _ => 1,
+                };
+                if !matches!(args[idx], Spanned { node: Operand::Constant(_), .. }) {
+                    self.tcx().dcx().emit_err(SimdIntrinsicArgConst {
+                        span: term.source_info.span,
+                        arg: idx + 1,
+                        intrinsic: name.to_string(),
+                    });
+                }
+            }
+        }
+        debug!(?func_ty);
+
+        for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
+            let op_arg_ty = op_arg.node.ty(self.body, self.tcx());
+
+            let op_arg_ty = self.normalize(op_arg_ty, term_location);
+            let category = if call_source.from_hir_call() {
+                ConstraintCategory::CallArgument(Some(self.infcx.tcx.erase_regions(func_ty)))
+            } else {
+                ConstraintCategory::Boring
+            };
+            if let Err(terr) =
+                self.sub_types(op_arg_ty, *fn_arg, term_location.to_locations(), category)
+            {
+                span_mirbug!(
+                    self,
+                    term,
+                    "bad arg #{:?} ({:?} <- {:?}): {:?}",
+                    n,
+                    fn_arg,
+                    op_arg_ty,
+                    terr
+                );
+            }
+        }
+    }
+
+    fn check_iscleanup(&mut self, block_data: &BasicBlockData<'tcx>) {
+        let is_cleanup = block_data.is_cleanup;
+        match block_data.terminator().kind {
+            TerminatorKind::Goto { target } => {
+                self.assert_iscleanup(block_data, target, is_cleanup)
+            }
+            TerminatorKind::SwitchInt { ref targets, .. } => {
+                for target in targets.all_targets() {
+                    self.assert_iscleanup(block_data, *target, is_cleanup);
+                }
+            }
+            TerminatorKind::UnwindResume => {
+                if !is_cleanup {
+                    span_mirbug!(self, block_data, "resume on non-cleanup block!")
+                }
+            }
+            TerminatorKind::UnwindTerminate(_) => {
+                if !is_cleanup {
+                    span_mirbug!(self, block_data, "terminate on non-cleanup block!")
+                }
+            }
+            TerminatorKind::Return => {
+                if is_cleanup {
+                    span_mirbug!(self, block_data, "return on cleanup block")
+                }
+            }
+            TerminatorKind::TailCall { .. } => {
+                if is_cleanup {
+                    span_mirbug!(self, block_data, "tailcall on cleanup block")
+                }
+            }
+            TerminatorKind::CoroutineDrop { .. } => {
+                if is_cleanup {
+                    span_mirbug!(self, block_data, "coroutine_drop in cleanup block")
+                }
+            }
+            TerminatorKind::Yield { resume, drop, .. } => {
+                if is_cleanup {
+                    span_mirbug!(self, block_data, "yield in cleanup block")
+                }
+                self.assert_iscleanup(block_data, resume, is_cleanup);
+                if let Some(drop) = drop {
+                    self.assert_iscleanup(block_data, drop, is_cleanup);
+                }
+            }
+            TerminatorKind::Unreachable => {}
+            TerminatorKind::Drop { target, unwind, .. }
+            | TerminatorKind::Assert { target, unwind, .. } => {
+                self.assert_iscleanup(block_data, target, is_cleanup);
+                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
+            }
+            TerminatorKind::Call { ref target, unwind, .. } => {
+                if let &Some(target) = target {
+                    self.assert_iscleanup(block_data, target, is_cleanup);
+                }
+                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
+            }
+            TerminatorKind::FalseEdge { real_target, imaginary_target } => {
+                self.assert_iscleanup(block_data, real_target, is_cleanup);
+                self.assert_iscleanup(block_data, imaginary_target, is_cleanup);
+            }
+            TerminatorKind::FalseUnwind { real_target, unwind } => {
+                self.assert_iscleanup(block_data, real_target, is_cleanup);
+                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
+            }
+            TerminatorKind::InlineAsm { ref targets, unwind, .. } => {
+                for &target in targets {
+                    self.assert_iscleanup(block_data, target, is_cleanup);
+                }
+                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
+            }
+        }
+    }
+
+    fn assert_iscleanup(&mut self, ctxt: &dyn fmt::Debug, bb: BasicBlock, iscleanuppad: bool) {
+        if self.body[bb].is_cleanup != iscleanuppad {
+            span_mirbug!(self, ctxt, "cleanuppad mismatch: {:?} should be {:?}", bb, iscleanuppad);
+        }
+    }
+
+    fn assert_iscleanup_unwind(
+        &mut self,
+        ctxt: &dyn fmt::Debug,
+        unwind: UnwindAction,
+        is_cleanup: bool,
+    ) {
+        match unwind {
+            UnwindAction::Cleanup(unwind) => {
+                if is_cleanup {
+                    span_mirbug!(self, ctxt, "unwind on cleanup block")
+                }
+                self.assert_iscleanup(ctxt, unwind, true);
+            }
+            UnwindAction::Continue => {
+                if is_cleanup {
+                    span_mirbug!(self, ctxt, "unwind on cleanup block")
+                }
+            }
+            UnwindAction::Unreachable | UnwindAction::Terminate(_) => (),
+        }
+    }
+
+    fn ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span) {
+        let tcx = self.tcx();
+
+        // Erase the regions from `ty` to get a global type. The
+        // `Sized` bound in no way depends on precise regions, so this
+        // shouldn't affect `is_sized`.
+        let erased_ty = tcx.erase_regions(ty);
+        // FIXME(#132279): Using `Ty::is_sized` causes us to incorrectly handle opaques here.
+        if !erased_ty.is_sized(tcx, self.infcx.typing_env(self.infcx.param_env)) {
+            // in current MIR construction, all non-control-flow rvalue
+            // expressions evaluate through `as_temp` or `into` a return
+            // slot or local, so to find all unsized rvalues it is enough
+            // to check all temps, return slots and locals.
+            if self.reported_errors.replace((ty, span)).is_none() {
+                // While this is located in `nll::typeck` this error is not
+                // an NLL error, it's a required check to prevent creation
+                // of unsized rvalues in a call expression.
+                self.tcx().dcx().emit_err(MoveUnsized { ty, span });
+            }
+        }
+    }
+
+    fn aggregate_field_ty(
+        &mut self,
+        ak: &AggregateKind<'tcx>,
+        field_index: FieldIdx,
+        location: Location,
+    ) -> Result<Ty<'tcx>, FieldAccessError> {
+        let tcx = self.tcx();
+
+        match *ak {
+            AggregateKind::Adt(adt_did, variant_index, args, _, active_field_index) => {
+                let def = tcx.adt_def(adt_did);
+                let variant = &def.variant(variant_index);
+                let adj_field_index = active_field_index.unwrap_or(field_index);
+                if let Some(field) = variant.fields.get(adj_field_index) {
+                    Ok(self.normalize(field.ty(tcx, args), location))
+                } else {
+                    Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
+                }
+            }
+            AggregateKind::Closure(_, args) => {
+                match args.as_closure().upvar_tys().get(field_index.as_usize()) {
+                    Some(ty) => Ok(*ty),
+                    None => Err(FieldAccessError::OutOfRange {
+                        field_count: args.as_closure().upvar_tys().len(),
+                    }),
+                }
+            }
+            AggregateKind::Coroutine(_, args) => {
+                // It doesn't make sense to look at a field beyond the prefix;
+                // these require a variant index, and are not initialized in
+                // aggregate rvalues.
+                match args.as_coroutine().prefix_tys().get(field_index.as_usize()) {
+                    Some(ty) => Ok(*ty),
+                    None => Err(FieldAccessError::OutOfRange {
+                        field_count: args.as_coroutine().prefix_tys().len(),
+                    }),
+                }
+            }
+            AggregateKind::CoroutineClosure(_, args) => {
+                match args.as_coroutine_closure().upvar_tys().get(field_index.as_usize()) {
+                    Some(ty) => Ok(*ty),
+                    None => Err(FieldAccessError::OutOfRange {
+                        field_count: args.as_coroutine_closure().upvar_tys().len(),
+                    }),
+                }
+            }
+            AggregateKind::Array(ty) => Ok(ty),
+            AggregateKind::Tuple | AggregateKind::RawPtr(..) => {
+                unreachable!("This should have been covered in check_rvalues");
+            }
+        }
+    }
+
     /// If this rvalue supports a user-given type annotation, then
     /// extract and return it. This represents the final type of the
     /// rvalue and will be unified with the inferred type.
@@ -2623,30 +2538,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
         tcx.predicates_of(def_id).instantiate(tcx, args)
     }
-
-    #[instrument(skip(self), level = "debug")]
-    fn typeck_mir(&mut self) {
-        self.last_span = self.body.span;
-        debug!(?self.body.span);
-
-        for (local, local_decl) in self.body.local_decls.iter_enumerated() {
-            self.check_local(local, local_decl);
-        }
-
-        for (block, block_data) in self.body.basic_blocks.iter_enumerated() {
-            let mut location = Location { block, statement_index: 0 };
-            for stmt in &block_data.statements {
-                if !stmt.source_info.span.is_dummy() {
-                    self.last_span = stmt.source_info.span;
-                }
-                self.check_stmt(stmt, location);
-                location.statement_index += 1;
-            }
-
-            self.check_terminator(block_data.terminator(), location);
-            self.check_iscleanup(block_data);
-        }
-    }
 }
 
 trait NormalizeLocation: fmt::Debug + Copy {
diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
index 32f689608f8..3710625ac12 100644
--- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
+++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
@@ -63,7 +63,7 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>, set_reuse: &dyn Fn(&mut CguReuseTr
             },
         };
 
-        for attr in tcx.hir().attrs(rustc_hir::CRATE_HIR_ID) {
+        for attr in tcx.hir_attrs(rustc_hir::CRATE_HIR_ID) {
             ams.check_attr(attr);
         }
 
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 87992ce2e11..9cc737d194c 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -475,7 +475,7 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
 ) -> OngoingCodegen<B> {
     let (coordinator_send, coordinator_receive) = channel();
 
-    let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
+    let crate_attrs = tcx.hir_attrs(rustc_hir::CRATE_HIR_ID);
     let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins);
 
     let crate_info = CrateInfo::new(tcx, target_cpu);
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 63f2f8fa3d1..e9c886d28ed 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -876,7 +876,7 @@ impl CrateInfo {
         let linked_symbols =
             crate_types.iter().map(|&c| (c, crate::back::linker::linked_symbols(tcx, c))).collect();
         let local_crate_name = tcx.crate_name(LOCAL_CRATE);
-        let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
+        let crate_attrs = tcx.hir_attrs(rustc_hir::CRATE_HIR_ID);
         let subsystem =
             ast::attr::first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
         let windows_subsystem = subsystem.map(|subsystem| {
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 27b8be1022e..998a4ff727e 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -60,7 +60,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         );
     }
 
-    let attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(did));
+    let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(did));
     let mut codegen_fn_attrs = CodegenFnAttrs::new();
     if tcx.should_inherit_track_caller(did) {
         codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
@@ -75,7 +75,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
 
     // When `no_builtins` is applied at the crate level, we should add the
     // `no-builtins` attribute to each function to ensure it takes effect in LTO.
-    let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
+    let crate_attrs = tcx.hir_attrs(rustc_hir::CRATE_HIR_ID);
     let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins);
     if no_builtins {
         codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_BUILTINS;
diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs
index 607cb2e497d..06ee7075170 100644
--- a/compiler/rustc_const_eval/src/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/check_consts/mod.rs
@@ -81,7 +81,7 @@ pub fn rustc_allow_const_fn_unstable(
     def_id: LocalDefId,
     feature_gate: Symbol,
 ) -> bool {
-    let attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(def_id));
+    let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
 
     find_attr!(attrs, AttributeKind::AllowConstFnUnstable(syms) if syms.contains(&feature_gate))
 }
diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index 828a14e707c..16d70af7e05 100644
--- a/compiler/rustc_driver_impl/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -268,8 +268,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
             let tcx = ex.tcx();
             let f = |annotation: &dyn pprust_hir::PpAnn| {
                 let sm = sess.source_map();
-                let hir_map = tcx.hir();
-                let attrs = |id| hir_map.attrs(id);
+                let attrs = |id| tcx.hir_attrs(id);
                 pprust_hir::print_crate(
                     sm,
                     tcx.hir_root_module(),
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 8dc5d361750..a266286664c 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -185,7 +185,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
 /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
 /// projections that would result in "inheriting lifetimes".
 fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let hir::OpaqueTy { origin, .. } = *tcx.hir().expect_opaque_ty(def_id);
+    let hir::OpaqueTy { origin, .. } = *tcx.hir_expect_opaque_ty(def_id);
 
     // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
     // `async-std` (and `pub async fn` in general).
@@ -785,7 +785,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
             check_type_alias_type_params_are_used(tcx, def_id);
         }
         DefKind::ForeignMod => {
-            let it = tcx.hir().expect_item(def_id);
+            let it = tcx.hir_expect_item(def_id);
             let hir::ItemKind::ForeignMod { abi, items } = it.kind else {
                 return;
             };
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index c193aad2afd..0a37a27b35b 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1031,7 +1031,7 @@ fn report_trait_method_mismatch<'tcx>(
             // When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
             // span points only at the type `Box<Self`>, but we want to cover the whole
             // argument pattern and type.
-            let (sig, body) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
+            let (sig, body) = tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
             let span = tcx
                 .hir_body_param_names(body)
                 .zip(sig.decl.inputs.iter())
@@ -1051,7 +1051,7 @@ fn report_trait_method_mismatch<'tcx>(
                 // Suggestion to change output type. We do not suggest in `async` functions
                 // to avoid complex logic or incorrect output.
                 if let ImplItemKind::Fn(sig, _) =
-                    &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind
+                    &tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).kind
                     && !sig.header.asyncness.is_async()
                 {
                     let msg = "change the output type to match the trait";
@@ -1190,12 +1190,12 @@ fn extract_spans_for_error_reporting<'tcx>(
 ) -> (Span, Option<Span>) {
     let tcx = infcx.tcx;
     let mut impl_args = {
-        let (sig, _) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
+        let (sig, _) = tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
         sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
     };
 
     let trait_args = trait_m.def_id.as_local().map(|def_id| {
-        let (sig, _) = tcx.hir().expect_trait_item(def_id).expect_fn();
+        let (sig, _) = tcx.hir_expect_trait_item(def_id).expect_fn();
         sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
     });
 
@@ -1371,7 +1371,7 @@ fn compare_number_of_generics<'tcx>(
                 spans
             };
             let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() {
-                let trait_item = tcx.hir().expect_trait_item(def_id);
+                let trait_item = tcx.hir_expect_trait_item(def_id);
                 let arg_spans: Vec<Span> = arg_spans(trait_.kind, trait_item.generics);
                 let impl_trait_spans: Vec<Span> = trait_item
                     .generics
@@ -1388,7 +1388,7 @@ fn compare_number_of_generics<'tcx>(
                 (trait_span.map(|s| vec![s]), vec![])
             };
 
-            let impl_item = tcx.hir().expect_impl_item(impl_.def_id.expect_local());
+            let impl_item = tcx.hir_expect_impl_item(impl_.def_id.expect_local());
             let impl_item_impl_trait_spans: Vec<Span> = impl_item
                 .generics
                 .params
@@ -1466,7 +1466,7 @@ fn compare_number_of_method_arguments<'tcx>(
             .def_id
             .as_local()
             .and_then(|def_id| {
-                let (trait_m_sig, _) = &tcx.hir().expect_trait_item(def_id).expect_fn();
+                let (trait_m_sig, _) = &tcx.hir_expect_trait_item(def_id).expect_fn();
                 let pos = trait_number_args.saturating_sub(1);
                 trait_m_sig.decl.inputs.get(pos).map(|arg| {
                     if pos == 0 {
@@ -1478,7 +1478,7 @@ fn compare_number_of_method_arguments<'tcx>(
             })
             .or_else(|| tcx.hir().span_if_local(trait_m.def_id));
 
-        let (impl_m_sig, _) = &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
+        let (impl_m_sig, _) = &tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
         let pos = impl_number_args.saturating_sub(1);
         let impl_span = impl_m_sig
             .decl
@@ -1580,10 +1580,10 @@ fn compare_synthetic_generics<'tcx>(
                     // as another generic argument
                     let new_name = tcx.opt_item_name(trait_def_id)?;
                     let trait_m = trait_m.def_id.as_local()?;
-                    let trait_m = tcx.hir().expect_trait_item(trait_m);
+                    let trait_m = tcx.hir_expect_trait_item(trait_m);
 
                     let impl_m = impl_m.def_id.as_local()?;
-                    let impl_m = tcx.hir().expect_impl_item(impl_m);
+                    let impl_m = tcx.hir_expect_impl_item(impl_m);
 
                     // in case there are no generics, take the spot between the function name
                     // and the opening paren of the argument list
@@ -1613,7 +1613,7 @@ fn compare_synthetic_generics<'tcx>(
                 err.span_label(impl_span, "expected `impl Trait`, found generic parameter");
                 let _: Option<_> = try {
                     let impl_m = impl_m.def_id.as_local()?;
-                    let impl_m = tcx.hir().expect_impl_item(impl_m);
+                    let impl_m = tcx.hir_expect_impl_item(impl_m);
                     let (sig, _) = impl_m.expect_fn();
                     let input_tys = sig.decl.inputs;
 
@@ -1855,7 +1855,7 @@ fn compare_const_predicate_entailment<'tcx>(
         debug!(?impl_ty, ?trait_ty);
 
         // Locate the Span containing just the type of the offending impl
-        let (ty, _) = tcx.hir().expect_impl_item(impl_ct_def_id).expect_const();
+        let (ty, _) = tcx.hir_expect_impl_item(impl_ct_def_id).expect_const();
         cause.span = ty.span;
 
         let mut diag = struct_span_code_err!(
@@ -1868,7 +1868,7 @@ fn compare_const_predicate_entailment<'tcx>(
 
         let trait_c_span = trait_ct.def_id.as_local().map(|trait_ct_def_id| {
             // Add a label to the Span containing just the type of the const
-            let (ty, _) = tcx.hir().expect_trait_item(trait_ct_def_id).expect_const();
+            let (ty, _) = tcx.hir_expect_trait_item(trait_ct_def_id).expect_const();
             ty.span
         });
 
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index a400aaa8142..fd5ffdc2d7a 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -513,7 +513,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
             continue;
         }
 
-        let gat_item_hir = tcx.hir().expect_trait_item(gat_def_id);
+        let gat_item_hir = tcx.hir_expect_trait_item(gat_def_id);
         debug!(?required_bounds);
         let param_env = tcx.param_env(gat_def_id);
 
diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs
index 750c09887a1..464ffa8711a 100644
--- a/compiler/rustc_hir_analysis/src/check_unused.rs
+++ b/compiler/rustc_hir_analysis/src/check_unused.rs
@@ -31,7 +31,7 @@ fn check_unused_traits(tcx: TyCtxt<'_>, (): ()) {
         if used_trait_imports.contains(&id) {
             continue;
         }
-        let item = tcx.hir().expect_item(id);
+        let item = tcx.hir_expect_item(id);
         if item.span.is_dummy() {
             continue;
         }
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index cee2f487639..c918abe4c07 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -82,7 +82,7 @@ fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaran
         _ => {}
     }
 
-    let impl_ = tcx.hir().expect_item(impl_did).expect_impl();
+    let impl_ = tcx.hir_expect_item(impl_did).expect_impl();
 
     Err(tcx.dcx().emit_err(errors::DropImplOnWrongItem { span: impl_.self_ty.span }))
 }
@@ -109,7 +109,7 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran
     match type_allowed_to_implement_copy(tcx, param_env, self_type, cause, impl_header.safety) {
         Ok(()) => Ok(()),
         Err(CopyImplementationError::InfringingFields(fields)) => {
-            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
             Err(infringing_fields_error(
                 tcx,
                 fields.into_iter().map(|(field, ty, reason)| (tcx.def_span(field.did), ty, reason)),
@@ -119,15 +119,15 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran
             ))
         }
         Err(CopyImplementationError::NotAnAdt) => {
-            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
             Err(tcx.dcx().emit_err(errors::CopyImplOnNonAdt { span }))
         }
         Err(CopyImplementationError::HasDestructor) => {
-            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
             Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span }))
         }
         Err(CopyImplementationError::HasUnsafeFields) => {
-            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
             Err(tcx
                 .dcx()
                 .span_delayed_bug(span, format!("cannot implement `Copy` for `{}`", self_type)))
@@ -157,7 +157,7 @@ fn visit_implementation_of_const_param_ty(
     match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, kind, cause) {
         Ok(()) => Ok(()),
         Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
-            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
             Err(infringing_fields_error(
                 tcx,
                 fields.into_iter().map(|(field, ty, reason)| (tcx.def_span(field.did), ty, reason)),
@@ -167,11 +167,11 @@ fn visit_implementation_of_const_param_ty(
             ))
         }
         Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => {
-            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
             Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnNonAdt { span }))
         }
         Err(ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(infringing_tys)) => {
-            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
             Err(infringing_fields_error(
                 tcx,
                 infringing_tys.into_iter().map(|(ty, reason)| (span, ty, reason)),
@@ -181,7 +181,7 @@ fn visit_implementation_of_const_param_ty(
             ))
         }
         Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {
-            let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
+            let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
             Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnUnsized { span }))
         }
     }
@@ -526,7 +526,7 @@ pub(crate) fn coerce_unsized_info<'tcx>(
                     note: true,
                 }));
             } else if diff_fields.len() > 1 {
-                let item = tcx.hir().expect_item(impl_did);
+                let item = tcx.hir_expect_item(impl_did);
                 let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(t), .. }) = &item.kind {
                     t.path.span
                 } else {
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index dbf7a7378f5..0b7fc44460e 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -376,7 +376,7 @@ fn emit_orphan_check_error<'tcx>(
 ) -> ErrorGuaranteed {
     match err {
         traits::OrphanCheckErr::NonLocalInputType(tys) => {
-            let item = tcx.hir().expect_item(impl_def_id);
+            let item = tcx.hir_expect_item(impl_def_id);
             let impl_ = item.expect_impl();
             let hir_trait_ref = impl_.of_trait.as_ref().unwrap();
 
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 49523912b14..cfb6cf8a287 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -469,8 +469,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
                 hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
                     let item = self
                         .tcx
-                        .hir()
-                        .expect_item(self.tcx.hir_get_parent_item(self.hir_id()).def_id);
+                        .hir_expect_item(self.tcx.hir_get_parent_item(self.hir_id()).def_id);
                     match &item.kind {
                         hir::ItemKind::Enum(_, generics)
                         | hir::ItemKind::Struct(_, generics)
@@ -1143,7 +1142,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
 }
 
 fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
-    let item = tcx.hir().expect_item(def_id);
+    let item = tcx.hir_expect_item(def_id);
 
     let (is_alias, is_auto, safety, items) = match item.kind {
         hir::ItemKind::Trait(is_auto, safety, .., items) => {
@@ -1342,7 +1341,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
         ),
 
         ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(sig, _, _), .. }) => {
-            let abi = tcx.hir().get_foreign_abi(hir_id);
+            let abi = tcx.hir_get_foreign_abi(hir_id);
             compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety())
         }
 
@@ -1597,7 +1596,7 @@ pub fn suggest_impl_trait<'tcx>(
 
 fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTraitHeader<'_>> {
     let icx = ItemCtxt::new(tcx, def_id);
-    let item = tcx.hir().expect_item(def_id);
+    let item = tcx.hir_expect_item(def_id);
     let impl_ = item.expect_impl();
     impl_.of_trait.as_ref().map(|ast_trait_ref| {
         let selfty = tcx.type_of(def_id).instantiate_identity();
diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs
index 4debd3977f5..7cbd31de6ba 100644
--- a/compiler/rustc_hir_analysis/src/collect/dump.rs
+++ b/compiler/rustc_hir_analysis/src/collect/dump.rs
@@ -13,7 +13,7 @@ pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) {
     for id in tcx.hir_crate_items(()).opaques() {
         if let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. }
         | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } =
-            tcx.hir().expect_opaque_ty(id).origin
+            tcx.hir_expect_opaque_ty(id).origin
             && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id)
             && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
         {
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 6936544838c..16caa4f6874 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -480,5 +480,5 @@ pub(crate) fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) ->
             }
         }
     }
-    HasTait.visit_ty_unambig(tcx.hir().expect_item(def_id).expect_ty_alias().0).is_break()
+    HasTait.visit_ty_unambig(tcx.hir_expect_item(def_id).expect_ty_alias().0).is_break()
 }
diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs
index 4dbdfa3d85a..78b20f9897c 100644
--- a/compiler/rustc_hir_analysis/src/delegation.rs
+++ b/compiler/rustc_hir_analysis/src/delegation.rs
@@ -404,11 +404,16 @@ fn check_constraints<'tcx>(
     };
 
     if let Some(local_sig_id) = sig_id.as_local()
-        && tcx.hir().opt_delegation_sig_id(local_sig_id).is_some()
+        && tcx.hir_opt_delegation_sig_id(local_sig_id).is_some()
     {
         emit("recursive delegation is not supported yet");
     }
 
+    if tcx.fn_sig(sig_id).skip_binder().skip_binder().c_variadic {
+        // See issue #127443 for explanation.
+        emit("delegation to C-variadic functions is not allowed");
+    }
+
     ret
 }
 
@@ -416,7 +421,7 @@ pub(crate) fn inherit_sig_for_delegation_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
 ) -> &'tcx [Ty<'tcx>] {
-    let sig_id = tcx.hir().opt_delegation_sig_id(def_id).unwrap();
+    let sig_id = tcx.hir_opt_delegation_sig_id(def_id).unwrap();
     let caller_sig = tcx.fn_sig(sig_id);
     if let Err(err) = check_constraints(tcx, def_id, sig_id) {
         let sig_len = caller_sig.instantiate_identity().skip_binder().inputs().len() + 1;
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 5f91f1d7b3e..8fff6eb9f6e 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -370,7 +370,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     #[instrument(level = "debug", skip(self), ret)]
     pub fn lower_resolved_lifetime(&self, resolved: rbv::ResolvedArg) -> ty::Region<'tcx> {
         let tcx = self.tcx();
-        let lifetime_name = |def_id| tcx.hir().name(tcx.local_def_id_to_hir_id(def_id));
+        let lifetime_name = |def_id| tcx.hir_name(tcx.local_def_id_to_hir_id(def_id));
 
         match resolved {
             rbv::ResolvedArg::StaticLifetime => tcx.lifetimes.re_static,
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 5e00161f693..2a24d626ac3 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -799,7 +799,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         // Emit a different diagnostic for local variables, as they are not
                         // type definitions themselves, but rather variables *of* that type.
                         Res::Local(hir_id) => {
-                            err.arg("local_name", self.tcx.hir().name(hir_id));
+                            err.arg("local_name", self.tcx.hir_name(hir_id));
                             Some(fluent_generated::hir_typeck_invalid_local)
                         }
                         Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => {
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 7e4026db738..7c6bb495be3 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -298,7 +298,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Combine the diverging and has_error flags.
         self.diverges.set(self.diverges.get() | old_diverges);
 
-        debug!("type of {} is...", self.tcx.hir().node_to_string(expr.hir_id));
+        debug!("type of {} is...", self.tcx.hir_id_to_string(expr.hir_id));
         debug!("... {:?}, expected is {:?}", ty, expected);
 
         ty
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 9ff7eeb2368..63e4a8fb44b 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -1235,7 +1235,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                 self.cx.tainted_by_errors()?;
                 bug!(
                     "no type for node {} in mem_categorization",
-                    self.cx.tcx().hir().node_to_string(id)
+                    self.cx.tcx().hir_id_to_string(id)
                 );
             }
         }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index da2d6579423..c82f7a91168 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -140,7 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub(crate) fn local_ty(&self, span: Span, nid: HirId) -> Ty<'tcx> {
         self.locals.borrow().get(&nid).cloned().unwrap_or_else(|| {
-            span_bug!(span, "no type for local variable {}", self.tcx.hir().node_to_string(nid))
+            span_bug!(span, "no type for local variable {}", self.tcx.hir_id_to_string(nid))
         })
     }
 
@@ -559,11 +559,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Some(&t) => t,
             None if let Some(e) = self.tainted_by_errors() => Ty::new_error(self.tcx, e),
             None => {
-                bug!(
-                    "no type for node {} in fcx {}",
-                    self.tcx.hir().node_to_string(id),
-                    self.tag()
-                );
+                bug!("no type for node {} in fcx {}", self.tcx.hir_id_to_string(id), self.tag());
             }
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 35a3491f7c0..37aaaed5477 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -613,7 +613,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     .iter()
                     .take(4)
                     .map(|(var_hir_id, upvar)| {
-                        let var_name = self.tcx.hir().name(*var_hir_id).to_string();
+                        let var_name = self.tcx.hir_name(*var_hir_id).to_string();
                         let msg = format!("`{var_name}` captured here");
                         (upvar.span, msg)
                     })
diff --git a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
index 69d7a6c97cb..72f8793d783 100644
--- a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
@@ -363,7 +363,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let import_items: Vec<_> = applicable_trait
             .import_ids
             .iter()
-            .map(|&import_id| self.tcx.hir().expect_item(import_id))
+            .map(|&import_id| self.tcx.hir_expect_item(import_id))
             .collect();
 
         // Find an identifier with which this trait was imported (note that `_` doesn't count).
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index f87e5b5202a..ee01d78965d 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -2344,7 +2344,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             return false;
         };
         let hir_id = self.fcx.tcx.local_def_id_to_hir_id(local_def_id);
-        let attrs = self.fcx.tcx.hir().attrs(hir_id);
+        let attrs = self.fcx.tcx.hir_attrs(hir_id);
         for attr in attrs {
             if sym::doc == attr.name_or_empty() {
             } else if sym::rustc_confusables == attr.name_or_empty() {
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index cb1e89fb9e5..1a1540f505d 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -791,7 +791,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             && let Ok(pick) = self.lookup_probe_for_diagnostic(
                 item_name,
                 Ty::new_ref(tcx, ty::Region::new_error_misc(tcx), ty, ptr_mutbl),
-                self.tcx.hir().expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id)),
+                self.tcx.hir_expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id)),
                 ProbeScope::TraitsInScope,
                 None,
             )
@@ -834,8 +834,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         if let SelfSource::MethodCall(rcvr_expr) = source {
             self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
-                let call_expr =
-                    self.tcx.hir().expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id));
+                let call_expr = self.tcx.hir_expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id));
                 let probe = self.lookup_probe_for_diagnostic(
                     item_name,
                     output_ty,
@@ -2373,7 +2372,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         Applicability::MachineApplicable,
                     );
                 } else {
-                    let call_expr = tcx.hir().expect_expr(tcx.parent_hir_id(expr.hir_id));
+                    let call_expr = tcx.hir_expect_expr(tcx.parent_hir_id(expr.hir_id));
 
                     if let Some(span) = call_expr.span.trim_start(item_name.span) {
                         err.span_suggestion(
@@ -2680,7 +2679,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 mod_id,
                 expr.hir_id,
             ) {
-                let call_expr = self.tcx.hir().expect_expr(self.tcx.parent_hir_id(expr.hir_id));
+                let call_expr = self.tcx.hir_expect_expr(self.tcx.parent_hir_id(expr.hir_id));
 
                 let lang_items = self.tcx.lang_items();
                 let never_mention_traits = [
@@ -2757,7 +2756,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let SelfSource::MethodCall(expr) = source else {
             return;
         };
-        let call_expr = tcx.hir().expect_expr(tcx.parent_hir_id(expr.hir_id));
+        let call_expr = tcx.hir_expect_expr(tcx.parent_hir_id(expr.hir_id));
 
         let ty::Adt(kind, args) = actual.kind() else {
             return;
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index f570d0d8a0d..37f3786c00a 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -781,7 +781,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 PlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
                 base => bug!("Expected upvar, found={:?}", base),
             };
-            let var_ident = self.tcx.hir().ident(var_hir_id);
+            let var_ident = self.tcx.hir_ident(var_hir_id);
 
             let Some(min_cap_list) = root_var_min_capture_list.get_mut(&var_hir_id) else {
                 let mutability = self.determine_capture_mutability(&typeck_results, &place);
@@ -988,13 +988,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 UpvarMigrationInfo::CapturingPrecise { source_expr: Some(capture_expr_id), var_name: captured_name } => {
                                     let cause_span = self.tcx.hir().span(*capture_expr_id);
                                     lint.span_label(cause_span, format!("in Rust 2018, this closure captures all of `{}`, but in Rust 2021, it will only capture `{}`",
-                                        self.tcx.hir().name(*var_hir_id),
+                                        self.tcx.hir_name(*var_hir_id),
                                         captured_name,
                                     ));
                                 }
                                 UpvarMigrationInfo::CapturingNothing { use_span } => {
                                     lint.span_label(*use_span, format!("in Rust 2018, this causes the closure to capture `{}`, but in Rust 2021, it has no effect",
-                                        self.tcx.hir().name(*var_hir_id),
+                                        self.tcx.hir_name(*var_hir_id),
                                     ));
                                 }
 
@@ -1009,13 +1009,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 match &lint_note.captures_info {
                                     UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => {
                                         lint.span_label(drop_location_span, format!("in Rust 2018, `{}` is dropped here, but in Rust 2021, only `{}` will be dropped here as part of the closure",
-                                            self.tcx.hir().name(*var_hir_id),
+                                            self.tcx.hir_name(*var_hir_id),
                                             captured_name,
                                         ));
                                     }
                                     UpvarMigrationInfo::CapturingNothing { use_span: _ } => {
                                         lint.span_label(drop_location_span, format!("in Rust 2018, `{v}` is dropped here along with the closure, but in Rust 2021 `{v}` is not part of the closure",
-                                            v = self.tcx.hir().name(*var_hir_id),
+                                            v = self.tcx.hir_name(*var_hir_id),
                                         ));
                                     }
                                 }
@@ -1026,7 +1026,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 // not capturing something anymore cannot cause a trait to fail to be implemented:
                                 match &lint_note.captures_info {
                                     UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => {
-                                        let var_name = self.tcx.hir().name(*var_hir_id);
+                                        let var_name = self.tcx.hir_name(*var_hir_id);
                                         lint.span_label(closure_head_span, format!("\
                                         in Rust 2018, this closure implements {missing_trait} \
                                         as `{var_name}` implements {missing_trait}, but in Rust 2021, \
@@ -2300,7 +2300,7 @@ fn construct_capture_info_string<'tcx>(
 }
 
 fn var_name(tcx: TyCtxt<'_>, var_hir_id: HirId) -> Symbol {
-    tcx.hir().name(var_hir_id)
+    tcx.hir_name(var_hir_id)
 }
 
 #[instrument(level = "debug", skip(tcx))]
diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs
index 8f2ca6babea..1b2056f541f 100644
--- a/compiler/rustc_incremental/src/assert_dep_graph.rs
+++ b/compiler/rustc_incremental/src/assert_dep_graph.rs
@@ -123,7 +123,7 @@ impl<'tcx> IfThisChanged<'tcx> {
     fn process_attrs(&mut self, def_id: LocalDefId) {
         let def_path_hash = self.tcx.def_path_hash(def_id.to_def_id());
         let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
-        let attrs = self.tcx.hir().attrs(hir_id);
+        let attrs = self.tcx.hir_attrs(hir_id);
         for attr in attrs {
             if attr.has_name(sym::rustc_if_this_changed) {
                 let dep_node_interned = self.argument(attr);
diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs
index 00600abb5f1..a2c1f1dbeda 100644
--- a/compiler/rustc_interface/src/proc_macro_decls.rs
+++ b/compiler/rustc_interface/src/proc_macro_decls.rs
@@ -8,7 +8,7 @@ fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> {
     let mut decls = None;
 
     for id in tcx.hir_free_items() {
-        let attrs = tcx.hir().attrs(id.hir_id());
+        let attrs = tcx.hir_attrs(id.hir_id());
         if attr::contains_name(attrs, sym::rustc_proc_macro_decls) {
             decls = Some(id.owner_id.def_id);
         }
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index f7be37dc4a2..918a42f3047 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -419,7 +419,7 @@ impl MissingDoc {
             return;
         }
 
-        let attrs = cx.tcx.hir().attrs(cx.tcx.local_def_id_to_hir_id(def_id));
+        let attrs = cx.tcx.hir_attrs(cx.tcx.local_def_id_to_hir_id(def_id));
         let has_doc = attrs.iter().any(has_doc);
         if !has_doc {
             cx.emit_span_lint(
@@ -997,7 +997,7 @@ declare_lint_pass!(InvalidNoMangleItems => [NO_MANGLE_CONST_ITEMS, NO_MANGLE_GEN
 
 impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
     fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
-        let attrs = cx.tcx.hir().attrs(it.hir_id());
+        let attrs = cx.tcx.hir_attrs(it.hir_id());
         let check_no_mangle_on_generic_fn = |no_mangle_attr: &hir::Attribute,
                                              impl_generics: Option<&hir::Generics<'_>>,
                                              generics: &hir::Generics<'_>,
@@ -1050,7 +1050,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
                 for it in *items {
                     if let hir::AssocItemKind::Fn { .. } = it.kind {
                         if let Some(no_mangle_attr) =
-                            attr::find_by_name(cx.tcx.hir().attrs(it.id.hir_id()), sym::no_mangle)
+                            attr::find_by_name(cx.tcx.hir_attrs(it.id.hir_id()), sym::no_mangle)
                         {
                             check_no_mangle_on_generic_fn(
                                 no_mangle_attr,
diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs
index 9ca148e1f25..4c2b82a9a23 100644
--- a/compiler/rustc_lint/src/expect.rs
+++ b/compiler/rustc_lint/src/expect.rs
@@ -38,7 +38,7 @@ fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option<Symbol>) {
             }
             LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => {
                 // We are an `eval_always` query, so looking at the attribute's `AttrId` is ok.
-                let attr_id = tcx.hir().attrs(hir_id)[attr_index as usize].id();
+                let attr_id = tcx.hir_attrs(hir_id)[attr_index as usize].id();
 
                 (attr_id, lint_index)
             }
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index 23d6efa0508..852bb01c096 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -48,7 +48,7 @@ impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
     where
         F: FnOnce(&mut Self),
     {
-        let attrs = self.context.tcx.hir().attrs(id);
+        let attrs = self.context.tcx.hir_attrs(id);
         let prev = self.context.last_node_with_lint_attrs;
         self.context.last_node_with_lint_attrs = id;
         debug!("late context: enter_attrs({:?})", attrs);
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 4ede9b44087..aa6eef906ea 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -152,7 +152,7 @@ fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LintId> {
 #[instrument(level = "trace", skip(tcx), ret)]
 fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLevelMap {
     let store = unerased_lint_store(tcx.sess);
-    let attrs = tcx.hir_attrs(owner);
+    let attrs = tcx.hir_attr_map(owner);
 
     let mut levels = LintLevelsBuilder {
         sess: tcx.sess,
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 49f9ad39780..722779d3268 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -342,8 +342,8 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
         let crate_ident = if let Some(name) = &cx.tcx.sess.opts.crate_name {
             Some(Ident::from_str(name))
         } else {
-            ast::attr::find_by_name(cx.tcx.hir().attrs(hir::CRATE_HIR_ID), sym::crate_name)
-                .and_then(|attr| {
+            ast::attr::find_by_name(cx.tcx.hir_attrs(hir::CRATE_HIR_ID), sym::crate_name).and_then(
+                |attr| {
                     if let Attribute::Unparsed(n) = attr
                         && let AttrItem { args: AttrArgs::Eq { eq_span: _, expr: lit }, .. } =
                             n.as_ref()
@@ -371,7 +371,8 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
                     } else {
                         None
                     }
-                })
+                },
+            )
         };
 
         if let Some(ident) = &crate_ident {
@@ -500,7 +501,7 @@ impl NonUpperCaseGlobals {
 
 impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
     fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
-        let attrs = cx.tcx.hir().attrs(it.hir_id());
+        let attrs = cx.tcx.hir_attrs(it.hir_id());
         match it.kind {
             hir::ItemKind::Static(..) if !ast::attr::contains_name(attrs, sym::no_mangle) => {
                 NonUpperCaseGlobals::check_upper_case(cx, "static variable", &it.ident);
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index fcadbfc3c4a..6f3c32af5ef 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1589,7 +1589,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
 impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations {
     fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, it: &hir::ForeignItem<'tcx>) {
         let mut vis = ImproperCTypesVisitor { cx, mode: CItemKind::Declaration };
-        let abi = cx.tcx.hir().get_foreign_abi(it.hir_id());
+        let abi = cx.tcx.hir_get_foreign_abi(it.hir_id());
 
         match it.kind {
             hir::ForeignItemKind::Fn(sig, _, _) => {
diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs
index 582c2215d92..be31aa629c8 100644
--- a/compiler/rustc_metadata/src/dependency_format.rs
+++ b/compiler/rustc_metadata/src/dependency_format.rs
@@ -84,7 +84,7 @@ pub(crate) fn calculate(tcx: TyCtxt<'_>) -> Dependencies {
 fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
     let sess = &tcx.sess;
 
-    if !sess.opts.output_types.should_codegen() {
+    if !sess.opts.output_types.should_link() {
         return IndexVec::new();
     }
 
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 88a88847e6b..57c941976e4 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1357,8 +1357,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             features: &tcx.features(),
         };
         let attr_iter = tcx
-            .hir()
-            .attrs(tcx.local_def_id_to_hir_id(def_id))
+            .hir_attrs(tcx.local_def_id_to_hir_id(def_id))
             .iter()
             .filter(|attr| analyze_attr(*attr, &mut state));
 
@@ -1839,7 +1838,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     fn encode_info_for_macro(&mut self, def_id: LocalDefId) {
         let tcx = self.tcx;
 
-        let hir::ItemKind::Macro(macro_def, _) = tcx.hir().expect_item(def_id).kind else { bug!() };
+        let hir::ItemKind::Macro(macro_def, _) = tcx.hir_expect_item(def_id).kind else { bug!() };
         self.tables.is_macro_rules.set(def_id.local_def_index, macro_def.macro_rules);
         record!(self.tables.macro_definition[def_id.to_def_id()] <- &*macro_def.body);
     }
@@ -1918,11 +1917,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             for &proc_macro in &tcx.resolutions(()).proc_macros {
                 let id = proc_macro;
                 let proc_macro = tcx.local_def_id_to_hir_id(proc_macro);
-                let mut name = hir.name(proc_macro);
+                let mut name = tcx.hir_name(proc_macro);
                 let span = hir.span(proc_macro);
                 // Proc-macros may have attributes like `#[allow_internal_unstable]`,
                 // so downstream crates need access to them.
-                let attrs = hir.attrs(proc_macro);
+                let attrs = tcx.hir_attrs(proc_macro);
                 let macro_kind = if ast::attr::contains_name(attrs, sym::proc_macro) {
                     MacroKind::Bang
                 } else if ast::attr::contains_name(attrs, sym::proc_macro_attribute) {
diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs
index c85af81ee25..73c0af84a9f 100644
--- a/compiler/rustc_middle/src/hir/map.rs
+++ b/compiler/rustc_middle/src/hir/map.rs
@@ -275,7 +275,7 @@ impl<'tcx> TyCtxt<'tcx> {
             span_bug!(
                 self.hir().span(hir_id),
                 "body_owned_by: {} has no associated body",
-                self.hir().node_to_string(hir_id)
+                self.hir_id_to_string(hir_id)
             );
         })
     }
@@ -374,7 +374,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// invoking `krate.attrs` because it registers a tighter
     /// dep-graph access.
     pub fn hir_krate_attrs(self) -> &'tcx [Attribute] {
-        self.hir().attrs(CRATE_HIR_ID)
+        self.hir_attrs(CRATE_HIR_ID)
     }
 
     pub fn hir_rustc_coherence_is_core(self) -> bool {
@@ -674,104 +674,178 @@ impl<'tcx> TyCtxt<'tcx> {
             }
         }
     }
-}
 
-impl<'hir> Map<'hir> {
-    pub fn get_foreign_abi(self, hir_id: HirId) -> ExternAbi {
-        let parent = self.tcx.hir_get_parent_item(hir_id);
+    /// Get a representation of this `id` for debugging purposes.
+    /// NOTE: Do NOT use this in diagnostics!
+    pub fn hir_id_to_string(self, id: HirId) -> String {
+        let path_str = |def_id: LocalDefId| self.def_path_str(def_id);
+
+        let span_str = || {
+            self.sess.source_map().span_to_snippet(Map { tcx: self }.span(id)).unwrap_or_default()
+        };
+        let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str());
+
+        match self.hir_node(id) {
+            Node::Item(item) => {
+                let item_str = match item.kind {
+                    ItemKind::ExternCrate(..) => "extern crate",
+                    ItemKind::Use(..) => "use",
+                    ItemKind::Static(..) => "static",
+                    ItemKind::Const(..) => "const",
+                    ItemKind::Fn { .. } => "fn",
+                    ItemKind::Macro(..) => "macro",
+                    ItemKind::Mod(..) => "mod",
+                    ItemKind::ForeignMod { .. } => "foreign mod",
+                    ItemKind::GlobalAsm { .. } => "global asm",
+                    ItemKind::TyAlias(..) => "ty",
+                    ItemKind::Enum(..) => "enum",
+                    ItemKind::Struct(..) => "struct",
+                    ItemKind::Union(..) => "union",
+                    ItemKind::Trait(..) => "trait",
+                    ItemKind::TraitAlias(..) => "trait alias",
+                    ItemKind::Impl { .. } => "impl",
+                };
+                format!("{id} ({item_str} {})", path_str(item.owner_id.def_id))
+            }
+            Node::ForeignItem(item) => {
+                format!("{id} (foreign item {})", path_str(item.owner_id.def_id))
+            }
+            Node::ImplItem(ii) => {
+                let kind = match ii.kind {
+                    ImplItemKind::Const(..) => "associated constant",
+                    ImplItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
+                        ImplicitSelfKind::None => "associated function",
+                        _ => "method",
+                    },
+                    ImplItemKind::Type(_) => "associated type",
+                };
+                format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id))
+            }
+            Node::TraitItem(ti) => {
+                let kind = match ti.kind {
+                    TraitItemKind::Const(..) => "associated constant",
+                    TraitItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
+                        ImplicitSelfKind::None => "associated function",
+                        _ => "trait method",
+                    },
+                    TraitItemKind::Type(..) => "associated type",
+                };
+
+                format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id))
+            }
+            Node::Variant(variant) => {
+                format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id))
+            }
+            Node::Field(field) => {
+                format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
+            }
+            Node::AnonConst(_) => node_str("const"),
+            Node::ConstBlock(_) => node_str("const"),
+            Node::ConstArg(_) => node_str("const"),
+            Node::Expr(_) => node_str("expr"),
+            Node::ExprField(_) => node_str("expr field"),
+            Node::Stmt(_) => node_str("stmt"),
+            Node::PathSegment(_) => node_str("path segment"),
+            Node::Ty(_) => node_str("type"),
+            Node::AssocItemConstraint(_) => node_str("assoc item constraint"),
+            Node::TraitRef(_) => node_str("trait ref"),
+            Node::OpaqueTy(_) => node_str("opaque type"),
+            Node::Pat(_) => node_str("pat"),
+            Node::TyPat(_) => node_str("pat ty"),
+            Node::PatField(_) => node_str("pattern field"),
+            Node::PatExpr(_) => node_str("pattern literal"),
+            Node::Param(_) => node_str("param"),
+            Node::Arm(_) => node_str("arm"),
+            Node::Block(_) => node_str("block"),
+            Node::Infer(_) => node_str("infer"),
+            Node::LetStmt(_) => node_str("local"),
+            Node::Ctor(ctor) => format!(
+                "{id} (ctor {})",
+                ctor.ctor_def_id().map_or("<missing path>".into(), |def_id| path_str(def_id)),
+            ),
+            Node::Lifetime(_) => node_str("lifetime"),
+            Node::GenericParam(param) => {
+                format!("{id} (generic_param {})", path_str(param.def_id))
+            }
+            Node::Crate(..) => String::from("(root_crate)"),
+            Node::WherePredicate(_) => node_str("where predicate"),
+            Node::Synthetic => unreachable!(),
+            Node::Err(_) => node_str("error"),
+            Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"),
+        }
+    }
+
+    pub fn hir_get_foreign_abi(self, hir_id: HirId) -> ExternAbi {
+        let parent = self.hir_get_parent_item(hir_id);
         if let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) =
-            self.tcx.hir_owner_node(parent)
+            self.hir_owner_node(parent)
         {
             return *abi;
         }
         bug!(
             "expected foreign mod or inlined parent, found {}",
-            self.node_to_string(HirId::make_owner(parent.def_id))
+            self.hir_id_to_string(HirId::make_owner(parent.def_id))
         )
     }
 
-    pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> {
-        match self.tcx.expect_hir_owner_node(id) {
+    pub fn hir_expect_item(self, id: LocalDefId) -> &'tcx Item<'tcx> {
+        match self.expect_hir_owner_node(id) {
             OwnerNode::Item(item) => item,
-            _ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))),
+            _ => bug!("expected item, found {}", self.hir_id_to_string(HirId::make_owner(id))),
         }
     }
 
-    pub fn expect_impl_item(self, id: LocalDefId) -> &'hir ImplItem<'hir> {
-        match self.tcx.expect_hir_owner_node(id) {
+    pub fn hir_expect_impl_item(self, id: LocalDefId) -> &'tcx ImplItem<'tcx> {
+        match self.expect_hir_owner_node(id) {
             OwnerNode::ImplItem(item) => item,
-            _ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))),
+            _ => bug!("expected impl item, found {}", self.hir_id_to_string(HirId::make_owner(id))),
         }
     }
 
-    pub fn expect_trait_item(self, id: LocalDefId) -> &'hir TraitItem<'hir> {
-        match self.tcx.expect_hir_owner_node(id) {
+    pub fn hir_expect_trait_item(self, id: LocalDefId) -> &'tcx TraitItem<'tcx> {
+        match self.expect_hir_owner_node(id) {
             OwnerNode::TraitItem(item) => item,
-            _ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))),
-        }
-    }
-
-    pub fn get_fn_output(self, def_id: LocalDefId) -> Option<&'hir FnRetTy<'hir>> {
-        Some(&self.tcx.opt_hir_owner_node(def_id)?.fn_decl()?.output)
-    }
-
-    pub fn expect_variant(self, id: HirId) -> &'hir Variant<'hir> {
-        match self.tcx.hir_node(id) {
-            Node::Variant(variant) => variant,
-            _ => bug!("expected variant, found {}", self.node_to_string(id)),
-        }
-    }
-
-    pub fn expect_field(self, id: HirId) -> &'hir FieldDef<'hir> {
-        match self.tcx.hir_node(id) {
-            Node::Field(field) => field,
-            _ => bug!("expected field, found {}", self.node_to_string(id)),
-        }
-    }
-
-    pub fn expect_foreign_item(self, id: OwnerId) -> &'hir ForeignItem<'hir> {
-        match self.tcx.hir_owner_node(id) {
-            OwnerNode::ForeignItem(item) => item,
             _ => {
-                bug!(
-                    "expected foreign item, found {}",
-                    self.node_to_string(HirId::make_owner(id.def_id))
-                )
+                bug!("expected trait item, found {}", self.hir_id_to_string(HirId::make_owner(id)))
             }
         }
     }
 
+    pub fn hir_get_fn_output(self, def_id: LocalDefId) -> Option<&'tcx FnRetTy<'tcx>> {
+        Some(&self.opt_hir_owner_node(def_id)?.fn_decl()?.output)
+    }
+
     #[track_caller]
-    pub fn expect_opaque_ty(self, id: LocalDefId) -> &'hir OpaqueTy<'hir> {
-        match self.tcx.hir_node_by_def_id(id) {
+    pub fn hir_expect_opaque_ty(self, id: LocalDefId) -> &'tcx OpaqueTy<'tcx> {
+        match self.hir_node_by_def_id(id) {
             Node::OpaqueTy(opaq) => opaq,
             _ => {
                 bug!(
                     "expected opaque type definition, found {}",
-                    self.node_to_string(self.tcx.local_def_id_to_hir_id(id))
+                    self.hir_id_to_string(self.local_def_id_to_hir_id(id))
                 )
             }
         }
     }
 
-    pub fn expect_expr(self, id: HirId) -> &'hir Expr<'hir> {
-        match self.tcx.hir_node(id) {
+    pub fn hir_expect_expr(self, id: HirId) -> &'tcx Expr<'tcx> {
+        match self.hir_node(id) {
             Node::Expr(expr) => expr,
-            _ => bug!("expected expr, found {}", self.node_to_string(id)),
+            _ => bug!("expected expr, found {}", self.hir_id_to_string(id)),
         }
     }
 
-    pub fn opt_delegation_sig_id(self, def_id: LocalDefId) -> Option<DefId> {
-        self.tcx.opt_hir_owner_node(def_id)?.fn_decl()?.opt_delegation_sig_id()
+    pub fn hir_opt_delegation_sig_id(self, def_id: LocalDefId) -> Option<DefId> {
+        self.opt_hir_owner_node(def_id)?.fn_decl()?.opt_delegation_sig_id()
     }
 
     #[inline]
-    fn opt_ident(self, id: HirId) -> Option<Ident> {
-        match self.tcx.hir_node(id) {
+    fn hir_opt_ident(self, id: HirId) -> Option<Ident> {
+        match self.hir_node(id) {
             Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident),
             // A `Ctor` doesn't have an identifier itself, but its parent
             // struct/variant does. Compare with `hir::Map::span`.
-            Node::Ctor(..) => match self.tcx.parent_hir_node(id) {
+            Node::Ctor(..) => match self.parent_hir_node(id) {
                 Node::Item(item) => Some(item.ident),
                 Node::Variant(variant) => Some(variant.ident),
                 _ => unreachable!(),
@@ -781,30 +855,32 @@ impl<'hir> Map<'hir> {
     }
 
     #[inline]
-    pub(super) fn opt_ident_span(self, id: HirId) -> Option<Span> {
-        self.opt_ident(id).map(|ident| ident.span)
+    pub(super) fn hir_opt_ident_span(self, id: HirId) -> Option<Span> {
+        self.hir_opt_ident(id).map(|ident| ident.span)
     }
 
     #[inline]
-    pub fn ident(self, id: HirId) -> Ident {
-        self.opt_ident(id).unwrap()
+    pub fn hir_ident(self, id: HirId) -> Ident {
+        self.hir_opt_ident(id).unwrap()
     }
 
     #[inline]
-    pub fn opt_name(self, id: HirId) -> Option<Symbol> {
-        self.opt_ident(id).map(|ident| ident.name)
+    pub fn hir_opt_name(self, id: HirId) -> Option<Symbol> {
+        self.hir_opt_ident(id).map(|ident| ident.name)
     }
 
-    pub fn name(self, id: HirId) -> Symbol {
-        self.opt_name(id).unwrap_or_else(|| bug!("no name for {}", self.node_to_string(id)))
+    pub fn hir_name(self, id: HirId) -> Symbol {
+        self.hir_opt_name(id).unwrap_or_else(|| bug!("no name for {}", self.hir_id_to_string(id)))
     }
 
     /// Given a node ID, gets a list of attributes associated with the AST
     /// corresponding to the node-ID.
-    pub fn attrs(self, id: HirId) -> &'hir [Attribute] {
-        self.tcx.hir_attrs(id.owner).get(id.local_id)
+    pub fn hir_attrs(self, id: HirId) -> &'tcx [Attribute] {
+        self.hir_attr_map(id.owner).get(id.local_id)
     }
+}
 
+impl<'hir> Map<'hir> {
     /// Gets the span of the definition of the specified HIR node.
     /// This is used by `tcx.def_span`.
     pub fn span(self, hir_id: HirId) -> Span {
@@ -977,12 +1053,6 @@ impl<'hir> Map<'hir> {
         }
     }
 
-    /// Get a representation of this `id` for debugging purposes.
-    /// NOTE: Do NOT use this in diagnostics!
-    pub fn node_to_string(self, id: HirId) -> String {
-        hir_id_to_string(self, id)
-    }
-
     /// Returns the HirId of `N` in `struct Foo<const N: usize = { ... }>` when
     /// called with the HirId for the `{ ... }` anon const
     pub fn opt_const_param_default_param_def_id(self, anon_const: HirId) -> Option<LocalDefId> {
@@ -1147,102 +1217,6 @@ fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
     upstream_crates
 }
 
-fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
-    let path_str = |def_id: LocalDefId| map.tcx.def_path_str(def_id);
-
-    let span_str = || map.tcx.sess.source_map().span_to_snippet(map.span(id)).unwrap_or_default();
-    let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str());
-
-    match map.tcx.hir_node(id) {
-        Node::Item(item) => {
-            let item_str = match item.kind {
-                ItemKind::ExternCrate(..) => "extern crate",
-                ItemKind::Use(..) => "use",
-                ItemKind::Static(..) => "static",
-                ItemKind::Const(..) => "const",
-                ItemKind::Fn { .. } => "fn",
-                ItemKind::Macro(..) => "macro",
-                ItemKind::Mod(..) => "mod",
-                ItemKind::ForeignMod { .. } => "foreign mod",
-                ItemKind::GlobalAsm { .. } => "global asm",
-                ItemKind::TyAlias(..) => "ty",
-                ItemKind::Enum(..) => "enum",
-                ItemKind::Struct(..) => "struct",
-                ItemKind::Union(..) => "union",
-                ItemKind::Trait(..) => "trait",
-                ItemKind::TraitAlias(..) => "trait alias",
-                ItemKind::Impl { .. } => "impl",
-            };
-            format!("{id} ({item_str} {})", path_str(item.owner_id.def_id))
-        }
-        Node::ForeignItem(item) => {
-            format!("{id} (foreign item {})", path_str(item.owner_id.def_id))
-        }
-        Node::ImplItem(ii) => {
-            let kind = match ii.kind {
-                ImplItemKind::Const(..) => "associated constant",
-                ImplItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
-                    ImplicitSelfKind::None => "associated function",
-                    _ => "method",
-                },
-                ImplItemKind::Type(_) => "associated type",
-            };
-            format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id))
-        }
-        Node::TraitItem(ti) => {
-            let kind = match ti.kind {
-                TraitItemKind::Const(..) => "associated constant",
-                TraitItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
-                    ImplicitSelfKind::None => "associated function",
-                    _ => "trait method",
-                },
-                TraitItemKind::Type(..) => "associated type",
-            };
-
-            format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id))
-        }
-        Node::Variant(variant) => {
-            format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id))
-        }
-        Node::Field(field) => {
-            format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
-        }
-        Node::AnonConst(_) => node_str("const"),
-        Node::ConstBlock(_) => node_str("const"),
-        Node::ConstArg(_) => node_str("const"),
-        Node::Expr(_) => node_str("expr"),
-        Node::ExprField(_) => node_str("expr field"),
-        Node::Stmt(_) => node_str("stmt"),
-        Node::PathSegment(_) => node_str("path segment"),
-        Node::Ty(_) => node_str("type"),
-        Node::AssocItemConstraint(_) => node_str("assoc item constraint"),
-        Node::TraitRef(_) => node_str("trait ref"),
-        Node::OpaqueTy(_) => node_str("opaque type"),
-        Node::Pat(_) => node_str("pat"),
-        Node::TyPat(_) => node_str("pat ty"),
-        Node::PatField(_) => node_str("pattern field"),
-        Node::PatExpr(_) => node_str("pattern literal"),
-        Node::Param(_) => node_str("param"),
-        Node::Arm(_) => node_str("arm"),
-        Node::Block(_) => node_str("block"),
-        Node::Infer(_) => node_str("infer"),
-        Node::LetStmt(_) => node_str("local"),
-        Node::Ctor(ctor) => format!(
-            "{id} (ctor {})",
-            ctor.ctor_def_id().map_or("<missing path>".into(), |def_id| path_str(def_id)),
-        ),
-        Node::Lifetime(_) => node_str("lifetime"),
-        Node::GenericParam(param) => {
-            format!("{id} (generic_param {})", path_str(param.def_id))
-        }
-        Node::Crate(..) => String::from("(root_crate)"),
-        Node::WherePredicate(_) => node_str("where predicate"),
-        Node::Synthetic => unreachable!(),
-        Node::Err(_) => node_str("error"),
-        Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"),
-    }
-}
-
 pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalModDefId) -> ModuleItems {
     let mut collector = ItemCollector::new(tcx, false);
 
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 6071a58367e..68b9a4f56b9 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -202,13 +202,13 @@ pub fn provide(providers: &mut Providers) {
             }
         })
     };
-    providers.hir_attrs = |tcx, id| {
+    providers.hir_attr_map = |tcx, id| {
         tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs)
     };
     providers.def_span = |tcx, def_id| tcx.hir().span(tcx.local_def_id_to_hir_id(def_id));
     providers.def_ident_span = |tcx, def_id| {
         let hir_id = tcx.local_def_id_to_hir_id(def_id);
-        tcx.hir().opt_ident_span(hir_id)
+        tcx.hir_opt_ident_span(hir_id)
     };
     providers.fn_arg_names = |tcx, def_id| {
         let hir = tcx.hir();
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index f880b1364c2..573f7895da2 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -653,7 +653,10 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io:
             write!(w, "static mut ")?
         }
         (_, _) if is_function => write!(w, "fn ")?,
-        (DefKind::AnonConst | DefKind::InlineConst, _) => {} // things like anon const, not an item
+        // things like anon const, not an item
+        (DefKind::AnonConst | DefKind::InlineConst, _) => {}
+        // `global_asm!` have fake bodies, which we may dump after mir-build
+        (DefKind::GlobalAsm, _) => {}
         _ => bug!("Unexpected def kind {:?}", kind),
     }
 
@@ -1200,7 +1203,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                             && let Some(upvars) = tcx.upvars_mentioned(def_id)
                         {
                             for (&var_id, place) in iter::zip(upvars.keys(), places) {
-                                let var_name = tcx.hir().name(var_id);
+                                let var_name = tcx.hir_name(var_id);
                                 struct_fmt.field(var_name.as_str(), place);
                             }
                         } else {
@@ -1221,7 +1224,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                             && let Some(upvars) = tcx.upvars_mentioned(def_id)
                         {
                             for (&var_id, place) in iter::zip(upvars.keys(), places) {
-                                let var_name = tcx.hir().name(var_id);
+                                let var_name = tcx.hir_name(var_id);
                                 struct_fmt.field(var_name.as_str(), place);
                             }
                         } else {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index c8708857565..781a898a6e9 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -198,7 +198,7 @@ rustc_queries! {
     ///
     /// This can be conveniently accessed by methods on `tcx.hir()`.
     /// Avoid calling this query directly.
-    query hir_attrs(key: hir::OwnerId) -> &'tcx hir::AttributeMap<'tcx> {
+    query hir_attr_map(key: hir::OwnerId) -> &'tcx hir::AttributeMap<'tcx> {
         desc { |tcx| "getting HIR owner attributes in `{}`", tcx.def_path_str(key) }
         feedable
     }
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 53f233f20eb..7e6151745e2 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -980,12 +980,9 @@ pub enum CodegenObligationError {
     /// overflow bug, since I believe this is the only case
     /// where ambiguity can result.
     Ambiguity,
-    /// This can trigger when we probe for the source of a `'static` lifetime requirement
-    /// on a trait object: `impl Foo for dyn Trait {}` has an implicit `'static` bound.
-    /// This can also trigger when we have a global bound that is not actually satisfied,
-    /// but was included during typeck due to the trivial_bounds feature.
+    /// This can trigger when we have a global bound that is not actually satisfied
+    /// due to trivial bounds.
     Unimplemented,
-    FulfillmentError,
     /// The selected impl has unconstrained generic parameters. This will emit an error
     /// during impl WF checking.
     UnconstrainedParam(ErrorGuaranteed),
diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs
index 9ce5373b031..8e54a9d487d 100644
--- a/compiler/rustc_middle/src/traits/specialization_graph.rs
+++ b/compiler/rustc_middle/src/traits/specialization_graph.rs
@@ -72,7 +72,7 @@ impl OverlapMode {
                     .as_local()
                     .into_iter()
                     .flat_map(|local_def_id| {
-                        tcx.hir().attrs(tcx.local_def_id_to_hir_id(local_def_id))
+                        tcx.hir_attrs(tcx.local_def_id_to_hir_id(local_def_id))
                     })
                     .find(|attr| attr.has_name(sym::rustc_strict_coherence))
                     .map(|attr| attr.span());
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 5d9b1ddfa38..703b6ce9247 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -296,7 +296,7 @@ pub struct CaptureInfo {
 
 pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String {
     let mut curr_string: String = match place.base {
-        HirPlaceBase::Upvar(upvar_id) => tcx.hir().name(upvar_id.var_path.hir_id).to_string(),
+        HirPlaceBase::Upvar(upvar_id) => tcx.hir_name(upvar_id.var_path.hir_id).to_string(),
         _ => bug!("Capture_information should only contain upvars"),
     };
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 70bb902d1ae..a2472157d0e 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1299,7 +1299,7 @@ impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
             ),
             bodies,
         })));
-        self.feed_owner_id().hir_attrs(attrs);
+        self.feed_owner_id().hir_attr_map(attrs);
     }
 }
 
@@ -2214,7 +2214,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Returns the origin of the opaque type `def_id`.
     #[instrument(skip(self), level = "trace", ret)]
     pub fn local_opaque_ty_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin<LocalDefId> {
-        self.hir().expect_opaque_ty(def_id).origin
+        self.hir_expect_opaque_ty(def_id).origin
     }
 
     pub fn finish(self) {
@@ -3118,9 +3118,11 @@ impl<'tcx> TyCtxt<'tcx> {
 
     pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
         self.mk_bound_variable_kinds(
-            &self.late_bound_vars_map(id.owner).get(&id.local_id).cloned().unwrap_or_else(|| {
-                bug!("No bound vars found for {}", self.hir().node_to_string(id))
-            }),
+            &self
+                .late_bound_vars_map(id.owner)
+                .get(&id.local_id)
+                .cloned()
+                .unwrap_or_else(|| bug!("No bound vars found for {}", self.hir_id_to_string(id))),
         )
     }
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 97cfe5946af..ad9d32fd6c1 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1696,7 +1696,7 @@ impl<'tcx> TyCtxt<'tcx> {
     // FIXME(@lcnr): Remove this function.
     pub fn get_attrs_unchecked(self, did: DefId) -> &'tcx [hir::Attribute] {
         if let Some(did) = did.as_local() {
-            self.hir().attrs(self.local_def_id_to_hir_id(did))
+            self.hir_attrs(self.local_def_id_to_hir_id(did))
         } else {
             self.attrs_for_def(did)
         }
@@ -1720,7 +1720,7 @@ impl<'tcx> TyCtxt<'tcx> {
     ) -> impl Iterator<Item = &'tcx hir::Attribute> {
         let did: DefId = did.into();
         if let Some(did) = did.as_local() {
-            self.hir().attrs(self.local_def_id_to_hir_id(did)).iter()
+            self.hir_attrs(self.local_def_id_to_hir_id(did)).iter()
         } else {
             self.attrs_for_def(did).iter()
         }
@@ -1764,7 +1764,7 @@ impl<'tcx> TyCtxt<'tcx> {
     ) -> impl Iterator<Item = &'tcx hir::Attribute> {
         let filter_fn = move |a: &&hir::Attribute| a.path_matches(attr);
         if let Some(did) = did.as_local() {
-            self.hir().attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
+            self.hir_attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
         } else {
             self.attrs_for_def(did).iter().filter(filter_fn)
         }
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 6c62c04f42e..f1d03d0a659 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -50,7 +50,7 @@ impl<'tcx> fmt::Debug for ty::AdtDef<'tcx> {
 
 impl fmt::Debug for ty::UpvarId {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let name = ty::tls::with(|tcx| tcx.hir().name(self.var_path.hir_id));
+        let name = ty::tls::with(|tcx| tcx.hir_name(self.var_path.hir_id));
         write!(f, "UpvarId({:?};`{}`;{:?})", self.var_path.hir_id, name, self.closure_expr_id)
     }
 }
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 7d9c23c05f9..06054e22e76 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -310,7 +310,7 @@ impl<'tcx> TypeckResults<'tcx> {
 
     pub fn node_type(&self, id: HirId) -> Ty<'tcx> {
         self.node_type_opt(id).unwrap_or_else(|| {
-            bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir().node_to_string(id)))
+            bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir_id_to_string(id)))
         })
     }
 
@@ -554,7 +554,7 @@ fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: HirId) {
     ty::tls::with(|tcx| {
         bug!(
             "node {} cannot be placed in TypeckResults with hir_owner {:?}",
-            tcx.hir().node_to_string(hir_id),
+            tcx.hir_id_to_string(hir_id),
             hir_owner
         )
     });
diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs
index f9fa750e750..2909dea98b7 100644
--- a/compiler/rustc_mir_build/src/builder/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/mod.rs
@@ -485,7 +485,7 @@ fn construct_fn<'tcx>(
     };
 
     if let Some(custom_mir_attr) =
-        tcx.hir().attrs(fn_id).iter().find(|attr| attr.name_or_empty() == sym::custom_mir)
+        tcx.hir_attrs(fn_id).iter().find(|attr| attr.name_or_empty() == sym::custom_mir)
     {
         return custom::build_custom_mir(
             tcx,
@@ -741,7 +741,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         coroutine: Option<Box<CoroutineInfo<'tcx>>>,
     ) -> Builder<'a, 'tcx> {
         let tcx = infcx.tcx;
-        let attrs = tcx.hir().attrs(hir_id);
+        let attrs = tcx.hir_attrs(hir_id);
         // Some functions always have overflow checks enabled,
         // however, they may not get codegen'd, depending on
         // the settings for the crate they are codegened in.
diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs
index 81561239491..27ff01b4803 100644
--- a/compiler/rustc_mir_build/src/builder/scope.rs
+++ b/compiler/rustc_mir_build/src/builder/scope.rs
@@ -942,14 +942,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         assert_eq!(orig_id.owner, self.hir_id.owner);
 
         let mut id = orig_id;
-        let hir = self.tcx.hir();
         loop {
             if id == self.hir_id {
                 // This is a moderately common case, mostly hit for previously unseen nodes.
                 break;
             }
 
-            if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) {
+            if self.tcx.hir_attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) {
                 // This is a rare case. It's for a node path that doesn't reach the root due to an
                 // intervening lint level attribute. This result doesn't get cached.
                 return id;
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index e46e8c9871a..b8af77245f2 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -1041,7 +1041,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
                         "Should have already errored about late bound consts: {def_id:?}"
                     );
                 };
-                let name = self.tcx.hir().name(hir_id);
+                let name = self.tcx.hir_name(hir_id);
                 let param = ty::ParamConst::new(index, name);
 
                 ExprKind::ConstParam { param, def_id }
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 3d55c1401b6..b3daed8a7e0 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -73,7 +73,6 @@ struct ThirBuildCx<'tcx> {
 impl<'tcx> ThirBuildCx<'tcx> {
     fn new(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
         let typeck_results = tcx.typeck(def);
-        let hir = tcx.hir();
         let hir_id = tcx.local_def_id_to_hir_id(def);
 
         let body_type = match tcx.hir_body_owner_kind(def) {
@@ -111,8 +110,8 @@ impl<'tcx> ThirBuildCx<'tcx> {
             typeck_results,
             rvalue_scopes: &typeck_results.rvalue_scopes,
             body_owner: def.to_def_id(),
-            apply_adjustments: hir
-                .attrs(hir_id)
+            apply_adjustments: tcx
+                .hir_attrs(hir_id)
                 .iter()
                 .all(|attr| attr.name_or_empty() != rustc_span::sym::custom_mir),
         }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index dadd1e85461..cbd29ba837e 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -1043,7 +1043,7 @@ fn find_fallback_pattern_typo<'tcx>(
         for item in cx.tcx.hir_crate_items(()).free_items() {
             if let DefKind::Use = cx.tcx.def_kind(item.owner_id) {
                 // Look for consts being re-exported.
-                let item = cx.tcx.hir().expect_item(item.owner_id.def_id);
+                let item = cx.tcx.hir_expect_item(item.owner_id.def_id);
                 let use_name = item.ident.name;
                 let hir::ItemKind::Use(path, _) = item.kind else {
                     continue;
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index c6ae2c0fb9b..ece5a53aaa9 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -52,7 +52,7 @@ fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>)
         hir::ImplItemKind::Const(..) => Target::AssocConst,
         hir::ImplItemKind::Fn(..) => {
             let parent_def_id = tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
-            let containing_item = tcx.hir().expect_item(parent_def_id);
+            let containing_item = tcx.hir_expect_item(parent_def_id);
             let containing_impl_is_for_trait = match &containing_item.kind {
                 hir::ItemKind::Impl(impl_) => impl_.of_trait.is_some(),
                 _ => bug!("parent of an ImplItem must be an Impl"),
@@ -114,7 +114,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         let mut doc_aliases = FxHashMap::default();
         let mut specified_inline = None;
         let mut seen = FxHashMap::default();
-        let attrs = self.tcx.hir().attrs(hir_id);
+        let attrs = self.tcx.hir_attrs(hir_id);
         for attr in attrs {
             match attr {
                 Attribute::Parsed(AttributeKind::Confusables { first_span, .. }) => {
@@ -899,7 +899,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         if let Some(location) = match target {
             Target::AssocTy => {
                 let parent_def_id = self.tcx.hir_get_parent_item(hir_id).def_id;
-                let containing_item = self.tcx.hir().expect_item(parent_def_id);
+                let containing_item = self.tcx.hir_expect_item(parent_def_id);
                 if Target::from_item(containing_item) == Target::Impl {
                     Some("type alias in implementation block")
                 } else {
@@ -908,7 +908,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             }
             Target::AssocConst => {
                 let parent_def_id = self.tcx.hir_get_parent_item(hir_id).def_id;
-                let containing_item = self.tcx.hir().expect_item(parent_def_id);
+                let containing_item = self.tcx.hir_expect_item(parent_def_id);
                 // We can't link to trait impl's consts.
                 let err = "associated constant in trait implementation block";
                 match containing_item.kind {
@@ -952,7 +952,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             tcx.dcx().emit_err(errors::DocAliasBadLocation { span, attr_str, location });
             return;
         }
-        let item_name = self.tcx.hir().name(hir_id);
+        let item_name = self.tcx.hir_name(hir_id);
         if item_name == doc_alias {
             tcx.dcx().emit_err(errors::DocAliasNotAnAlias { span, attr_str });
             return;
@@ -1481,7 +1481,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         // `#[must_use]` can be applied to a trait method definition with a default body
         if let Target::Method(MethodKind::Trait { body: true }) = target
             && let parent_def_id = self.tcx.hir_get_parent_item(hir_id).def_id
-            && let containing_item = self.tcx.hir().expect_item(parent_def_id)
+            && let containing_item = self.tcx.hir_expect_item(parent_def_id)
             && let hir::ItemKind::Trait(..) = containing_item.kind
         {
             return;
@@ -2572,7 +2572,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         match (target, force_inline_attr) {
             (Target::Closure, None) => {
                 let is_coro = matches!(
-                    self.tcx.hir().expect_expr(hir_id).kind,
+                    self.tcx.hir_expect_expr(hir_id).kind,
                     hir::ExprKind::Closure(hir::Closure {
                         kind: hir::ClosureKind::Coroutine(..)
                             | hir::ClosureKind::CoroutineClosure(..),
@@ -2644,8 +2644,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
         const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg, sym::cfg_attr];
         let spans = self
             .tcx
-            .hir()
-            .attrs(where_predicate.hir_id)
+            .hir_attrs(where_predicate.hir_id)
             .iter()
             .filter(|attr| !ATTRS_ALLOWED.iter().any(|&sym| attr.has_name(sym)))
             .map(|attr| attr.span())
@@ -2814,7 +2813,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
 }
 
 fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>) {
-    let attrs = tcx.hir().attrs(item.hir_id());
+    let attrs = tcx.hir_attrs(item.hir_id());
 
     for attr in attrs {
         if attr.has_name(sym::inline) {
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 7a14a7a5db2..7029c60c343 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -361,7 +361,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                     self.tcx.hir_fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id))
                 && matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None)
                 && let TyKind::Path(hir::QPath::Resolved(_, path)) =
-                    self.tcx.hir().expect_item(local_impl_of).expect_impl().self_ty.kind
+                    self.tcx.hir_expect_item(local_impl_of).expect_impl().self_ty.kind
                 && let Res::Def(def_kind, did) = path.res
             {
                 match def_kind {
@@ -424,7 +424,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                     for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) {
                         if let Some(local_def_id) = impl_def_id.as_local()
                             && let ItemKind::Impl(impl_ref) =
-                                self.tcx.hir().expect_item(local_def_id).kind
+                                self.tcx.hir_expect_item(local_def_id).kind
                         {
                             // skip items
                             // mark dependent traits live
@@ -448,7 +448,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                     for impl_id in self.tcx.all_impls(trait_id) {
                         if let Some(local_impl_id) = impl_id.as_local()
                             && let ItemKind::Impl(impl_ref) =
-                                self.tcx.hir().expect_item(local_impl_id).kind
+                                self.tcx.hir_expect_item(local_impl_id).kind
                         {
                             if !matches!(trait_item.kind, hir::TraitItemKind::Type(..))
                                 && !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty)
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index 323b414cca0..e13d94c1031 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -19,7 +19,7 @@ use rustc_span::{Symbol, sym};
 use crate::errors::DuplicateDiagnosticItemInCrate;
 
 fn observe_item<'tcx>(tcx: TyCtxt<'tcx>, diagnostic_items: &mut DiagnosticItems, owner: OwnerId) {
-    let attrs = tcx.hir().attrs(owner.into());
+    let attrs = tcx.hir_attrs(owner.into());
     if let Some(name) = extract(attrs) {
         // insert into our table
         collect_item(tcx, diagnostic_items, name, owner.to_def_id());
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index 25e679a8460..d2729876ebb 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -31,7 +31,7 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
     }
 
     // If the user wants no main function at all, then stop here.
-    if attr::contains_name(tcx.hir().attrs(CRATE_HIR_ID), sym::no_main) {
+    if attr::contains_name(tcx.hir_attrs(CRATE_HIR_ID), sym::no_main) {
         return None;
     }
 
@@ -45,7 +45,7 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
 }
 
 fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Option<Span> {
-    let attrs = ctxt.tcx.hir().attrs(id.hir_id());
+    let attrs = ctxt.tcx.hir_attrs(id.hir_id());
     attr::find_by_name(attrs, sym).map(|attr| attr.span())
 }
 
@@ -61,7 +61,7 @@ fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
 
     let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID);
 
-    let attrs = ctxt.tcx.hir().attrs(id.hir_id());
+    let attrs = ctxt.tcx.hir_attrs(id.hir_id());
     let entry_point_type = rustc_ast::entry::entry_point_type(
         attrs,
         at_root,
diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs
index 509c2f54775..84b92d49f24 100644
--- a/compiler/rustc_passes/src/hir_id_validator.rs
+++ b/compiler/rustc_passes/src/hir_id_validator.rs
@@ -60,19 +60,18 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> {
             .expect("owning item has no entry");
 
         if max != self.hir_ids_seen.len() - 1 {
-            let hir = self.tcx.hir();
             let pretty_owner = self.tcx.hir_def_path(owner.def_id).to_string_no_crate_verbose();
 
             let missing_items: Vec<_> = (0..=max as u32)
                 .map(|i| ItemLocalId::from_u32(i))
                 .filter(|&local_id| !self.hir_ids_seen.contains(local_id))
-                .map(|local_id| hir.node_to_string(HirId { owner, local_id }))
+                .map(|local_id| self.tcx.hir_id_to_string(HirId { owner, local_id }))
                 .collect();
 
             let seen_items: Vec<_> = self
                 .hir_ids_seen
                 .iter()
-                .map(|local_id| hir.node_to_string(HirId { owner, local_id }))
+                .map(|local_id| self.tcx.hir_id_to_string(HirId { owner, local_id }))
                 .collect();
 
             self.error(|| {
@@ -137,7 +136,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
             self.error(|| {
                 format!(
                     "HirIdValidator: The recorded owner of {} is {} instead of {}",
-                    self.tcx.hir().node_to_string(hir_id),
+                    self.tcx.hir_id_to_string(hir_id),
                     self.tcx.hir_def_path(hir_id.owner.def_id).to_string_no_crate_verbose(),
                     self.tcx.hir_def_path(owner.def_id).to_string_no_crate_verbose()
                 )
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 822804893fe..ed70d9ee91f 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -157,7 +157,7 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: LocalDefId) {
 
     if let Some(upvars) = tcx.upvars_mentioned(def_id) {
         for &var_hir_id in upvars.keys() {
-            let var_name = tcx.hir().name(var_hir_id);
+            let var_name = tcx.hir_name(var_hir_id);
             maps.add_variable(Upvar(var_hir_id, var_name));
         }
     }
diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs
index 8e59c0b3251..b06f16cc7bd 100644
--- a/compiler/rustc_passes/src/loops.rs
+++ b/compiler/rustc_passes/src/loops.rs
@@ -222,7 +222,7 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> {
 
                 if let Some(break_expr) = opt_expr {
                     let (head, loop_label, loop_kind) = if let Some(loop_id) = loop_id {
-                        match self.tcx.hir().expect_expr(loop_id).kind {
+                        match self.tcx.hir_expect_expr(loop_id).kind {
                             hir::ExprKind::Loop(_, label, source, sp) => {
                                 (Some(sp), label, Some(source))
                             }
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index fd465717bf7..599a08bac20 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -291,7 +291,7 @@ impl<'tcx> ReachableContext<'tcx> {
             _ => {
                 bug!(
                     "found unexpected node kind in worklist: {} ({:?})",
-                    self.tcx.hir().node_to_string(self.tcx.local_def_id_to_hir_id(search_item)),
+                    self.tcx.hir_id_to_string(self.tcx.local_def_id_to_hir_id(search_item)),
                     node,
                 );
             }
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 0fcf6a80ec4..aea4386295f 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -118,7 +118,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
     ) where
         F: FnOnce(&mut Self),
     {
-        let attrs = self.tcx.hir().attrs(self.tcx.local_def_id_to_hir_id(def_id));
+        let attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id));
         debug!("annotate(id = {:?}, attrs = {:?})", def_id, attrs);
 
         let depr = attr::find_attr!(attrs, AttributeKind::Deprecation{deprecation, span} => (*deprecation, *span));
@@ -795,7 +795,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
             }) => {
                 let features = self.tcx.features();
                 if features.staged_api() {
-                    let attrs = self.tcx.hir().attrs(item.hir_id());
+                    let attrs = self.tcx.hir_attrs(item.hir_id());
                     let stab = attr::find_attr!(attrs, AttributeKind::Stability{stability, span} => (*stability, *span));
 
                     // FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem
@@ -1034,7 +1034,7 @@ fn is_unstable_reexport(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
     }
 
     // If this is a path that isn't a use, we don't need to do anything special
-    if !matches!(tcx.hir().expect_item(def_id).kind, ItemKind::Use(..)) {
+    if !matches!(tcx.hir_expect_item(def_id).kind, ItemKind::Use(..)) {
         return false;
     }
 
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 91553700219..cf32f237b86 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -493,7 +493,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
     ) {
         // Non-opaque macros cannot make other items more accessible than they already are.
         let hir_id = self.tcx.local_def_id_to_hir_id(local_def_id);
-        let attrs = self.tcx.hir().attrs(hir_id);
+        let attrs = self.tcx.hir_attrs(hir_id);
 
         if attr::find_attr!(attrs, AttributeKind::MacroTransparency(x) => *x)
             .unwrap_or(Transparency::fallback(md.macro_rules))
@@ -573,7 +573,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
             // have normal hygiene, so we can treat them like other items without type
             // privacy and mark them reachable.
             DefKind::Macro(_) => {
-                let item = self.tcx.hir().expect_item(def_id);
+                let item = self.tcx.hir_expect_item(def_id);
                 if let hir::ItemKind::Macro(MacroDef { macro_rules: false, .. }, _) = item.kind {
                     if vis.is_accessible_from(module, self.tcx) {
                         self.update(def_id, macro_ev, Level::Reachable);
@@ -597,7 +597,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
 
             DefKind::Struct | DefKind::Union => {
                 // While structs and unions have type privacy, their fields do not.
-                let item = self.tcx.hir().expect_item(def_id);
+                let item = self.tcx.hir_expect_item(def_id);
                 if let hir::ItemKind::Struct(ref struct_def, _)
                 | hir::ItemKind::Union(ref struct_def, _) = item.kind
                 {
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 9f062b3935f..817aa5b4385 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -153,9 +153,13 @@ resolve_extern_crate_self_requires_renaming =
     `extern crate self;` requires renaming
     .suggestion = rename the `self` crate to be able to import it
 
+resolve_forward_declared_generic_in_const_param_ty =
+    const parameter types cannot reference parameters before they are declared
+    .label = const parameter type cannot reference `{$param}` before it is declared
+
 resolve_forward_declared_generic_param =
-    generic parameters with a default cannot use forward declared identifiers
-    .label = defaulted generic parameters cannot be forward declared
+    generic parameter defaults cannot reference parameters before they are declared
+    .label = cannot reference `{$param}` before it is declared
 
 resolve_found_an_item_configured_out =
     found an item that was configured out
@@ -377,9 +381,11 @@ resolve_self_imports_only_allowed_within_multipart_suggestion =
 resolve_self_imports_only_allowed_within_suggestion =
     consider importing the module directly
 
+resolve_self_in_const_generic_ty =
+    cannot use `Self` in const parameter type
+
 resolve_self_in_generic_param_default =
     generic parameters cannot use `Self` in their defaults
-    .label = `Self` in generic parameter default
 
 resolve_similarly_named_defined_here =
     similarly named {$candidate_descr} `{$candidate}` defined here
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 88d1126de1a..41f4254eede 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -42,10 +42,10 @@ use crate::imports::{Import, ImportKind};
 use crate::late::{PatternSource, Rib};
 use crate::{
     AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingError, BindingKey, Finalize,
-    HasGenericParams, LexicalScopeBinding, MacroRulesScope, Module, ModuleKind,
-    ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError,
-    ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used, VisResolutionError,
-    errors as errs, path_names_to_string,
+    ForwardGenericParamBanReason, HasGenericParams, LexicalScopeBinding, MacroRulesScope, Module,
+    ModuleKind, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult,
+    PrivacyError, ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used,
+    VisResolutionError, errors as errs, path_names_to_string,
 };
 
 type Res = def::Res<ast::NodeId>;
@@ -887,9 +887,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 participle,
                 name,
             }),
-            ResolutionError::ForwardDeclaredGenericParam => {
-                self.dcx().create_err(errs::ForwardDeclaredGenericParam { span })
-            }
+            ResolutionError::ForwardDeclaredGenericParam(param, reason) => match reason {
+                ForwardGenericParamBanReason::Default => {
+                    self.dcx().create_err(errs::ForwardDeclaredGenericParam { param, span })
+                }
+                ForwardGenericParamBanReason::ConstParamTy => self
+                    .dcx()
+                    .create_err(errs::ForwardDeclaredGenericInConstParamTy { param, span }),
+            },
             ResolutionError::ParamInTyOfConstParam { name } => {
                 self.dcx().create_err(errs::ParamInTyOfConstParam { span, name })
             }
@@ -908,9 +913,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => self
                 .dcx()
                 .create_err(errs::ParamInEnumDiscriminant { span, name, param_kind: is_type }),
-            ResolutionError::SelfInGenericParamDefault => {
-                self.dcx().create_err(errs::SelfInGenericParamDefault { span })
-            }
+            ResolutionError::ForwardDeclaredSelf(reason) => match reason {
+                ForwardGenericParamBanReason::Default => {
+                    self.dcx().create_err(errs::SelfInGenericParamDefault { span })
+                }
+                ForwardGenericParamBanReason::ConstParamTy => {
+                    self.dcx().create_err(errs::SelfInConstGenericTy { span })
+                }
+            },
             ResolutionError::UnreachableLabel { name, definition_span, suggestion } => {
                 let ((sub_suggestion_label, sub_suggestion), sub_unreachable_label) =
                     match suggestion {
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index b5d3e5ea776..2ae6892bc93 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -338,6 +338,16 @@ pub(crate) struct ForwardDeclaredGenericParam {
     #[primary_span]
     #[label]
     pub(crate) span: Span,
+    pub(crate) param: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_forward_declared_generic_in_const_param_ty)]
+pub(crate) struct ForwardDeclaredGenericInConstParamTy {
+    #[primary_span]
+    #[label]
+    pub(crate) span: Span,
+    pub(crate) param: Symbol,
 }
 
 #[derive(Diagnostic)]
@@ -353,7 +363,13 @@ pub(crate) struct ParamInTyOfConstParam {
 #[diag(resolve_self_in_generic_param_default, code = E0735)]
 pub(crate) struct SelfInGenericParamDefault {
     #[primary_span]
-    #[label]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(resolve_self_in_const_generic_ty)]
+pub(crate) struct SelfInConstGenericTy {
+    #[primary_span]
     pub(crate) span: Span,
 }
 
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index d9776be4dd0..5f0a2a597e9 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -1117,13 +1117,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         debug!("validate_res_from_ribs({:?})", res);
         let ribs = &all_ribs[rib_index + 1..];
 
-        // An invalid forward use of a generic parameter from a previous default.
-        if let RibKind::ForwardGenericParamBan = all_ribs[rib_index].kind {
+        // An invalid forward use of a generic parameter from a previous default
+        // or in a const param ty.
+        if let RibKind::ForwardGenericParamBan(reason) = all_ribs[rib_index].kind {
             if let Some(span) = finalize {
                 let res_error = if rib_ident.name == kw::SelfUpper {
-                    ResolutionError::SelfInGenericParamDefault
+                    ResolutionError::ForwardDeclaredSelf(reason)
                 } else {
-                    ResolutionError::ForwardDeclaredGenericParam
+                    ResolutionError::ForwardDeclaredGenericParam(rib_ident.name, reason)
                 };
                 self.report_error(span, res_error);
             }
@@ -1131,17 +1132,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             return Res::Err;
         }
 
-        if let RibKind::ConstParamTy = all_ribs[rib_index].kind {
-            if let Some(span) = finalize {
-                self.report_error(
-                    span,
-                    ResolutionError::ParamInTyOfConstParam { name: rib_ident.name },
-                );
-            }
-            assert_eq!(res, Res::Err);
-            return Res::Err;
-        }
-
         match res {
             Res::Local(_) => {
                 use ResolutionError::*;
@@ -1153,7 +1143,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         | RibKind::FnOrCoroutine
                         | RibKind::Module(..)
                         | RibKind::MacroDefinition(..)
-                        | RibKind::ForwardGenericParamBan => {
+                        | RibKind::ForwardGenericParamBan(_) => {
                             // Nothing to do. Continue.
                         }
                         RibKind::Item(..) | RibKind::AssocItem => {
@@ -1247,12 +1237,27 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         | RibKind::MacroDefinition(..)
                         | RibKind::InlineAsmSym
                         | RibKind::AssocItem
-                        | RibKind::ConstParamTy
-                        | RibKind::ForwardGenericParamBan => {
+                        | RibKind::ForwardGenericParamBan(_) => {
                             // Nothing to do. Continue.
                             continue;
                         }
 
+                        RibKind::ConstParamTy => {
+                            if !self.tcx.features().generic_const_parameter_types() {
+                                if let Some(span) = finalize {
+                                    self.report_error(
+                                        span,
+                                        ResolutionError::ParamInTyOfConstParam {
+                                            name: rib_ident.name,
+                                        },
+                                    );
+                                }
+                                return Res::Err;
+                            } else {
+                                continue;
+                            }
+                        }
+
                         RibKind::ConstantItem(trivial, _) => {
                             if let ConstantHasGenerics::No(cause) = trivial {
                                 // HACK(min_const_generics): If we encounter `Self` in an anonymous
@@ -1325,8 +1330,23 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         | RibKind::MacroDefinition(..)
                         | RibKind::InlineAsmSym
                         | RibKind::AssocItem
-                        | RibKind::ConstParamTy
-                        | RibKind::ForwardGenericParamBan => continue,
+                        | RibKind::ForwardGenericParamBan(_) => continue,
+
+                        RibKind::ConstParamTy => {
+                            if !self.tcx.features().generic_const_parameter_types() {
+                                if let Some(span) = finalize {
+                                    self.report_error(
+                                        span,
+                                        ResolutionError::ParamInTyOfConstParam {
+                                            name: rib_ident.name,
+                                        },
+                                    );
+                                }
+                                return Res::Err;
+                            } else {
+                                continue;
+                            }
+                        }
 
                         RibKind::ConstantItem(trivial, _) => {
                             if let ConstantHasGenerics::No(cause) = trivial {
@@ -1377,6 +1397,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             }
             _ => {}
         }
+
         res
     }
 
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 2c3e4bb505c..d28988cd74f 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -207,7 +207,7 @@ pub(crate) enum RibKind<'ra> {
     /// All bindings in this rib are generic parameters that can't be used
     /// from the default of a generic parameter because they're not declared
     /// before said generic parameter. Also see the `visit_generics` override.
-    ForwardGenericParamBan,
+    ForwardGenericParamBan(ForwardGenericParamBanReason),
 
     /// We are inside of the type of a const parameter. Can't refer to any
     /// parameters.
@@ -218,6 +218,12 @@ pub(crate) enum RibKind<'ra> {
     InlineAsmSym,
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub(crate) enum ForwardGenericParamBanReason {
+    Default,
+    ConstParamTy,
+}
+
 impl RibKind<'_> {
     /// Whether this rib kind contains generic parameters, as opposed to local
     /// variables.
@@ -232,7 +238,7 @@ impl RibKind<'_> {
             RibKind::ConstParamTy
             | RibKind::AssocItem
             | RibKind::Item(..)
-            | RibKind::ForwardGenericParamBan => true,
+            | RibKind::ForwardGenericParamBan(_) => true,
         }
     }
 
@@ -246,7 +252,7 @@ impl RibKind<'_> {
             | RibKind::Item(..)
             | RibKind::ConstantItem(..)
             | RibKind::Module(..)
-            | RibKind::ForwardGenericParamBan
+            | RibKind::ForwardGenericParamBan(_)
             | RibKind::ConstParamTy
             | RibKind::InlineAsmSym => true,
         }
@@ -1561,8 +1567,10 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         // provide previous type parameters as they're built. We
         // put all the parameters on the ban list and then remove
         // them one by one as they are processed and become available.
-        let mut forward_ty_ban_rib = Rib::new(RibKind::ForwardGenericParamBan);
-        let mut forward_const_ban_rib = Rib::new(RibKind::ForwardGenericParamBan);
+        let mut forward_ty_ban_rib =
+            Rib::new(RibKind::ForwardGenericParamBan(ForwardGenericParamBanReason::Default));
+        let mut forward_const_ban_rib =
+            Rib::new(RibKind::ForwardGenericParamBan(ForwardGenericParamBanReason::Default));
         for param in params.iter() {
             match param.kind {
                 GenericParamKind::Type { .. } => {
@@ -1593,16 +1601,24 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
         }
 
+        // NOTE: We use different ribs here not for a technical reason, but just
+        // for better diagnostics.
         let mut forward_ty_ban_rib_const_param_ty = Rib {
             bindings: forward_ty_ban_rib.bindings.clone(),
             patterns_with_skipped_bindings: FxHashMap::default(),
-            kind: RibKind::ConstParamTy,
+            kind: RibKind::ForwardGenericParamBan(ForwardGenericParamBanReason::ConstParamTy),
         };
         let mut forward_const_ban_rib_const_param_ty = Rib {
             bindings: forward_const_ban_rib.bindings.clone(),
             patterns_with_skipped_bindings: FxHashMap::default(),
-            kind: RibKind::ConstParamTy,
+            kind: RibKind::ForwardGenericParamBan(ForwardGenericParamBanReason::ConstParamTy),
         };
+        // We'll ban these with a `ConstParamTy` rib, so just clear these ribs for better
+        // diagnostics, so we don't mention anything about const param tys having generics at all.
+        if !self.r.tcx.features().generic_const_parameter_types() {
+            forward_ty_ban_rib_const_param_ty.bindings.clear();
+            forward_const_ban_rib_const_param_ty.bindings.clear();
+        }
 
         self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
             for param in params {
@@ -1628,9 +1644,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                         // Allow all following defaults to refer to this type parameter.
                         let i = &Ident::with_dummy_span(param.ident.name);
                         forward_ty_ban_rib.bindings.remove(i);
-                        if this.r.tcx.features().generic_const_parameter_types() {
-                            forward_ty_ban_rib_const_param_ty.bindings.remove(i);
-                        }
+                        forward_ty_ban_rib_const_param_ty.bindings.remove(i);
                     }
                     GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
                         // Const parameters can't have param bounds.
@@ -1641,9 +1655,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                         if this.r.tcx.features().generic_const_parameter_types() {
                             this.visit_ty(ty)
                         } else {
+                            this.ribs[TypeNS].push(Rib::new(RibKind::ConstParamTy));
+                            this.ribs[ValueNS].push(Rib::new(RibKind::ConstParamTy));
                             this.with_lifetime_rib(LifetimeRibKind::ConstParamTy, |this| {
                                 this.visit_ty(ty)
                             });
+                            this.ribs[TypeNS].pop().unwrap();
+                            this.ribs[ValueNS].pop().unwrap();
                         }
                         forward_const_ban_rib_const_param_ty = this.ribs[ValueNS].pop().unwrap();
                         forward_ty_ban_rib_const_param_ty = this.ribs[TypeNS].pop().unwrap();
@@ -1662,9 +1680,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                         // Allow all following defaults to refer to this const parameter.
                         let i = &Ident::with_dummy_span(param.ident.name);
                         forward_const_ban_rib.bindings.remove(i);
-                        if this.r.tcx.features().generic_const_parameter_types() {
-                            forward_const_ban_rib_const_param_ty.bindings.remove(i);
-                        }
+                        forward_const_ban_rib_const_param_ty.bindings.remove(i);
                     }
                 }
             }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index f724ecf76b3..495ce843fcd 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -31,7 +31,10 @@ use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
 use effective_visibilities::EffectiveVisibilitiesVisitor;
 use errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
 use imports::{Import, ImportData, ImportKind, NameResolution};
-use late::{HasGenericParams, PathSource, PatternSource, UnnecessaryQualification};
+use late::{
+    ForwardGenericParamBanReason, HasGenericParams, PathSource, PatternSource,
+    UnnecessaryQualification,
+};
 use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
 use rustc_arena::{DroplessArena, TypedArena};
 use rustc_ast::expand::StrippedCfgItem;
@@ -272,7 +275,7 @@ enum ResolutionError<'ra> {
         shadowed_binding_span: Span,
     },
     /// Error E0128: generic parameters with a default cannot use forward-declared identifiers.
-    ForwardDeclaredGenericParam,
+    ForwardDeclaredGenericParam(Symbol, ForwardGenericParamBanReason),
     // FIXME(generic_const_parameter_types): This should give custom output specifying it's only
     // problematic to use *forward declared* parameters when the feature is enabled.
     /// ERROR E0770: the type of const parameters must not depend on other generic parameters.
@@ -286,7 +289,7 @@ enum ResolutionError<'ra> {
     /// This error is emitted even with `generic_const_exprs`.
     ParamInEnumDiscriminant { name: Symbol, param_kind: ParamKindInEnumDiscriminant },
     /// Error E0735: generic parameters with a default cannot use `Self`
-    SelfInGenericParamDefault,
+    ForwardDeclaredSelf(ForwardGenericParamBanReason),
     /// Error E0767: use of unreachable label
     UnreachableLabel { name: Symbol, definition_span: Span, suggestion: Option<LabelSuggestion> },
     /// Error E0323, E0324, E0325: mismatch between trait item and impl item.
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index acd3b758351..aa1921fc8e7 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -272,7 +272,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let tcx = tables.tcx;
         let did = tables[def_id];
         let attrs_iter = if let Some(did) = did.as_local() {
-            tcx.hir().attrs(tcx.local_def_id_to_hir_id(did)).iter()
+            tcx.hir_attrs(tcx.local_def_id_to_hir_id(did)).iter()
         } else {
             tcx.attrs_for_def(did).iter()
         };
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index 42d37418fb8..baf2489b2b8 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -509,7 +509,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 hir::MatchSource::TryDesugar(scrut_hir_id),
             ) => {
                 if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
-                    let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
+                    let scrut_expr = self.tcx.hir_expect_expr(scrut_hir_id);
                     let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
                         let arg_expr = args.first().expect("try desugaring call w/out arg");
                         self.typeck_results
@@ -548,7 +548,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             }) => match source {
                 hir::MatchSource::TryDesugar(scrut_hir_id) => {
                     if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
-                        let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
+                        let scrut_expr = self.tcx.hir_expect_expr(scrut_hir_id);
                         let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
                             let arg_expr = args.first().expect("try desugaring call w/out arg");
                             self.typeck_results
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 a6d8eb6add7..40958ec1088 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
@@ -1351,7 +1351,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
             && !has_impl_trait(def_id)
             // FIXME(fn_delegation): In delegation item argument spans are equal to last path
             // segment. This leads to ICE's when emitting `multipart_suggestion`.
-            && tcx.hir().opt_delegation_sig_id(expr.hir_id.owner.def_id).is_none()
+            && tcx.hir_opt_delegation_sig_id(expr.hir_id.owner.def_id).is_none()
         {
             let successor =
                 method_args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
index 51b2a0b36bb..5583deda99a 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
@@ -743,7 +743,7 @@ fn foo(&self) -> Self::T { String::new() }
         if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *proj_ty.self_ty().kind() {
             let opaque_local_def_id = def_id.as_local();
             let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
-                tcx.hir().expect_opaque_ty(opaque_local_def_id)
+                tcx.hir_expect_opaque_ty(opaque_local_def_id)
             } else {
                 return false;
             };
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
index fecb38ab597..c7f0a88f951 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
@@ -1023,7 +1023,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 format!(" for lifetime parameter `{name}`")
             }
             infer::UpvarRegion(ref upvar_id, _) => {
-                let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
+                let var_name = self.tcx.hir_name(upvar_id.var_path.hir_id);
                 format!(" for capture of `{var_name}` by closure")
             }
             infer::Nll(..) => bug!("NLL variable found in lexical phase"),
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
index a7e68e6419d..cdbb92f4c7b 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
@@ -778,8 +778,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 let exp_local_id = exp_def_id.as_local()?;
 
                 match (
-                    &self.tcx.hir().expect_opaque_ty(last_local_id),
-                    &self.tcx.hir().expect_opaque_ty(exp_local_id),
+                    &self.tcx.hir_expect_opaque_ty(last_local_id),
+                    &self.tcx.hir_expect_opaque_ty(exp_local_id),
                 ) {
                     (
                         hir::OpaqueTy { bounds: last_bounds, .. },
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index ad46a15a5ac..4f89f3c2b49 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -22,7 +22,6 @@ use rustc_hir::{
     expr_needs_parens, is_range_literal,
 };
 use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk};
-use rustc_middle::hir::map;
 use rustc_middle::traits::IsConstable;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::print::{
@@ -93,7 +92,7 @@ impl<'a, 'tcx> CoroutineData<'a, 'tcx> {
     fn get_from_await_ty<F>(
         &self,
         visitor: AwaitsVisitor,
-        hir: map::Map<'tcx>,
+        tcx: TyCtxt<'tcx>,
         ty_matches: F,
     ) -> Option<Span>
     where
@@ -102,7 +101,7 @@ impl<'a, 'tcx> CoroutineData<'a, 'tcx> {
         visitor
             .awaits
             .into_iter()
-            .map(|id| hir.expect_expr(id))
+            .map(|id| tcx.hir_expect_expr(id))
             .find(|await_expr| ty_matches(ty::Binder::dummy(self.0.expr_ty_adjusted(await_expr))))
             .map(|expr| expr.span)
     }
@@ -2180,8 +2179,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         err: &mut Diag<'_, G>,
         obligation: &PredicateObligation<'tcx>,
     ) -> bool {
-        let hir = self.tcx.hir();
-
         // Attempt to detect an async-await error by looking at the obligation causes, looking
         // for a coroutine to be present.
         //
@@ -2350,7 +2347,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
         let mut interior_or_upvar_span = None;
 
-        let from_awaited_ty = coroutine_data.get_from_await_ty(visitor, hir, ty_matches);
+        let from_awaited_ty = coroutine_data.get_from_await_ty(visitor, self.tcx, ty_matches);
         debug!(?from_awaited_ty);
 
         // Avoid disclosing internal information to downstream crates.
@@ -2428,7 +2425,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
         // Special case the primary error message when send or sync is the trait that was
         // not implemented.
-        let hir = self.tcx.hir();
         let trait_explanation = if let Some(name @ (sym::Send | sym::Sync)) =
             self.tcx.get_diagnostic_name(trait_pred.def_id())
         {
@@ -2455,7 +2451,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             .parent(coroutine_did)
                             .as_local()
                             .map(|parent_did| self.tcx.local_def_id_to_hir_id(parent_did))
-                            .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
+                            .and_then(|parent_hir_id| self.tcx.hir_opt_name(parent_hir_id))
                             .map(|name| {
                                 format!("future returned by `{name}` is not {trait_name}")
                             })?,
@@ -2479,7 +2475,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             .parent(coroutine_did)
                             .as_local()
                             .map(|parent_did| self.tcx.local_def_id_to_hir_id(parent_did))
-                            .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
+                            .and_then(|parent_hir_id| self.tcx.hir_opt_name(parent_hir_id))
                             .map(|name| {
                                 format!("async iterator returned by `{name}` is not {trait_name}")
                             })?,
@@ -2502,7 +2498,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                 .parent(coroutine_did)
                                 .as_local()
                                 .map(|parent_did| self.tcx.local_def_id_to_hir_id(parent_did))
-                                .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
+                                .and_then(|parent_hir_id| self.tcx.hir_opt_name(parent_hir_id))
                                 .map(|name| {
                                     format!("iterator returned by `{name}` is not {trait_name}")
                                 })?
@@ -3569,7 +3565,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             ObligationCauseCode::OpaqueReturnType(expr_info) => {
                 let (expr_ty, expr) = if let Some((expr_ty, hir_id)) = expr_info {
                     let expr_ty = tcx.short_string(expr_ty, err.long_ty_path());
-                    let expr = tcx.hir().expect_expr(hir_id);
+                    let expr = tcx.hir_expect_expr(hir_id);
                     (expr_ty, expr)
                 } else if let Some(body_id) = tcx.hir_node_by_def_id(body_id).body_id()
                     && let body = tcx.hir_body(body_id)
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index cc329ca3328..4a889abfc28 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -70,7 +70,7 @@ pub(crate) fn codegen_select_candidate<'tcx>(
                 infcx.err_ctxt().report_overflow_obligation_cycle(&cycle);
             }
         }
-        return Err(CodegenObligationError::FulfillmentError);
+        return Err(CodegenObligationError::Unimplemented);
     }
 
     let impl_source = infcx.resolve_vars_if_possible(impl_source);
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index c84055f5b84..b7684e85d41 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -21,7 +21,7 @@ pub(crate) fn provide(providers: &mut Providers) {
 }
 
 fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] {
-    let item = tcx.hir().expect_item(def_id);
+    let item = tcx.hir_expect_item(def_id);
     match item.kind {
         hir::ItemKind::Trait(.., trait_item_refs) => {
             // We collect RPITITs for each trait method's return type and create a
@@ -96,7 +96,7 @@ fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> DefIdMap<DefId>
 fn associated_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AssocItem {
     let id = tcx.local_def_id_to_hir_id(def_id);
     let parent_def_id = tcx.hir_get_parent_item(id);
-    let parent_item = tcx.hir().expect_item(parent_def_id.def_id);
+    let parent_item = tcx.hir_expect_item(parent_def_id.def_id);
     match parent_item.kind {
         hir::ItemKind::Impl(impl_) => {
             if let Some(impl_item_ref) = impl_.items.iter().find(|i| i.id.owner_id.def_id == def_id)
@@ -201,7 +201,7 @@ fn associated_types_for_impl_traits_in_associated_fn(
 
             let mut visitor = RPITVisitor { rpits: FxIndexSet::default() };
 
-            if let Some(output) = tcx.hir().get_fn_output(fn_def_id) {
+            if let Some(output) = tcx.hir_get_fn_output(fn_def_id) {
                 visitor.visit_fn_ret_ty(output);
 
                 tcx.arena.alloc_from_iter(visitor.rpits.iter().map(|opaque_ty_def_id| {
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 6205578bf74..aeaa83c77b5 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -161,7 +161,7 @@ fn fn_sig_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Spa
 }
 
 fn impl_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> {
-    let item = tcx.hir().expect_item(def_id);
+    let item = tcx.hir_expect_item(def_id);
     if let hir::ItemKind::Impl(impl_) = item.kind {
         let trait_args = impl_
             .of_trait
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 6dc5a9c4a47..90b3517eded 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -107,11 +107,9 @@ fn resolve_associated_item<'tcx>(
     let input = typing_env.as_query_input(trait_ref);
     let vtbl = match tcx.codegen_select_candidate(input) {
         Ok(vtbl) => vtbl,
-        Err(
-            CodegenObligationError::Ambiguity
-            | CodegenObligationError::Unimplemented
-            | CodegenObligationError::FulfillmentError,
-        ) => return Ok(None),
+        Err(CodegenObligationError::Ambiguity | CodegenObligationError::Unimplemented) => {
+            return Ok(None);
+        }
         Err(CodegenObligationError::UnconstrainedParam(guar)) => return Err(guar),
     };
 
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index a107925fb18..3aad97d86cc 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -187,7 +187,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
         if !hir_id.is_owner() {
             return;
         }
-        let Some(defines) = self.tcx.hir_attrs(hir_id.owner).define_opaque else {
+        let Some(defines) = self.tcx.hir_attr_map(hir_id.owner).define_opaque else {
             return;
         };
         for &(span, define) in defines {
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index 5aa048c4cbc..8472f903050 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -373,8 +373,8 @@ pub enum ErrorKind {
     TooManyLinks,
     /// A filename was invalid.
     ///
-    /// This error can also cause if it exceeded the filename length limit.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    /// This error can also occur if a length limit for a name was exceeded.
+    #[stable(feature = "io_error_invalid_filename", since = "CURRENT_RUSTC_VERSION")]
     InvalidFilename,
     /// Program argument list too long.
     ///
diff --git a/src/doc/rustc-dev-guide/src/hir.md b/src/doc/rustc-dev-guide/src/hir.md
index 51893d537d7..75f5a9e2045 100644
--- a/src/doc/rustc-dev-guide/src/hir.md
+++ b/src/doc/rustc-dev-guide/src/hir.md
@@ -139,12 +139,12 @@ defined in the map. By matching on this, you can find out what sort of
 node the `HirId` referred to and also get a pointer to the data
 itself. Often, you know what sort of node `n` is – e.g. if you know
 that `n` must be some HIR expression, you can do
-[`tcx.hir().expect_expr(n)`][expect_expr], which will extract and return the
+[`tcx.hir_expect_expr(n)`][expect_expr], which will extract and return the
 [`&hir::Expr`][Expr], panicking if `n` is not in fact an expression.
 
 [find]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.find
 [`Node`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/enum.Node.html
-[expect_expr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.expect_expr
+[expect_expr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.expect_expr
 [Expr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.Expr.html
 
 Finally, you can use the HIR map to find the parents of nodes, via
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 8c6ea00d489..e973b89b237 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -181,7 +181,7 @@ pub(crate) fn try_inline_glob(
                 .filter_map(|child| child.res.opt_def_id())
                 .filter(|def_id| !cx.tcx.is_doc_hidden(def_id))
                 .collect();
-            let attrs = cx.tcx.hir().attrs(import.hir_id());
+            let attrs = cx.tcx.hir_attrs(import.hir_id());
             let mut items = build_module_items(
                 cx,
                 did,
@@ -455,7 +455,7 @@ pub(crate) fn build_impl(
     }
 
     let impl_item = match did.as_local() {
-        Some(did) => match &tcx.hir().expect_item(did).kind {
+        Some(did) => match &tcx.hir_expect_item(did).kind {
             hir::ItemKind::Impl(impl_) => Some(impl_),
             _ => panic!("`DefID` passed to `build_impl` is not an `impl"),
         },
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 97ff4c2ef40..b213be5747b 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -112,7 +112,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
     items.extend(doc.inlined_foreigns.iter().flat_map(|((_, renamed), (res, local_import_id))| {
         let Some(def_id) = res.opt_def_id() else { return Vec::new() };
         let name = renamed.unwrap_or_else(|| cx.tcx.item_name(def_id));
-        let import = cx.tcx.hir().expect_item(*local_import_id);
+        let import = cx.tcx.hir_expect_item(*local_import_id);
         match import.kind {
             hir::ItemKind::Use(path, kind) => {
                 let hir::UsePath { segments, span, .. } = *path;
@@ -125,7 +125,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
     items.extend(doc.items.values().flat_map(|(item, renamed, _)| {
         // Now we actually lower the imports, skipping everything else.
         if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind {
-            let name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
+            let name = renamed.unwrap_or_else(|| cx.tcx.hir_name(item.hir_id()));
             clean_use_statement(item, name, path, hir::UseKind::Glob, cx, &mut inserted)
         } else {
             // skip everything else
@@ -986,7 +986,7 @@ fn clean_proc_macro<'tcx>(
     kind: MacroKind,
     cx: &mut DocContext<'tcx>,
 ) -> ItemKind {
-    let attrs = cx.tcx.hir().attrs(item.hir_id());
+    let attrs = cx.tcx.hir_attrs(item.hir_id());
     if kind == MacroKind::Derive
         && let Some(derive_name) =
             hir_attr_lists(attrs, sym::proc_macro_derive).find_map(|mi| mi.ident())
@@ -1019,7 +1019,7 @@ fn clean_fn_or_proc_macro<'tcx>(
     name: &mut Symbol,
     cx: &mut DocContext<'tcx>,
 ) -> ItemKind {
-    let attrs = cx.tcx.hir().attrs(item.hir_id());
+    let attrs = cx.tcx.hir_attrs(item.hir_id());
     let macro_kind = attrs.iter().find_map(|a| {
         if a.has_name(sym::proc_macro) {
             Some(MacroKind::Bang)
@@ -1756,7 +1756,7 @@ fn maybe_expand_private_type_alias<'tcx>(
     let alias = if !cx.cache.effective_visibilities.is_exported(cx.tcx, def_id.to_def_id())
         && !cx.current_type_aliases.contains_key(&def_id.to_def_id())
     {
-        &cx.tcx.hir().expect_item(def_id).kind
+        &cx.tcx.hir_expect_item(def_id).kind
     } else {
         return None;
     };
@@ -2762,7 +2762,7 @@ fn clean_maybe_renamed_item<'tcx>(
     use hir::ItemKind;
 
     let def_id = item.owner_id.to_def_id();
-    let mut name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
+    let mut name = renamed.unwrap_or_else(|| cx.tcx.hir_name(item.hir_id()));
     cx.with_param_env(def_id, |cx| {
         let kind = match item.kind {
             ItemKind::Static(ty, mutability, body_id) => StaticItem(Static {
@@ -2937,7 +2937,7 @@ fn clean_extern_crate<'tcx>(
     let cnum = cx.tcx.extern_mod_stmt_cnum(krate.owner_id.def_id).unwrap_or(LOCAL_CRATE);
     // this is the ID of the crate itself
     let crate_def_id = cnum.as_def_id();
-    let attrs = cx.tcx.hir().attrs(krate.hir_id());
+    let attrs = cx.tcx.hir_attrs(krate.hir_id());
     let ty_vis = cx.tcx.visibility(krate.owner_id);
     let please_inline = ty_vis.is_public()
         && attrs.iter().any(|a| {
@@ -3006,7 +3006,7 @@ fn clean_use_statement_inner<'tcx>(
     }
 
     let visibility = cx.tcx.visibility(import.owner_id);
-    let attrs = cx.tcx.hir().attrs(import.hir_id());
+    let attrs = cx.tcx.hir_attrs(import.hir_id());
     let inline_attr = hir_attr_lists(attrs, sym::doc).get_word_attr(sym::inline);
     let pub_underscore = visibility.is_public() && name == kw::Underscore;
     let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id);
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 88af9a7388c..f7f0c9766e2 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -216,7 +216,7 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions
 
         let collector = rustc_interface::create_and_enter_global_ctxt(compiler, krate, |tcx| {
             let crate_name = tcx.crate_name(LOCAL_CRATE).to_string();
-            let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
+            let crate_attrs = tcx.hir_attrs(CRATE_HIR_ID);
             let opts = scrape_test_config(crate_name, crate_attrs, args_path);
             let enable_per_target_ignores = options.enable_per_target_ignores;
 
diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs
index 907e2a3eb2f..18ad442d017 100644
--- a/src/librustdoc/doctest/rust.rs
+++ b/src/librustdoc/doctest/rust.rs
@@ -95,7 +95,7 @@ impl HirCollector<'_> {
         sp: Span,
         nested: F,
     ) {
-        let ast_attrs = self.tcx.hir().attrs(self.tcx.local_def_id_to_hir_id(def_id));
+        let ast_attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id));
         if let Some(ref cfg) =
             extract_cfg_from_attrs(ast_attrs.iter(), self.tcx, &FxHashSet::default())
             && !cfg.matches(&self.tcx.sess.psess, Some(self.tcx.features()))
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index edfcc1291b9..4150c5609a9 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -1,5 +1,5 @@
 // Local js definitions:
-/* global addClass, getSettingValue, hasClass, searchState, updateLocalStorage */
+/* global addClass, getSettingValue, hasClass, updateLocalStorage */
 /* global onEachLazy, removeClass, getVar */
 
 "use strict";
@@ -121,12 +121,9 @@ function getNakedUrl() {
  * doesn't have a parent node.
  *
  * @param {HTMLElement} newNode
- * @param {HTMLElement} referenceNode
+ * @param {HTMLElement & { parentNode: HTMLElement }} referenceNode
  */
 function insertAfter(newNode, referenceNode) {
-    // You're not allowed to pass an element with no parent.
-    // I dunno how to make TS's typechecker see that.
-    // @ts-expect-error
     referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
 }
 
@@ -305,11 +302,10 @@ function preLoadCss(cssUrl) {
                 window.searchState.timeout = null;
             }
         },
-        // @ts-expect-error
         isDisplayed: () => {
             const outputElement = window.searchState.outputElement();
-            return outputElement &&
-                outputElement.parentElement &&
+            return !!outputElement &&
+                !!outputElement.parentElement &&
                 outputElement.parentElement.id === ALTERNATIVE_DISPLAY_ID;
         },
         // Sets the focus on the search bar at the top of the page
@@ -325,8 +321,6 @@ function preLoadCss(cssUrl) {
                 search = window.searchState.outputElement();
             }
             switchDisplayedElement(search);
-            // @ts-expect-error
-            window.searchState.mouseMovedAfterSearch = false;
             document.title = window.searchState.title;
         },
         removeQueryParameters: () => {
@@ -503,34 +497,40 @@ function preLoadCss(cssUrl) {
         handleHashes(ev);
     }
 
-    // @ts-expect-error
+    /**
+     * @param {HTMLElement|null} elem
+     */
     function openParentDetails(elem) {
         while (elem) {
             if (elem.tagName === "DETAILS") {
+                // @ts-expect-error
                 elem.open = true;
             }
-            elem = elem.parentNode;
+            elem = elem.parentElement;
         }
     }
 
-    // @ts-expect-error
+    /**
+     * @param {string} id
+     */
     function expandSection(id) {
         openParentDetails(document.getElementById(id));
     }
 
-    // @ts-expect-error
+    /**
+     * @param {KeyboardEvent} ev
+     */
     function handleEscape(ev) {
-        // @ts-expect-error
-        searchState.clearInputTimeout();
-        // @ts-expect-error
-        searchState.hideResults();
+        window.searchState.clearInputTimeout();
+        window.searchState.hideResults();
         ev.preventDefault();
-        // @ts-expect-error
-        searchState.defocus();
+        window.searchState.defocus();
         window.hideAllModals(true); // true = reset focus for tooltips
     }
 
-    // @ts-expect-error
+    /**
+     * @param {KeyboardEvent} ev
+     */
     function handleShortcut(ev) {
         // Don't interfere with browser shortcuts
         const disableShortcuts = getSettingValue("disable-shortcuts") === "true";
@@ -538,8 +538,8 @@ function preLoadCss(cssUrl) {
             return;
         }
 
-        // @ts-expect-error
-        if (document.activeElement.tagName === "INPUT" &&
+        if (document.activeElement &&
+            document.activeElement.tagName === "INPUT" &&
             // @ts-expect-error
             document.activeElement.type !== "checkbox" &&
             // @ts-expect-error
@@ -559,8 +559,7 @@ function preLoadCss(cssUrl) {
             case "S":
             case "/":
                 ev.preventDefault();
-                // @ts-expect-error
-                searchState.focus();
+                window.searchState.focus();
                 break;
 
             case "+":
@@ -586,7 +585,6 @@ function preLoadCss(cssUrl) {
     document.addEventListener("keydown", handleShortcut);
 
     function addSidebarItems() {
-        // @ts-expect-error
         if (!window.SIDEBAR_ITEMS) {
             return;
         }
@@ -675,7 +673,6 @@ function preLoadCss(cssUrl) {
     }
 
     // <https://github.com/search?q=repo%3Arust-lang%2Frust+[RUSTDOCIMPL]+trait.impl&type=code>
-    // @ts-expect-error
     window.register_implementors = imp => {
         const implementors = document.getElementById("implementors-list");
         const synthetic_implementors = document.getElementById("synthetic-implementors-list");
@@ -767,9 +764,7 @@ function preLoadCss(cssUrl) {
             }
         }
     };
-    // @ts-expect-error
     if (window.pending_implementors) {
-        // @ts-expect-error
         window.register_implementors(window.pending_implementors);
     }
 
@@ -802,16 +797,14 @@ function preLoadCss(cssUrl) {
      *
      * - After processing all of the impls, it sorts the sidebar items by name.
      *
-     * @param {{[cratename: string]: Array<Array<string|0>>}} imp
+     * @param {rustdoc.TypeImpls} imp
      */
-    // @ts-expect-error
     window.register_type_impls = imp => {
         // @ts-expect-error
         if (!imp || !imp[window.currentCrate]) {
             return;
         }
-        // @ts-expect-error
-        window.pending_type_impls = null;
+        window.pending_type_impls = undefined;
         const idMap = new Map();
 
         let implementations = document.getElementById("implementations-list");
@@ -997,9 +990,7 @@ function preLoadCss(cssUrl) {
             list.replaceChildren(...newChildren);
         }
     };
-    // @ts-expect-error
     if (window.pending_type_impls) {
-        // @ts-expect-error
         window.register_type_impls(window.pending_type_impls);
     }
 
@@ -1695,8 +1686,7 @@ function preLoadCss(cssUrl) {
     addSidebarCrates();
     onHashChange(null);
     window.addEventListener("hashchange", onHashChange);
-    // @ts-expect-error
-    searchState.setup();
+    window.searchState.setup();
 }());
 
 // Hide, show, and resize the sidebar
diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts
index 1554c045a32..4b43c00730d 100644
--- a/src/librustdoc/html/static/js/rustdoc.d.ts
+++ b/src/librustdoc/html/static/js/rustdoc.d.ts
@@ -7,6 +7,8 @@ declare global {
     interface Window {
         /** Make the current theme easy to find */
         currentTheme: HTMLLinkElement|null;
+        /** Generated in `render/context.rs` */
+        SIDEBAR_ITEMS?: { [key: string]: string[] };
         /** Used by the popover tooltip code. */
         RUSTDOC_TOOLTIP_HOVER_MS: number;
         /** Used by the popover tooltip code. */
@@ -42,6 +44,17 @@ declare global {
          * Set up event listeners for a scraped source example.
          */
         updateScrapedExample?: function(HTMLElement, HTMLElement),
+        /**
+         * register trait implementors, called by code generated in
+         * `write_shared.rs`
+         */
+        register_implementors?: function(rustdoc.Implementors): void,
+        /**
+         * fallback in case `register_implementors` isn't defined yet.
+         */
+        pending_implementors?: rustdoc.Implementors,
+        register_type_impls?: function(rustdoc.TypeImpls): void,
+        pending_type_impls?: rustdoc.TypeImpls,
     }
     interface HTMLElement {
         /** Used by the popover tooltip code. */
@@ -413,4 +426,16 @@ declare namespace rustdoc {
     };
 
     type VlqData = VlqData[] | number;
+
+    /**
+     * Maps from crate names to trait implementation data.
+     * Provied by generated `trait.impl` files.
+     */
+    type Implementors = {
+        [key: string]: Array<[string, number, Array<string>]>
+    }
+
+    type TypeImpls = {
+        [cratename: string]: Array<Array<string|0>>
+    }
 }
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 7b6921afa08..68e381fa3f1 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -143,7 +143,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 && self.cx.tcx.has_attr(def_id, sym::macro_export)
                 && inserted.insert(def_id)
             {
-                let item = self.cx.tcx.hir().expect_item(local_def_id);
+                let item = self.cx.tcx.hir_expect_item(local_def_id);
                 top_level_module
                     .items
                     .insert((local_def_id, Some(item.ident.name)), (item, None, None));
@@ -153,8 +153,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         self.cx.cache.hidden_cfg = self
             .cx
             .tcx
-            .hir()
-            .attrs(CRATE_HIR_ID)
+            .hir_attrs(CRATE_HIR_ID)
             .iter()
             .filter(|attr| attr.has_name(sym::doc))
             .flat_map(|attr| attr.meta_item_list().into_iter().flatten())
@@ -245,7 +244,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         };
 
         let document_hidden = self.cx.render_options.document_hidden;
-        let use_attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(def_id));
+        let use_attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
         // Don't inline `doc(hidden)` imports so they can be stripped at a later stage.
         let is_no_inline = hir_attr_lists(use_attrs, sym::doc).has_word(sym::no_inline)
             || (document_hidden && hir_attr_lists(use_attrs, sym::doc).has_word(sym::hidden));
@@ -449,7 +448,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                         continue;
                     }
 
-                    let attrs = tcx.hir().attrs(tcx.local_def_id_to_hir_id(item.owner_id.def_id));
+                    let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(item.owner_id.def_id));
 
                     // If there was a private module in the current path then don't bother inlining
                     // anything as it will probably be stripped anyway.
diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
index 2b59c218d57..f9a2f011a14 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
@@ -465,7 +465,7 @@ impl Attributes {
 
 impl<'tcx> LateLintPass<'tcx> for Attributes {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        let attrs = cx.tcx.hir().attrs(item.hir_id());
+        let attrs = cx.tcx.hir_attrs(item.hir_id());
         if is_relevant_item(cx, item) {
             inline_always::check(cx, item.span, item.ident.name, attrs);
         }
@@ -474,13 +474,13 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
         if is_relevant_impl(cx, item) {
-            inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()));
+            inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir_attrs(item.hir_id()));
         }
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
         if is_relevant_trait(cx, item) {
-            inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()));
+            inline_always::check(cx, item.span, item.ident.name, cx.tcx.hir_attrs(item.hir_id()));
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
index 085ed9222c9..7c64bf46e7b 100644
--- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
@@ -97,7 +97,7 @@ fn is_zst<'tcx>(cx: &LateContext<'tcx>, field: &FieldDef, args: ty::GenericArgsR
 }
 
 fn has_c_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
-    let attrs = cx.tcx.hir().attrs(hir_id);
+    let attrs = cx.tcx.hir_attrs(hir_id);
 
     find_attr!(attrs, AttributeKind::Repr(r) if r.iter().any(|(x, _)| *x == ReprAttr::ReprC))
 }
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index 66a3e5e3d3c..8d9222e4bf6 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -197,9 +197,9 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
             && let ImplItemKind::Fn(_, b) = &impl_item.kind
             && let Body { value: func_expr, .. } = cx.tcx.hir_body(*b)
             && let &ty::Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind()
-            && let attrs = cx.tcx.hir().attrs(item.hir_id())
+            && let attrs = cx.tcx.hir_attrs(item.hir_id())
             && !attrs.iter().any(|attr| attr.doc_str().is_some())
-            && cx.tcx.hir().attrs(impl_item_hir).is_empty()
+            && cx.tcx.hir_attrs(impl_item_hir).is_empty()
         {
             if adt_def.is_struct() {
                 check_struct(cx, item, self_ty, func_expr, adt_def, args, cx.tcx.typeck_body(*b));
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index db3e6034c5b..2ae35b40055 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -384,7 +384,7 @@ fn check_unsafe_derive_deserialize<'tcx>(
             .tcx
             .inherent_impls(def.did())
             .iter()
-            .map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local()))
+            .map(|imp_did| cx.tcx.hir_expect_item(imp_did.expect_local()))
             .any(|imp| has_unsafe(cx, imp))
     {
         span_lint_hir_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
index e8638595c4b..e75abf28bac 100644
--- a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
@@ -25,7 +25,7 @@ pub fn check(
         && cx
             .tcx
             .hir_parent_iter(owner_id.into())
-            .any(|(id, _node)| is_doc_hidden(cx.tcx.hir().attrs(id)))
+            .any(|(id, _node)| is_doc_hidden(cx.tcx.hir_attrs(id)))
     {
         return;
     }
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index 33ba401d60c..9298f56b68b 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -163,7 +163,6 @@ impl<'tcx> Delegate<'tcx> for EscapeDelegate<'_, 'tcx> {
 
     fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId) {
         if cmt.place.projections.is_empty() {
-            let map = &self.cx.tcx.hir();
             if is_argument(self.cx.tcx, cmt.hir_id) {
                 // Skip closure arguments
                 let parent_id = self.cx.tcx.parent_hir_id(cmt.hir_id);
@@ -174,7 +173,7 @@ impl<'tcx> Delegate<'tcx> for EscapeDelegate<'_, 'tcx> {
                 // skip if there is a `self` parameter binding to a type
                 // that contains `Self` (i.e.: `self: Box<Self>`), see #4804
                 if let Some(trait_self_ty) = self.trait_self_ty {
-                    if map.name(cmt.hir_id) == kw::SelfLower && cmt.place.ty().contains(trait_self_ty) {
+                    if self.cx.tcx.hir_name(cmt.hir_id) == kw::SelfLower && cmt.place.ty().contains(trait_self_ty) {
                         return;
                     }
                 }
diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
index 9bf3baba4b5..591912cc8d5 100644
--- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
+++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
@@ -84,7 +84,7 @@ impl LateLintPass<'_> for ExhaustiveItems {
             _ => return,
         };
         if cx.effective_visibilities.is_exported(item.owner_id.def_id)
-            && let attrs = cx.tcx.hir().attrs(item.hir_id())
+            && let attrs = cx.tcx.hir_attrs(item.hir_id())
             && !attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
             && fields.iter().all(|f| cx.tcx.visibility(f.def_id).is_public())
         {
diff --git a/src/tools/clippy/clippy_lints/src/format_impl.rs b/src/tools/clippy/clippy_lints/src/format_impl.rs
index ff75fcf2b41..5b42a40d850 100644
--- a/src/tools/clippy/clippy_lints/src/format_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/format_impl.rs
@@ -209,9 +209,8 @@ impl FormatImplExpr<'_, '_> {
         // Handle dereference of &self -> self that is equivalent (i.e. via *self in fmt() impl)
         // Since the argument to fmt is itself a reference: &self
         let reference = peel_ref_operators(self.cx, arg);
-        let map = self.cx.tcx.hir();
         // Is the reference self?
-        if path_to_local(reference).map(|x| map.name(x)) == Some(kw::SelfLower) {
+        if path_to_local(reference).map(|x| self.cx.tcx.hir_name(x)) == Some(kw::SelfLower) {
             let FormatTraitNames { name, .. } = self.format_trait_impl;
             span_lint(
                 self.cx,
diff --git a/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs b/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs
index 0bdb99d7b9a..8822b87f92f 100644
--- a/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs
+++ b/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs
@@ -43,8 +43,7 @@ impl<'tcx> LateLintPass<'tcx> for FourForwardSlashes {
         let sm = cx.sess().source_map();
         let mut span = cx
             .tcx
-            .hir()
-            .attrs(item.hir_id())
+            .hir_attrs(item.hir_id())
             .iter()
             .filter(|i| i.is_doc_comment())
             .fold(item.span.shrink_to_lo(), |span, attr| span.to(attr.span()));
diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
index f1c9657f224..c3e0d5e8b69 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -21,7 +21,7 @@ use core::ops::ControlFlow;
 use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT};
 
 pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
-    let attrs = cx.tcx.hir().attrs(item.hir_id());
+    let attrs = cx.tcx.hir_attrs(item.hir_id());
     let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
     if let hir::ItemKind::Fn {
         ref sig,
@@ -51,7 +51,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
     if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind {
         let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
-        let attrs = cx.tcx.hir().attrs(item.hir_id());
+        let attrs = cx.tcx.hir_attrs(item.hir_id());
         let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
         if let Some(attr) = attr {
             check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig);
@@ -74,7 +74,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
         let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
 
-        let attrs = cx.tcx.hir().attrs(item.hir_id());
+        let attrs = cx.tcx.hir_attrs(item.hir_id());
         let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
         if let Some(attr) = attr {
             check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, attrs, sig);
diff --git a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
index 5b58113169b..e1dd7872b9d 100644
--- a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
+++ b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
@@ -182,7 +182,7 @@ fn suggestion<'tcx>(
 }
 
 fn field_with_attrs_span(tcx: TyCtxt<'_>, field: &hir::ExprField<'_>) -> Span {
-    if let Some(attr) = tcx.hir().attrs(field.hir_id).first() {
+    if let Some(attr) = tcx.hir_attrs(field.hir_id).first() {
         field.span.with_lo(attr.span().lo())
     } else {
         field.span
diff --git a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
index 9b4a3b3f9c8..6a436fb4a9d 100644
--- a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
+++ b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
@@ -34,8 +34,7 @@ impl<'tcx> LateLintPass<'tcx> for InlineFnWithoutBody {
         if let TraitItemKind::Fn(_, TraitFn::Required(_)) = item.kind
             && let Some(attr) = cx
                 .tcx
-                .hir()
-                .attrs(item.hir_id())
+                .hir_attrs(item.hir_id())
                 .iter()
                 .find(|a| a.has_name(sym::inline))
         {
diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs
index 20be22850b7..b712b351d06 100644
--- a/src/tools/clippy/clippy_lints/src/macro_use.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_use.rs
@@ -98,7 +98,7 @@ impl LateLintPass<'_> for MacroUseImports {
         if cx.sess().opts.edition >= Edition::Edition2018
             && let hir::ItemKind::Use(path, _kind) = &item.kind
             && let hir_id = item.hir_id()
-            && let attrs = cx.tcx.hir().attrs(hir_id)
+            && let attrs = cx.tcx.hir_attrs(hir_id)
             && let Some(mac_attr) = attrs.iter().find(|attr| attr.has_name(sym::macro_use))
             && let Some(id) = path.res.iter().find_map(|res| match res {
                 Res::Def(DefKind::Mod, id) => Some(id),
diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
index 496e0660d4f..64b07a5536b 100644
--- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
@@ -89,11 +89,11 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
         match item.kind {
             ItemKind::Enum(def, _) if def.variants.len() > 1 => {
                 let iter = def.variants.iter().filter_map(|v| {
-                    (matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir().attrs(v.hir_id)))
+                    (matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir_attrs(v.hir_id)))
                         .then_some((v.def_id, v.span))
                 });
                 if let Ok((id, span)) = iter.exactly_one()
-                    && !attr::contains_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive)
+                    && !attr::contains_name(cx.tcx.hir_attrs(item.hir_id()), sym::non_exhaustive)
                 {
                     self.potential_enums.push((item.owner_id.def_id, id, item.span, span));
                 }
@@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive {
                         "this seems like a manual implementation of the non-exhaustive pattern",
                         |diag| {
                             if let Some(non_exhaustive) =
-                                attr::find_by_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive)
+                                attr::find_by_name(cx.tcx.hir_attrs(item.hir_id()), sym::non_exhaustive)
                             {
                                 diag.span_note(non_exhaustive.span(), "the struct is already non-exhaustive");
                             } else {
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
index d697f427c70..d29d1ea3e96 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
@@ -42,7 +42,7 @@ pub(super) fn check_match<'tcx>(
         cx,
         scrutinee,
         arms.iter()
-            .map(|arm| (cx.tcx.hir().attrs(arm.hir_id), Some(arm.pat), arm.body, arm.guard)),
+            .map(|arm| (cx.tcx.hir_attrs(arm.hir_id), Some(arm.pat), arm.body, arm.guard)),
         e,
         false,
     )
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
index 41e4c75f843..250f17fa902 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
@@ -75,7 +75,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
                         HirIdMapEntry::Occupied(entry) => return *entry.get() == b_id,
                     }
                     // the names technically don't have to match; this makes the lint more conservative
-                    && cx.tcx.hir().name(a_id) == cx.tcx.hir().name(b_id)
+                    && cx.tcx.hir_name(a_id) == cx.tcx.hir_name(b_id)
                     && cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b)
                     && pat_contains_local(lhs.pat, a_id)
                     && pat_contains_local(rhs.pat, b_id)
diff --git a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
index 1c64f78678a..7c190e123b7 100644
--- a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
@@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_
 fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool {
     cx.tcx
         .hir_parent_id_iter(id)
-        .any(|id| cx.tcx.hir().attrs(id).iter().any(|attr| attr.has_name(sym::cfg)))
+        .any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg)))
 }
 
 /// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 94d3657d9f1..7dde21d3edb 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -4731,7 +4731,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
         }
         let name = impl_item.ident.name.as_str();
         let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
-        let item = cx.tcx.hir().expect_item(parent);
+        let item = cx.tcx.hir_expect_item(parent);
         let self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
 
         let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }));
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index 47a9e17b3cf..3470c266c49 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -182,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
     }
 
     fn check_crate(&mut self, cx: &LateContext<'tcx>) {
-        let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID);
+        let attrs = cx.tcx.hir_attrs(hir::CRATE_HIR_ID);
         self.check_missing_docs_attrs(cx, CRATE_DEF_ID, attrs, cx.tcx.def_span(CRATE_DEF_ID), "the", "crate");
     }
 
@@ -224,7 +224,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
 
         let (article, desc) = cx.tcx.article_and_description(it.owner_id.to_def_id());
 
-        let attrs = cx.tcx.hir().attrs(it.hir_id());
+        let attrs = cx.tcx.hir_attrs(it.hir_id());
         if !is_from_proc_macro(cx, it) {
             self.check_missing_docs_attrs(cx, it.owner_id.def_id, attrs, it.span, article, desc);
         }
@@ -234,7 +234,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx hir::TraitItem<'_>) {
         let (article, desc) = cx.tcx.article_and_description(trait_item.owner_id.to_def_id());
 
-        let attrs = cx.tcx.hir().attrs(trait_item.hir_id());
+        let attrs = cx.tcx.hir_attrs(trait_item.hir_id());
         if !is_from_proc_macro(cx, trait_item) {
             self.check_missing_docs_attrs(cx, trait_item.owner_id.def_id, attrs, trait_item.span, article, desc);
         }
@@ -252,7 +252,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
         }
 
         let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id());
-        let attrs = cx.tcx.hir().attrs(impl_item.hir_id());
+        let attrs = cx.tcx.hir_attrs(impl_item.hir_id());
         if !is_from_proc_macro(cx, impl_item) {
             self.check_missing_docs_attrs(cx, impl_item.owner_id.def_id, attrs, impl_item.span, article, desc);
         }
@@ -261,7 +261,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
 
     fn check_field_def(&mut self, cx: &LateContext<'tcx>, sf: &'tcx hir::FieldDef<'_>) {
         if !sf.is_positional() {
-            let attrs = cx.tcx.hir().attrs(sf.hir_id);
+            let attrs = cx.tcx.hir_attrs(sf.hir_id);
             if !is_from_proc_macro(cx, sf) {
                 self.check_missing_docs_attrs(cx, sf.def_id, attrs, sf.span, "a", "struct field");
             }
@@ -270,7 +270,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
     }
 
     fn check_variant(&mut self, cx: &LateContext<'tcx>, v: &'tcx hir::Variant<'_>) {
-        let attrs = cx.tcx.hir().attrs(v.hir_id);
+        let attrs = cx.tcx.hir_attrs(v.hir_id);
         if !is_from_proc_macro(cx, v) {
             self.check_missing_docs_attrs(cx, v.def_id, attrs, v.span, "a", "variant");
         }
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index 3cf1a80607e..2c578d81602 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -98,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
         match it.kind {
             hir::ItemKind::Fn { .. } => {
                 let desc = "a function";
-                let attrs = cx.tcx.hir().attrs(it.hir_id());
+                let attrs = cx.tcx.hir_attrs(it.hir_id());
                 check_missing_inline_attrs(cx, attrs, it.span, desc);
             },
             hir::ItemKind::Trait(ref _is_auto, ref _unsafe, _generics, _bounds, trait_items) => {
@@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
                                 // an impl is not provided
                                 let desc = "a default trait method";
                                 let item = cx.tcx.hir_trait_item(tit.id);
-                                let attrs = cx.tcx.hir().attrs(item.hir_id());
+                                let attrs = cx.tcx.hir_attrs(item.hir_id());
                                 check_missing_inline_attrs(cx, attrs, item.span, desc);
                             }
                         },
@@ -168,7 +168,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
             }
         }
 
-        let attrs = cx.tcx.hir().attrs(impl_item.hir_id());
+        let attrs = cx.tcx.hir_attrs(impl_item.hir_id());
         check_missing_inline_attrs(cx, attrs, impl_item.span, desc);
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
index a7452c8a3c8..be728e6c8b7 100644
--- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -334,7 +334,7 @@ impl<'tcx> Visitor<'tcx> for ReadVisitor<'_, 'tcx> {
                     self.cx,
                     MIXED_READ_WRITE_IN_EXPRESSION,
                     expr.span,
-                    format!("unsequenced read of `{}`", self.cx.tcx.hir().name(self.var)),
+                    format!("unsequenced read of `{}`", self.cx.tcx.hir_name(self.var)),
                     |diag| {
                         diag.span_note(
                             self.write_expr.span,
diff --git a/src/tools/clippy/clippy_lints/src/needless_if.rs b/src/tools/clippy/clippy_lints/src/needless_if.rs
index 7eefb016aca..c90019f6ee1 100644
--- a/src/tools/clippy/clippy_lints/src/needless_if.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_if.rs
@@ -65,7 +65,7 @@ impl LateLintPass<'_> for NeedlessIf {
                 stmt.span,
                 "this `if` branch is empty",
                 "you can remove it",
-                if cond.can_have_side_effects() || !cx.tcx.hir().attrs(stmt.hir_id).is_empty() {
+                if cond.can_have_side_effects() || !cx.tcx.hir_attrs(stmt.hir_id).is_empty() {
                     // `{ foo }` or `{ foo } && bar` placed into a statement position would be
                     // interpreted as a block statement, force it to be an expression
                     if cond_snippet.starts_with('{') {
diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs
index 863a1f895c9..3efbed0c236 100644
--- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs
@@ -261,7 +261,7 @@ fn check<'tcx>(
     binding_id: HirId,
 ) -> Option<()> {
     let usage = first_usage(cx, binding_id, local_stmt.hir_id, block)?;
-    let binding_name = cx.tcx.hir().opt_name(binding_id)?;
+    let binding_name = cx.tcx.hir_opt_name(binding_id)?;
     let let_snippet = local_snippet_without_semicolon(cx, local)?;
 
     match usage.expr.kind {
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
index dc10de24bc8..576bb27b254 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
@@ -147,7 +147,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
                     // We don't check unsafe functions.
                     return;
                 }
-                let attrs = cx.tcx.hir().attrs(hir_id);
+                let attrs = cx.tcx.hir_attrs(hir_id);
                 if header.abi != ExternAbi::Rust || requires_exact_signature(attrs) {
                     return;
                 }
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index dc85176ebb9..7bee89086b8 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
 
         match kind {
             FnKind::ItemFn(.., header) => {
-                let attrs = cx.tcx.hir().attrs(hir_id);
+                let attrs = cx.tcx.hir_attrs(hir_id);
                 if header.abi != ExternAbi::Rust || requires_exact_signature(attrs) {
                     return;
                 }
diff --git a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs
index 1baa3cb2f0f..fe8a02c64c6 100644
--- a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs
+++ b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs
@@ -40,7 +40,7 @@ impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi {
         if let ItemKind::Fn { sig: fn_sig, .. } = &item.kind
             && !item.span.from_expansion()
         {
-            let attrs = cx.tcx.hir().attrs(item.hir_id());
+            let attrs = cx.tcx.hir_attrs(item.hir_id());
             let mut app = Applicability::MaybeIncorrect;
             let fn_snippet = snippet_with_applicability(cx, fn_sig.span.with_hi(item.ident.span.lo()), "..", &mut app);
             for attr in attrs {
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index d4da12451f1..9b53608ae7f 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -351,7 +351,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
         if let ImplItemKind::Const(_, body_id) = &impl_item.kind {
             let item_def_id = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
-            let item = cx.tcx.hir().expect_item(item_def_id);
+            let item = cx.tcx.hir_expect_item(item_def_id);
 
             match &item.kind {
                 ItemKind::Impl(Impl {
diff --git a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
index c3c09946c27..378fed481f4 100644
--- a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
@@ -181,7 +181,7 @@ fn in_impl<'tcx>(
 ) -> Option<(&'tcx rustc_hir::Ty<'tcx>, &'tcx rustc_hir::Ty<'tcx>)> {
     if let Some(block) = get_enclosing_block(cx, e.hir_id)
         && let Some(impl_def_id) = cx.tcx.impl_of_method(block.hir_id.owner.to_def_id())
-        && let item = cx.tcx.hir().expect_item(impl_def_id.expect_local())
+        && let item = cx.tcx.hir_expect_item(impl_def_id.expect_local())
         && let ItemKind::Impl(item) = &item.kind
         && let Some(of_trait) = &item.of_trait
         && let Some(seg) = of_trait.path.segments.last()
@@ -200,7 +200,7 @@ fn in_impl<'tcx>(
 fn are_equal(cx: &LateContext<'_>, middle_ty: Ty<'_>, hir_ty: &rustc_hir::Ty<'_>) -> bool {
     if let ty::Adt(adt_def, _) = middle_ty.kind()
         && let Some(local_did) = adt_def.did().as_local()
-        && let item = cx.tcx.hir().expect_item(local_did)
+        && let item = cx.tcx.hir_expect_item(local_did)
         && let middle_ty_id = item.owner_id.to_def_id()
         && let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind
         && let Res::Def(_, hir_ty_id) = path.res
diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
index 49bc5608346..320c0286bb7 100644
--- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
@@ -280,7 +280,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
                 if header.abi != ExternAbi::Rust {
                     return;
                 }
-                let attrs = cx.tcx.hir().attrs(hir_id);
+                let attrs = cx.tcx.hir_attrs(hir_id);
                 for a in attrs {
                     if let Some(meta_items) = a.meta_item_list() {
                         if a.has_name(sym::proc_macro_derive)
diff --git a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
index db03657c9af..fd21893232d 100644
--- a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
+++ b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
@@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for PubUnderscoreFields {
             // Only pertains to fields that start with an underscore, and are public.
             if field.ident.as_str().starts_with('_') && is_visible(field)
                 // We ignore fields that have `#[doc(hidden)]`.
-                && !is_doc_hidden(cx.tcx.hir().attrs(field.hir_id))
+                && !is_doc_hidden(cx.tcx.hir_attrs(field.hir_id))
                 // We ignore fields that are `PhantomData`.
                 && !is_path_lang_item(cx, field.ty, LangItem::PhantomData)
             {
diff --git a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
index 6bd68dd4109..49b522994fb 100644
--- a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
+++ b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
@@ -93,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec {
                             },
                         ),
                         VecInitKind::WithExprCapacity(hir_id) => {
-                            let e = cx.tcx.hir().expect_expr(hir_id);
+                            let e = cx.tcx.hir_expect_expr(hir_id);
                             span_lint_hir_and_then(
                                 cx,
                                 READ_ZERO_BYTE_VEC,
diff --git a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
index 5a25483c397..07ae92fa984 100644
--- a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
@@ -74,7 +74,7 @@ fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, spa
         // We only show this warning for public exported methods.
         && cx.effective_visibilities.is_exported(fn_def)
         // We don't want to emit this lint if the `#[must_use]` attribute is already there.
-        && !cx.tcx.hir().attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use))
+        && !cx.tcx.hir_attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use))
         && cx.tcx.visibility(fn_def.to_def_id()).is_public()
         && let ret_ty = return_ty(cx, owner_id)
         && let self_arg = nth_arg(cx, owner_id, 0)
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 3ba6d628459..4cb73df8b48 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -231,7 +231,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
             && let Some(stmt) = block.stmts.iter().last()
             && let StmtKind::Let(local) = &stmt.kind
             && local.ty.is_none()
-            && cx.tcx.hir().attrs(local.hir_id).is_empty()
+            && cx.tcx.hir_attrs(local.hir_id).is_empty()
             && let Some(initexpr) = &local.init
             && let PatKind::Binding(_, local_id, _, _) = local.pat.kind
             && path_to_local_id(retexpr, local_id)
@@ -401,7 +401,7 @@ fn check_final_expr<'tcx>(
             // This allows the addition of attributes, like `#[allow]` (See: clippy#9361)
             // `#[expect(clippy::needless_return)]` needs to be handled separately to
             // actually fulfill the expectation (clippy::#12998)
-            match cx.tcx.hir().attrs(expr.hir_id) {
+            match cx.tcx.hir_attrs(expr.hir_id) {
                 [] => {},
                 [attr] => {
                     if matches!(Level::from_attr(attr), Some(Level::Expect(_)))
diff --git a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
index fc02c3a5171..8b2d597b9e3 100644
--- a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
+++ b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
@@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors {
         }
 
         let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
-        let item = cx.tcx.hir().expect_item(parent);
+        let item = cx.tcx.hir_expect_item(parent);
         let self_ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
         let ret_ty = return_ty(cx, impl_item.owner_id);
 
diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
index 746bf018bcc..be533ca915e 100644
--- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -429,8 +429,7 @@ fn block_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
 fn include_attrs_in_span(cx: &LateContext<'_>, hir_id: HirId, span: Span) -> Span {
     span.to(cx
         .tcx
-        .hir()
-        .attrs(hir_id)
+        .hir_attrs(hir_id)
         .iter()
         .fold(span, |acc, attr| acc.to(attr.span())))
 }
diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs
index 2c6c7569316..582aa6e6001 100644
--- a/src/tools/clippy/clippy_lints/src/unused_self.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_self.rs
@@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
             return;
         }
         let parent = cx.tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
-        let parent_item = cx.tcx.hir().expect_item(parent);
+        let parent_item = cx.tcx.hir_expect_item(parent);
         let assoc_item = cx.tcx.associated_item(impl_item.owner_id);
         let contains_todo = |cx, body: &'_ Body<'_>| -> bool {
             clippy_utils::visitors::for_each_expr_without_closures(body.value, |e| {
diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs
index 6f6683eb971..b466a8e127a 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap.rs
@@ -318,7 +318,7 @@ impl<'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'_, 'tcx> {
             {
                 if call_to_unwrap == unwrappable.safe_to_unwrap {
                     let is_entire_condition = unwrappable.is_entire_condition;
-                    let unwrappable_variable_name = self.cx.tcx.hir().name(unwrappable.local_id);
+                    let unwrappable_variable_name = self.cx.tcx.hir_name(unwrappable.local_id);
                     let suggested_pattern = if call_to_unwrap {
                         unwrappable.kind.success_variant_pattern()
                     } else {
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 9d8c161873c..4309cd2c9ab 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -793,7 +793,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
 }
 
 fn has_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
-    let attrs = cx.tcx.hir().attrs(hir_id);
+    let attrs = cx.tcx.hir_attrs(hir_id);
     get_attr(cx.sess(), attrs, "author").count() > 0
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/utils/dump_hir.rs b/src/tools/clippy/clippy_lints/src/utils/dump_hir.rs
index b108951978f..9910be9bc28 100644
--- a/src/tools/clippy/clippy_lints/src/utils/dump_hir.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/dump_hir.rs
@@ -59,6 +59,6 @@ impl<'tcx> LateLintPass<'tcx> for DumpHir {
 }
 
 fn has_attr(cx: &LateContext<'_>, hir_id: hir::HirId) -> bool {
-    let attrs = cx.tcx.hir().attrs(hir_id);
+    let attrs = cx.tcx.hir_attrs(hir_id);
     get_attr(cx.sess(), attrs, "dump").count() > 0
 }
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
index 89b4c48b8b1..16d51fa0902 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
@@ -247,7 +247,7 @@ fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<'
 /// This function extracts the version value of a `clippy::version` attribute if the given value has
 /// one
 pub(super) fn extract_clippy_version_value(cx: &LateContext<'_>, item: &'_ Item<'_>) -> Option<Symbol> {
-    let attrs = cx.tcx.hir().attrs(item.hir_id());
+    let attrs = cx.tcx.hir_attrs(item.hir_id());
     attrs.iter().find_map(|attr| {
         if let hir::Attribute::Unparsed(attr_kind) = &attr
             // Identify attribute
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index d8969246844..80613a51c14 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -2036,15 +2036,14 @@ pub fn has_attr(attrs: &[hir::Attribute], symbol: Symbol) -> bool {
 }
 
 pub fn has_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
-    find_attr!(cx.tcx.hir().attrs(hir_id), AttributeKind::Repr(..))
+    find_attr!(cx.tcx.hir_attrs(hir_id), AttributeKind::Repr(..))
 }
 
 pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool {
-    let map = &tcx.hir();
     let mut prev_enclosing_node = None;
     let mut enclosing_node = node;
     while Some(enclosing_node) != prev_enclosing_node {
-        if has_attr(map.attrs(enclosing_node), symbol) {
+        if has_attr(tcx.hir_attrs(enclosing_node), symbol) {
             return true;
         }
         prev_enclosing_node = Some(enclosing_node);
@@ -2061,7 +2060,7 @@ pub fn in_automatically_derived(tcx: TyCtxt<'_>, id: HirId) -> bool {
         .filter(|(_, node)| matches!(node, OwnerNode::Item(item) if matches!(item.kind, ItemKind::Impl(_))))
         .any(|(id, _)| {
             has_attr(
-                tcx.hir().attrs(tcx.local_def_id_to_hir_id(id.def_id)),
+                tcx.hir_attrs(tcx.local_def_id_to_hir_id(id.def_id)),
                 sym::automatically_derived,
             )
         })
@@ -2344,16 +2343,14 @@ pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> {
 
 pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
     cx.tcx
-        .hir()
-        .attrs(hir::CRATE_HIR_ID)
+        .hir_attrs(hir::CRATE_HIR_ID)
         .iter()
         .any(|attr| attr.name_or_empty() == sym::no_std)
 }
 
 pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
     cx.tcx
-        .hir()
-        .attrs(hir::CRATE_HIR_ID)
+        .hir_attrs(hir::CRATE_HIR_ID)
         .iter()
         .any(|attr| attr.name_or_empty() == sym::no_core)
 }
@@ -2643,8 +2640,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Sym
                         // We could also check for the type name `test::TestDescAndFn`
                         if let Res::Def(DefKind::Struct, _) = path.res {
                             let has_test_marker = tcx
-                                .hir()
-                                .attrs(item.hir_id())
+                                .hir_attrs(item.hir_id())
                                 .iter()
                                 .any(|a| a.has_name(sym::rustc_test_marker));
                             if has_test_marker {
@@ -2688,7 +2684,7 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool {
 /// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent
 /// use [`is_in_cfg_test`]
 pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool {
-    tcx.hir().attrs(id).iter().any(|attr| {
+    tcx.hir_attrs(id).iter().any(|attr| {
         if attr.has_name(sym::cfg)
             && let Some(items) = attr.meta_item_list()
             && let [item] = &*items
@@ -2713,12 +2709,10 @@ pub fn is_in_test(tcx: TyCtxt<'_>, hir_id: HirId) -> bool {
 
 /// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied.
 pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
-    let hir = tcx.hir();
-
     tcx.has_attr(def_id, sym::cfg)
         || tcx
             .hir_parent_iter(tcx.local_def_id_to_hir_id(def_id))
-            .flat_map(|(parent_id, _)| hir.attrs(parent_id))
+            .flat_map(|(parent_id, _)| tcx.hir_attrs(parent_id))
             .any(|attr| attr.has_name(sym::cfg))
 }
 
diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs
index 5bb2b12988a..0316de172de 100644
--- a/src/tools/clippy/clippy_utils/src/msrvs.rs
+++ b/src/tools/clippy/clippy_utils/src/msrvs.rs
@@ -108,7 +108,7 @@ impl Msrv {
             let start = cx.last_node_with_lint_attrs;
             if let Some(msrv_attr) = once(start)
                 .chain(cx.tcx.hir_parent_id_iter(start))
-                .find_map(|id| parse_attrs(cx.tcx.sess, cx.tcx.hir().attrs(id)))
+                .find_map(|id| parse_attrs(cx.tcx.sess, cx.tcx.hir_attrs(id)))
             {
                 return Some(msrv_attr);
             }
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 24b4f0d9e6d..9cc66593dcc 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -847,7 +847,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
             let mut start_snip = snippet_with_applicability(self.cx, start_span, "..", &mut self.applicability);
 
             // identifier referring to the variable currently triggered (i.e.: `fp`)
-            let ident_str = map.name(id).to_string();
+            let ident_str = self.cx.tcx.hir_name(id).to_string();
             // full identifier that includes projection (i.e.: `fp.field`)
             let ident_str_with_proj = snippet(self.cx, span, "..").to_string();
 
@@ -876,7 +876,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
                         // item is used in a call
                         // i.e.: `Call`: `|x| please(x)` or `MethodCall`: `|x| [1, 2, 3].contains(x)`
                         ExprKind::Call(_, call_args) | ExprKind::MethodCall(_, _, call_args, _) => {
-                            let expr = self.cx.tcx.hir().expect_expr(cmt.hir_id);
+                            let expr = self.cx.tcx.hir_expect_expr(cmt.hir_id);
                             let arg_ty_kind = self.cx.typeck_results().expr_ty(expr).kind();
 
                             if matches!(arg_ty_kind, ty::Ref(_, _, Mutability::Not)) {
diff --git a/tests/mir-opt/global_asm.rs b/tests/mir-opt/global_asm.rs
new file mode 100644
index 00000000000..22b782d365e
--- /dev/null
+++ b/tests/mir-opt/global_asm.rs
@@ -0,0 +1,9 @@
+// skip-filecheck
+//@ needs-asm-support
+
+// `global_asm!` gets a fake body, make sure it is handled correctly
+
+// EMIT_MIR global_asm.{global_asm#0}.SimplifyLocals-final.after.mir
+core::arch::global_asm!("/* */");
+
+fn main() {}
diff --git a/tests/mir-opt/global_asm.{global_asm#0}.SimplifyLocals-final.after.mir b/tests/mir-opt/global_asm.{global_asm#0}.SimplifyLocals-final.after.mir
new file mode 100644
index 00000000000..cec3c4a8261
--- /dev/null
+++ b/tests/mir-opt/global_asm.{global_asm#0}.SimplifyLocals-final.after.mir
@@ -0,0 +1,9 @@
+// MIR for `{global_asm#0}` after SimplifyLocals-final
+
+{global_asm#0}: ! = {
+    let mut _0: !;
+
+    bb0: {
+        asm!("/* */", options()) -> unwind unreachable;
+    }
+}
diff --git a/tests/ui/const-generics/const-param-type-depends-on-const-param.rs b/tests/ui/const-generics/const-param-type-depends-on-const-param.rs
index ee0e1326baa..3372ea5b853 100644
--- a/tests/ui/const-generics/const-param-type-depends-on-const-param.rs
+++ b/tests/ui/const-generics/const-param-type-depends-on-const-param.rs
@@ -9,11 +9,11 @@
 // We may want to lift this restriction in the future.
 
 pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
-//~^ ERROR: the type of const parameters must not depend on other generic parameters
-//[min]~^^ ERROR `[u8; N]` is forbidden
+//~^ ERROR the type of const parameters must not depend on other generic parameters
+//[min]~^^ ERROR `[u8; N]` is forbidden as the type of a const generic parameter
 
 pub struct SelfDependent<const N: [u8; N]>;
-//~^ ERROR: the type of const parameters must not depend on other generic parameters
-//[min]~^^ ERROR `[u8; N]` is forbidden
+//~^ ERROR the type of const parameters must not depend on other generic parameters
+//[min]~^^ ERROR `[u8; N]` is forbidden as the type of a const generic parameter
 
 fn main() {}
diff --git a/tests/ui/const-generics/const-param-type-depends-on-parent-param.rs b/tests/ui/const-generics/const-param-type-depends-on-parent-param.rs
new file mode 100644
index 00000000000..83fe8c139f9
--- /dev/null
+++ b/tests/ui/const-generics/const-param-type-depends-on-parent-param.rs
@@ -0,0 +1,8 @@
+#![feature(adt_const_params)]
+
+trait Trait<const N: usize> {
+    fn foo<const M: [u8; N]>() {}
+    //~^ ERROR the type of const parameters must not depend on other generic parameters
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/const-param-type-depends-on-parent-param.stderr b/tests/ui/const-generics/const-param-type-depends-on-parent-param.stderr
new file mode 100644
index 00000000000..ed0a4b118d4
--- /dev/null
+++ b/tests/ui/const-generics/const-param-type-depends-on-parent-param.stderr
@@ -0,0 +1,9 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/const-param-type-depends-on-parent-param.rs:4:26
+   |
+LL |     fn foo<const M: [u8; N]>() {}
+   |                          ^ the type must not depend on the parameter `N`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0770`.
diff --git a/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr b/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr
index 72d7001fdf1..c074e2e897e 100644
--- a/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr
+++ b/tests/ui/const-generics/defaults/default-const-param-cannot-reference-self.stderr
@@ -2,19 +2,19 @@ error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/default-const-param-cannot-reference-self.rs:1:34
    |
 LL | struct Struct<const N: usize = { Self; 10 }>;
-   |                                  ^^^^ `Self` in generic parameter default
+   |                                  ^^^^
 
 error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/default-const-param-cannot-reference-self.rs:4:30
    |
 LL | enum Enum<const N: usize = { Self; 10 }> { }
-   |                              ^^^^ `Self` in generic parameter default
+   |                              ^^^^
 
 error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/default-const-param-cannot-reference-self.rs:7:32
    |
 LL | union Union<const N: usize = { Self; 10 }> { not_empty: () }
-   |                                ^^^^ `Self` in generic parameter default
+   |                                ^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/const-generics/defaults/forward-declared.rs b/tests/ui/const-generics/defaults/forward-declared.rs
index ede3d873bdc..bd3abd4dcaa 100644
--- a/tests/ui/const-generics/defaults/forward-declared.rs
+++ b/tests/ui/const-generics/defaults/forward-declared.rs
@@ -1,13 +1,13 @@
 struct Foo<const N: usize = M, const M: usize = 10>;
-//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
 
 enum Bar<const N: usize = M, const M: usize = 10> {}
-//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
 
 struct Foo2<const N: usize = N>;
-//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
 
 enum Bar2<const N: usize = N> {}
-//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
 
 fn main() {}
diff --git a/tests/ui/const-generics/defaults/forward-declared.stderr b/tests/ui/const-generics/defaults/forward-declared.stderr
index 4856c7a1fd2..4331996bffc 100644
--- a/tests/ui/const-generics/defaults/forward-declared.stderr
+++ b/tests/ui/const-generics/defaults/forward-declared.stderr
@@ -1,26 +1,26 @@
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/forward-declared.rs:1:29
    |
 LL | struct Foo<const N: usize = M, const M: usize = 10>;
-   |                             ^ defaulted generic parameters cannot be forward declared
+   |                             ^ cannot reference `M` before it is declared
 
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/forward-declared.rs:4:27
    |
 LL | enum Bar<const N: usize = M, const M: usize = 10> {}
-   |                           ^ defaulted generic parameters cannot be forward declared
+   |                           ^ cannot reference `M` before it is declared
 
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/forward-declared.rs:7:30
    |
 LL | struct Foo2<const N: usize = N>;
-   |                              ^ defaulted generic parameters cannot be forward declared
+   |                              ^ cannot reference `N` before it is declared
 
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/forward-declared.rs:10:28
    |
 LL | enum Bar2<const N: usize = N> {}
-   |                            ^ defaulted generic parameters cannot be forward declared
+   |                            ^ cannot reference `N` before it is declared
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.rs b/tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.rs
index 91c1c80e07c..2abf7f44e20 100644
--- a/tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.rs
+++ b/tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.rs
@@ -4,8 +4,8 @@
 use std::marker::PhantomData;
 
 struct UsesConst<const N: [u8; M], const M: usize>;
-//~^ ERROR: the type of const parameters must not depend on other generic parameters
+//~^ ERROR: const parameter types cannot reference parameters before they are declared
 struct UsesType<const N: [T; 2], T>(PhantomData<T>);
-//~^ ERROR: the type of const parameters must not depend on other generic parameters
+//~^ ERROR: const parameter types cannot reference parameters before they are declared
 
 fn main() {}
diff --git a/tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.stderr b/tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.stderr
index b0dbdff8413..5526668b0be 100644
--- a/tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.stderr
+++ b/tests/ui/const-generics/generic_const_parameter_types/forward_declared_type.stderr
@@ -1,15 +1,14 @@
-error[E0770]: the type of const parameters must not depend on other generic parameters
+error: const parameter types cannot reference parameters before they are declared
   --> $DIR/forward_declared_type.rs:6:32
    |
 LL | struct UsesConst<const N: [u8; M], const M: usize>;
-   |                                ^ the type must not depend on the parameter `M`
+   |                                ^ const parameter type cannot reference `M` before it is declared
 
-error[E0770]: the type of const parameters must not depend on other generic parameters
+error: const parameter types cannot reference parameters before they are declared
   --> $DIR/forward_declared_type.rs:8:27
    |
 LL | struct UsesType<const N: [T; 2], T>(PhantomData<T>);
-   |                           ^ the type must not depend on the parameter `T`
+   |                           ^ const parameter type cannot reference `T` before it is declared
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0770`.
diff --git a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr
index 29171c8006a..2d47797aef2 100644
--- a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr
+++ b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr
@@ -16,7 +16,7 @@ LL |     type Assoc<const N: Self>;
    = note: the only supported types are integers, `bool`, and `char`
 
 error: anonymous constants referencing generics are not yet supported
-  --> $DIR/references-parent-generics.rs:14:21
+  --> $DIR/references-parent-generics.rs:15:21
    |
 LL |     let x: T::Assoc<3>;
    |                     ^
diff --git a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr
index 64b41318814..68ce17317f6 100644
--- a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr
+++ b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr
@@ -1,16 +1,9 @@
-error: `Self` is forbidden as the type of a const generic parameter
+error[E0770]: the type of const parameters must not depend on other generic parameters
   --> $DIR/references-parent-generics.rs:7:25
    |
 LL |     type Assoc<const N: Self>;
-   |                         ^^^^
-   |
-   = note: the only supported types are integers, `bool`, and `char`
-
-error: anonymous constants referencing generics are not yet supported
-  --> $DIR/references-parent-generics.rs:14:21
-   |
-LL |     let x: T::Assoc<3>;
-   |                     ^
+   |                         ^^^^ the type must not depend on the parameter `Self`
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0770`.
diff --git a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs
index 21994eb83b4..b91050d540c 100644
--- a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs
+++ b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs
@@ -5,14 +5,15 @@
 
 trait Foo {
     type Assoc<const N: Self>;
-    //~^ ERROR `Self` is forbidden as the type of a const generic parameter
+    //[nofeat]~^ ERROR the type of const parameters must not depend on other generic parameters
+    //[feat]~^^ ERROR `Self` is forbidden as the type of a const generic parameter
 }
 
 fn foo<T: Foo>() {
     // We used to end up feeding the type of this anon const to be `T`, but the anon const
     // doesn't inherit the generics of `foo`, which led to index oob errors.
     let x: T::Assoc<3>;
-    //~^ ERROR anonymous constants referencing generics are not yet supported
+    //[feat]~^ ERROR anonymous constants referencing generics are not yet supported
 }
 
 fn main() {}
diff --git a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr
index 9f0b2efae96..dc28dea6851 100644
--- a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr
+++ b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr
@@ -4,11 +4,11 @@ error: generic parameters with a default must be trailing
 LL | struct Bar<T = [u8; N], const N: usize>(T);
    |            ^
 
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21
    |
 LL | struct Bar<T = [u8; N], const N: usize>(T);
-   |                     ^ defaulted generic parameters cannot be forward declared
+   |                     ^ cannot reference `N` before it is declared
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
index 320c9c1c84d..3f0e5e96fc8 100644
--- a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
+++ b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
@@ -13,11 +13,11 @@ LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
    = note: type parameters may not be used in const expressions
    = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
 
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21
    |
 LL | struct Bar<T = [u8; N], const N: usize>(T);
-   |                     ^ defaulted generic parameters cannot be forward declared
+   |                     ^ cannot reference `N` before it is declared
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs
index 2794ff3eaa9..d212cc425a0 100644
--- a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs
+++ b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs
@@ -6,7 +6,7 @@ struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
 //[min]~^ ERROR generic parameters may not be used in const operations
 
 struct Bar<T = [u8; N], const N: usize>(T);
-//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
 //~| ERROR generic parameters with a default
 
 fn main() {}
diff --git a/tests/ui/consts/const-unsized.stderr b/tests/ui/consts/const-unsized.stderr
index 8328e19aac2..cee364b33f7 100644
--- a/tests/ui/consts/const-unsized.stderr
+++ b/tests/ui/consts/const-unsized.stderr
@@ -58,18 +58,18 @@ error[E0507]: cannot move out of a shared reference
 LL | static STATIC_BAR: str = *"bar";
    |                          ^^^^^^ move occurs because value has type `str`, which does not implement the `Copy` trait
 
-error[E0161]: cannot move a value of type `str`
-  --> $DIR/const-unsized.rs:20:48
-   |
-LL |     println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR);
-   |                                                ^^^^^^^^^ the size of `str` cannot be statically determined
-
 error[E0161]: cannot move a value of type `dyn Debug + Sync`
   --> $DIR/const-unsized.rs:20:38
    |
 LL |     println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR);
    |                                      ^^^^^^^ the size of `dyn Debug + Sync` cannot be statically determined
 
+error[E0161]: cannot move a value of type `str`
+  --> $DIR/const-unsized.rs:20:48
+   |
+LL |     println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR);
+   |                                                ^^^^^^^^^ the size of `str` cannot be statically determined
+
 error: aborting due to 10 previous errors
 
 Some errors have detailed explanations: E0161, E0277, E0507.
diff --git a/tests/ui/delegation/fn-header-variadic.rs b/tests/ui/delegation/fn-header-variadic.rs
new file mode 100644
index 00000000000..2c83d64d0b3
--- /dev/null
+++ b/tests/ui/delegation/fn-header-variadic.rs
@@ -0,0 +1,25 @@
+//@ aux-crate:fn_header_aux=fn-header-aux.rs
+
+#![feature(c_variadic)]
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod to_reuse {
+    pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
+}
+
+reuse to_reuse::variadic_fn;
+//~^ ERROR delegation to C-variadic functions is not allowed
+reuse fn_header_aux::variadic_fn_extern;
+//~^ ERROR delegation to C-variadic functions is not allowed
+
+fn main() {
+    unsafe {
+        variadic_fn(0);
+        variadic_fn(0, 1);
+        variadic_fn_extern(0);
+        variadic_fn_extern(0, 1);
+    }
+    let _: unsafe extern "C" fn(usize, ...) = variadic_fn;
+    let _: unsafe extern "C" fn(usize, ...) = variadic_fn_extern;
+}
diff --git a/tests/ui/delegation/fn-header-variadic.stderr b/tests/ui/delegation/fn-header-variadic.stderr
new file mode 100644
index 00000000000..688a965fb4d
--- /dev/null
+++ b/tests/ui/delegation/fn-header-variadic.stderr
@@ -0,0 +1,22 @@
+error: delegation to C-variadic functions is not allowed
+  --> $DIR/fn-header-variadic.rs:11:17
+   |
+LL |     pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
+   |     ------------------------------------------------------------- callee defined here
+...
+LL | reuse to_reuse::variadic_fn;
+   |                 ^^^^^^^^^^^
+
+error: delegation to C-variadic functions is not allowed
+  --> $DIR/fn-header-variadic.rs:13:22
+   |
+LL | reuse fn_header_aux::variadic_fn_extern;
+   |                      ^^^^^^^^^^^^^^^^^^
+   |
+  ::: $DIR/auxiliary/fn-header-aux.rs:7:1
+   |
+LL | pub unsafe extern "C" fn variadic_fn_extern(n: usize, mut args: ...) {}
+   | -------------------------------------------------------------------- callee defined here
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/delegation/fn-header.rs b/tests/ui/delegation/fn-header.rs
index db20e1058e0..9de0d549f20 100644
--- a/tests/ui/delegation/fn-header.rs
+++ b/tests/ui/delegation/fn-header.rs
@@ -10,20 +10,17 @@
 mod to_reuse {
     pub unsafe fn unsafe_fn() {}
     pub extern "C" fn extern_fn() {}
-    pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {}
     pub const fn const_fn() {}
     pub async fn async_fn() {}
 }
 
 reuse to_reuse::unsafe_fn;
 reuse to_reuse::extern_fn;
-reuse to_reuse::variadic_fn;
 reuse to_reuse::const_fn;
 reuse to_reuse::async_fn;
 
 reuse fn_header_aux::unsafe_fn_extern;
 reuse fn_header_aux::extern_fn_extern;
-reuse fn_header_aux::variadic_fn_extern;
 reuse fn_header_aux::const_fn_extern;
 reuse fn_header_aux::async_fn_extern;
 
@@ -46,12 +43,4 @@ fn main() {
     extern_fn_extern();
     let _: extern "C" fn() = extern_fn;
     let _: extern "C" fn() = extern_fn_extern;
-    unsafe {
-        variadic_fn(0);
-        variadic_fn(0, 1);
-        variadic_fn_extern(0);
-        variadic_fn_extern(0, 1);
-    }
-    let _: unsafe extern "C" fn(usize, ...) = variadic_fn;
-    let _: unsafe extern "C" fn(usize, ...) = variadic_fn_extern;
 }
diff --git a/tests/ui/delegation/ice-issue-138362.rs b/tests/ui/delegation/ice-issue-138362.rs
new file mode 100644
index 00000000000..c3066009855
--- /dev/null
+++ b/tests/ui/delegation/ice-issue-138362.rs
@@ -0,0 +1,15 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+trait HasSelf {
+    fn method(self);
+}
+trait NoSelf {
+    fn method();
+}
+impl NoSelf for u8 {
+    reuse HasSelf::method;
+    //~^ ERROR this function takes 1 argument but 0 arguments were supplied
+}
+
+fn main() {}
diff --git a/tests/ui/delegation/ice-issue-138362.stderr b/tests/ui/delegation/ice-issue-138362.stderr
new file mode 100644
index 00000000000..9feddc9feae
--- /dev/null
+++ b/tests/ui/delegation/ice-issue-138362.stderr
@@ -0,0 +1,19 @@
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
+  --> $DIR/ice-issue-138362.rs:11:20
+   |
+LL |     reuse HasSelf::method;
+   |                    ^^^^^^ argument #1 is missing
+   |
+note: method defined here
+  --> $DIR/ice-issue-138362.rs:5:8
+   |
+LL |     fn method(self);
+   |        ^^^^^^ ----
+help: provide the argument
+   |
+LL |     reuse HasSelf::method(/* value */);
+   |                          +++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/tests/ui/error-codes/E0128.stderr b/tests/ui/error-codes/E0128.stderr
index c1ccb4c9e74..22f1e200e29 100644
--- a/tests/ui/error-codes/E0128.stderr
+++ b/tests/ui/error-codes/E0128.stderr
@@ -1,8 +1,8 @@
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/E0128.rs:1:14
    |
 LL | struct Foo<T=U, U=()> {
-   |              ^ defaulted generic parameters cannot be forward declared
+   |              ^ cannot reference `U` before it is declared
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/generics/generic-non-trailing-defaults.rs b/tests/ui/generics/generic-non-trailing-defaults.rs
index 16ea71d48c8..ef500c42068 100644
--- a/tests/ui/generics/generic-non-trailing-defaults.rs
+++ b/tests/ui/generics/generic-non-trailing-defaults.rs
@@ -5,6 +5,6 @@ struct Vec<A = Heap, T>(A, T);
 
 struct Foo<A, B = Vec<C>, C>(A, B, C);
 //~^ ERROR generic parameters with a default must be trailing
-//~| ERROR generic parameters with a default cannot use
+//~| ERROR generic parameter defaults cannot reference parameters before they are declared
 
 fn main() {}
diff --git a/tests/ui/generics/generic-non-trailing-defaults.stderr b/tests/ui/generics/generic-non-trailing-defaults.stderr
index 713ba091b86..d9057e932f5 100644
--- a/tests/ui/generics/generic-non-trailing-defaults.stderr
+++ b/tests/ui/generics/generic-non-trailing-defaults.stderr
@@ -10,11 +10,11 @@ error: generic parameters with a default must be trailing
 LL | struct Foo<A, B = Vec<C>, C>(A, B, C);
    |               ^
 
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/generic-non-trailing-defaults.rs:6:23
    |
 LL | struct Foo<A, B = Vec<C>, C>(A, B, C);
-   |                       ^ defaulted generic parameters cannot be forward declared
+   |                       ^ cannot reference `C` before it is declared
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/generics/generic-type-params-forward-mention.rs b/tests/ui/generics/generic-type-params-forward-mention.rs
index 000c47095d2..4a8f76d34aa 100644
--- a/tests/ui/generics/generic-type-params-forward-mention.rs
+++ b/tests/ui/generics/generic-type-params-forward-mention.rs
@@ -1,6 +1,6 @@
 // Ensure that we get an error and not an ICE for this problematic case.
 struct Foo<T = Option<U>, U = bool>(T, U);
-//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
 fn main() {
     let x: Foo;
 }
diff --git a/tests/ui/generics/generic-type-params-forward-mention.stderr b/tests/ui/generics/generic-type-params-forward-mention.stderr
index d7a6faa1941..ecc2387b48b 100644
--- a/tests/ui/generics/generic-type-params-forward-mention.stderr
+++ b/tests/ui/generics/generic-type-params-forward-mention.stderr
@@ -1,8 +1,8 @@
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/generic-type-params-forward-mention.rs:2:23
    |
 LL | struct Foo<T = Option<U>, U = bool>(T, U);
-   |                       ^ defaulted generic parameters cannot be forward declared
+   |                       ^ cannot reference `U` before it is declared
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr b/tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr
index f3a550801b9..f659a144def 100644
--- a/tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr
+++ b/tests/ui/generics/issue-61631-default-type-param-cannot-reference-self.stderr
@@ -2,37 +2,37 @@ error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:13:25
    |
 LL | struct Snobound<'a, P = Self> { x: Option<&'a P> }
-   |                         ^^^^ `Self` in generic parameter default
+   |                         ^^^^
 
 error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:16:23
    |
 LL | enum Enobound<'a, P = Self> { A, B(Option<&'a P>) }
-   |                       ^^^^ `Self` in generic parameter default
+   |                       ^^^^
 
 error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:19:24
    |
 LL | union Unobound<'a, P = Self> { x: i32, y: Option<&'a P> }
-   |                        ^^^^ `Self` in generic parameter default
+   |                        ^^^^
 
 error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:25:31
    |
 LL | struct Ssized<'a, P: Sized = [Self]> { x: Option<&'a P> }
-   |                               ^^^^ `Self` in generic parameter default
+   |                               ^^^^
 
 error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:28:29
    |
 LL | enum Esized<'a, P: Sized = [Self]> { A, B(Option<&'a P>) }
-   |                             ^^^^ `Self` in generic parameter default
+   |                             ^^^^
 
 error[E0735]: generic parameters cannot use `Self` in their defaults
   --> $DIR/issue-61631-default-type-param-cannot-reference-self.rs:31:30
    |
 LL | union Usized<'a, P: Sized = [Self]> { x: i32, y: Option<&'a P> }
-   |                              ^^^^ `Self` in generic parameter default
+   |                              ^^^^
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/issues/issue-18183.stderr b/tests/ui/issues/issue-18183.stderr
index 11015d75d97..07fa4cdc753 100644
--- a/tests/ui/issues/issue-18183.stderr
+++ b/tests/ui/issues/issue-18183.stderr
@@ -1,8 +1,8 @@
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/issue-18183.rs:1:20
    |
 LL | pub struct Foo<Bar=Bar>(Bar);
-   |                    ^^^ defaulted generic parameters cannot be forward declared
+   |                    ^^^ cannot reference `Bar` before it is declared
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-26812.rs b/tests/ui/issues/issue-26812.rs
index e0723e016b3..8eb030a8ec9 100644
--- a/tests/ui/issues/issue-26812.rs
+++ b/tests/ui/issues/issue-26812.rs
@@ -1,5 +1,5 @@
 fn avg<T=T::Item>(_: T) {}
-//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+//~^ ERROR generic parameter defaults cannot reference parameters before they are declared
 //~| ERROR defaults for type parameters
 //~| WARN previously accepted
 
diff --git a/tests/ui/issues/issue-26812.stderr b/tests/ui/issues/issue-26812.stderr
index 4a18b23fd8b..bb60d67e287 100644
--- a/tests/ui/issues/issue-26812.stderr
+++ b/tests/ui/issues/issue-26812.stderr
@@ -1,8 +1,8 @@
-error[E0128]: generic parameters with a default cannot use forward declared identifiers
+error[E0128]: generic parameter defaults cannot reference parameters before they are declared
   --> $DIR/issue-26812.rs:1:10
    |
 LL | fn avg<T=T::Item>(_: T) {}
-   |          ^^^^^^^ defaulted generic parameters cannot be forward declared
+   |          ^^^^^^^ cannot reference `T` before it is declared
 
 error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
   --> $DIR/issue-26812.rs:1:8
diff --git a/tests/ui/rmeta/rmeta_bin-pass.rs b/tests/ui/rmeta/rmeta_bin-pass.rs
new file mode 100644
index 00000000000..7de4f3ba961
--- /dev/null
+++ b/tests/ui/rmeta/rmeta_bin-pass.rs
@@ -0,0 +1,14 @@
+//@ compile-flags: --emit=obj,metadata --crate-type=bin
+//@ aux-build:rmeta-meta.rs
+//@ no-prefer-dynamic
+//@ build-pass
+
+// Check that building a metadata bin crate works with a dependent, metadata
+// crate if linking is not requested.
+
+extern crate rmeta_meta;
+use rmeta_meta::Foo;
+
+pub fn main() {
+    let _ = Foo { field: 42 };
+}
diff --git a/tests/ui/rmeta/rmeta_bin.rs b/tests/ui/rmeta/rmeta_bin.rs
new file mode 100644
index 00000000000..c7d2050cd59
--- /dev/null
+++ b/tests/ui/rmeta/rmeta_bin.rs
@@ -0,0 +1,14 @@
+//@ build-fail
+//@ compile-flags: --crate-type=bin
+//@ aux-build:rmeta-meta.rs
+//@ no-prefer-dynamic
+//@ error-pattern: crate `rmeta_meta` required to be available in rlib format, but was not found
+
+// Check that building a bin crate fails if a dependent crate is metadata-only.
+
+extern crate rmeta_meta;
+use rmeta_meta::Foo;
+
+fn main() {
+    let _ = Foo { field: 42 };
+}
diff --git a/tests/ui/rmeta/rmeta_bin.stderr b/tests/ui/rmeta/rmeta_bin.stderr
new file mode 100644
index 00000000000..830169e032a
--- /dev/null
+++ b/tests/ui/rmeta/rmeta_bin.stderr
@@ -0,0 +1,4 @@
+error: crate `rmeta_meta` required to be available in rlib format, but was not found in this form
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs b/tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs
index f3f9ce0bd87..3a574af9bba 100644
--- a/tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs
+++ b/tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs
@@ -26,14 +26,7 @@ extern "C" fn main(argc: core::ffi::c_int, argv: *const *const u8) -> core::ffi:
     let actual = unsafe {
         let mut actual: libc::sigaction = core::mem::zeroed();
         libc::sigaction(libc::SIGPIPE, core::ptr::null(), &mut actual);
-        #[cfg(not(target_os = "aix"))]
-        {
-            actual.sa_sigaction
-        }
-        #[cfg(target_os = "aix")]
-        {
-            actual.sa_union.__su_sigaction as libc::sighandler_t
-        }
+        actual.sa_sigaction
     };
 
     assert_eq!(actual, expected, "actual and expected SIGPIPE disposition in child differs");
diff --git a/tests/ui/runtime/on-broken-pipe/auxiliary/sigpipe-utils.rs b/tests/ui/runtime/on-broken-pipe/auxiliary/sigpipe-utils.rs
index d16a2b4d8c8..3d93d50ca3f 100644
--- a/tests/ui/runtime/on-broken-pipe/auxiliary/sigpipe-utils.rs
+++ b/tests/ui/runtime/on-broken-pipe/auxiliary/sigpipe-utils.rs
@@ -20,14 +20,7 @@ pub fn assert_sigpipe_handler(expected_handler: SignalHandler) {
         let actual = unsafe {
             let mut actual: libc::sigaction = std::mem::zeroed();
             libc::sigaction(libc::SIGPIPE, std::ptr::null(), &mut actual);
-            #[cfg(not(target_os = "aix"))]
-            {
-                actual.sa_sigaction
-            }
-            #[cfg(target_os = "aix")]
-            {
-                actual.sa_union.__su_sigaction as libc::sighandler_t
-            }
+            actual.sa_sigaction
         };
 
         let expected = match expected_handler {
diff --git a/tests/ui/runtime/signal-alternate-stack-cleanup.rs b/tests/ui/runtime/signal-alternate-stack-cleanup.rs
index 8fce0928273..f2af86be0a5 100644
--- a/tests/ui/runtime/signal-alternate-stack-cleanup.rs
+++ b/tests/ui/runtime/signal-alternate-stack-cleanup.rs
@@ -29,14 +29,7 @@ fn main() {
         // Install signal handler that runs on alternate signal stack.
         let mut action: sigaction = std::mem::zeroed();
         action.sa_flags = (SA_ONSTACK | SA_SIGINFO) as _;
-        #[cfg(not(target_os = "aix"))]
-        {
-            action.sa_sigaction = signal_handler as sighandler_t;
-        }
-        #[cfg(target_os = "aix")]
-        {
-            action.sa_union.__su_sigaction = signal_handler as sighandler_t;
-        }
+        action.sa_sigaction = signal_handler as sighandler_t;
         sigaction(SIGWINCH, &action, std::ptr::null_mut());
 
         // Send SIGWINCH on exit.
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
index 55a5e4cd497..0fca91fd2f2 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
@@ -7,12 +7,12 @@ LL |     let _ = x as &dyn Bar<'static, 'a>; // Error
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:22:18
+  --> $DIR/type-checking-test-4.rs:22:13
    |
 LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) {
    |                -- lifetime `'a` defined here
 LL |     let _ = x as &dyn Bar<'a, 'static>; // Error
-   |                  ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
   --> $DIR/type-checking-test-4.rs:28:5